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);
61 static coap_observer_t *
62 add_observer(uip_ipaddr_t *
addr, uint16_t port,
const uint8_t *token,
63 size_t token_len,
const char *uri,
int uri_len)
66 coap_remove_observer_by_uri(addr, port, uri);
68 coap_observer_t *o =
memb_alloc(&observers_memb);
71 int max =
sizeof(o->url) - 1;
75 memcpy(o->url, uri, max);
79 o->token_len = token_len;
80 memcpy(o->token, token, token_len);
83 PRINTF(
"Adding observer (%u/%u) for /%s [0x%02X%02X]\n",
84 list_length(observers_list) + 1, COAP_MAX_OBSERVERS,
85 o->url, o->token[0], o->token[1]);
95 coap_remove_observer(coap_observer_t *o)
97 PRINTF(
"Removing observer for /%s [0x%02X%02X]\n", o->url, o->token[0],
105 coap_remove_observer_by_client(uip_ipaddr_t *addr, uint16_t port)
108 coap_observer_t *obs =
NULL;
110 for(obs = (coap_observer_t *)
list_head(observers_list); obs;
112 PRINTF(
"Remove check client ");
114 PRINTF(
":%u\n", port);
115 if(uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port) {
116 coap_remove_observer(obs);
124 coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port,
125 uint8_t *token,
size_t token_len)
128 coap_observer_t *obs =
NULL;
130 for(obs = (coap_observer_t *)
list_head(observers_list); obs;
132 PRINTF(
"Remove check Token 0x%02X%02X\n", token[0], token[1]);
133 if(uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port
134 && obs->token_len == token_len
135 && memcmp(obs->token, token, token_len) == 0) {
136 coap_remove_observer(obs);
144 coap_remove_observer_by_uri(uip_ipaddr_t *addr, uint16_t port,
148 coap_observer_t *obs =
NULL;
150 for(obs = (coap_observer_t *)
list_head(observers_list); obs;
152 PRINTF(
"Remove check URL %p\n", uri);
154 || (uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port))
155 && (obs->url == uri || memcmp(obs->url, uri, strlen(obs->url)) == 0)) {
156 coap_remove_observer(obs);
164 coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port, uint16_t mid)
167 coap_observer_t *obs =
NULL;
169 for(obs = (coap_observer_t *)
list_head(observers_list); obs;
171 PRINTF(
"Remove check MID %u\n", mid);
172 if(uip_ipaddr_cmp(&obs->addr, addr) && obs->port == port
173 && obs->last_mid == mid) {
174 coap_remove_observer(obs);
184 coap_notify_observers(resource_t *resource)
186 coap_notify_observers_sub(resource,
NULL);
189 coap_notify_observers_sub(resource_t *resource,
const char *subpath)
192 coap_packet_t notification[1];
193 coap_packet_t request[1];
194 coap_observer_t *obs =
NULL;
195 int url_len, obs_url_len;
196 char url[COAP_OBSERVER_URL_LEN];
198 url_len = strlen(resource->url);
199 strncpy(url, resource->url, COAP_OBSERVER_URL_LEN - 1);
200 if(url_len < COAP_OBSERVER_URL_LEN - 1 && subpath !=
NULL) {
201 strncpy(&url[url_len], subpath, COAP_OBSERVER_URL_LEN - url_len - 1);
204 url[COAP_OBSERVER_URL_LEN - 1] =
'\0';
206 PRINTF(
"Observe: Notification from %s\n", url);
208 coap_init_message(notification, COAP_TYPE_NON, CONTENT_2_05, 0);
210 coap_init_message(request, COAP_TYPE_CON, COAP_GET, 0);
211 coap_set_header_uri_path(request, url);
214 url_len = strlen(url);
215 for(obs = (coap_observer_t *)
list_head(observers_list); obs;
217 obs_url_len = strlen(obs->url);
221 if((obs_url_len == url_len
222 || (obs_url_len > url_len
223 && (resource->flags & HAS_SUB_RESOURCES)
224 && obs->url[url_len] ==
'/'))
225 && strncmp(url, obs->url, url_len) == 0) {
226 coap_transaction_t *transaction =
NULL;
230 if((transaction = coap_new_transaction(coap_get_mid(), &obs->addr, obs->port))) {
231 if(obs->obs_counter % COAP_OBSERVE_REFRESH_INTERVAL == 0) {
232 PRINTF(
" Force Confirmable for\n");
233 notification->type = COAP_TYPE_CON;
236 PRINTF(
" Observer ");
237 PRINT6ADDR(&obs->addr);
238 PRINTF(
":%u\n", obs->port);
241 obs->last_mid = transaction->mid;
244 notification->mid = transaction->mid;
246 resource->get_handler(request, notification,
247 transaction->packet + COAP_MAX_HEADER_SIZE,
248 REST_MAX_CHUNK_SIZE,
NULL);
250 if(notification->code < BAD_REQUEST_4_00) {
251 coap_set_header_observe(notification, (obs->obs_counter)++);
253 coap_set_token(notification, obs->token, obs->token_len);
255 transaction->packet_len =
256 coap_serialize_message(notification, transaction->packet);
258 coap_send_transaction(transaction);
265 coap_observe_handler(resource_t *resource,
void *request,
void *response)
267 coap_packet_t *
const coap_req = (coap_packet_t *)request;
268 coap_packet_t *
const coap_res = (coap_packet_t *)response;
269 coap_observer_t * obs;
271 if(coap_req->code == COAP_GET && coap_res->code < 128) {
272 if(IS_OPTION(coap_req, COAP_OPTION_OBSERVE)) {
273 if(coap_req->observe == 0) {
274 obs = add_observer(&
UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport,
275 coap_req->token, coap_req->token_len,
276 coap_req->uri_path, coap_req->uri_path_len);
278 coap_set_header_observe(coap_res, (obs->obs_counter)++);
285 static char content[16];
286 coap_set_payload(coap_res,
288 snprintf(content,
sizeof(content),
"Added %u/%u",
290 COAP_MAX_OBSERVERS));
293 coap_res->code = SERVICE_UNAVAILABLE_5_03;
294 coap_set_payload(coap_res,
"TooManyObservers", 16);
296 }
else if(coap_req->observe == 1) {
299 coap_remove_observer_by_token(&
UIP_IP_BUF->srcipaddr,
300 UIP_UDP_BUF->srcport, coap_req->token,
301 coap_req->token_len);
void list_remove(list_t list, void *item)
Remove a specific element from a list.
#define LIST(name)
Declare a linked list.
static uip_ds6_addr_t * addr
Pointer to a router list entry.
CoAP module for observing resources (draft-ietf-core-observe-11).
#define MEMB(name, structure, num)
Declare a memory block.
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
#define UIP_IP_BUF
Pointer to IP header.
void * list_head(list_t list)
Get a pointer to the first element of a list.
#define NULL
The null pointer.
void list_add(list_t list, void *item)
Add an item at the end of a list.
int list_length(list_t list)
Get the length of a list.
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
char memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().