From b44d125d80f3ae09da939e96e4f36e320ff28a03 Mon Sep 17 00:00:00 2001 From: Matthias Kovatsch Date: Mon, 30 Jan 2012 22:01:31 +0100 Subject: [PATCH 01/15] Observe handler now checks if GET request. --- apps/er-coap-07/er-coap-07-observing.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/er-coap-07/er-coap-07-observing.c b/apps/er-coap-07/er-coap-07-observing.c index f3dc7425d..4da0f5f67 100644 --- a/apps/er-coap-07/er-coap-07-observing.c +++ b/apps/er-coap-07/er-coap-07-observing.c @@ -191,7 +191,7 @@ coap_observe_handler(resource_t *resource, void *request, void *response) static char content[26]; - if (coap_res && coap_res->code<128) /* response without error code */ + if (coap_req->code==COAP_GET && coap_res && coap_res->code<128) /* GET request and response without error code */ { if (IS_OPTION(coap_req, COAP_OPTION_OBSERVE)) { From 4a02790c7681250e91441b3a1c50ae59010ddf23 Mon Sep 17 00:00:00 2001 From: Matthias Kovatsch Date: Tue, 31 Jan 2012 04:38:07 +0100 Subject: [PATCH 02/15] Simplified Erbium support for separate responses. --- apps/er-coap-03/er-coap-03-engine.c | 2 +- apps/er-coap-03/er-coap-03.h | 2 +- apps/er-coap-07/er-coap-07-engine.c | 98 ++++++++++--------- apps/er-coap-07/er-coap-07-separate.c | 69 ++++++++++--- apps/er-coap-07/er-coap-07-separate.h | 24 ++++- apps/er-coap-07/er-coap-07-transactions.c | 4 +- apps/er-coap-07/er-coap-07.h | 14 ++- apps/erbium/erbium.c | 2 +- apps/erbium/erbium.h | 2 +- .../er-rest-example/rest-server-example.c | 98 +++++++++++++++++-- 10 files changed, 238 insertions(+), 77 deletions(-) diff --git a/apps/er-coap-03/er-coap-03-engine.c b/apps/er-coap-03/er-coap-03-engine.c index 610209f13..048261349 100644 --- a/apps/er-coap-03/er-coap-03-engine.c +++ b/apps/er-coap-03/er-coap-03-engine.c @@ -206,7 +206,7 @@ handle_incoming_data(void) } } else { - error = MEMORY_ALLOC_ERR; + error = MEMORY_ALLOCATION_ERROR; } } else diff --git a/apps/er-coap-03/er-coap-03.h b/apps/er-coap-03/er-coap-03.h index 9b5f3a887..f6a2639ba 100644 --- a/apps/er-coap-03/er-coap-03.h +++ b/apps/er-coap-03/er-coap-03.h @@ -226,7 +226,7 @@ typedef enum NO_ERROR, /* Memory errors */ - MEMORY_ALLOC_ERR, + MEMORY_ALLOCATION_ERROR, MEMORY_BOUNDARY_EXCEEDED, /* CoAP errors */ diff --git a/apps/er-coap-07/er-coap-07-engine.c b/apps/er-coap-07/er-coap-07-engine.c index 1d27b6760..df86d5719 100644 --- a/apps/er-coap-07/er-coap-07-engine.c +++ b/apps/er-coap-07/er-coap-07-engine.c @@ -100,7 +100,7 @@ handle_incoming_data(void) if (coap_error_code==NO_ERROR) { - /*TODO duplicates suppression, if required */ + /*TODO duplicates suppression, if required by application */ PRINTF(" Parsed: v %u, t %u, oc %u, c %u, mid %u\n", message->version, message->type, message->option_count, message->code, message->mid); PRINTF(" URL: %.*s\n", message->uri_path_len, message->uri_path); @@ -112,10 +112,10 @@ handle_incoming_data(void) /* Use transaction buffer for response to confirmable request. */ if ( (transaction = coap_new_transaction(message->mid, &UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport)) ) { - static uint32_t block_num = 0; - static uint16_t block_size = REST_MAX_CHUNK_SIZE; - static uint32_t block_offset = 0; - static int32_t new_offset = 0; + uint32_t block_num = 0; + uint16_t block_size = REST_MAX_CHUNK_SIZE; + uint32_t block_offset = 0; + int32_t new_offset = 0; /* prepare response */ if (message->type==COAP_TYPE_CON) @@ -143,11 +143,6 @@ handle_incoming_data(void) block_size = MIN(block_size, REST_MAX_CHUNK_SIZE); new_offset = block_offset; } - else - { - block_size = REST_MAX_CHUNK_SIZE; - new_offset = 0; - } /* Invoke resource handler. */ if (service_cbk) @@ -155,42 +150,55 @@ handle_incoming_data(void) /* Call REST framework and check if found and allowed. */ if (service_cbk(message, response, transaction->packet+COAP_MAX_HEADER_SIZE, block_size, &new_offset)) { - /* Apply blockwise transfers. */ - if ( IS_OPTION(message, COAP_OPTION_BLOCK2) ) + if (coap_error_code==NO_ERROR) { - /* unchanged new_offset indicates that resource is unaware of blockwise transfer */ - if (new_offset==block_offset) + /* Apply blockwise transfers. */ + if ( IS_OPTION(message, COAP_OPTION_BLOCK2) ) { - PRINTF("Blockwise: unaware resource with payload length %u/%u\n", response->payload_len, block_size); - if (block_offset >= response->payload_len) + /* unchanged new_offset indicates that resource is unaware of blockwise transfer */ + if (new_offset==block_offset) { - PRINTF("handle_incoming_data(): block_offset >= response->payload_len\n"); + PRINTF("Blockwise: unaware resource with payload length %u/%u\n", response->payload_len, block_size); + if (block_offset >= response->payload_len) + { + PRINTF("handle_incoming_data(): block_offset >= response->payload_len\n"); - response->code = BAD_OPTION_4_02; - coap_set_payload(response, "BlockOutOfScope", 15); /* a const char str[] and sizeof(str) produces larger code size */ + response->code = BAD_OPTION_4_02; + coap_set_payload(response, "BlockOutOfScope", 15); /* a const char str[] and sizeof(str) produces larger code size */ + } + else + { + coap_set_header_block2(response, block_num, response->payload_len - block_offset > block_size, block_size); + coap_set_payload(response, response->payload+block_offset, MIN(response->payload_len - block_offset, block_size)); + } /* if (valid offset) */ } else { - coap_set_header_block2(response, block_num, response->payload_len - block_offset > block_size, block_size); - coap_set_payload(response, response->payload+block_offset, MIN(response->payload_len - block_offset, block_size)); - } /* if (valid offset) */ + /* resource provides chunk-wise data */ + PRINTF("Blockwise: blockwise resource, new offset %ld\n", new_offset); + coap_set_header_block2(response, block_num, new_offset!=-1 || response->payload_len > block_size, block_size); + if (response->payload_len > block_size) coap_set_payload(response, response->payload, block_size); + } /* if (resource aware of blockwise) */ } - else + else if (new_offset!=0) { - /* resource provides chunk-wise data */ - PRINTF("Blockwise: blockwise resource, new offset %ld\n", new_offset); - coap_set_header_block2(response, block_num, new_offset!=-1 || response->payload_len > block_size, block_size); - if (response->payload_len > block_size) coap_set_payload(response, response->payload, block_size); - } /* if (resource aware of blockwise) */ - } - else if (new_offset!=0) - { - PRINTF("Blockwise: no block option for blockwise resource, using block size %u\n", REST_MAX_CHUNK_SIZE); + PRINTF("Blockwise: no block option for blockwise resource, using block size %u\n", REST_MAX_CHUNK_SIZE); - coap_set_header_block2(response, 0, new_offset!=-1, REST_MAX_CHUNK_SIZE); - coap_set_payload(response, response->payload, MIN(response->payload_len, REST_MAX_CHUNK_SIZE)); - } /* if (blockwise request) */ + coap_set_header_block2(response, 0, new_offset!=-1, REST_MAX_CHUNK_SIZE); + coap_set_payload(response, response->payload, MIN(response->payload_len, REST_MAX_CHUNK_SIZE)); + } /* if (blockwise request) */ + } /* no errors/hooks */ + } /* successful service callback */ + + /* Serialize response. */ + if (coap_error_code==NO_ERROR) + { + if ((transaction->packet_len = coap_serialize_message(response, transaction->packet))==0) + { + coap_error_code = PACKET_SERIALIZATION_ERROR; + } } + } else { @@ -198,14 +206,8 @@ handle_incoming_data(void) coap_error_message = "Service callback undefined"; } /* if (service callback) */ - /* serialize Response. */ - if ((transaction->packet_len = coap_serialize_message(response, transaction->packet))==0) - { - coap_error_code = PACKET_SERIALIZATION_ERROR; - } - } else { - coap_error_code = MEMORY_ALLOC_ERR; + coap_error_code = MEMORY_ALLOCATION_ERROR; coap_error_message = "Transaction buffer allocation failed"; } /* if (transaction buffer) */ } @@ -241,12 +243,20 @@ handle_incoming_data(void) } } /* if (ACKed transaction) */ transaction = NULL; - } + + } /* Request or Response */ + } /* if (parsed correctly) */ - if (coap_error_code==NO_ERROR) { + if (coap_error_code==NO_ERROR) + { if (transaction) coap_send_transaction(transaction); } + else if (coap_error_code==MANUAL_RESPONSE) + { + PRINTF("Clearing transaction for manual response"); + coap_clear_transaction(transaction); + } else { PRINTF("ERROR %u: %s\n", coap_error_code, coap_error_message); diff --git a/apps/er-coap-07/er-coap-07-separate.c b/apps/er-coap-07/er-coap-07-separate.c index 259398f26..b5f9c5c3a 100644 --- a/apps/er-coap-07/er-coap-07-separate.c +++ b/apps/er-coap-07/er-coap-07-separate.c @@ -40,6 +40,7 @@ #include #include "er-coap-07-separate.h" +#include "er-coap-07-transactions.h" #define DEBUG 0 #if DEBUG @@ -53,20 +54,66 @@ #endif /*-----------------------------------------------------------------------------------*/ -void coap_separate_handler(resource_t *resource, void *request, void *response) +int coap_separate_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; - PRINTF("Separate response for /%s \n", resource->url); - /* send separate ACK. */ - coap_packet_t ack[1]; - /* ACK with empty code (0) */ - coap_init_message(ack, COAP_TYPE_ACK, 0, coap_req->mid); - /* Should only overwrite Header which is already parsed to request. */ - coap_send_message(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, (uip_appdata + uip_ext_len), coap_serialize_message(ack, (uip_appdata + uip_ext_len))); + PRINTF("Separate response for /%s MID %u\n", resource->url, coap_res->mid); - /* Change response to separate response. */ - coap_res->type = COAP_TYPE_CON; - coap_res->mid = coap_get_mid(); + /* Only ack CON requests. */ + if (coap_req->type==COAP_TYPE_CON) + { + coap_transaction_t *const t = coap_get_transaction_by_mid(coap_res->mid); + + /* send separate ACK. */ + coap_packet_t ack[1]; + /* ACK with empty code (0) */ + coap_init_message(ack, COAP_TYPE_ACK, 0, coap_req->mid); + /* Serializing into IPBUF: Only overwrites header parts that are already parsed into the request struct. */ + coap_send_message(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, (uip_appdata), coap_serialize_message(ack, uip_appdata)); + + /* Change response to separate response. */ + coap_res->type = COAP_TYPE_CON; + coap_res->mid = coap_get_mid(); + + /* Update MID in transaction for identification. */ + t->mid = coap_res->mid; + } + + /* Pre-handlers could skip the handling by returning 0. */ + return 1; +} + +int +coap_separate_response(void *response, coap_separate_t *separate_store) +{ + coap_packet_t *const coap_res = (coap_packet_t *) response; + coap_transaction_t *const t = coap_get_transaction_by_mid(coap_res->mid); + + if (t) + { + uip_ipaddr_copy(&separate_store->addr, &t->addr); + separate_store->port = t->port; + + separate_store->mid = coap_res->mid; + separate_store->type = coap_res->type; + + memcpy(separate_store->token, coap_res->token, coap_res->token_len); + separate_store->token_len = coap_res->token_len; + + separate_store->block2_num = coap_res->block2_num; + separate_store->block2_more = coap_res->block2_more; + separate_store->block2_size = coap_res->block2_size; + separate_store->block2_offset = coap_res->block2_offset; + + /* Signal the engine to skip automatic response and clear transaction by engine. */ + coap_error_code = MANUAL_RESPONSE; + + return 1; + } + else + { + return 0; + } } diff --git a/apps/er-coap-07/er-coap-07-separate.h b/apps/er-coap-07/er-coap-07-separate.h index ace2388f5..8d677ea0d 100644 --- a/apps/er-coap-07/er-coap-07-separate.h +++ b/apps/er-coap-07/er-coap-07-separate.h @@ -41,6 +41,28 @@ #include "er-coap-07.h" -void coap_separate_handler(resource_t *resource, void *request, void *response); +typedef struct coap_separate { + + uip_ipaddr_t addr; + uint16_t port; + + coap_message_type_t type; + uint16_t mid; + + uint8_t token_len; + uint8_t token[COAP_TOKEN_LEN]; + + uint32_t block2_num; + uint8_t block2_more; + uint16_t block2_size; + uint32_t block2_offset; + + /* Add fields for addition information to be saved here, e.g.: */ + char buffer[17]; + +} coap_separate_t; + +int coap_separate_handler(resource_t *resource, void *request, void *response); +int coap_separate_response(void *response, coap_separate_t *separate_store); #endif /* COAP_SEPARATE_H_ */ diff --git a/apps/er-coap-07/er-coap-07-transactions.c b/apps/er-coap-07/er-coap-07-transactions.c index 4dfff6553..10070a29e 100644 --- a/apps/er-coap-07/er-coap-07-transactions.c +++ b/apps/er-coap-07/er-coap-07-transactions.c @@ -87,6 +87,8 @@ coap_new_transaction(uint16_t mid, uip_ipaddr_t *addr, uint16_t port) /* save client address */ uip_ipaddr_copy(&t->addr, addr); t->port = port; + + list_add(transactions_list, t); /* List itself makes sure same element is not added twice. */ } return t; @@ -122,8 +124,6 @@ coap_send_transaction(coap_transaction_t *t) etimer_restart(&t->retrans_timer); /* interval updated above */ process_current = process_actual; - list_add(transactions_list, t); /* List itself makes sure same element is not added twice. */ - t = NULL; } else diff --git a/apps/er-coap-07/er-coap-07.h b/apps/er-coap-07/er-coap-07.h index 62f943898..2284f0a00 100644 --- a/apps/er-coap-07/er-coap-07.h +++ b/apps/er-coap-07/er-coap-07.h @@ -140,15 +140,13 @@ typedef enum { GATEWAY_TIMEOUT_5_04 = 164, /* GATEWAY_TIMEOUT */ PROXYING_NOT_SUPPORTED_5_05 = 165, /* PROXYING_NOT_SUPPORTED */ - /* Memory errors */ - IMPLEMENTATION_ERROR = 192, - MEMORY_ALLOC_ERR = 193, - MEMORY_BOUNDARY_EXCEEDED = 194, + /* Erbium errors */ + MEMORY_ALLOCATION_ERROR = 192, + PACKET_SERIALIZATION_ERROR, + + /* Erbium hooks */ + MANUAL_RESPONSE - /* CoAP errors */ - UNIMPLEMENTED_CRITICAL_OPTION, - UNKNOWN_CRITICAL_OPTION, - PACKET_SERIALIZATION_ERROR } coap_status_t; /* CoAP header options */ diff --git a/apps/erbium/erbium.c b/apps/erbium/erbium.c index d2708616c..f624dd594 100644 --- a/apps/erbium/erbium.c +++ b/apps/erbium/erbium.c @@ -60,7 +60,7 @@ LIST(restful_periodic_services); void -rest_init_framework(void) +rest_init_engine(void) { list_init(restful_services); diff --git a/apps/erbium/erbium.h b/apps/erbium/erbium.h index f550deeed..1c29ab125 100644 --- a/apps/erbium/erbium.h +++ b/apps/erbium/erbium.h @@ -282,7 +282,7 @@ periodic_resource_t periodic_resource_##name = {NULL, &resource_##name, period, /* * Initializes REST framework and starts HTTP or COAP process */ -void rest_init_framework(void); +void rest_init_engine(void); /* * Resources wanted to be accessible should be activated with the following code. diff --git a/examples/er-rest-example/rest-server-example.c b/examples/er-rest-example/rest-server-example.c index 0195295b3..88dab13a0 100644 --- a/examples/er-rest-example/rest-server-example.c +++ b/examples/er-rest-example/rest-server-example.c @@ -47,11 +47,12 @@ #define REST_RES_HELLO 1 #define REST_RES_MIRROR 0 /* causes largest code size */ #define REST_RES_CHUNKS 1 -#define REST_RES_POLLING 1 +#define REST_RES_POLLING 0 +#define REST_RES_SEPARATE 1 #define REST_RES_EVENT 1 #define REST_RES_LEDS 1 #define REST_RES_TOGGLE 1 -#define REST_RES_LIGHT 1 +#define REST_RES_LIGHT 0 #define REST_RES_BATTERY 1 @@ -149,8 +150,7 @@ mirror_handler(void* request, void* response, uint8_t *buffer, uint16_t preferre /* The ETag and Token is copied to the header. */ uint8_t opaque[] = {0x0A, 0xBC, 0xDE}; - /* Strings are not copied and should be static or in program memory (char *str = "string in .text";). - * They must be '\0'-terminated as the setters use strlen(). */ + /* Strings are not copied, so use static string buffers or strings in .text memory (char *str = "string in .text";). */ static char location[] = {'/','f','/','a','?','k','&','e', 0}; /* Getter for the header option Content-Type. If the option is not set, text/plain is returned by default. */ @@ -390,6 +390,79 @@ polling_periodic_handler(resource_t *r) } #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" +#include "er-coap-07-transactions.h" +/* + * CoAP-specific example for separate responses. + * This resource is . + */ +RESOURCE(separate, METHOD_GET, "debug/separate", "title=\"Separate demo\""); + +static uint8_t separate_active = 0; +static coap_separate_t separate_store[1]; + +void +separate_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + /* + * Example allows only one open separate response. + * For multiple, the application must manage the list of stores. + */ + 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); + } + else + { + separate_active = 1; + + /* Take over and skip response by engine. */ + coap_separate_response(response, separate_store); + + /* + * At the moment, only the minimal information is stored in the store (client address, port, token, MID, type, and Block2). + * Extend the store, if the application requires additional information from this handler. + * buffer is an example field for custom information. + */ + snprintf(separate_store->buffer, sizeof(separate_store->buffer), "StoredInfo"); + } +} + +void +separate_finalize_handler() +{ + if (separate_active) + { + coap_transaction_t *transaction = NULL; + if ( (transaction = coap_new_transaction(separate_store->mid, &separate_store->addr, separate_store->port)) ) + { + coap_packet_t response[1]; /* This way the packet can be treated as pointer as usual. */ + coap_init_message(response, separate_store->type, CONTENT_2_05, separate_store->mid); + + coap_set_payload(response, separate_store->buffer, strlen(separate_store->buffer)); + + /* Warning: No check for serialization error. */ + transaction->packet_len = coap_serialize_message(response, transaction->packet); + coap_send_transaction(transaction); + /* The engine will clear the transaction (right after send for NON, after acked for CON). */ + + separate_active = 0; + } + else + { + /* + * Set timer for retry, send error message, ... + * The example simply waits for another button press. + */ + } + } /* if (separate_active) */ +} +#endif + #if defined (PLATFORM_HAS_BUTTON) && REST_RES_EVENT /* * Example for an event resource. @@ -594,8 +667,8 @@ PROCESS_THREAD(rest_server_example, ev, data) configure_routing(); #endif - /* Initialize the REST framework. */ - rest_init_framework(); + /* Initialize the REST engine. */ + rest_init_engine(); /* Activate the application-specific resources. */ #if REST_RES_HELLO @@ -610,6 +683,11 @@ PROCESS_THREAD(rest_server_example, ev, data) #if REST_RES_POLLING rest_activate_periodic_resource(&periodic_resource_polling); #endif +#if REST_RES_SEPARATE && WITH_COAP > 3 + rest_set_pre_handler(&resource_separate, coap_separate_handler); + rest_activate_resource(&resource_separate); +#endif + #if defined (PLATFORM_HAS_BUTTON) && REST_RES_EVENT SENSORS_ACTIVATE(button_sensor); rest_activate_event_resource(&resource_event); @@ -634,11 +712,17 @@ PROCESS_THREAD(rest_server_example, ev, data) /* Define application-specific events here. */ while(1) { PROCESS_WAIT_EVENT(); -#if defined (PLATFORM_HAS_BUTTON) && REST_RES_EVENT +#if defined (PLATFORM_HAS_BUTTON) if (ev == sensors_event && data == &button_sensor) { PRINTF("BUTTON\n"); +#if REST_RES_EVENT /* Call the event_handler for this application-specific event. */ event_event_handler(&resource_event); +#endif +#if REST_RES_SEPARATE && WITH_COAP>3 + /* Also call the separate response example handler. */ + separate_finalize_handler(); +#endif } #endif /* PLATFORM_HAS_BUTTON */ } /* while (1) */ From dc6142fa0b6d5f00c9f2e2b3163d3f33ab88fde6 Mon Sep 17 00:00:00 2001 From: Matthias Kovatsch Date: Wed, 1 Feb 2012 03:24:49 +0100 Subject: [PATCH 03/15] Revised Erbium observing. --- apps/er-coap-03/er-coap-03-observing.c | 4 +- apps/er-coap-03/er-coap-03-observing.h | 2 +- apps/er-coap-03/er-coap-03.c | 6 +- apps/er-coap-03/er-coap-03.h | 4 +- apps/er-coap-07/er-coap-07-engine.c | 4 +- apps/er-coap-07/er-coap-07-observing.c | 20 ++-- apps/er-coap-07/er-coap-07-observing.h | 6 +- .../er-rest-example/rest-server-example.c | 109 +++++++++--------- 8 files changed, 79 insertions(+), 76 deletions(-) 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); From c1aa211dc757bc46e07f27e5ff527e037eafc03d Mon Sep 17 00:00:00 2001 From: Matthias Kovatsch Date: Wed, 1 Feb 2012 03:58:35 +0100 Subject: [PATCH 04/15] Added RST-MID matching for observing. --- apps/er-coap-07/er-coap-07-engine.c | 4 ++-- apps/er-coap-07/er-coap-07-observing.c | 24 ++++++++++++++++++++++++ apps/er-coap-07/er-coap-07-observing.h | 2 ++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/apps/er-coap-07/er-coap-07-engine.c b/apps/er-coap-07/er-coap-07-engine.c index f0545d61e..326d811a9 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)) { - /* RST must be empty, so it is a full client reset. */ - coap_remove_observer_by_client(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport); + /* Erbium stores last MID for each observer. */ + coap_remove_observer_by_mid(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, message->mid); } } diff --git a/apps/er-coap-07/er-coap-07-observing.c b/apps/er-coap-07/er-coap-07-observing.c index 5324a3a00..d9852f4e0 100644 --- a/apps/er-coap-07/er-coap-07-observing.c +++ b/apps/er-coap-07/er-coap-07-observing.c @@ -69,6 +69,7 @@ coap_add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, size_ o->port = port; o->token_len = token_len; memcpy(o->token, token, token_len); + o->last_mid = 0; stimer_set(&o->refresh_timer, COAP_OBSERVING_REFRESH_INTERVAL); @@ -107,6 +108,7 @@ coap_remove_observer_by_client(uip_ipaddr_t *addr, uint16_t port) } return removed; } + int coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port, uint8_t *token, size_t token_len) { @@ -124,6 +126,7 @@ coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port, uint8_t *token, } return removed; } + int coap_remove_observer_by_url(uip_ipaddr_t *addr, uint16_t port, const char *url) { @@ -141,6 +144,24 @@ coap_remove_observer_by_url(uip_ipaddr_t *addr, uint16_t port, const char *url) } return removed; } + +int +coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port, uint16_t mid) +{ + int removed = 0; + coap_observer_t* obs = NULL; + + for (obs = (coap_observer_t*)list_head(observers_list); obs; obs = obs->next) + { + PRINTF("Remove check URL %p\n", url); + if (uip_ipaddr_cmp(&obs->addr, addr) && obs->port==port && obs->last_mid==mid) + { + coap_remove_observer(obs); + removed++; + } + } + return removed; +} /*-----------------------------------------------------------------------------------*/ void coap_notify_observers(const char *url, int type, uint32_t observe, uint8_t *payload, size_t payload_len) @@ -177,6 +198,9 @@ coap_notify_observers(const char *url, int type, uint32_t observe, uint8_t *payl PRINTF(":%u\n", obs->port); PRINTF(" %.*s\n", payload_len, payload); + /* Update last MID for RST matching. */ + obs->last_mid = transaction->mid; + coap_send_transaction(transaction); } } diff --git a/apps/er-coap-07/er-coap-07-observing.h b/apps/er-coap-07/er-coap-07-observing.h index d30acbebc..7b09ba83e 100644 --- a/apps/er-coap-07/er-coap-07-observing.h +++ b/apps/er-coap-07/er-coap-07-observing.h @@ -61,6 +61,7 @@ typedef struct coap_observer { uint16_t port; uint8_t token_len; uint8_t token[COAP_TOKEN_LEN]; + uint16_t last_mid; struct stimer refresh_timer; } coap_observer_t; @@ -72,6 +73,7 @@ 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(uip_ipaddr_t *addr, uint16_t port, const char *url); +int coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port, uint16_t mid); void coap_notify_observers(const char *url, int type, uint32_t observe, uint8_t *payload, size_t payload_len); From 860de0dd01f17f440d8122de9d88a062c7f959b5 Mon Sep 17 00:00:00 2001 From: Matthias Kovatsch Date: Wed, 1 Feb 2012 05:16:16 +0100 Subject: [PATCH 05/15] Bugfixes for observing. Many thanks to Klaus Hartke. --- apps/er-coap-07/er-coap-07-engine.c | 6 +----- apps/er-coap-07/er-coap-07-observing.c | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/apps/er-coap-07/er-coap-07-engine.c b/apps/er-coap-07/er-coap-07-engine.c index 326d811a9..b9f790e29 100644 --- a/apps/er-coap-07/er-coap-07-engine.c +++ b/apps/er-coap-07/er-coap-07-engine.c @@ -223,11 +223,7 @@ handle_incoming_data(void) { PRINTF("Received RST\n"); /* Cancel possible subscriptions. */ - if (IS_OPTION(message, COAP_OPTION_TOKEN)) - { - /* Erbium stores last MID for each observer. */ - coap_remove_observer_by_mid(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, message->mid); - } + coap_remove_observer_by_mid(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, message->mid); } if ( (transaction = coap_get_transaction_by_mid(message->mid)) ) diff --git a/apps/er-coap-07/er-coap-07-observing.c b/apps/er-coap-07/er-coap-07-observing.c index d9852f4e0..11eef1935 100644 --- a/apps/er-coap-07/er-coap-07-observing.c +++ b/apps/er-coap-07/er-coap-07-observing.c @@ -118,7 +118,7 @@ coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port, uint8_t *token, for (obs = (coap_observer_t*)list_head(observers_list); obs; obs = obs->next) { PRINTF("Remove check Token 0x%02X%02X\n", token[0], token[1]); - if (uip_ipaddr_cmp(&obs->addr, addr) && obs->port==port && memcmp(obs->token, token, token_len)==0) + if (uip_ipaddr_cmp(&obs->addr, addr) && obs->port==port && obs->token_len==token_len && memcmp(obs->token, token, token_len)==0) { coap_remove_observer(obs); removed++; @@ -153,7 +153,7 @@ coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port, uint16_t mid) for (obs = (coap_observer_t*)list_head(observers_list); obs; obs = obs->next) { - PRINTF("Remove check URL %p\n", url); + PRINTF("Remove check MID %u\n", mid); if (uip_ipaddr_cmp(&obs->addr, addr) && obs->port==port && obs->last_mid==mid) { coap_remove_observer(obs); From 499d3052ee5ad19b7c951cfa59d343af83765ede Mon Sep 17 00:00:00 2001 From: Ilya Dmitrichenko Date: Wed, 22 Feb 2012 00:46:32 +0000 Subject: [PATCH 06/15] Fixed TARGET=native compilation issues on Darwin. --- cpu/native/Makefile.native | 6 +++++- cpu/x86/Makefile.x86 | 6 +++++- platform/native/Makefile.native | 4 ++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/cpu/native/Makefile.native b/cpu/native/Makefile.native index d2a8c1d3c..56fb6688b 100644 --- a/cpu/native/Makefile.native +++ b/cpu/native/Makefile.native @@ -14,7 +14,11 @@ CFLAGSWERROR=-Werror -pedantic -std=c99 -Werror endif CFLAGSNO = -Wall -g -I/usr/local/include $(CFLAGSWERROR) CFLAGS += $(CFLAGSNO) -O -LDFLAGS = -Wl,-Map=contiki-$(TARGET).map,-export-dynamic +ifeq ($(HOST_OS),Linux) + LDFLAGS = -Wl,-Map=contiki-$(TARGET).map,-export-dynamic +else + LDFLAGS = -Wl +endif ### Compilation rules diff --git a/cpu/x86/Makefile.x86 b/cpu/x86/Makefile.x86 index be3f62579..612603f52 100644 --- a/cpu/x86/Makefile.x86 +++ b/cpu/x86/Makefile.x86 @@ -10,7 +10,11 @@ OBJCOPY = objcopy STRIP = strip CFLAGSNO = -Wall -g -I/usr/local/include CFLAGS += $(CFLAGSNO) -LDFLAGS = -Wl,-Map=contiki-$(TARGET).map,-export-dynamic +ifeq ($(HOST_OS),Linux) + LDFLAGS = -Wl,-Map=contiki-$(TARGET).map,-export-dynamic +else + LDFLAGS = -Wl +endif ### Compilation rules diff --git a/platform/native/Makefile.native b/platform/native/Makefile.native index 63ba12e9d..36368e266 100644 --- a/platform/native/Makefile.native +++ b/platform/native/Makefile.native @@ -2,6 +2,10 @@ ifndef CONTIKI $(error CONTIKI not defined! You must specify where CONTIKI resides!) endif +ifeq ($(HOST_OS),Darwin) + AROPTS = rc +endif + ifdef UIP_CONF_IPV6 CFLAGS += -DWITH_UIP6=1 endif From 70d3acf9afd78180de27cb6b7aa36b903b735a63 Mon Sep 17 00:00:00 2001 From: Ilya Dmitrichenko Date: Wed, 22 Feb 2012 00:47:51 +0000 Subject: [PATCH 07/15] Fixed baudrate issue on Darwin. --- examples/ipv6/native-border-router/slip-config.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/ipv6/native-border-router/slip-config.c b/examples/ipv6/native-border-router/slip-config.c index fb00d18cc..daad4907a 100644 --- a/examples/ipv6/native-border-router/slip-config.c +++ b/examples/ipv6/native-border-router/slip-config.c @@ -127,7 +127,11 @@ slip_config_handle_arguments(int argc, char **argv) fprintf(stderr,"usage: %s [options] ipaddress\n", prog); fprintf(stderr,"example: border-router.native -L -v2 -s ttyUSB1 aaaa::1/64\n"); fprintf(stderr,"Options are:\n"); +#ifdef linux fprintf(stderr," -B baudrate 9600,19200,38400,57600,115200,921600 (default 115200)\n"); +#else +fprintf(stderr," -B baudrate 9600,19200,38400,57600,115200 (default 115200)\n"); +#endif fprintf(stderr," -H Hardware CTS/RTS flow control (default disabled)\n"); fprintf(stderr," -L Log output format (adds time stamps)\n"); fprintf(stderr," -s siodev Serial device (default /dev/ttyUSB0)\n"); @@ -175,9 +179,11 @@ exit(1); case 115200: slip_config_b_rate = B115200; break; +#ifdef linux case 921600: slip_config_b_rate = B921600; break; +#endif default: err(1, "unknown baudrate %d", baudrate); break; From 7621bdfc777a44b80b83df3caa67c490c60a9ab8 Mon Sep 17 00:00:00 2001 From: Ilya Dmitrichenko Date: Wed, 22 Feb 2012 17:28:33 +0000 Subject: [PATCH 08/15] Fixed ifconfig for Darwin --- examples/ipv6/native-border-router/tun-bridge.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/ipv6/native-border-router/tun-bridge.c b/examples/ipv6/native-border-router/tun-bridge.c index db695c289..3eae3795f 100644 --- a/examples/ipv6/native-border-router/tun-bridge.c +++ b/examples/ipv6/native-border-router/tun-bridge.c @@ -125,13 +125,17 @@ void ifconf(const char *tundev, const char *ipaddr) { #ifdef linux - ssystem("ifconfig %s inet `hostname` up", tundev); + ssystem("ifconfig %s inet6 `hostname` up", tundev); ssystem("ifconfig %s add %s", tundev, ipaddr); +#elif defined(__MACH__) + ssystem("ifconfig %s inet6 %s up", tundev, ipaddr); + ssystem("sysctl -w net.inet.ip.forwarding=1"); #else - ssystem("ifconfig %s inet `hostname` %s up", tundev, ipaddr); + ssystem("ifconfig %s inet6 `hostname` %s up", tundev, ipaddr); ssystem("sysctl -w net.inet.ip.forwarding=1"); #endif /* !linux */ + /* Print the configuration to the console. */ ssystem("ifconfig %s\n", tundev); } /*---------------------------------------------------------------------------*/ From b67e49051cc9b55d52c5e08b1c9b6dc2d4f13d3c Mon Sep 17 00:00:00 2001 From: Ilya Dmitrichenko Date: Tue, 28 Feb 2012 21:28:57 +0000 Subject: [PATCH 09/15] Use `__APPLE__` instead of `__MACH__`. --- examples/ipv6/native-border-router/tun-bridge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ipv6/native-border-router/tun-bridge.c b/examples/ipv6/native-border-router/tun-bridge.c index 3eae3795f..54d16339c 100644 --- a/examples/ipv6/native-border-router/tun-bridge.c +++ b/examples/ipv6/native-border-router/tun-bridge.c @@ -127,7 +127,7 @@ ifconf(const char *tundev, const char *ipaddr) #ifdef linux ssystem("ifconfig %s inet6 `hostname` up", tundev); ssystem("ifconfig %s add %s", tundev, ipaddr); -#elif defined(__MACH__) +#elif defined(__APPLE__) ssystem("ifconfig %s inet6 %s up", tundev, ipaddr); ssystem("sysctl -w net.inet.ip.forwarding=1"); #else From 49cd7878e3ca45ac0a609a1511f9a9bdba4094ef Mon Sep 17 00:00:00 2001 From: Ilya Dmitrichenko Date: Tue, 28 Feb 2012 21:36:05 +0000 Subject: [PATCH 10/15] Avoid deprecated error on Darwin. --- cpu/native/mtarch.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cpu/native/mtarch.c b/cpu/native/mtarch.c index 5bb01a0cc..e9df427d0 100644 --- a/cpu/native/mtarch.c +++ b/cpu/native/mtarch.c @@ -40,7 +40,12 @@ static void *main_fiber; -#elif defined(__linux) +#elif defined(__linux) || defined(__APPLE__) + +#ifdef __APPLE__ +/* Avoid deprecated error on Darwin */ +#define _XOPEN_SOURCE +#endif #include #include From 1214086f97abc74eee07d7d7e08e75b55906a989 Mon Sep 17 00:00:00 2001 From: Ilya Dmitrichenko Date: Fri, 2 Mar 2012 10:04:59 +0000 Subject: [PATCH 11/15] Fixed TARGET=minimal-net compilation issues on Darwin. --- platform/minimal-net/Makefile.minimal-net | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/minimal-net/Makefile.minimal-net b/platform/minimal-net/Makefile.minimal-net index dd35c8880..296d5684e 100644 --- a/platform/minimal-net/Makefile.minimal-net +++ b/platform/minimal-net/Makefile.minimal-net @@ -2,6 +2,10 @@ ifndef CONTIKI $(error CONTIKI not defined! You must specify where CONTIKI resides!) endif +ifeq ($(HOST_OS),Darwin) + AROPTS = rc +endif + CONTIKI_TARGET_DIRS = . CONTIKI_TARGET_MAIN = ${addprefix $(OBJECTDIR)/,contiki-main.o} From 358530e1d3b52c514dd2511e64e0976d5a9d0fb1 Mon Sep 17 00:00:00 2001 From: David Kopf Date: Fri, 2 Mar 2012 15:28:26 -0500 Subject: [PATCH 12/15] Add higher baud rates, option for link-local address assignment --- tools/tunslip6.c | 57 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/tools/tunslip6.c b/tools/tunslip6.c index 4192dae4f..3b6a51601 100644 --- a/tools/tunslip6.c +++ b/tools/tunslip6.c @@ -29,7 +29,6 @@ * * This file is part of the uIP TCP/IP stack. * - * $Id: tunslip6.c,v 1.6 2010/11/29 18:14:54 joxe Exp $ * */ @@ -596,6 +595,49 @@ ifconf(const char *tundev, const char *ipaddr) ssystem("ifconfig %s inet `hostname` up", tundev); if (timestamp) stamptime(); ssystem("ifconfig %s add %s", tundev, ipaddr); + +/* radvd needs a link local address for routing */ +#if 0 +/* fe80::1/64 is good enough */ + ssystem("ifconfig %s add fe80::1/64", tundev); +#elif 1 +/* Generate a link local address a la sixxs/aiccu */ +/* First a full parse, stripping off the prefix length */ +{ +char lladdr[40]; +char c,*ptr=(char *)ipaddr; +uint16_t digit,ai,a[8],cc,scc,i; + for(ai=0;ai<8;ai++) a[ai]=0; + ai=0;cc=scc=0; + while(c=*ptr++) { + if(c=='/') break; + if(c==':') { + if(cc) scc = ai; + cc = 1; + if (++ai>7) break; + } else { + cc=0; + digit = c-'0'; if (digit > 9) digit = 10 + (c & 0xdf) - 'A'; + a[ai] = (a[ai] << 4) + digit; + } + } + /* Get # elided and shift what's after to the end */ + cc=8-ai; + for(i=0;i Date: Fri, 2 Mar 2012 15:51:42 -0500 Subject: [PATCH 13/15] Redo html output, more options, httpd state variables to allow neighbors and routes to span tcp segments. --- apps/webserver-nano/httpd-cgi.c | 273 ++++++++++++++++++++++---------- apps/webserver-nano/httpd.h | 32 +++- 2 files changed, 215 insertions(+), 90 deletions(-) diff --git a/apps/webserver-nano/httpd-cgi.c b/apps/webserver-nano/httpd-cgi.c index 8a78bee0a..ba36461e1 100644 --- a/apps/webserver-nano/httpd-cgi.c +++ b/apps/webserver-nano/httpd-cgi.c @@ -283,7 +283,7 @@ generate_file_stats(void *arg) { struct httpd_state *s = (struct httpd_state *)arg; #if WEBSERVER_CONF_LOADTIME - static const char httpd_cgi_filestat1[] HTTPD_STRING_ATTR = "



This page has been sent %u times (%1u.%u sec)"; + static const char httpd_cgi_filestat1[] HTTPD_STRING_ATTR = "



This page has been sent %u times (%1u.%02u sec)"; #else static const char httpd_cgi_filestat1[] HTTPD_STRING_ATTR = "



This page has been sent %u times"; #endif @@ -301,7 +301,7 @@ generate_file_stats(void *arg) #if WEBSERVER_CONF_LOADTIME s->pagetime = clock_time() - s->pagetime; numprinted=httpd_snprintf((char *)uip_appdata, uip_mss(), httpd_cgi_filestat1, httpd_fs_open(s->filename, 0), - (unsigned int)s->pagetime/CLOCK_SECOND,(unsigned int)s->pagetime%CLOCK_SECOND); + (unsigned int)s->pagetime/CLOCK_SECOND,(100*((unsigned int)s->pagetime%CLOCK_SECOND))/CLOCK_SECOND); #else numprinted=httpd_snprintf((char *)uip_appdata, uip_mss(), httpd_cgi_filestat1, httpd_fs_open(s->filename, 0)); #endif @@ -433,10 +433,12 @@ PT_THREAD(processes(struct httpd_state *s, char *ptr)) #endif /* WEBSERVER_CONF_PROCESSES */ #if WEBSERVER_CONF_ADDRESSES || WEBSERVER_CONF_NEIGHBORS || WEBSERVER_CONF_ROUTES -static const char httpd_cgi_addrh[] HTTPD_STRING_ATTR = ""; -static const char httpd_cgi_addrf[] HTTPD_STRING_ATTR = "[Room for %u more]"; -static const char httpd_cgi_addrb[] HTTPD_STRING_ATTR = "
"; -static const char httpd_cgi_addrn[] HTTPD_STRING_ATTR = "(none)
"; +#if WEBSERVER_CONF_SHOW_ROOM +static const char httpd_cgi_addrf[] HTTPD_STRING_ATTR = "[Room for %u more]\n"; +#else +static const char httpd_cgi_addrf[] HTTPD_STRING_ATTR = "[Table is full]\n"; +#endif +static const char httpd_cgi_addrn[] HTTPD_STRING_ATTR = "[None]\n"; #endif #if WEBSERVER_CONF_ADDRESSES @@ -447,16 +449,21 @@ static unsigned short make_addresses(void *p) { uint8_t i,j=0; -uint16_t numprinted; - numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(),httpd_cgi_addrh); +uint16_t numprinted = 0; for (i=0; istarti;j=s->startj; + for (;i (uip_mss() - 50)) { + s->savei=i;s->savej=j; + return numprinted; + } } } - numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrf,UIP_DS6_NBR_NB-j); +#if WEBSERVER_CONF_SHOW_ROOM + numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrf,UIP_DS6_NBR_NB-j); +#else + if(UIP_DS6_NBR_NB == j) { + numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrf); + } +#endif + + /* Signal that this was the last segment */ + s->savei = 0; return numprinted; } /*---------------------------------------------------------------------------*/ @@ -496,7 +541,13 @@ PT_THREAD(neighbors(struct httpd_state *s, char *ptr)) { PSOCK_BEGIN(&s->sout); - PSOCK_GENERATOR_SEND(&s->sout, make_neighbors, s->u.ptr); + /* Send as many TCP segments as needed for the neighbor table */ + /* Move to next seqment after each successful transmission */ + s->starti=s->startj=0; + do { + PSOCK_GENERATOR_SEND(&s->sout, make_neighbors, (void *)s); + s->starti=s->savei+1;s->startj=s->savej; + } while(s->savei); PSOCK_END(&s->sout); } @@ -508,27 +559,57 @@ extern uip_ds6_route_t uip_ds6_routing_table[]; static unsigned short make_routes(void *p) { -static const char httpd_cgi_rtes1[] HTTPD_STRING_ATTR = "(%u (via "; -static const char httpd_cgi_rtes2[] HTTPD_STRING_ATTR = ") %lus
"; -static const char httpd_cgi_rtes3[] HTTPD_STRING_ATTR = ")
"; -uint8_t i,j=0; -uint16_t numprinted; - numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(),httpd_cgi_addrh); - for (i=0; istarti;j=s->startj; + for (;i (uip_mss() - 200)) { + s->savei=i;s->savej=j; + return numprinted; + } } } if (j==0) numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrn); - numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrf,UIP_DS6_ROUTE_NB-j); +#if WEBSERVER_CONF_SHOW_ROOM + numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrf,UIP_DS6_ROUTE_NB-j); +#else + if(UIP_DS6_ROUTE_NB == j) { + numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrf); + } +#endif + + /* Signal that this was the last segment */ + s->savei = 0; return numprinted; } /*---------------------------------------------------------------------------*/ @@ -536,8 +617,14 @@ static PT_THREAD(routes(struct httpd_state *s, char *ptr)) { PSOCK_BEGIN(&s->sout); - - PSOCK_GENERATOR_SEND(&s->sout, make_routes, s->u.ptr); + + /* Send as many TCP segments as needed for the route table */ + /* Move to next seqment after each successful transmission */ + s->starti=s->startj=0; + do { + PSOCK_GENERATOR_SEND(&s->sout, make_routes, s); + s->starti=s->savei+1;s->startj=s->savej; + } while(s->savei); PSOCK_END(&s->sout); } @@ -548,18 +635,15 @@ PT_THREAD(routes(struct httpd_state *s, char *ptr)) static unsigned short generate_sensor_readings(void *arg) { - uint16_t numprinted; + uint16_t numprinted=0; uint16_t days,h,m,s; unsigned long seconds=clock_seconds(); - static const char httpd_cgi_sensor0[] HTTPD_STRING_ATTR = "[Updated %d seconds ago]

"; - static const char httpd_cgi_sensor1[] HTTPD_STRING_ATTR = "

Temperature: %s\n";
+  static const char httpd_cgi_sensor0[] HTTPD_STRING_ATTR = "[Updated %d seconds ago]\n";
+  static const char httpd_cgi_sensor1[] HTTPD_STRING_ATTR = "Temperature: %s\n";
   static const char httpd_cgi_sensor2[] HTTPD_STRING_ATTR = "Battery    : %s\n";
-//  static const char httpd_cgi_sensr12[] HTTPD_STRING_ATTR = "Temperature: %s   Battery: %s
"; static const char httpd_cgi_sensor3[] HTTPD_STRING_ATTR = "Uptime : %02d:%02d:%02d\n"; static const char httpd_cgi_sensor3d[] HTTPD_STRING_ATTR = "Uptime : %u days %02u:%02u:%02u\n"; -// static const char httpd_cgi_sensor4[] HTTPD_STRING_ATTR = "Sleeping time : %02d:%02d:%02d (%d%%)
"; - numprinted=0; /* Generate temperature and voltage strings for each platform */ #if CONTIKI_TARGET_AVR_ATMEGA128RFA1 {uint8_t i; @@ -623,29 +707,36 @@ generate_sensor_readings(void *arg) #elif CONTIKI_TARGET_REDBEE_ECONOTAG //#include "adc.h" { +#if 0 +/* Scan ADC channels if not already being done elsewhere */ uint8_t c; - adc_reading[8]=0; - adc_init(); - while (adc_reading[8]==0) adc_service(); - // for (c=0; csout); PSOCK_GENERATOR_SEND(&s->sout, generate_sensor_readings, s); -#if RADIOSTATS - PSOCK_GENERATOR_SEND(&s->sout, generate_radio_stats, s); +#if WEBSERVER_CONF_STATISTICS + PSOCK_GENERATOR_SEND(&s->sout, generate_stats, s); #endif PSOCK_END(&s->sout); @@ -971,15 +1055,40 @@ PT_THREAD(ajax_call(struct httpd_state *s, char *ptr)) SENSORS_DEACTIVATE(acc_sensor); #elif CONTIKI_TARGET_REDBEE_ECONOTAG -{ uint8_t c; - adc_reading[8]=0; - adc_init(); - while (adc_reading[8]==0) adc_service(); - adc_disable(); - numprinted = snprintf(buf, sizeof(buf),"b(%u);adc(%u,%u,%u,%u,%u,%u,%u,%u);", - 1200*0xfff/adc_reading[8],adc_reading[0],adc_reading[1],adc_reading[2],adc_reading[3],adc_reading[4],adc_reading[5],adc_reading[6],adc_reading[7]); +#if 0 +/* Scan ADC channels if not already done elsewhere */ +{ uint8_t c; + adc_reading[8]=0; + adc_init(); + while (adc_reading[8]==0) adc_service(); + adc_disable(); +#endif + +#if 0 + numprinted = snprintf(buf, sizeof(buf),"b(%u);adc(%u,%u,%u,%u,%u,%u,%u,%u);", + 1200*0xfff/adc_reading[8],adc_reading[0],adc_reading[1],adc_reading[2],adc_reading[3],adc_reading[4],adc_reading[5],adc_reading[6],adc_reading[7]); +#else + // numprinted = snprintf(buf, sizeof(buf),"b(%u);",1200*0xfff/adc_reading[8]); + numprinted = snprintf(buf, sizeof(buf),"b(%u);adc(%u,%u,%u);",1200*0xfff/adc_reading[8],adc_reading[1],adc_reading[7],adc_reading[8]); +#endif } - + if (iter<3) { + static const char httpd_cgi_ajax11[] HTTPD_STRING_ATTR = "wt('Econtag ["; + static const char httpd_cgi_ajax12[] HTTPD_STRING_ATTR = "]');"; + numprinted += httpd_snprintf(buf+numprinted, sizeof(buf)-numprinted,httpd_cgi_ajax11); +#if WEBSERVER_CONF_PRINTADDR +/* Note address table is filled from the end down */ +{int i; + for (i=0; i Date: Fri, 2 Mar 2012 16:01:12 -0500 Subject: [PATCH 14/15] Add display options to border router web page, default now uses stack instead of static buffer. Turn radio off until prefix is acquired. --- core/net/mac/contikimac.c | 6 + .../ipv6/rpl-border-router/border-router.c | 139 ++++++++++++++++-- 2 files changed, 130 insertions(+), 15 deletions(-) diff --git a/core/net/mac/contikimac.c b/core/net/mac/contikimac.c index c65a975c9..81640793e 100644 --- a/core/net/mac/contikimac.c +++ b/core/net/mac/contikimac.c @@ -535,6 +535,12 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_ struct hdr *chdr; #endif /* WITH_CONTIKIMAC_HEADER */ + /* Exit if RDC and radio were explicitly turned off */ + if (!contikimac_is_on && !contikimac_keep_radio_on) { + PRINTF("contikimac: radio is turned off\n"); + return MAC_TX_ERR_FATAL; + } + if(packetbuf_totlen() == 0) { PRINTF("contikimac: send_packet data len 0\n"); return MAC_TX_ERR_FATAL; diff --git a/examples/ipv6/rpl-border-router/border-router.c b/examples/ipv6/rpl-border-router/border-router.c index 418425ff9..33d9f754b 100644 --- a/examples/ipv6/rpl-border-router/border-router.c +++ b/examples/ipv6/rpl-border-router/border-router.c @@ -74,6 +74,13 @@ AUTOSTART_PROCESSES(&border_router_process,&webserver_nogui_process); #else /* Use simple webserver with only one page */ #include "httpd-simple.h" + +#define WEBSERVER_CONF_LOADTIME 0 +#define WEBSERVER_CONF_FILESTATS 0 +#define WEBSERVER_CONF_NEIGHBOR_STATUS 0 +#define WEBSERVER_CONF_ROUTE_LINKS 0 +#define BUF_USES_STACK 1 + PROCESS(webserver_nogui_process, "Web server"); PROCESS_THREAD(webserver_nogui_process, ev, data) { @@ -92,11 +99,19 @@ AUTOSTART_PROCESSES(&border_router_process,&webserver_nogui_process); static const char *TOP = "ContikiRPL\n"; static const char *BOTTOM = "\n"; -static char buf[128]; +#if BUF_USES_STACK +static char *bufptr, *bufend; +#define ADD(...) do { \ + bufptr += snprintf(bufptr, bufend - bufptr, __VA_ARGS__); \ + } while(0) +#else +static char buf[256]; static int blen; #define ADD(...) do { \ blen += snprintf(&buf[blen], sizeof(buf) - blen, __VA_ARGS__); \ } while(0) +#endif + /*---------------------------------------------------------------------------*/ static void ipaddr_add(const uip_ipaddr_t *addr) @@ -106,15 +121,12 @@ ipaddr_add(const uip_ipaddr_t *addr) for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) { a = (addr->u8[i] << 8) + addr->u8[i + 1]; if(a == 0 && f >= 0) { - if(f++ == 0 && sizeof(buf) - blen >= 2) { - buf[blen++] = ':'; - buf[blen++] = ':'; - } + if(f++ == 0) ADD("::"); } else { if(f > 0) { f = -1; - } else if(i > 0 && blen < sizeof(buf)) { - buf[blen++] = ':'; + } else if(i > 0) { + ADD(":"); } ADD("%x", a); } @@ -125,46 +137,130 @@ static PT_THREAD(generate_routes(struct httpd_state *s)) { static int i; +#if BUF_USES_STACK + char buf[256]; +#endif +#if WEBSERVER_CONF_LOADTIME + static clock_time_t numticks; + numticks = clock_time(); +#endif + PSOCK_BEGIN(&s->sout); SEND_STRING(&s->sout, TOP); - +#if BUF_USES_STACK + bufptr = buf;bufend=bufptr+sizeof(buf); +#else blen = 0; +#endif ADD("Neighbors
");
   for(i = 0; i < UIP_DS6_NBR_NB; i++) {
     if(uip_ds6_nbr_cache[i].isused) {
+
+#if WEBSERVER_CONF_NEIGHBOR_STATUS
+#if BUF_USES_STACK
+{char* j=bufptr+25;
       ipaddr_add(&uip_ds6_nbr_cache[i].ipaddr);
+      while (bufptr < j) ADD(" ");
+      switch (uip_ds6_nbr_cache[i].state) {
+      case NBR_INCOMPLETE: ADD(" INCOMPLETE");break;
+      case NBR_REACHABLE: ADD(" REACHABLE");break;
+      case NBR_STALE: ADD(" STALE");break;      
+      case NBR_DELAY: ADD(" DELAY");break;
+      case NBR_PROBE: ADD(" NBR_PROBE");break;
+      }
+}
+#else
+{uint8_t j=blen+25;
+      ipaddr_add(&uip_ds6_nbr_cache[i].ipaddr);
+      while (blen < j) ADD(" ");
+      switch (uip_ds6_nbr_cache[i].state) {
+      case NBR_INCOMPLETE: ADD(" INCOMPLETE");break;
+      case NBR_REACHABLE: ADD(" REACHABLE");break;
+      case NBR_STALE: ADD(" STALE");break;      
+      case NBR_DELAY: ADD(" DELAY");break;
+      case NBR_PROBE: ADD(" NBR_PROBE");break;
+      }
+}
+#endif
+#else
+      ipaddr_add(&uip_ds6_nbr_cache[i].ipaddr);
+#endif
+
       ADD("\n");
+#if BUF_USES_STACK
+      if(bufptr > bufend - 45) {
+        SEND_STRING(&s->sout, buf);
+        bufptr = buf; bufend = bufptr + sizeof(buf);
+      }
+#else
       if(blen > sizeof(buf) - 45) {
         SEND_STRING(&s->sout, buf);
         blen = 0;
       }
+#endif
     }
   }
-
   ADD("
Routes
");
   SEND_STRING(&s->sout, buf);
+#if BUF_USES_STACK
+  bufptr = buf; bufend = bufptr + sizeof(buf);
+#else
   blen = 0;
+#endif
   for(i = 0; i < UIP_DS6_ROUTE_NB; i++) {
     if(uip_ds6_routing_table[i].isused) {
+#if BUF_USES_STACK
+#if WEBSERVER_CONF_ROUTE_LINKS
+      ADD("");
+      ipaddr_add(&uip_ds6_routing_table[i].ipaddr);
+      ADD("");
+#else
+      ipaddr_add(&uip_ds6_routing_table[i].ipaddr);
+#endif
+#else
+#if WEBSERVER_CONF_ROUTE_LINKS
+      ADD("");
+      SEND_STRING(&s->sout, buf); //TODO: why tunslip6 needs an output here, wpcapslip does not
+      blen = 0;
+      ipaddr_add(&uip_ds6_routing_table[i].ipaddr);
+      ADD("");
+#else
+      ipaddr_add(&uip_ds6_routing_table[i].ipaddr);
+#endif
+#endif
       ADD("/%u (via ", uip_ds6_routing_table[i].length);
       ipaddr_add(&uip_ds6_routing_table[i].nexthop);
-      if(uip_ds6_routing_table[i].state.lifetime < 600) {
+      if(1 || (uip_ds6_routing_table[i].state.lifetime < 600)) {
         ADD(") %lus\n", uip_ds6_routing_table[i].state.lifetime);
       } else {
         ADD(")\n");
       }
       SEND_STRING(&s->sout, buf);
+#if BUF_USES_STACK
+      bufptr = buf; bufend = bufptr + sizeof(buf);
+#else
       blen = 0;
+#endif
     }
   }
   ADD("
"); -//if(blen > 0) { - SEND_STRING(&s->sout, buf); -// blen = 0; -//} +#if WEBSERVER_CONF_FILESTATS + static uint16_t numtimes; + ADD("
This page sent %u times",++numtimes); +#endif + +#if WEBSERVER_CONF_LOADTIME + numticks = clock_time() - numticks + 1; + ADD(" (%u.%02u sec)",numticks/CLOCK_SECOND,(100*(numticks%CLOCK_SECOND))/CLOCK_SECOND)); +#endif + + SEND_STRING(&s->sout, buf); SEND_STRING(&s->sout, BOTTOM); PSOCK_END(&s->sout); @@ -173,6 +269,7 @@ PT_THREAD(generate_routes(struct httpd_state *s)) httpd_simple_script_t httpd_simple_get_script(const char *name) { + return generate_routes; } @@ -226,19 +323,26 @@ PROCESS_THREAD(border_router_process, ev, data) PROCESS_BEGIN(); +/* While waiting for the prefix to be sent through the SLIP connection, the future + * border router can join an existing DAG as a parent or child, or acquire a default + * router that will later take precedence over the SLIP fallback interface. + * Prevent that by turning the radio off until we are initialized as a DAG root. + */ prefix_set = 0; + NETSTACK_MAC.off(0); PROCESS_PAUSE(); SENSORS_ACTIVATE(button_sensor); PRINTF("RPL-Border router started\n"); - +#if 0 /* The border router runs with a 100% duty cycle in order to ensure high packet reception rates. Note if the MAC RDC is not turned off now, aggressive power management of the cpu will interfere with establishing the SLIP connection */ NETSTACK_MAC.off(1); +#endif /* Request prefix until it has been received */ while(!prefix_set) { @@ -253,6 +357,11 @@ PROCESS_THREAD(border_router_process, ev, data) PRINTF("created a new RPL dag\n"); } + /* Now turn the radio on, but disable radio duty cycling. + * Since we are the DAG root, reception delays would constrain mesh throughbut. + */ + NETSTACK_MAC.off(1); + #if DEBUG || 1 print_local_addresses(); #endif From 1637a807e2ef4ec2738aea28cce9cf2addde5dce Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Wed, 29 Feb 2012 16:45:05 -0800 Subject: [PATCH 15/15] fixed compilation error --- tools/tunslip6.c | 67 ++++++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/tools/tunslip6.c b/tools/tunslip6.c index 3b6a51601..4976ce72d 100644 --- a/tools/tunslip6.c +++ b/tools/tunslip6.c @@ -603,39 +603,44 @@ ifconf(const char *tundev, const char *ipaddr) #elif 1 /* Generate a link local address a la sixxs/aiccu */ /* First a full parse, stripping off the prefix length */ -{ -char lladdr[40]; -char c,*ptr=(char *)ipaddr; -uint16_t digit,ai,a[8],cc,scc,i; - for(ai=0;ai<8;ai++) a[ai]=0; - ai=0;cc=scc=0; - while(c=*ptr++) { - if(c=='/') break; - if(c==':') { - if(cc) scc = ai; - cc = 1; - if (++ai>7) break; - } else { - cc=0; - digit = c-'0'; if (digit > 9) digit = 10 + (c & 0xdf) - 'A'; - a[ai] = (a[ai] << 4) + digit; + { + char lladdr[40]; + char c, *ptr=(char *)ipaddr; + uint16_t digit,ai,a[8],cc,scc,i; + for(ai=0; ai<8; ai++) { + a[ai]=0; } - } - /* Get # elided and shift what's after to the end */ - cc=8-ai; - for(i=0;i7) break; + } else { + cc=0; + digit = c-'0'; + if (digit > 9) + digit = 10 + (c & 0xdf) - 'A'; + a[ai] = (a[ai] << 4) + digit; + } } + /* Get # elided and shift what's after to the end */ + cc=8-ai; + for(i=0;i