46 #define PRINTF(...) printf(__VA_ARGS__)
47 #define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15])
48 #define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5])
51 #define PRINT6ADDR(addr)
52 #define PRINTLLADDR(addr)
56 MEMB(observers_memb, coap_observer_t, COAP_MAX_OBSERVERS);
62 coap_add_observer(uip_ipaddr_t *addr, uint16_t port,
const uint8_t *token,
63 size_t token_len,
const char *uri)
66 coap_remove_observer_by_uri(addr, port, uri);
68 coap_observer_t *o =
memb_alloc(&observers_memb);
74 o->token_len = token_len;
75 memcpy(o->token, token, token_len);
78 PRINTF(
"Adding observer (%u/%u) for /%s [0x%02X%02X]\n",
79 list_length(observers_list) + 1, COAP_MAX_OBSERVERS,
80 o->url, o->token[0], o->token[1]);
90 coap_remove_observer(coap_observer_t *o)
92 PRINTF(
"Removing observer for /%s [0x%02X%02X]\n", o->url, o->token[0],
100 coap_remove_observer_by_client(uip_ipaddr_t *addr, uint16_t port)
103 coap_observer_t *obs =
NULL;
105 for(obs = (coap_observer_t *)
list_head(observers_list); obs;
107 PRINTF(
"Remove check client ");
109 PRINTF(
":%u\n", port);
110 if(uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port) {
111 coap_remove_observer(obs);
119 coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port,
120 uint8_t *token,
size_t token_len)
123 coap_observer_t *obs =
NULL;
125 for(obs = (coap_observer_t *)
list_head(observers_list); obs;
127 PRINTF(
"Remove check Token 0x%02X%02X\n", token[0], token[1]);
128 if(uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port
129 && obs->token_len == token_len
130 && memcmp(obs->token, token, token_len) == 0) {
131 coap_remove_observer(obs);
139 coap_remove_observer_by_uri(uip_ipaddr_t *addr, uint16_t port,
143 coap_observer_t *obs =
NULL;
145 for(obs = (coap_observer_t *)
list_head(observers_list); obs;
147 PRINTF(
"Remove check URL %p\n", uri);
149 || (uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port))
150 && (obs->url == uri || memcmp(obs->url, uri, strlen(obs->url)) == 0)) {
151 coap_remove_observer(obs);
159 coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port, uint16_t mid)
162 coap_observer_t *obs =
NULL;
164 for(obs = (coap_observer_t *)
list_head(observers_list); obs;
166 PRINTF(
"Remove check MID %u\n", mid);
167 if(uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port
168 && obs->last_mid == mid) {
169 coap_remove_observer(obs);
179 coap_notify_observers(resource_t *resource)
182 coap_packet_t notification[1];
183 coap_init_message(notification, COAP_TYPE_NON, CONTENT_2_05, 0);
184 coap_observer_t *obs =
NULL;
186 PRINTF(
"Observe: Notification from %s\n", resource->url);
189 for(obs = (coap_observer_t *)
list_head(observers_list); obs;
191 if(obs->url == resource->url) {
192 coap_transaction_t *transaction =
NULL;
196 if((transaction = coap_new_transaction(coap_get_mid(), &obs->addr, obs->port))) {
197 if(obs->obs_counter % COAP_OBSERVE_REFRESH_INTERVAL == 0) {
198 PRINTF(
" Force Confirmable for\n");
199 notification->type = COAP_TYPE_CON;
202 PRINTF(
" Observer ");
203 PRINT6ADDR(&obs->addr);
204 PRINTF(
":%u\n", obs->port);
207 obs->last_mid = transaction->mid;
210 notification->mid = transaction->mid;
212 resource->get_handler(
NULL, notification,
213 transaction->packet + COAP_MAX_HEADER_SIZE,
214 REST_MAX_CHUNK_SIZE,
NULL);
216 if(notification->code < BAD_REQUEST_4_00) {
217 coap_set_header_observe(notification, (obs->obs_counter)++);
219 coap_set_token(notification, obs->token, obs->token_len);
221 transaction->packet_len =
222 coap_serialize_message(notification, transaction->packet);
224 coap_send_transaction(transaction);
231 coap_observe_handler(resource_t *resource,
void *request,
void *response)
233 coap_packet_t *
const coap_req = (coap_packet_t *)request;
234 coap_packet_t *
const coap_res = (coap_packet_t *)response;
235 coap_observer_t * obs;
237 static char content[16];
239 if(coap_req->code == COAP_GET && coap_res->code < 128) {
240 if(IS_OPTION(coap_req, COAP_OPTION_OBSERVE)) {
241 if(coap_req->observe == 0) {
242 obs = coap_add_observer(&
UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport,
243 coap_req->token, coap_req->token_len,
246 coap_set_header_observe(coap_res, (obs->obs_counter)++);
260 coap_res->code = SERVICE_UNAVAILABLE_5_03;
261 coap_set_payload(coap_res,
"TooManyObservers", 16);
263 }
else if(coap_req->observe == 1) {
266 coap_remove_observer_by_token(&
UIP_IP_BUF->srcipaddr,
267 UIP_UDP_BUF->srcport, coap_req->token,
268 coap_req->token_len);
char memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
#define NULL
The null pointer.
void list_remove(list_t list, void *item)
Remove a specific element from a list.
int list_length(list_t list)
Get the length of a list.
#define UIP_IP_BUF
Pointer to IP header.
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
void * list_head(list_t list)
Get a pointer to the first element of a list.
#define MEMB(name, structure, num)
Declare a memory block.
void list_add(list_t list, void *item)
Add an item at the end of a list.
#define LIST(name)
Declare a linked list.
CoAP module for observing resources (draft-ietf-core-observe-11).