diff --git a/apps/er-coap-03/er-coap-03-observing.c b/apps/er-coap-03/er-coap-03-observing.c index 2da95248c..dc8fbc048 100644 --- a/apps/er-coap-03/er-coap-03-observing.c +++ b/apps/er-coap-03/er-coap-03-observing.c @@ -58,7 +58,7 @@ LIST(observers_list); /*-----------------------------------------------------------------------------------*/ coap_observer_t * -coap_add_observer(const char *url, uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, size_t token_len) +coap_add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, size_t token_len, const char *url) { coap_observer_t *o = memb_alloc(&observers_memb); @@ -173,7 +173,7 @@ coap_observe_handler(resource_t *resource, void *request, void *response) { if (IS_OPTION((coap_packet_t *)request, COAP_OPTION_TOKEN)) { - if (coap_add_observer(resource->url, &UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, ((coap_packet_t *)request)->token, ((coap_packet_t *)request)->token_len)) + if (coap_add_observer(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, ((coap_packet_t *)request)->token, ((coap_packet_t *)request)->token_len, resource->url)) { coap_set_header_observe(response, 0); coap_set_payload(response, (uint8_t *)content, snprintf(content, sizeof(content), "Added as observer %u/%u", list_length(observers_list), COAP_MAX_OBSERVERS)); diff --git a/apps/er-coap-03/er-coap-03-observing.h b/apps/er-coap-03/er-coap-03-observing.h index 90cbdf0b0..287c11e9f 100644 --- a/apps/er-coap-03/er-coap-03-observing.h +++ b/apps/er-coap-03/er-coap-03-observing.h @@ -65,7 +65,7 @@ typedef struct coap_observer { } coap_observer_t; list_t coap_get_observers(void); -coap_observer_t *coap_add_observer(const char *url, uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, size_t token_len); +coap_observer_t *coap_add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, size_t token_len, const char *url); void coap_remove_observer(coap_observer_t *o); int coap_remove_observer_by_client(uip_ipaddr_t *addr, uint16_t port); int coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port, uint8_t *token, size_t token_len); diff --git a/apps/er-coap-03/er-coap-03.c b/apps/er-coap-03/er-coap-03.c index 9a9189261..4f7a5b81c 100644 --- a/apps/er-coap-03/er-coap-03.c +++ b/apps/er-coap-03/er-coap-03.c @@ -745,7 +745,7 @@ coap_set_header_uri_query(void *packet, const char *query) /*- PAYLOAD -------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/ int -coap_get_payload(void *packet, const uint8_t **payload) +coap_get_payload(void *packet, uint8_t **payload) { if (((coap_packet_t *)packet)->payload) { *payload = ((coap_packet_t *)packet)->payload; @@ -757,11 +757,11 @@ coap_get_payload(void *packet, const uint8_t **payload) } int -coap_set_payload(void *packet, uint8_t *payload, size_t length) +coap_set_payload(void *packet, const void *payload, size_t length) { PRINTF("setting payload (%u/%u)\n", length, REST_MAX_CHUNK_SIZE); - ((coap_packet_t *)packet)->payload = payload; + ((coap_packet_t *)packet)->payload = (uint8_t *) payload; ((coap_packet_t *)packet)->payload_len = MIN(REST_MAX_CHUNK_SIZE, length); return ((coap_packet_t *)packet)->payload_len; diff --git a/apps/er-coap-03/er-coap-03.h b/apps/er-coap-03/er-coap-03.h index f6a2639ba..ebd2f164f 100644 --- a/apps/er-coap-03/er-coap-03.h +++ b/apps/er-coap-03/er-coap-03.h @@ -278,7 +278,7 @@ int coap_set_header_block(void *packet, uint32_t num, uint8_t more, uint16_t siz int coap_get_header_uri_query(void *packet, const char **query); /*CAUTION in-place string might not be 0-terminated */ int coap_set_header_uri_query(void *packet, const char *query); -int coap_get_payload(void *packet, const uint8_t **payload); -int coap_set_payload(void *packet, uint8_t *payload, size_t length); +int coap_get_payload(void *packet, uint8_t **payload); +int coap_set_payload(void *packet, const void *payload, size_t length); #endif /* COAP_03_H_ */ diff --git a/apps/er-coap-07/er-coap-07-engine.c b/apps/er-coap-07/er-coap-07-engine.c index df86d5719..f0545d61e 100644 --- a/apps/er-coap-07/er-coap-07-engine.c +++ b/apps/er-coap-07/er-coap-07-engine.c @@ -225,8 +225,8 @@ handle_incoming_data(void) /* Cancel possible subscriptions. */ if (IS_OPTION(message, COAP_OPTION_TOKEN)) { - PRINTF(" Token 0x%02X%02X\n", message->token[0], message->token[1]); - coap_remove_observer_by_token(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, message->token, message->token_len); + /* RST must be empty, so it is a full client reset. */ + coap_remove_observer_by_client(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport); } } diff --git a/apps/er-coap-07/er-coap-07-observing.c b/apps/er-coap-07/er-coap-07-observing.c index 4da0f5f67..5324a3a00 100644 --- a/apps/er-coap-07/er-coap-07-observing.c +++ b/apps/er-coap-07/er-coap-07-observing.c @@ -58,7 +58,7 @@ LIST(observers_list); /*-----------------------------------------------------------------------------------*/ coap_observer_t * -coap_add_observer(const char *url, uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, size_t token_len) +coap_add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, size_t token_len, const char *url) { coap_observer_t *o = memb_alloc(&observers_memb); @@ -125,7 +125,7 @@ coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port, uint8_t *token, return removed; } int -coap_remove_observer_by_url(const char *url) +coap_remove_observer_by_url(uip_ipaddr_t *addr, uint16_t port, const char *url) { int removed = 0; coap_observer_t* obs = NULL; @@ -133,7 +133,7 @@ coap_remove_observer_by_url(const char *url) for (obs = (coap_observer_t*)list_head(observers_list); obs; obs = obs->next) { PRINTF("Remove check URL %p\n", url); - if (obs->url==url || memcmp(obs->url, url, strlen(obs->url))==0) + if (uip_ipaddr_cmp(&obs->addr, addr) && obs->port==port && (obs->url==url || memcmp(obs->url, url, strlen(obs->url))==0)) { coap_remove_observer(obs); removed++; @@ -189,17 +189,21 @@ coap_observe_handler(resource_t *resource, void *request, void *response) coap_packet_t *const coap_req = (coap_packet_t *) request; coap_packet_t *const coap_res = (coap_packet_t *) response; - static char content[26]; + static char content[16]; - if (coap_req->code==COAP_GET && coap_res && coap_res->code<128) /* GET request and response without error code */ + if (coap_req->code==COAP_GET && coap_res->code<128) /* GET request and response without error code */ { if (IS_OPTION(coap_req, COAP_OPTION_OBSERVE)) { - if (coap_add_observer(resource->url, &UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, coap_req->token, coap_req->token_len)) + if (coap_add_observer(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, coap_req->token, coap_req->token_len, resource->url)) { coap_set_header_observe(coap_res, 0); - coap_set_payload(coap_res, content, snprintf(content, sizeof(content), "Added as observer %u/%u", list_length(observers_list), COAP_MAX_OBSERVERS)); + /* + * For demonstration purposes only. A subscription should return the same representation as a normal GET. + * TODO: Comment the following line for any real application. + */ + coap_set_payload(coap_res, content, snprintf(content, sizeof(content), "Added %u/%u", list_length(observers_list), COAP_MAX_OBSERVERS)); } else { @@ -210,7 +214,7 @@ coap_observe_handler(resource_t *resource, void *request, void *response) else /* if (observe) */ { /* Remove client if it is currently observing. */ - coap_remove_observer_by_client(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport); + coap_remove_observer_by_url(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, resource->url); } /* if (observe) */ } } diff --git a/apps/er-coap-07/er-coap-07-observing.h b/apps/er-coap-07/er-coap-07-observing.h index 078e9b430..d30acbebc 100644 --- a/apps/er-coap-07/er-coap-07-observing.h +++ b/apps/er-coap-07/er-coap-07-observing.h @@ -66,12 +66,12 @@ typedef struct coap_observer { list_t coap_get_observers(void); -coap_observer_t *coap_add_observer(const char *url, uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, size_t token_len); -void coap_remove_observer(coap_observer_t *o); +coap_observer_t *coap_add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, size_t token_len, const char *url); +void coap_remove_observer(coap_observer_t *o); int coap_remove_observer_by_client(uip_ipaddr_t *addr, uint16_t port); int coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port, uint8_t *token, size_t token_len); -int coap_remove_observer_by_url(const char *url); +int coap_remove_observer_by_url(uip_ipaddr_t *addr, uint16_t port, const char *url); void coap_notify_observers(const char *url, int type, uint32_t observe, uint8_t *payload, size_t payload_len); diff --git a/examples/er-rest-example/rest-server-example.c b/examples/er-rest-example/rest-server-example.c index 88dab13a0..65ccdc48e 100644 --- a/examples/er-rest-example/rest-server-example.c +++ b/examples/er-rest-example/rest-server-example.c @@ -47,8 +47,8 @@ #define REST_RES_HELLO 1 #define REST_RES_MIRROR 0 /* causes largest code size */ #define REST_RES_CHUNKS 1 -#define REST_RES_POLLING 0 #define REST_RES_SEPARATE 1 +#define REST_RES_PUSHING 1 #define REST_RES_EVENT 1 #define REST_RES_LEDS 1 #define REST_RES_TOGGLE 1 @@ -313,8 +313,8 @@ chunks_handler(void* request, void* response, uint8_t *buffer, uint16_t preferre REST.set_response_status(response, REST.status.BAD_OPTION); /* A block error message should not exceed the minimum block size (16). */ - const char error_msg[] = "BlockOutOfScope"; - REST.set_response_payload(response, (uint8_t *)error_msg, sizeof(error_msg)-1); + const char *error_msg = "BlockOutOfScope"; + REST.set_response_payload(response, error_msg, strlen(error_msg)); return; } @@ -349,47 +349,6 @@ chunks_handler(void* request, void* response, uint8_t *buffer, uint16_t preferre } #endif -#if REST_RES_POLLING -/* - * Example for a periodic resource. - * It takes an additional period parameter, which defines the interval to call [name]_periodic_handler(). - * A default post_handler takes care of subscriptions by managing a list of subscribers to notify. - */ -PERIODIC_RESOURCE(polling, METHOD_GET, "debug/poll", "title=\"Periodic demo\";rt=\"Observable\"", 5*CLOCK_SECOND); - -void -polling_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) -{ - REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - - /* Usually, a CoAP server would response with the current resource representation. */ - const char msg[] = "It's periodic!"; - REST.set_response_payload(response, (uint8_t *)msg, sizeof(msg)-1); - - /* A post_handler that handles subscriptions will be called for periodic resources by the REST framework. */ -} - -/* - * Additionally, a handler function named [resource name]_handler must be implemented for each PERIODIC_RESOURCE. - * It will be called by the REST manager process with the defined period. - */ -int -polling_periodic_handler(resource_t *r) -{ - static uint32_t periodic_i = 0; - static char content[16]; - - PRINTF("TICK /%s\n", r->url); - periodic_i = periodic_i + 1; - - /* Notify the registered observers with the given message type, observe option, and payload. */ - REST.notify_subscribers(r->url, 1, periodic_i, (uint8_t *)content, snprintf(content, sizeof(content), "TICK %lu", periodic_i)); - /* |-> implementation-specific, e.g. CoAP: 1=CON and 0=NON notification */ - - return 1; -} -#endif - #if REST_RES_SEPARATE && WITH_COAP > 3 /* Required to manually (=not by the engine) handle the response transaction. */ #include "er-coap-07-separate.h" @@ -413,8 +372,8 @@ separate_handler(void* request, void* response, uint8_t *buffer, uint16_t prefer if (separate_active) { REST.set_response_status(response, REST.status.SERVICE_UNAVAILABLE); - const char msg[] = "AlreadyInUse"; - REST.set_response_payload(response, (uint8_t *)msg, sizeof(msg)-1); + const char *msg = "AlreadyInUse"; + REST.set_response_payload(response, msg, strlen(msg)); } else { @@ -463,6 +422,47 @@ separate_finalize_handler() } #endif +#if REST_RES_PUSHING +/* + * Example for a periodic resource. + * It takes an additional period parameter, which defines the interval to call [name]_periodic_handler(). + * A default post_handler takes care of subscriptions by managing a list of subscribers to notify. + */ +PERIODIC_RESOURCE(pushing, METHOD_GET, "debug/push", "title=\"Periodic demo\";rt=\"Observable\"", 5*CLOCK_SECOND); + +void +pushing_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + + /* Usually, a CoAP server would response with the resource representation matching the periodic_handler. */ + const char *msg = "It's periodic!"; + REST.set_response_payload(response, msg, strlen(msg)); + + /* A post_handler that handles subscriptions will be called for periodic resources by the REST framework. */ +} + +/* + * Additionally, a handler function named [resource name]_handler must be implemented for each PERIODIC_RESOURCE. + * It will be called by the REST manager process with the defined period. + */ +int +pushing_periodic_handler(resource_t *r) +{ + static uint32_t periodic_i = 0; + static char content[16]; + + PRINTF("TICK /%s\n", r->url); + periodic_i = periodic_i + 1; + + /* Notify the registered observers with the given message type, observe option, and payload. */ + REST.notify_subscribers(r->url, 1, periodic_i, (uint8_t *)content, snprintf(content, sizeof(content), "TICK %lu", periodic_i)); + /* |-> implementation-specific, e.g. CoAP: 1=CON and 0=NON notification */ + + return 1; +} +#endif + #if defined (PLATFORM_HAS_BUTTON) && REST_RES_EVENT /* * Example for an event resource. @@ -475,10 +475,9 @@ void event_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - /* Usually, a CoAP server would response with the current resource representation. */ - const char msg[] = "It's eventful!"; - REST.set_response_payload(response, (uint8_t *)msg, sizeof(msg)-1); + const char *msg = "It's eventful!"; + REST.set_response_payload(response, (uint8_t *)msg, strlen(msg)); /* A post_handler that handles subscriptions/observing will be called for periodic resources by the framework. */ } @@ -600,8 +599,8 @@ light_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred else { REST.set_response_status(response, REST.status.UNSUPPORTED_MADIA_TYPE); - const char msg[] = "Supporting content-types text/plain, application/xml, and application/json"; - REST.set_response_payload(response, (uint8_t *)msg, sizeof(msg)-1); + const char *msg = "Supporting content-types text/plain, application/xml, and application/json"; + REST.set_response_payload(response, msg, strlen(msg)); } } #endif /* PLATFORM_HAS_LIGHT */ @@ -634,8 +633,8 @@ battery_handler(void* request, void* response, uint8_t *buffer, uint16_t preferr else { REST.set_response_status(response, REST.status.UNSUPPORTED_MADIA_TYPE); - const char msg[] = "Supporting content-types text/plain and application/json"; - REST.set_response_payload(response, (uint8_t *)msg, sizeof(msg)-1); + const char *msg = "Supporting content-types text/plain and application/json"; + REST.set_response_payload(response, msg, strlen(msg)); } } #endif /* PLATFORM_HAS_BATTERY */ @@ -680,8 +679,8 @@ PROCESS_THREAD(rest_server_example, ev, data) #if REST_RES_CHUNKS rest_activate_resource(&resource_chunks); #endif -#if REST_RES_POLLING - rest_activate_periodic_resource(&periodic_resource_polling); +#if REST_RES_PUSHING + rest_activate_periodic_resource(&periodic_resource_pushing); #endif #if REST_RES_SEPARATE && WITH_COAP > 3 rest_set_pre_handler(&resource_separate, coap_separate_handler);