[JIRA IOT-738] fixed to calculate message length for option
authorjihwan.seo <jihwan.seo@samsung.com>
Wed, 23 Sep 2015 07:59:36 +0000 (16:59 +0900)
committerPatrick Lankswert <patrick.lankswert@intel.com>
Fri, 25 Sep 2015 18:36:28 +0000 (18:36 +0000)
message length in Header is wrong
for long option number and value for CoAP over TCP

Change-Id: I72452c07e2b5ffe43749cae5c3a4bae6d7c2f3f2
Signed-off-by: jihwan.seo <jihwan.seo@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/2985
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Patrick Lankswert <patrick.lankswert@intel.com>
(cherry picked from commit c77eae61f8232159e9d1e0e23b46f6cfb2ea4b5e)
Reviewed-on: https://gerrit.iotivity.org/gerrit/3049

resource/csdk/connectivity/inc/caprotocolmessage.h
resource/csdk/connectivity/lib/libcoap-4.1.1/pdu.c
resource/csdk/connectivity/lib/libcoap-4.1.1/pdu.h
resource/csdk/connectivity/src/caprotocolmessage.c

index c80d87b..1da4209 100644 (file)
@@ -48,6 +48,8 @@ typedef uint32_t code_t;
 #define HAVE_TIME_H 1
 #endif
 
+static const uint8_t PAYLOAD_MARKER = 1;
+
 /**
  * generates pdu structure from the given information.
  * @param[in]   code                 code of the pdu packet.
index 857fba5..b5dd712 100644 (file)
@@ -421,6 +421,53 @@ unsigned int coap_get_tcp_header_length_for_transport(coap_transport_type transp
     return length;
 }
 
+size_t coap_get_opt_header_length(unsigned short key, size_t length)
+{
+    size_t headerLength = 0;
+
+    unsigned short optDeltaLength = 0;
+    if (COAP_OPTION_FIELD_8_BIT >= key)
+    {
+        optDeltaLength = 0;
+    }
+    else if (COAP_OPTION_FIELD_8_BIT < key && COAP_OPTION_FIELD_16_BIT >= key)
+    {
+        optDeltaLength = 1;
+    }
+    else if (COAP_OPTION_FIELD_16_BIT < key && COAP_OPTION_FIELD_32_BIT >= key)
+    {
+        optDeltaLength = 2;
+    }
+    else
+    {
+        printf("Error : Reserved for the Payload marker for Delta");
+        return 0;
+    }
+
+    size_t optLength = 0;
+    if (COAP_OPTION_FIELD_8_BIT >= length)
+    {
+        optLength = 0;
+    }
+    else if (COAP_OPTION_FIELD_8_BIT < length && COAP_OPTION_FIELD_16_BIT >= length)
+    {
+        optLength = 1;
+    }
+    else if (COAP_OPTION_FIELD_16_BIT < length && COAP_OPTION_FIELD_32_BIT >= length)
+    {
+        optLength = 2;
+    }
+    else
+    {
+        printf("Error : Reserved for the Payload marker for length");
+        return 0;
+    }
+
+    headerLength = length + optDeltaLength + optLength + 1;
+
+    return headerLength;
+}
+
 #endif
 
 void coap_add_code(const coap_pdu_t *pdu, coap_transport_type transport, unsigned int code)
index 77dd6f6..b8cc1ea 100644 (file)
@@ -178,6 +178,10 @@ typedef int coap_tid_t;
 #define COAP_TCP_LENGTH_FIELD_NUM_16_BIT     14
 #define COAP_TCP_LENGTH_FIELD_NUM_32_BIT     15
 
+#define COAP_OPTION_FIELD_8_BIT      12
+#define COAP_OPTION_FIELD_16_BIT     256
+#define COAP_OPTION_FIELD_32_BIT     65536
+
 typedef enum
 {
     coap_udp = 0,
@@ -462,6 +466,15 @@ unsigned int coap_get_tcp_header_length(unsigned char *data);
  * @return header length.
  */
 unsigned int coap_get_tcp_header_length_for_transport(coap_transport_type transport);
+
+/**
+ * Get option length.
+ *
+ * @param key      delta of option
+ * @param length   length of option
+ * @return total option length
+ */
+size_t coap_get_opt_header_length(unsigned short key, size_t length);
 #endif
 
 /**
index e3fbe3c..67dbdba 100644 (file)
@@ -295,23 +295,42 @@ coap_pdu_t *CAGeneratePDUImpl(code_t code, const CAInfo_t *info,
     coap_transport_type transport;
     unsigned int length = COAP_MAX_PDU_SIZE;
 #ifdef TCP_ADAPTER
-    unsigned int headerLength = 0;
+    unsigned int msgLength = 0;
     if (CA_ADAPTER_TCP == endpoint->adapter)
     {
         if (options)
         {
+            unsigned short prevOptNumber = 0;
             for (coap_list_t *opt = options; opt; opt = opt->next)
             {
-                headerLength += COAP_OPTION_LENGTH(*(coap_option *) opt->data) + 1;
+                unsigned short curOptNumber = COAP_OPTION_KEY(*(coap_option *) opt->data);
+                if (prevOptNumber > curOptNumber)
+                {
+                    OIC_LOG(ERROR, TAG, "option list is wrong");
+                    return NULL;
+                }
+
+                size_t optValueLen = COAP_OPTION_LENGTH(*(coap_option *) opt->data);
+                size_t optLength = coap_get_opt_header_length(curOptNumber - prevOptNumber, optValueLen);
+                if (0 == optLength)
+                {
+                    OIC_LOG(ERROR, TAG, "Reserved for the Payload marker for the option");
+                    return NULL;
+                }
+                msgLength += optLength;
+                prevOptNumber = curOptNumber;
+                OIC_LOG_V(DEBUG, TAG, "curOptNumber[%d], prevOptNumber[%d], optValueLen[%d], "
+                        "optLength[%d], msgLength[%d]",
+                          curOptNumber, prevOptNumber, optValueLen, optLength, msgLength);
             }
         }
 
         if (info->payloadSize > 0)
         {
-            headerLength = headerLength + info->payloadSize + 1;
+            msgLength = msgLength + info->payloadSize + PAYLOAD_MARKER;
         }
-        transport = coap_get_tcp_header_type_from_size(headerLength);
-        length = headerLength + coap_get_tcp_header_length_for_transport(transport)
+        transport = coap_get_tcp_header_type_from_size(msgLength);
+        length = msgLength + coap_get_tcp_header_length_for_transport(transport)
                 + info->tokenLength;
     }
     else
@@ -334,7 +353,7 @@ coap_pdu_t *CAGeneratePDUImpl(code_t code, const CAInfo_t *info,
 #ifdef TCP_ADAPTER
     if (CA_ADAPTER_TCP == endpoint->adapter)
     {
-        coap_add_length(pdu, transport, headerLength);
+        coap_add_length(pdu, transport, msgLength);
     }
     else
 #endif