terence zhang / Mbed OS mbed-os-example-wakaama

Dependencies:   C12832 LM75B

Revision:
2:5a8853c481ad
Parent:
0:f9d13e09cf11
Child:
10:df97539c6ddd
--- a/wakaama/er-coap-13/er-coap-13.c	Fri Apr 28 08:16:22 2017 +0000
+++ b/wakaama/er-coap-13/er-coap-13.c	Fri Apr 28 09:53:26 2017 +0000
@@ -48,7 +48,7 @@
 
 #include "liblwm2m.h" /* for lwm2m_malloc() and lwm2m_free() */
 
-#define DEBUG 0
+#define DEBUG 1
 #if DEBUG
 #include <stdio.h>
 #define PRINTF(...) printf(__VA_ARGS__)
@@ -66,7 +66,7 @@
 static uint16_t current_mid = 0;
 
 coap_status_t coap_error_code = NO_ERROR;
-char *coap_error_message = "";
+const char *coap_error_message = "";
 /*-----------------------------------------------------------------------------------*/
 /*- LOCAL HELP FUNCTIONS ------------------------------------------------------------*/
 /*-----------------------------------------------------------------------------------*/
@@ -88,7 +88,7 @@
 coap_parse_int_option(uint8_t *bytes, size_t length)
 {
   uint32_t var = 0;
-  int i = 0;
+  size_t i = 0;
   while (i<length)
   {
     var <<= 8;
@@ -120,11 +120,11 @@
 coap_set_option_header(unsigned int delta, size_t length, uint8_t *buffer)
 {
   size_t written = 0;
+  unsigned int *x = &delta;
 
   buffer[0] = coap_option_nibble(delta)<<4 | coap_option_nibble(length);
 
   /* avoids code duplication without function overhead */
-  unsigned int *x = &delta;
   do
   {
     if (*x>268)
@@ -175,7 +175,7 @@
 
   if (split_char!='\0')
   {
-    int j;
+    size_t j;
     uint8_t *part_start = array;
     uint8_t *part_end = NULL;
     size_t temp_length;
@@ -231,7 +231,7 @@
 /*-----------------------------------------------------------------------------------*/
 static
 void
-coap_merge_multi_option(char **dst, size_t *dst_len, uint8_t *option, size_t option_len, char separator)
+coap_merge_multi_option(uint8_t **dst, size_t *dst_len, uint8_t *option, size_t option_len, char separator)
 {
   /* Merge multiple options. */
   if (*dst_len > 0)
@@ -248,12 +248,11 @@
   else
   {
     /* dst is empty: set to option */
-    *dst = (char *) option;
+    *dst = option;
     *dst_len = option_len;
   }
 }
 
-static
 void
 coap_add_multi_option(multi_option_t **dst, uint8_t *option, size_t option_len, uint8_t is_static)
 {
@@ -262,7 +261,7 @@
   if (opt)
   {
     opt->next = NULL;
-    opt->len = option_len;
+    opt->len = (uint8_t)option_len;
     if (is_static)
     {
       opt->data = option;
@@ -271,7 +270,7 @@
     else
     {
         opt->is_static = 0;
-        opt->data = (char *)lwm2m_malloc(option_len);
+        opt->data = (uint8_t *)lwm2m_malloc(option_len);
         if (opt->data == NULL)
         {
             lwm2m_free(opt);
@@ -296,13 +295,13 @@
   }
 }
 
-static
 void
 free_multi_option(multi_option_t *dst)
 {
   if (dst)
   {
     multi_option_t *n = dst->next;
+    dst->next = NULL;
     if (dst->is_static == 0)
     {
         lwm2m_free(dst->data);
@@ -345,11 +344,11 @@
 /*-----------------------------------------------------------------------------------*/
 static
 int
-coap_get_variable(const char *buffer, size_t length, const char *name, const char **output)
+coap_get_variable(const uint8_t *buffer, size_t length, const char *name, const char **output)
 {
-  const char *start = NULL;
-  const char *end = NULL;
-  const char *value_end = NULL;
+  const uint8_t *start = NULL;
+  const uint8_t *end = NULL;
+  const uint8_t *value_end = NULL;
   size_t name_len = 0;
 
   /*initialize the output buffer first*/
@@ -360,18 +359,18 @@
 
   for (start = buffer; start + name_len < end; ++start){
     if ((start == buffer || start[-1] == '&') && start[name_len] == '=' &&
-        strncmp(name, start, name_len)==0) {
+        strncmp(name, (char *)start, name_len)==0) {
 
       /* Point start to variable value */
       start += name_len + 1;
 
       /* Point end to the end of the value */
-      value_end = (const char *) memchr(start, '&', end - start);
+      value_end = (const uint8_t *) memchr(start, '&', end - start);
       if (value_end == NULL) {
         value_end = end;
       }
 
-      *output = start;
+      *output = (char *)start;
 
       return (value_end - start);
     }
@@ -410,6 +409,112 @@
     free_multi_option(coap_pkt->uri_path);
     free_multi_option(coap_pkt->uri_query);
     free_multi_option(coap_pkt->location_path);
+    coap_pkt->uri_path = NULL;
+    coap_pkt->uri_query = NULL;
+    coap_pkt->location_path = NULL;
+}
+
+/*-----------------------------------------------------------------------------------*/
+size_t coap_serialize_get_size(void *packet)
+{
+    coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
+    size_t length = 0;
+
+    length = COAP_HEADER_LEN + coap_pkt->payload_len + coap_pkt->token_len;
+
+    if (IS_OPTION(coap_pkt, COAP_OPTION_IF_MATCH))
+    {
+        length += COAP_MAX_OPTION_HEADER_LEN + coap_pkt->if_match_len;
+    }
+    if (IS_OPTION(coap_pkt, COAP_OPTION_URI_HOST))
+    {
+        length += COAP_MAX_OPTION_HEADER_LEN + coap_pkt->uri_host_len;
+    }
+    if (IS_OPTION(coap_pkt, COAP_OPTION_ETAG))
+    {
+        length += COAP_MAX_OPTION_HEADER_LEN + coap_pkt->etag_len;
+    }
+    if (IS_OPTION(coap_pkt, COAP_OPTION_IF_NONE_MATCH))
+    {
+        // can be stored in extended fields
+        length += COAP_MAX_OPTION_HEADER_LEN;
+    }
+    if (IS_OPTION(coap_pkt, COAP_OPTION_OBSERVE))
+    {
+        // can be stored in extended fields
+        length += COAP_MAX_OPTION_HEADER_LEN;
+    }
+    if (IS_OPTION(coap_pkt, COAP_OPTION_URI_PORT))
+    {
+        // can be stored in extended fields
+        length += COAP_MAX_OPTION_HEADER_LEN;
+    }
+    if (IS_OPTION(coap_pkt, COAP_OPTION_LOCATION_PATH))
+    {
+        multi_option_t * optP;
+
+        for (optP = coap_pkt->location_path ; optP != NULL ; optP = optP->next)
+        {
+            length += COAP_MAX_OPTION_HEADER_LEN + optP->len;
+        }
+    }
+    if (IS_OPTION(coap_pkt, COAP_OPTION_URI_PATH))
+    {
+        multi_option_t * optP;
+
+        for (optP = coap_pkt->uri_path ; optP != NULL ; optP = optP->next)
+        {
+            length += COAP_MAX_OPTION_HEADER_LEN + optP->len;
+        }
+    }
+    if (IS_OPTION(coap_pkt, COAP_OPTION_CONTENT_TYPE))
+    {
+        // can be stored in extended fields
+        length += COAP_MAX_OPTION_HEADER_LEN;
+    }
+    if (IS_OPTION(coap_pkt, COAP_OPTION_MAX_AGE))
+    {
+        // can be stored in extended fields
+        length += COAP_MAX_OPTION_HEADER_LEN;
+    }
+    if (IS_OPTION(coap_pkt, COAP_OPTION_URI_QUERY))
+    {
+        multi_option_t * optP;
+
+        for (optP = coap_pkt->uri_query ; optP != NULL ; optP = optP->next)
+        {
+            length += COAP_MAX_OPTION_HEADER_LEN + optP->len;
+        }
+    }
+    if (IS_OPTION(coap_pkt, COAP_OPTION_ACCEPT))
+    {
+        length += coap_pkt->accept_num * COAP_MAX_OPTION_HEADER_LEN;
+    }
+    if (IS_OPTION(coap_pkt, COAP_OPTION_LOCATION_QUERY))
+    {
+        length += COAP_MAX_OPTION_HEADER_LEN + coap_pkt->location_query_len;
+    }
+    if (IS_OPTION(coap_pkt, COAP_OPTION_BLOCK2))
+    {
+        // can be stored in extended fields
+        length += COAP_MAX_OPTION_HEADER_LEN;
+    }
+    if (IS_OPTION(coap_pkt, COAP_OPTION_BLOCK1))
+    {
+        // can be stored in extended fields
+        length += COAP_MAX_OPTION_HEADER_LEN;
+    }
+    if (IS_OPTION(coap_pkt, COAP_OPTION_SIZE))
+    {
+        // can be stored in extended fields
+        length += COAP_MAX_OPTION_HEADER_LEN;
+    }
+    if (IS_OPTION(coap_pkt, COAP_OPTION_PROXY_URI))
+    {
+        length += COAP_MAX_OPTION_HEADER_LEN + coap_pkt->proxy_uri_len;
+    }
+
+    return length;
 }
 
 /*-----------------------------------------------------------------------------------*/
@@ -476,24 +581,14 @@
   coap_free_header(packet);
 
   /* Pack payload */
-  if ((option - coap_pkt->buffer)<=COAP_MAX_HEADER_SIZE)
+  /* Payload marker */
+  if (coap_pkt->payload_len)
   {
-    /* Payload marker */
-    if (coap_pkt->payload_len)
-    {
-      *option = 0xFF;
-      ++option;
-    }
+    *option = 0xFF;
+    ++option;
+  }
 
-    memmove(option, coap_pkt->payload, coap_pkt->payload_len);
-  }
-  else
-  {
-    /* An error occured. Caller must check for !=0. */
-    coap_pkt->buffer = NULL;
-    coap_error_message = "Serialized header exceeds COAP_MAX_HEADER_SIZE";
-    return 0;
-  }
+  memmove(option, coap_pkt->payload, coap_pkt->payload_len);
 
   PRINTF("-Done %u B (header len %u, payload len %u)-\n", coap_pkt->payload_len + option - buffer, option - buffer, coap_pkt->payload_len);
 
@@ -515,6 +610,11 @@
 coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
 {
   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
+  uint8_t *current_option;
+  unsigned int option_number = 0;
+  unsigned int option_delta = 0;
+  size_t option_length = 0;
+  unsigned int *x;
 
   /* Initialize packet */
   memset(coap_pkt, 0, sizeof(coap_packet_t));
@@ -535,7 +635,7 @@
     return BAD_REQUEST_4_00;
   }
 
-  uint8_t *current_option = data + COAP_HEADER_LEN;
+  current_option = data + COAP_HEADER_LEN;
 
   if (coap_pkt->token_len != 0)
   {
@@ -557,10 +657,6 @@
   /* parse options */
   current_option += coap_pkt->token_len;
 
-  unsigned int option_number = 0;
-  unsigned int option_delta = 0;
-  size_t option_length = 0;
-
   while (current_option < data+data_len)
   {
     /* Payload marker 0xFF, currently only checking for 0xF* because rest is reserved */
@@ -569,12 +665,6 @@
       coap_pkt->payload = ++current_option;
       coap_pkt->payload_len = data_len - (coap_pkt->payload - data);
 
-      /* also for receiving, the Erbium upper bound is REST_MAX_CHUNK_SIZE */
-      if (coap_pkt->payload_len > REST_MAX_CHUNK_SIZE)
-      {
-        coap_pkt->payload_len = REST_MAX_CHUNK_SIZE;
-      }
-
       break;
     }
 
@@ -583,7 +673,7 @@
     ++current_option;
 
     /* avoids code duplication without function overhead */
-    unsigned int *x = &option_delta;
+    x = &option_delta;
     do
     {
       if (*x==13)
@@ -604,7 +694,15 @@
 
     option_number += option_delta;
 
-    PRINTF("OPTION %u (delta %u, len %u): ", option_number, option_delta, option_length);
+    if (current_option + option_length > data + data_len)
+    {
+        PRINTF("OPTION %u (delta %u, len %u) has invalid length.\n", option_number, option_delta, option_length);
+        return BAD_REQUEST_4_00;
+    }
+    else
+    {
+        PRINTF("OPTION %u (delta %u, len %u): ", option_number, option_delta, option_length);
+    }
 
     SET_OPTION(coap_pkt, option_number);
 
@@ -619,7 +717,7 @@
         PRINTF("Max-Age [%lu]\n", coap_pkt->max_age);
         break;
       case COAP_OPTION_ETAG:
-        coap_pkt->etag_len = MIN(COAP_ETAG_LEN, option_length);
+        coap_pkt->etag_len = (uint8_t)(MIN(COAP_ETAG_LEN, option_length));
         memcpy(coap_pkt->etag, current_option, coap_pkt->etag_len);
         PRINTF("ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", coap_pkt->etag_len,
           coap_pkt->etag[0],
@@ -642,7 +740,7 @@
         break;
       case COAP_OPTION_IF_MATCH:
         /*FIXME support multiple ETags */
-        coap_pkt->if_match_len = MIN(COAP_ETAG_LEN, option_length);
+        coap_pkt->if_match_len = (uint8_t)(MIN(COAP_ETAG_LEN, option_length));
         memcpy(coap_pkt->if_match, current_option, coap_pkt->if_match_len);
         PRINTF("If-Match %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", coap_pkt->if_match_len,
           coap_pkt->if_match[0],
@@ -661,7 +759,7 @@
         break;
 
       case COAP_OPTION_URI_HOST:
-        coap_pkt->uri_host = (char *) current_option;
+        coap_pkt->uri_host = current_option;
         coap_pkt->uri_host_len = option_length;
         PRINTF("Uri-Host [%.*s]\n", coap_pkt->uri_host_len, coap_pkt->uri_host);
         break;
@@ -673,13 +771,13 @@
         /* 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_path), &(coap_pkt->uri_path_len), current_option, option_length, 0);
         coap_add_multi_option( &(coap_pkt->uri_path), current_option, option_length, 1);
-        PRINTF("Uri-Path [%.*s]\n", sizeof(multi_option_t), coap_pkt->uri_path);
+        PRINTF("Uri-Path [%.*s]\n", option_length, current_option);
         break;
       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( (char **) &(coap_pkt->uri_query), &(coap_pkt->uri_query_len), current_option, option_length, '&');
         coap_add_multi_option( &(coap_pkt->uri_query), current_option, option_length, 1);
-        PRINTF("Uri-Query [%.*s]\n", sizeof(multi_option_t), coap_pkt->uri_query);
+        PRINTF("Uri-Query [%.*s]\n", option_length, current_option);
         break;
 
       case COAP_OPTION_LOCATION_PATH:
@@ -687,13 +785,13 @@
         break;
       case COAP_OPTION_LOCATION_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( (char **) &(coap_pkt->location_query), &(coap_pkt->location_query_len), current_option, option_length, '&');
-        PRINTF("Location-Query [%.*s]\n", coap_pkt->location_query_len, coap_pkt->location_query);
+        coap_merge_multi_option( &(coap_pkt->location_query), &(coap_pkt->location_query_len), current_option, option_length, '&');
+        PRINTF("Location-Query [%.*s]\n", option_length, current_option);
         break;
 
       case COAP_OPTION_PROXY_URI:
         /*FIXME check for own end-point */
-        coap_pkt->proxy_uri = (char *) current_option;
+        coap_pkt->proxy_uri = current_option;
         coap_pkt->proxy_uri_len = option_length;
         /*TODO length > 270 not implemented (actually not required) */
         PRINTF("Proxy-Uri NOT IMPLEMENTED [%.*s]\n", coap_pkt->proxy_uri_len, coap_pkt->proxy_uri);
@@ -765,7 +863,7 @@
   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
 
   if (coap_pkt->payload_len) {
-    return coap_get_variable((const char *)coap_pkt->payload, coap_pkt->payload_len, name, output);
+    return coap_get_variable(coap_pkt->payload, coap_pkt->payload_len, name, output);
   }
   return 0;
 }
@@ -871,7 +969,7 @@
 {
   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
 
-  coap_pkt->etag_len = MIN(COAP_ETAG_LEN, etag_len);
+  coap_pkt->etag_len = (uint8_t)(MIN(COAP_ETAG_LEN, etag_len));
   memcpy(coap_pkt->etag, etag, coap_pkt->etag_len);
 
   SET_OPTION(coap_pkt, COAP_OPTION_ETAG);
@@ -895,7 +993,7 @@
 {
   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
 
-  coap_pkt->if_match_len = MIN(COAP_ETAG_LEN, etag_len);
+  coap_pkt->if_match_len = (uint8_t)(MIN(COAP_ETAG_LEN, etag_len));
   memcpy(coap_pkt->if_match, etag, coap_pkt->if_match_len);
 
   SET_OPTION(coap_pkt, COAP_OPTION_IF_MATCH);
@@ -931,7 +1029,7 @@
 {
   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
 
-  coap_pkt->token_len = MIN(COAP_TOKEN_LEN, token_len);
+  coap_pkt->token_len = (uint8_t)(MIN(COAP_TOKEN_LEN, token_len));
   memcpy(coap_pkt->token, token, coap_pkt->token_len);
 
   SET_OPTION(coap_pkt, COAP_OPTION_TOKEN);
@@ -945,7 +1043,7 @@
 
   if (!IS_OPTION(coap_pkt, COAP_OPTION_PROXY_URI)) return 0;
 
-  *uri = coap_pkt->proxy_uri;
+  *uri = (const char *)coap_pkt->proxy_uri;
   return coap_pkt->proxy_uri_len;
 }
 
@@ -954,7 +1052,7 @@
 {
   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
 
-  coap_pkt->proxy_uri = uri;
+  coap_pkt->proxy_uri = (uint8_t *)uri;
   coap_pkt->proxy_uri_len = strlen(uri);
 
   SET_OPTION(coap_pkt, COAP_OPTION_PROXY_URI);
@@ -968,7 +1066,7 @@
 
   if (!IS_OPTION(coap_pkt, COAP_OPTION_URI_HOST)) return 0;
 
-  *host = coap_pkt->uri_host;
+  *host = (char *)coap_pkt->uri_host;
   return coap_pkt->uri_host_len;
 }
 
@@ -977,7 +1075,7 @@
 {
   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
 
-  coap_pkt->uri_host = host;
+  coap_pkt->uri_host = (uint8_t *)host;
   coap_pkt->uri_host_len = strlen(host);
 
   SET_OPTION(coap_pkt, COAP_OPTION_URI_HOST);
@@ -1126,18 +1224,18 @@
 
   if (!IS_OPTION(coap_pkt, COAP_OPTION_LOCATION_QUERY)) return 0;
 
-  *query = coap_pkt->location_query;
+  *query = (const char*)coap_pkt->location_query;
   return coap_pkt->location_query_len;
 }
 
 int
-coap_set_header_location_query(void *packet, const char *query)
+coap_set_header_location_query(void *packet, char *query)
 {
   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
 
   while (query[0]=='?') ++query;
 
-  coap_pkt->location_query = query;
+  coap_pkt->location_query = (uint8_t *)query;
   coap_pkt->location_query_len = strlen(query);
 
   SET_OPTION(coap_pkt, COAP_OPTION_LOCATION_QUERY);
@@ -1273,10 +1371,8 @@
 {
   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
 
-  //PRINTF("setting payload (%u/%u)\n", length, REST_MAX_CHUNK_SIZE);
-
   coap_pkt->payload = (uint8_t *) payload;
-  coap_pkt->payload_len = MIN(REST_MAX_CHUNK_SIZE, length);
+  coap_pkt->payload_len = (uint16_t)(length);
 
   return coap_pkt->payload_len;
 }