44 #include "er-coap-observe-client.h"
47 #if COAP_OBSERVE_CLIENT
51 #define PRINTF(...) printf(__VA_ARGS__)
52 #define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:" \
53 "%02x%02x:%02x%02x:%02x%02x:%02x%02x]", \
54 ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], \
55 ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], \
56 ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], \
57 ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], \
58 ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], \
59 ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], \
60 ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], \
61 ((uint8_t *)addr)[14], ((uint8_t *)addr)[15])
62 #define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", \
63 (lladdr)->addr[0], (lladdr)->addr[1], \
64 (lladdr)->addr[2], (lladdr)->addr[3], \
65 (lladdr)->addr[4], (lladdr)->addr[5])
68 #define PRINT6ADDR(addr)
69 #define PRINTLLADDR(addr)
72 MEMB(obs_subjects_memb, coap_observee_t, COAP_MAX_OBSERVEES);
73 LIST(obs_subjects_list);
77 get_token(
void *packet,
const uint8_t **token)
79 coap_packet_t *
const coap_pkt = (coap_packet_t *)packet;
81 *token = coap_pkt->token;
83 return coap_pkt->token_len;
87 set_token(
void *packet,
const uint8_t *token,
size_t token_len)
89 coap_packet_t *
const coap_pkt = (coap_packet_t *)packet;
91 coap_pkt->token_len = MIN(COAP_TOKEN_LEN, token_len);
92 memcpy(coap_pkt->token, token, coap_pkt->token_len);
94 return coap_pkt->token_len;
98 coap_obs_add_observee(uip_ipaddr_t *
addr, uint16_t port,
99 const uint8_t *token,
size_t token_len,
const char *url,
100 notification_callback_t notification_callback,
106 coap_obs_remove_observee_by_url(addr, port, url);
112 o->token_len = token_len;
113 memcpy(o->token, token, token_len);
115 o->notification_callback = notification_callback;
118 PRINTF(
"Adding obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0],
127 coap_obs_remove_observee(coap_observee_t *o)
129 PRINTF(
"Removing obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0],
136 coap_get_obs_subject_by_token(
const uint8_t *token,
size_t token_len)
138 coap_observee_t *obs =
NULL;
140 for(obs = (coap_observee_t *)
list_head(obs_subjects_list); obs;
142 PRINTF(
"Looking for token 0x%02X%02X\n", token[0], token[1]);
143 if(obs->token_len == token_len
144 && memcmp(obs->token, token, token_len) == 0) {
153 coap_obs_remove_observee_by_token(uip_ipaddr_t *addr, uint16_t port,
154 uint8_t *token,
size_t token_len)
157 coap_observee_t *obs =
NULL;
159 for(obs = (coap_observee_t *)
list_head(obs_subjects_list); obs;
161 PRINTF(
"Remove check Token 0x%02X%02X\n", token[0], token[1]);
162 if(uip_ipaddr_cmp(&obs->addr, addr)
164 && obs->token_len == token_len
165 && memcmp(obs->token, token, token_len) == 0) {
166 coap_obs_remove_observee(obs);
174 coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port,
178 coap_observee_t *obs =
NULL;
180 for(obs = (coap_observee_t *)
list_head(obs_subjects_list); obs;
182 PRINTF(
"Remove check URL %s\n", url);
183 if(uip_ipaddr_cmp(&obs->addr, addr)
185 && (obs->url == url || memcmp(obs->url, url, strlen(obs->url)) == 0)) {
186 coap_obs_remove_observee(obs);
194 simple_reply(coap_message_type_t type, uip_ip6addr_t *addr, uint16_t port,
195 coap_packet_t *notification)
197 static coap_packet_t response[1];
200 coap_init_message(response, type, NO_ERROR, notification->mid);
201 len = coap_serialize_message(response,
uip_appdata);
205 static coap_notification_flag_t
206 classify_notification(
void *response,
int first)
210 pkt = (coap_packet_t *)response;
212 PRINTF(
"no response\n");
213 return NO_REPLY_FROM_SERVER;
215 PRINTF(
"server replied\n");
216 if(!IS_RESPONSE_CODE_2_XX(pkt)) {
217 PRINTF(
"error response code\n");
218 return ERROR_RESPONSE_CODE;
220 if(!IS_OPTION(pkt, COAP_OPTION_OBSERVE)) {
221 PRINTF(
"server does not support observe\n");
222 return OBSERVE_NOT_SUPPORTED;
227 return NOTIFICATION_OK;
231 coap_handle_notification(uip_ipaddr_t *addr, uint16_t port,
232 coap_packet_t *notification)
235 const uint8_t *token;
237 coap_observee_t *obs;
238 coap_notification_flag_t flag;
241 PRINTF(
"coap_handle_notification()\n");
242 pkt = (coap_packet_t *)notification;
243 token_len = get_token(pkt, &token);
244 PRINTF(
"Getting token\n");
246 PRINTF(
"Error while handling coap observe notification: "
247 "no token in message\n");
250 PRINTF(
"Getting observee info\n");
251 obs = coap_get_obs_subject_by_token(token, token_len);
253 PRINTF(
"Error while handling coap observe notification: "
254 "no matching token found\n");
255 simple_reply(COAP_TYPE_RST, addr, port, notification);
258 if(notification->type == COAP_TYPE_CON) {
259 simple_reply(COAP_TYPE_ACK, addr, port, notification);
261 if(obs->notification_callback !=
NULL) {
262 flag = classify_notification(notification, 0);
265 if(flag == NOTIFICATION_OK) {
266 coap_get_header_observe(notification, &observe);
267 if(observe == obs->last_observe) {
268 PRINTF(
"Discarding duplicate\n");
271 obs->last_observe = observe;
273 obs->notification_callback(obs, notification, flag);
278 handle_obs_registration_response(
void *data,
void *response)
280 coap_observee_t *obs;
281 notification_callback_t notification_callback;
282 coap_notification_flag_t flag;
284 PRINTF(
"handle_obs_registration_response(): ");
285 obs = (coap_observee_t *)data;
286 notification_callback = obs->notification_callback;
287 flag = classify_notification(response, 1);
288 if(notification_callback) {
289 notification_callback(obs, response, flag);
291 if(flag != OBSERVE_OK) {
292 coap_obs_remove_observee(obs);
297 coap_generate_token(uint8_t **token_ptr)
299 static uint8_t token = 0;
303 *token_ptr = (uint8_t *)&token;
304 return sizeof(token);
308 coap_obs_request_registration(uip_ipaddr_t *addr, uint16_t port,
char *uri,
309 notification_callback_t notification_callback,
312 coap_packet_t request[1];
313 coap_transaction_t *t;
316 coap_observee_t *obs;
319 coap_init_message(request, COAP_TYPE_CON, COAP_GET, coap_get_mid());
320 coap_set_header_uri_path(request, uri);
321 coap_set_header_observe(request, 0);
322 token_len = coap_generate_token(&token);
323 set_token(request, token, token_len);
324 t = coap_new_transaction(request->mid, addr, port);
326 obs = coap_obs_add_observee(addr, port, (uint8_t *)token, token_len, uri,
327 notification_callback, data);
329 t->callback = handle_obs_registration_response;
330 t->callback_data = obs;
331 t->packet_len = coap_serialize_message(request, t->packet);
332 coap_send_transaction(t);
334 PRINTF(
"Could not allocate obs_subject resource buffer");
335 coap_clear_transaction(t);
338 PRINTF(
"Could not allocate transaction buffer");
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.
#define MEMB(name, structure, num)
Declare a memory block.
uip_appdata
Pointer to the application data in the packet buffer.
#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 NULL
The null pointer.
void list_add(list_t list, void *item)
Add an item at the end of a list.
An implementation of the Constrained Application Protocol (RFC).
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().