mirror of
https://github.com/oliverschmidt/contiki.git
synced 2024-09-09 23:54:32 +00:00
Merge pull request #1216 from nfi/coap-fixes
CoAP fixes and improvements
This commit is contained in:
commit
f9ed78a327
@ -58,9 +58,9 @@ LIST(observers_list);
|
|||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/*- Internal API ------------------------------------------------------------*/
|
/*- Internal API ------------------------------------------------------------*/
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
coap_observer_t *
|
static coap_observer_t *
|
||||||
coap_add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token,
|
add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token,
|
||||||
size_t token_len, const char *uri)
|
size_t token_len, const char *uri, int uri_len)
|
||||||
{
|
{
|
||||||
/* Remove existing observe relationship, if any. */
|
/* Remove existing observe relationship, if any. */
|
||||||
coap_remove_observer_by_uri(addr, port, uri);
|
coap_remove_observer_by_uri(addr, port, uri);
|
||||||
@ -68,7 +68,12 @@ coap_add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token,
|
|||||||
coap_observer_t *o = memb_alloc(&observers_memb);
|
coap_observer_t *o = memb_alloc(&observers_memb);
|
||||||
|
|
||||||
if(o) {
|
if(o) {
|
||||||
o->url = uri;
|
int max = sizeof(o->url) - 1;
|
||||||
|
if(max > uri_len) {
|
||||||
|
max = uri_len;
|
||||||
|
}
|
||||||
|
memcpy(o->url, uri, max);
|
||||||
|
o->url[max] = 0;
|
||||||
uip_ipaddr_copy(&o->addr, addr);
|
uip_ipaddr_copy(&o->addr, addr);
|
||||||
o->port = port;
|
o->port = port;
|
||||||
o->token_len = token_len;
|
o->token_len = token_len;
|
||||||
@ -177,18 +182,47 @@ coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port, uint16_t mid)
|
|||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
coap_notify_observers(resource_t *resource)
|
coap_notify_observers(resource_t *resource)
|
||||||
|
{
|
||||||
|
coap_notify_observers_sub(resource, NULL);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
coap_notify_observers_sub(resource_t *resource, const char *subpath)
|
||||||
{
|
{
|
||||||
/* build notification */
|
/* build notification */
|
||||||
coap_packet_t notification[1]; /* this way the packet can be treated as pointer as usual */
|
coap_packet_t notification[1]; /* this way the packet can be treated as pointer as usual */
|
||||||
coap_init_message(notification, COAP_TYPE_NON, CONTENT_2_05, 0);
|
coap_packet_t request[1]; /* this way the packet can be treated as pointer as usual */
|
||||||
coap_observer_t *obs = NULL;
|
coap_observer_t *obs = NULL;
|
||||||
|
int url_len, obs_url_len;
|
||||||
|
char url[COAP_OBSERVER_URL_LEN];
|
||||||
|
|
||||||
PRINTF("Observe: Notification from %s\n", resource->url);
|
url_len = strlen(resource->url);
|
||||||
|
strncpy(url, resource->url, COAP_OBSERVER_URL_LEN - 1);
|
||||||
|
if(url_len < COAP_OBSERVER_URL_LEN - 1 && subpath != NULL) {
|
||||||
|
strncpy(&url[url_len], subpath, COAP_OBSERVER_URL_LEN - url_len - 1);
|
||||||
|
}
|
||||||
|
/* Ensure url is null terminated because strncpy does not guarantee this */
|
||||||
|
url[COAP_OBSERVER_URL_LEN - 1] = '\0';
|
||||||
|
/* url now contains the notify URL that needs to match the observer */
|
||||||
|
PRINTF("Observe: Notification from %s\n", url);
|
||||||
|
|
||||||
|
coap_init_message(notification, COAP_TYPE_NON, CONTENT_2_05, 0);
|
||||||
|
/* create a "fake" request for the URI */
|
||||||
|
coap_init_message(request, COAP_TYPE_CON, COAP_GET, 0);
|
||||||
|
coap_set_header_uri_path(request, url);
|
||||||
|
|
||||||
/* iterate over observers */
|
/* iterate over observers */
|
||||||
|
url_len = strlen(url);
|
||||||
for(obs = (coap_observer_t *)list_head(observers_list); obs;
|
for(obs = (coap_observer_t *)list_head(observers_list); obs;
|
||||||
obs = obs->next) {
|
obs = obs->next) {
|
||||||
if(obs->url == resource->url) { /* using RESOURCE url pointer as handle */
|
obs_url_len = strlen(obs->url);
|
||||||
|
|
||||||
|
/* Do a match based on the parent/sub-resource match so that it is
|
||||||
|
possible to do parent-node observe */
|
||||||
|
if((obs_url_len == url_len
|
||||||
|
|| (obs_url_len > url_len
|
||||||
|
&& (resource->flags & HAS_SUB_RESOURCES)
|
||||||
|
&& obs->url[url_len] == '/'))
|
||||||
|
&& strncmp(url, obs->url, url_len) == 0) {
|
||||||
coap_transaction_t *transaction = NULL;
|
coap_transaction_t *transaction = NULL;
|
||||||
|
|
||||||
/*TODO implement special transaction for CON, sharing the same buffer to allow for more observers */
|
/*TODO implement special transaction for CON, sharing the same buffer to allow for more observers */
|
||||||
@ -209,7 +243,7 @@ coap_notify_observers(resource_t *resource)
|
|||||||
/* prepare response */
|
/* prepare response */
|
||||||
notification->mid = transaction->mid;
|
notification->mid = transaction->mid;
|
||||||
|
|
||||||
resource->get_handler(NULL, notification,
|
resource->get_handler(request, notification,
|
||||||
transaction->packet + COAP_MAX_HEADER_SIZE,
|
transaction->packet + COAP_MAX_HEADER_SIZE,
|
||||||
REST_MAX_CHUNK_SIZE, NULL);
|
REST_MAX_CHUNK_SIZE, NULL);
|
||||||
|
|
||||||
@ -237,9 +271,9 @@ coap_observe_handler(resource_t *resource, void *request, void *response)
|
|||||||
if(coap_req->code == COAP_GET && 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(IS_OPTION(coap_req, COAP_OPTION_OBSERVE)) {
|
||||||
if(coap_req->observe == 0) {
|
if(coap_req->observe == 0) {
|
||||||
obs = coap_add_observer(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport,
|
obs = add_observer(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport,
|
||||||
coap_req->token, coap_req->token_len,
|
coap_req->token, coap_req->token_len,
|
||||||
resource->url);
|
coap_req->uri_path, coap_req->uri_path_len);
|
||||||
if(obs) {
|
if(obs) {
|
||||||
coap_set_header_observe(coap_res, (obs->obs_counter)++);
|
coap_set_header_observe(coap_res, (obs->obs_counter)++);
|
||||||
/*
|
/*
|
||||||
|
@ -43,6 +43,8 @@
|
|||||||
#include "er-coap-transactions.h"
|
#include "er-coap-transactions.h"
|
||||||
#include "stimer.h"
|
#include "stimer.h"
|
||||||
|
|
||||||
|
#define COAP_OBSERVER_URL_LEN 20
|
||||||
|
|
||||||
typedef struct coap_observable {
|
typedef struct coap_observable {
|
||||||
uint32_t observe_clock;
|
uint32_t observe_clock;
|
||||||
struct stimer orphan_timer;
|
struct stimer orphan_timer;
|
||||||
@ -54,7 +56,7 @@ typedef struct coap_observable {
|
|||||||
typedef struct coap_observer {
|
typedef struct coap_observer {
|
||||||
struct coap_observer *next; /* for LIST */
|
struct coap_observer *next; /* for LIST */
|
||||||
|
|
||||||
const char *url;
|
char url[COAP_OBSERVER_URL_LEN];
|
||||||
uip_ipaddr_t addr;
|
uip_ipaddr_t addr;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
uint8_t token_len;
|
uint8_t token_len;
|
||||||
@ -68,11 +70,6 @@ typedef struct coap_observer {
|
|||||||
} coap_observer_t;
|
} coap_observer_t;
|
||||||
|
|
||||||
list_t coap_get_observers(void);
|
list_t coap_get_observers(void);
|
||||||
|
|
||||||
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);
|
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_client(uip_ipaddr_t *addr, uint16_t port);
|
||||||
int coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port,
|
int coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port,
|
||||||
@ -83,6 +80,7 @@ int coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port,
|
|||||||
uint16_t mid);
|
uint16_t mid);
|
||||||
|
|
||||||
void coap_notify_observers(resource_t *resource);
|
void coap_notify_observers(resource_t *resource);
|
||||||
|
void coap_notify_observers_sub(resource_t *resource, const char *subpath);
|
||||||
|
|
||||||
void coap_observe_handler(resource_t *resource, void *request,
|
void coap_observe_handler(resource_t *resource, void *request,
|
||||||
void *response);
|
void *response);
|
||||||
|
@ -124,7 +124,7 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
end = attrib + strlen(attrib);
|
end = attrib + strlen(attrib);
|
||||||
} else {
|
} else if(resource->attributes != NULL) {
|
||||||
attrib = strstr(resource->attributes, filter);
|
attrib = strstr(resource->attributes, filter);
|
||||||
if(attrib == NULL
|
if(attrib == NULL
|
||||||
|| (attrib[strlen(filter)] != '='
|
|| (attrib[strlen(filter)] != '='
|
||||||
@ -159,8 +159,8 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PRINTF("res: /%s (%p)\npos: s%d, o%ld, b%d\n", resource->url, resource,
|
PRINTF("res: /%s (%p)\npos: s%zu, o%ld, b%zu\n", resource->url, resource,
|
||||||
strpos, *offset, bufpos);
|
strpos, (long)*offset, bufpos);
|
||||||
|
|
||||||
if(strpos > 0) {
|
if(strpos > 0) {
|
||||||
ADD_CHAR_IF_POSSIBLE(',');
|
ADD_CHAR_IF_POSSIBLE(',');
|
||||||
@ -170,7 +170,7 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer,
|
|||||||
ADD_STRING_IF_POSSIBLE(resource->url, >=);
|
ADD_STRING_IF_POSSIBLE(resource->url, >=);
|
||||||
ADD_CHAR_IF_POSSIBLE('>');
|
ADD_CHAR_IF_POSSIBLE('>');
|
||||||
|
|
||||||
if(resource->attributes[0]) {
|
if(resource->attributes != NULL && resource->attributes[0]) {
|
||||||
ADD_CHAR_IF_POSSIBLE(';');
|
ADD_CHAR_IF_POSSIBLE(';');
|
||||||
ADD_STRING_IF_POSSIBLE(resource->attributes, >);
|
ADD_STRING_IF_POSSIBLE(resource->attributes, >);
|
||||||
}
|
}
|
||||||
@ -183,7 +183,7 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(bufpos > 0) {
|
if(bufpos > 0) {
|
||||||
PRINTF("BUF %d: %.*s\n", bufpos, bufpos, (char *)buffer);
|
PRINTF("BUF %zu: %.*s\n", bufpos, (int)bufpos, (char *)buffer);
|
||||||
|
|
||||||
coap_set_payload(response, buffer, bufpos);
|
coap_set_payload(response, buffer, bufpos);
|
||||||
coap_set_header_content_format(response, APPLICATION_LINK_FORMAT);
|
coap_set_header_content_format(response, APPLICATION_LINK_FORMAT);
|
||||||
|
@ -113,15 +113,9 @@ coap_send_transaction(coap_transaction_t *t)
|
|||||||
(float)t->retrans_timer.timer.interval / CLOCK_SECOND);
|
(float)t->retrans_timer.timer.interval / CLOCK_SECOND);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*FIXME
|
PROCESS_CONTEXT_BEGIN(transaction_handler_process);
|
||||||
* Hack: Setting timer for responsible process.
|
|
||||||
* Maybe there is a better way, but avoid posting everything to the process.
|
|
||||||
*/
|
|
||||||
struct process *process_actual = PROCESS_CURRENT();
|
|
||||||
|
|
||||||
process_current = transaction_handler_process;
|
|
||||||
etimer_restart(&t->retrans_timer); /* interval updated above */
|
etimer_restart(&t->retrans_timer); /* interval updated above */
|
||||||
process_current = process_actual;
|
PROCESS_CONTEXT_END(transaction_handler_process);
|
||||||
|
|
||||||
t = NULL;
|
t = NULL;
|
||||||
} else {
|
} else {
|
||||||
|
@ -113,19 +113,21 @@ coap_set_option_header(unsigned int delta, size_t length, uint8_t *buffer)
|
|||||||
|
|
||||||
buffer[0] = coap_option_nibble(delta) << 4 | coap_option_nibble(length);
|
buffer[0] = coap_option_nibble(delta) << 4 | coap_option_nibble(length);
|
||||||
|
|
||||||
/* avoids code duplication without function overhead */
|
if(delta > 268) {
|
||||||
unsigned int *x = δ
|
buffer[++written] = ((delta - 269) >> 8) & 0xff;
|
||||||
|
buffer[++written] = (delta - 269) & 0xff;
|
||||||
do {
|
} else if(delta > 12) {
|
||||||
if(*x > 268) {
|
buffer[++written] = (delta - 13);
|
||||||
buffer[++written] = (*x - 269) >> 8;
|
|
||||||
buffer[++written] = (*x - 269);
|
|
||||||
} else if(*x > 12) {
|
|
||||||
buffer[++written] = (*x - 13);
|
|
||||||
}
|
}
|
||||||
} while(x != &length && (x = &length));
|
|
||||||
|
|
||||||
PRINTF("WRITTEN %u B opt header\n", 1 + written);
|
if(length > 268) {
|
||||||
|
buffer[++written] = ((length - 269) >> 8) & 0xff;
|
||||||
|
buffer[++written] = (length - 269) & 0xff;
|
||||||
|
} else if(length > 12) {
|
||||||
|
buffer[++written] = (length - 13);
|
||||||
|
}
|
||||||
|
|
||||||
|
PRINTF("WRITTEN %zu B opt header\n", 1 + written);
|
||||||
|
|
||||||
return ++written;
|
return ++written;
|
||||||
}
|
}
|
||||||
@ -148,7 +150,7 @@ coap_serialize_int_option(unsigned int number, unsigned int current_number,
|
|||||||
if(0xFFFFFFFF & value) {
|
if(0xFFFFFFFF & value) {
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
PRINTF("OPTION %u (delta %u, len %u)\n", number, number - current_number,
|
PRINTF("OPTION %u (delta %u, len %zu)\n", number, number - current_number,
|
||||||
i);
|
i);
|
||||||
|
|
||||||
i = coap_set_option_header(number - current_number, i, buffer);
|
i = coap_set_option_header(number - current_number, i, buffer);
|
||||||
@ -175,8 +177,8 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number,
|
|||||||
{
|
{
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
|
||||||
PRINTF("ARRAY type %u, len %u, full [%.*s]\n", number, length, length,
|
PRINTF("ARRAY type %u, len %zu, full [%.*s]\n", number, length,
|
||||||
array);
|
(int)length, array);
|
||||||
|
|
||||||
if(split_char != '\0') {
|
if(split_char != '\0') {
|
||||||
int j;
|
int j;
|
||||||
@ -185,7 +187,7 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number,
|
|||||||
size_t temp_length;
|
size_t temp_length;
|
||||||
|
|
||||||
for(j = 0; j <= length + 1; ++j) {
|
for(j = 0; j <= length + 1; ++j) {
|
||||||
PRINTF("STEP %u/%u (%c)\n", j, length, array[j]);
|
PRINTF("STEP %u/%zu (%c)\n", j, length, array[j]);
|
||||||
if(array[j] == split_char || j == length) {
|
if(array[j] == split_char || j == length) {
|
||||||
part_end = array + j;
|
part_end = array + j;
|
||||||
temp_length = part_end - part_start;
|
temp_length = part_end - part_start;
|
||||||
@ -195,8 +197,8 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number,
|
|||||||
memcpy(&buffer[i], part_start, temp_length);
|
memcpy(&buffer[i], part_start, temp_length);
|
||||||
i += temp_length;
|
i += temp_length;
|
||||||
|
|
||||||
PRINTF("OPTION type %u, delta %u, len %u, part [%.*s]\n", number,
|
PRINTF("OPTION type %u, delta %u, len %zu, part [%.*s]\n", number,
|
||||||
number - current_number, i, temp_length, part_start);
|
number - current_number, i, (int)temp_length, part_start);
|
||||||
|
|
||||||
++j; /* skip the splitter */
|
++j; /* skip the splitter */
|
||||||
current_number = number;
|
current_number = number;
|
||||||
@ -208,7 +210,7 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number,
|
|||||||
memcpy(&buffer[i], array, length);
|
memcpy(&buffer[i], array, length);
|
||||||
i += length;
|
i += length;
|
||||||
|
|
||||||
PRINTF("OPTION type %u, delta %u, len %u\n", number,
|
PRINTF("OPTION type %u, delta %u, len %zu\n", number,
|
||||||
number - current_number, length);
|
number - current_number, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,7 +334,7 @@ coap_serialize_message(void *packet, uint8_t *buffer)
|
|||||||
|
|
||||||
/* empty packet, dont need to do more stuff */
|
/* empty packet, dont need to do more stuff */
|
||||||
if(!coap_pkt->code) {
|
if(!coap_pkt->code) {
|
||||||
PRINTF("-Done serializing empty message at %p-\n", option);
|
PRINTF("-Done serializing empty message at %p-\n", coap_pkt->buffer);
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,6 +370,7 @@ coap_serialize_message(void *packet, uint8_t *buffer)
|
|||||||
"Location-Path");
|
"Location-Path");
|
||||||
COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_PATH, uri_path, '/',
|
COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_PATH, uri_path, '/',
|
||||||
"Uri-Path");
|
"Uri-Path");
|
||||||
|
PRINTF("Serialize content format: %d\n", coap_pkt->content_format);
|
||||||
COAP_SERIALIZE_INT_OPTION(COAP_OPTION_CONTENT_FORMAT, content_format,
|
COAP_SERIALIZE_INT_OPTION(COAP_OPTION_CONTENT_FORMAT, content_format,
|
||||||
"Content-Format");
|
"Content-Format");
|
||||||
COAP_SERIALIZE_INT_OPTION(COAP_OPTION_MAX_AGE, max_age, "Max-Age");
|
COAP_SERIALIZE_INT_OPTION(COAP_OPTION_MAX_AGE, max_age, "Max-Age");
|
||||||
@ -403,8 +406,9 @@ coap_serialize_message(void *packet, uint8_t *buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
PRINTF("-Done %u B (header len %u, payload len %u)-\n",
|
PRINTF("-Done %u B (header len %u, payload len %u)-\n",
|
||||||
coap_pkt->payload_len + option - buffer, option - buffer,
|
(unsigned int)(coap_pkt->payload_len + option - buffer),
|
||||||
coap_pkt->payload_len);
|
(unsigned int)(option - buffer),
|
||||||
|
(unsigned int)coap_pkt->payload_len);
|
||||||
|
|
||||||
PRINTF("Dump [0x%02X %02X %02X %02X %02X %02X %02X %02X]\n",
|
PRINTF("Dump [0x%02X %02X %02X %02X %02X %02X %02X %02X]\n",
|
||||||
coap_pkt->buffer[0],
|
coap_pkt->buffer[0],
|
||||||
@ -500,25 +504,31 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
|||||||
option_length = current_option[0] & 0x0F;
|
option_length = current_option[0] & 0x0F;
|
||||||
++current_option;
|
++current_option;
|
||||||
|
|
||||||
/* avoids code duplication without function overhead */
|
if(option_delta == 13) {
|
||||||
unsigned int *x = &option_delta;
|
option_delta += current_option[0];
|
||||||
|
|
||||||
do {
|
|
||||||
if(*x == 13) {
|
|
||||||
*x += current_option[0];
|
|
||||||
++current_option;
|
++current_option;
|
||||||
} else if(*x == 14) {
|
} else if(option_delta == 14) {
|
||||||
*x += 255;
|
option_delta += 255;
|
||||||
*x += current_option[0] << 8;
|
option_delta += current_option[0] << 8;
|
||||||
++current_option;
|
++current_option;
|
||||||
*x += current_option[0];
|
option_delta += current_option[0];
|
||||||
|
++current_option;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(option_length == 13) {
|
||||||
|
option_length += current_option[0];
|
||||||
|
++current_option;
|
||||||
|
} else if(option_length == 14) {
|
||||||
|
option_length += 255;
|
||||||
|
option_length += current_option[0] << 8;
|
||||||
|
++current_option;
|
||||||
|
option_length += current_option[0];
|
||||||
++current_option;
|
++current_option;
|
||||||
}
|
}
|
||||||
} while(x != &option_length && (x = &option_length));
|
|
||||||
|
|
||||||
option_number += option_delta;
|
option_number += option_delta;
|
||||||
|
|
||||||
PRINTF("OPTION %u (delta %u, len %u): ", option_number, option_delta,
|
PRINTF("OPTION %u (delta %u, len %zu): ", option_number, option_delta,
|
||||||
option_length);
|
option_length);
|
||||||
|
|
||||||
SET_OPTION(coap_pkt, option_number);
|
SET_OPTION(coap_pkt, option_number);
|
||||||
@ -532,7 +542,7 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
|||||||
case COAP_OPTION_MAX_AGE:
|
case COAP_OPTION_MAX_AGE:
|
||||||
coap_pkt->max_age = coap_parse_int_option(current_option,
|
coap_pkt->max_age = coap_parse_int_option(current_option,
|
||||||
option_length);
|
option_length);
|
||||||
PRINTF("Max-Age [%lu]\n", coap_pkt->max_age);
|
PRINTF("Max-Age [%lu]\n", (unsigned long)coap_pkt->max_age);
|
||||||
break;
|
break;
|
||||||
case COAP_OPTION_ETAG:
|
case COAP_OPTION_ETAG:
|
||||||
coap_pkt->etag_len = MIN(COAP_ETAG_LEN, option_length);
|
coap_pkt->etag_len = MIN(COAP_ETAG_LEN, option_length);
|
||||||
@ -569,7 +579,7 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
|||||||
coap_pkt->proxy_uri = (char *)current_option;
|
coap_pkt->proxy_uri = (char *)current_option;
|
||||||
coap_pkt->proxy_uri_len = option_length;
|
coap_pkt->proxy_uri_len = option_length;
|
||||||
#endif
|
#endif
|
||||||
PRINTF("Proxy-Uri NOT IMPLEMENTED [%.*s]\n", coap_pkt->proxy_uri_len,
|
PRINTF("Proxy-Uri NOT IMPLEMENTED [%.*s]\n", (int)coap_pkt->proxy_uri_len,
|
||||||
coap_pkt->proxy_uri);
|
coap_pkt->proxy_uri);
|
||||||
coap_error_message = "This is a constrained server (Contiki)";
|
coap_error_message = "This is a constrained server (Contiki)";
|
||||||
return PROXYING_NOT_SUPPORTED_5_05;
|
return PROXYING_NOT_SUPPORTED_5_05;
|
||||||
@ -580,7 +590,7 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
|||||||
coap_pkt->proxy_scheme_len = option_length;
|
coap_pkt->proxy_scheme_len = option_length;
|
||||||
#endif
|
#endif
|
||||||
PRINTF("Proxy-Scheme NOT IMPLEMENTED [%.*s]\n",
|
PRINTF("Proxy-Scheme NOT IMPLEMENTED [%.*s]\n",
|
||||||
coap_pkt->proxy_scheme_len, coap_pkt->proxy_scheme);
|
(int)coap_pkt->proxy_scheme_len, coap_pkt->proxy_scheme);
|
||||||
coap_error_message = "This is a constrained server (Contiki)";
|
coap_error_message = "This is a constrained server (Contiki)";
|
||||||
return PROXYING_NOT_SUPPORTED_5_05;
|
return PROXYING_NOT_SUPPORTED_5_05;
|
||||||
break;
|
break;
|
||||||
@ -588,7 +598,8 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
|||||||
case COAP_OPTION_URI_HOST:
|
case COAP_OPTION_URI_HOST:
|
||||||
coap_pkt->uri_host = (char *)current_option;
|
coap_pkt->uri_host = (char *)current_option;
|
||||||
coap_pkt->uri_host_len = option_length;
|
coap_pkt->uri_host_len = option_length;
|
||||||
PRINTF("Uri-Host [%.*s]\n", coap_pkt->uri_host_len, coap_pkt->uri_host);
|
PRINTF("Uri-Host [%.*s]\n", (int)coap_pkt->uri_host_len,
|
||||||
|
coap_pkt->uri_host);
|
||||||
break;
|
break;
|
||||||
case COAP_OPTION_URI_PORT:
|
case COAP_OPTION_URI_PORT:
|
||||||
coap_pkt->uri_port = coap_parse_int_option(current_option,
|
coap_pkt->uri_port = coap_parse_int_option(current_option,
|
||||||
@ -600,14 +611,14 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
|||||||
coap_merge_multi_option((char **)&(coap_pkt->uri_path),
|
coap_merge_multi_option((char **)&(coap_pkt->uri_path),
|
||||||
&(coap_pkt->uri_path_len), current_option,
|
&(coap_pkt->uri_path_len), current_option,
|
||||||
option_length, '/');
|
option_length, '/');
|
||||||
PRINTF("Uri-Path [%.*s]\n", coap_pkt->uri_path_len, coap_pkt->uri_path);
|
PRINTF("Uri-Path [%.*s]\n", (int)coap_pkt->uri_path_len, coap_pkt->uri_path);
|
||||||
break;
|
break;
|
||||||
case COAP_OPTION_URI_QUERY:
|
case COAP_OPTION_URI_QUERY:
|
||||||
/* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */
|
/* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */
|
||||||
coap_merge_multi_option((char **)&(coap_pkt->uri_query),
|
coap_merge_multi_option((char **)&(coap_pkt->uri_query),
|
||||||
&(coap_pkt->uri_query_len), current_option,
|
&(coap_pkt->uri_query_len), current_option,
|
||||||
option_length, '&');
|
option_length, '&');
|
||||||
PRINTF("Uri-Query [%.*s]\n", coap_pkt->uri_query_len,
|
PRINTF("Uri-Query [%.*s]\n", (int)coap_pkt->uri_query_len,
|
||||||
coap_pkt->uri_query);
|
coap_pkt->uri_query);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -616,7 +627,7 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
|||||||
coap_merge_multi_option((char **)&(coap_pkt->location_path),
|
coap_merge_multi_option((char **)&(coap_pkt->location_path),
|
||||||
&(coap_pkt->location_path_len), current_option,
|
&(coap_pkt->location_path_len), current_option,
|
||||||
option_length, '/');
|
option_length, '/');
|
||||||
PRINTF("Location-Path [%.*s]\n", coap_pkt->location_path_len,
|
PRINTF("Location-Path [%.*s]\n", (int)coap_pkt->location_path_len,
|
||||||
coap_pkt->location_path);
|
coap_pkt->location_path);
|
||||||
break;
|
break;
|
||||||
case COAP_OPTION_LOCATION_QUERY:
|
case COAP_OPTION_LOCATION_QUERY:
|
||||||
@ -624,14 +635,14 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
|||||||
coap_merge_multi_option((char **)&(coap_pkt->location_query),
|
coap_merge_multi_option((char **)&(coap_pkt->location_query),
|
||||||
&(coap_pkt->location_query_len), current_option,
|
&(coap_pkt->location_query_len), current_option,
|
||||||
option_length, '&');
|
option_length, '&');
|
||||||
PRINTF("Location-Query [%.*s]\n", coap_pkt->location_query_len,
|
PRINTF("Location-Query [%.*s]\n", (int)coap_pkt->location_query_len,
|
||||||
coap_pkt->location_query);
|
coap_pkt->location_query);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COAP_OPTION_OBSERVE:
|
case COAP_OPTION_OBSERVE:
|
||||||
coap_pkt->observe = coap_parse_int_option(current_option,
|
coap_pkt->observe = coap_parse_int_option(current_option,
|
||||||
option_length);
|
option_length);
|
||||||
PRINTF("Observe [%lu]\n", coap_pkt->observe);
|
PRINTF("Observe [%lu]\n", (unsigned long)coap_pkt->observe);
|
||||||
break;
|
break;
|
||||||
case COAP_OPTION_BLOCK2:
|
case COAP_OPTION_BLOCK2:
|
||||||
coap_pkt->block2_num = coap_parse_int_option(current_option,
|
coap_pkt->block2_num = coap_parse_int_option(current_option,
|
||||||
@ -641,7 +652,8 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
|||||||
coap_pkt->block2_offset = (coap_pkt->block2_num & ~0x0000000F)
|
coap_pkt->block2_offset = (coap_pkt->block2_num & ~0x0000000F)
|
||||||
<< (coap_pkt->block2_num & 0x07);
|
<< (coap_pkt->block2_num & 0x07);
|
||||||
coap_pkt->block2_num >>= 4;
|
coap_pkt->block2_num >>= 4;
|
||||||
PRINTF("Block2 [%lu%s (%u B/blk)]\n", coap_pkt->block2_num,
|
PRINTF("Block2 [%lu%s (%u B/blk)]\n",
|
||||||
|
(unsigned long)coap_pkt->block2_num,
|
||||||
coap_pkt->block2_more ? "+" : "", coap_pkt->block2_size);
|
coap_pkt->block2_more ? "+" : "", coap_pkt->block2_size);
|
||||||
break;
|
break;
|
||||||
case COAP_OPTION_BLOCK1:
|
case COAP_OPTION_BLOCK1:
|
||||||
@ -652,16 +664,17 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
|
|||||||
coap_pkt->block1_offset = (coap_pkt->block1_num & ~0x0000000F)
|
coap_pkt->block1_offset = (coap_pkt->block1_num & ~0x0000000F)
|
||||||
<< (coap_pkt->block1_num & 0x07);
|
<< (coap_pkt->block1_num & 0x07);
|
||||||
coap_pkt->block1_num >>= 4;
|
coap_pkt->block1_num >>= 4;
|
||||||
PRINTF("Block1 [%lu%s (%u B/blk)]\n", coap_pkt->block1_num,
|
PRINTF("Block1 [%lu%s (%u B/blk)]\n",
|
||||||
|
(unsigned long)coap_pkt->block1_num,
|
||||||
coap_pkt->block1_more ? "+" : "", coap_pkt->block1_size);
|
coap_pkt->block1_more ? "+" : "", coap_pkt->block1_size);
|
||||||
break;
|
break;
|
||||||
case COAP_OPTION_SIZE2:
|
case COAP_OPTION_SIZE2:
|
||||||
coap_pkt->size2 = coap_parse_int_option(current_option, option_length);
|
coap_pkt->size2 = coap_parse_int_option(current_option, option_length);
|
||||||
PRINTF("Size2 [%lu]\n", coap_pkt->size2);
|
PRINTF("Size2 [%lu]\n", (unsigned long)coap_pkt->size2);
|
||||||
break;
|
break;
|
||||||
case COAP_OPTION_SIZE1:
|
case COAP_OPTION_SIZE1:
|
||||||
coap_pkt->size1 = coap_parse_int_option(current_option, option_length);
|
coap_pkt->size1 = coap_parse_int_option(current_option, option_length);
|
||||||
PRINTF("Size1 [%lu]\n", coap_pkt->size1);
|
PRINTF("Size1 [%lu]\n", (unsigned long)coap_pkt->size1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PRINTF("unknown (%u)\n", option_number);
|
PRINTF("unknown (%u)\n", option_number);
|
||||||
@ -744,7 +757,7 @@ coap_set_header_content_format(void *packet, unsigned int format)
|
|||||||
{
|
{
|
||||||
coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
|
coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
|
||||||
|
|
||||||
coap_pkt->content_format = (coap_content_format_t)format;
|
coap_pkt->content_format = format;
|
||||||
SET_OPTION(coap_pkt, COAP_OPTION_CONTENT_FORMAT);
|
SET_OPTION(coap_pkt, COAP_OPTION_CONTENT_FORMAT);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -765,7 +778,7 @@ coap_set_header_accept(void *packet, unsigned int accept)
|
|||||||
{
|
{
|
||||||
coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
|
coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
|
||||||
|
|
||||||
coap_pkt->accept = (coap_content_format_t)accept;
|
coap_pkt->accept = accept;
|
||||||
SET_OPTION(coap_pkt, COAP_OPTION_ACCEPT);
|
SET_OPTION(coap_pkt, COAP_OPTION_ACCEPT);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ typedef struct {
|
|||||||
|
|
||||||
uint8_t options[COAP_OPTION_SIZE1 / OPTION_MAP_SIZE + 1]; /* bitmap to check if option is set */
|
uint8_t options[COAP_OPTION_SIZE1 / OPTION_MAP_SIZE + 1]; /* bitmap to check if option is set */
|
||||||
|
|
||||||
coap_content_format_t content_format; /* parse options once and store; allows setting options in random order */
|
uint16_t content_format; /* parse options once and store; allows setting options in random order */
|
||||||
uint32_t max_age;
|
uint32_t max_age;
|
||||||
uint8_t etag_len;
|
uint8_t etag_len;
|
||||||
uint8_t etag[COAP_ETAG_LEN];
|
uint8_t etag[COAP_ETAG_LEN];
|
||||||
@ -111,7 +111,7 @@ typedef struct {
|
|||||||
size_t uri_path_len;
|
size_t uri_path_len;
|
||||||
const char *uri_path;
|
const char *uri_path;
|
||||||
int32_t observe;
|
int32_t observe;
|
||||||
coap_content_format_t accept;
|
uint16_t accept;
|
||||||
uint8_t if_match_len;
|
uint8_t if_match_len;
|
||||||
uint8_t if_match[COAP_ETAG_LEN];
|
uint8_t if_match[COAP_ETAG_LEN];
|
||||||
uint32_t block2_num;
|
uint32_t block2_num;
|
||||||
@ -135,13 +135,13 @@ typedef struct {
|
|||||||
/* option format serialization */
|
/* option format serialization */
|
||||||
#define COAP_SERIALIZE_INT_OPTION(number, field, text) \
|
#define COAP_SERIALIZE_INT_OPTION(number, field, text) \
|
||||||
if(IS_OPTION(coap_pkt, number)) { \
|
if(IS_OPTION(coap_pkt, number)) { \
|
||||||
PRINTF(text " [%u]\n", coap_pkt->field); \
|
PRINTF(text " [%u]\n", (unsigned int)coap_pkt->field); \
|
||||||
option += coap_serialize_int_option(number, current_number, option, coap_pkt->field); \
|
option += coap_serialize_int_option(number, current_number, option, coap_pkt->field); \
|
||||||
current_number = number; \
|
current_number = number; \
|
||||||
}
|
}
|
||||||
#define COAP_SERIALIZE_BYTE_OPTION(number, field, text) \
|
#define COAP_SERIALIZE_BYTE_OPTION(number, field, text) \
|
||||||
if(IS_OPTION(coap_pkt, number)) { \
|
if(IS_OPTION(coap_pkt, number)) { \
|
||||||
PRINTF(text " %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", coap_pkt->field##_len, \
|
PRINTF(text " %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", (unsigned int)coap_pkt->field##_len, \
|
||||||
coap_pkt->field[0], \
|
coap_pkt->field[0], \
|
||||||
coap_pkt->field[1], \
|
coap_pkt->field[1], \
|
||||||
coap_pkt->field[2], \
|
coap_pkt->field[2], \
|
||||||
@ -156,18 +156,18 @@ typedef struct {
|
|||||||
}
|
}
|
||||||
#define COAP_SERIALIZE_STRING_OPTION(number, field, splitter, text) \
|
#define COAP_SERIALIZE_STRING_OPTION(number, field, splitter, text) \
|
||||||
if(IS_OPTION(coap_pkt, number)) { \
|
if(IS_OPTION(coap_pkt, number)) { \
|
||||||
PRINTF(text " [%.*s]\n", coap_pkt->field##_len, coap_pkt->field); \
|
PRINTF(text " [%.*s]\n", (int)coap_pkt->field##_len, coap_pkt->field); \
|
||||||
option += coap_serialize_array_option(number, current_number, option, (uint8_t *)coap_pkt->field, coap_pkt->field##_len, splitter); \
|
option += coap_serialize_array_option(number, current_number, option, (uint8_t *)coap_pkt->field, coap_pkt->field##_len, splitter); \
|
||||||
current_number = number; \
|
current_number = number; \
|
||||||
}
|
}
|
||||||
#define COAP_SERIALIZE_BLOCK_OPTION(number, field, text) \
|
#define COAP_SERIALIZE_BLOCK_OPTION(number, field, text) \
|
||||||
if(IS_OPTION(coap_pkt, number)) \
|
if(IS_OPTION(coap_pkt, number)) \
|
||||||
{ \
|
{ \
|
||||||
PRINTF(text " [%lu%s (%u B/blk)]\n", coap_pkt->field##_num, coap_pkt->field##_more ? "+" : "", coap_pkt->field##_size); \
|
PRINTF(text " [%lu%s (%u B/blk)]\n", (unsigned long)coap_pkt->field##_num, coap_pkt->field##_more ? "+" : "", coap_pkt->field##_size); \
|
||||||
uint32_t block = coap_pkt->field##_num << 4; \
|
uint32_t block = coap_pkt->field##_num << 4; \
|
||||||
if(coap_pkt->field##_more) { block |= 0x8; } \
|
if(coap_pkt->field##_more) { block |= 0x8; } \
|
||||||
block |= 0xF & coap_log_2(coap_pkt->field##_size / 16); \
|
block |= 0xF & coap_log_2(coap_pkt->field##_size / 16); \
|
||||||
PRINTF(text " encoded: 0x%lX\n", block); \
|
PRINTF(text " encoded: 0x%lX\n", (unsigned long)block); \
|
||||||
option += coap_serialize_int_option(number, current_number, option, block); \
|
option += coap_serialize_int_option(number, current_number, option, block); \
|
||||||
current_number = number; \
|
current_number = number; \
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,15 @@ LIST(restful_periodic_services);
|
|||||||
void
|
void
|
||||||
rest_init_engine(void)
|
rest_init_engine(void)
|
||||||
{
|
{
|
||||||
|
/* avoid initializing twice */
|
||||||
|
static uint8_t initialized = 0;
|
||||||
|
|
||||||
|
if(initialized) {
|
||||||
|
PRINTF("REST engine process already running - double initialization?\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
initialized = 1;
|
||||||
|
|
||||||
list_init(restful_services);
|
list_init(restful_services);
|
||||||
|
|
||||||
REST.set_service_callback(rest_invoke_restful_service);
|
REST.set_service_callback(rest_invoke_restful_service);
|
||||||
@ -124,15 +133,19 @@ rest_invoke_restful_service(void *request, void *response, uint8_t *buffer,
|
|||||||
|
|
||||||
resource_t *resource = NULL;
|
resource_t *resource = NULL;
|
||||||
const char *url = NULL;
|
const char *url = NULL;
|
||||||
|
int url_len, res_url_len;
|
||||||
|
|
||||||
|
url_len = REST.get_url(request, &url);
|
||||||
for(resource = (resource_t *)list_head(restful_services);
|
for(resource = (resource_t *)list_head(restful_services);
|
||||||
resource; resource = resource->next) {
|
resource; resource = resource->next) {
|
||||||
|
|
||||||
/* if the web service handles that kind of requests and urls matches */
|
/* if the web service handles that kind of requests and urls matches */
|
||||||
if((REST.get_url(request, &url) == strlen(resource->url)
|
res_url_len = strlen(resource->url);
|
||||||
|| (REST.get_url(request, &url) > strlen(resource->url)
|
if((url_len == res_url_len
|
||||||
&& (resource->flags & HAS_SUB_RESOURCES)))
|
|| (url_len > res_url_len
|
||||||
&& strncmp(resource->url, url, strlen(resource->url)) == 0) {
|
&& (resource->flags & HAS_SUB_RESOURCES)
|
||||||
|
&& url[res_url_len] == '/'))
|
||||||
|
&& strncmp(resource->url, url, res_url_len) == 0) {
|
||||||
found = 1;
|
found = 1;
|
||||||
rest_resource_flags_t method = REST.get_method_type(request);
|
rest_resource_flags_t method = REST.get_method_type(request);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user