base code related to coap header of 'CoAP Over TCP' in libcoap.
[platform/upstream/iotivity.git] / resource / csdk / connectivity / lib / libcoap-4.1.1 / pdu.c
index d246654..f1847d8 100644 (file)
@@ -44,17 +44,25 @@ coap_pdu_resources_init()
 #include "mem.h"
 #endif /* WITH_CONTIKI */
 
-void coap_pdu_clear(coap_pdu_t *pdu, size_t size)
+void coap_pdu_clear(coap_pdu_t *pdu, size_t size, coap_transport_type transport, unsigned int length)
 {
     assert(pdu);
 
     memset(pdu, 0, sizeof(coap_pdu_t) + size);
     pdu->max_size = size;
     pdu->hdr = (coap_hdr_t *) ((unsigned char *) pdu + sizeof(coap_pdu_t));
-    pdu->hdr->version = COAP_DEFAULT_VERSION;
 
-    /* data is NULL unless explicitly set by coap_add_data() */
-    pdu->length = sizeof(coap_hdr_t);
+    if (coap_udp == transport)
+    {
+        pdu->hdr->coap_hdr_udp_t.version = COAP_DEFAULT_VERSION;
+        /* data is NULL unless explicitly set by coap_add_data() */
+        pdu->length = sizeof(pdu->hdr->coap_hdr_udp_t);
+    }
+    else
+    {
+        /* data is NULL unless explicitly set by coap_add_data() */
+        pdu->length = length;
+    }
 }
 
 #ifdef WITH_LWIP
@@ -84,16 +92,39 @@ coap_pdu_from_pbuf(struct pbuf *pbuf)
 #endif
 
 coap_pdu_t *
-coap_pdu_init(unsigned char type, unsigned char code, unsigned short id, size_t size)
+coap_pdu_init(unsigned char type, unsigned char code, unsigned short id,
+              size_t size, coap_transport_type transport)
 {
     coap_pdu_t *pdu;
 #ifdef WITH_LWIP
     struct pbuf *p;
 #endif
 
+    unsigned int length = 0;
+    switch(transport)
+    {
+        case coap_udp:
+            length = sizeof(pdu->hdr->coap_hdr_udp_t);
+            break;
+        case coap_tcp:
+            length = COAP_TCP_HEADER_NO_FIELD;
+            break;
+        case coap_tcp_8bit:
+            length = COAP_TCP_HEADER_8_BIT;
+            break;
+        case coap_tcp_16bit:
+            length = COAP_TCP_HEADER_16_BIT;
+            break;
+        case coap_tcp_32bit:
+            length = COAP_TCP_HEADER_32_BIT;
+            break;
+        default:
+            debug("it has wrong type\n");
+    }
+
     assert(size <= COAP_MAX_PDU_SIZE);
     /* Size must be large enough to fit the header. */
-    if (size < sizeof(coap_hdr_t) || size > COAP_MAX_PDU_SIZE)
+    if (size < length || size > COAP_MAX_PDU_SIZE)
         return NULL;
 
     /* size must be large enough for hdr */
@@ -120,10 +151,37 @@ coap_pdu_init(unsigned char type, unsigned char code, unsigned short id, size_t
 #endif
     if (pdu)
     {
-        coap_pdu_clear(pdu, size);
-        pdu->hdr->id = id;
-        pdu->hdr->type = type;
-        pdu->hdr->code = code;
+        coap_pdu_clear(pdu, size, transport, length);
+
+        switch(transport)
+        {
+            case coap_udp:
+                pdu->hdr->coap_hdr_udp_t.id = id;
+                pdu->hdr->coap_hdr_udp_t.type = type;
+                pdu->hdr->coap_hdr_udp_t.code = code;
+                break;
+            case coap_tcp:
+                pdu->hdr->coap_hdr_tcp_t.message_length = 0;
+                pdu->hdr->coap_hdr_tcp_t.code = code;
+                break;
+            case coap_tcp_8bit:
+                pdu->hdr->coap_hdr_tcp_8bit_t.message_length = COAP_TCP_LENGTH_FIELD_NUM_8_BIT;
+                pdu->hdr->coap_hdr_tcp_8bit_t.length_byte = 0;
+                pdu->hdr->coap_hdr_tcp_8bit_t.code = code;
+                break;
+            case coap_tcp_16bit:
+                pdu->hdr->coap_hdr_tcp_16bit_t.message_length = COAP_TCP_LENGTH_FIELD_NUM_16_BIT;
+                pdu->hdr->coap_hdr_tcp_16bit_t.length_byte = 0;
+                pdu->hdr->coap_hdr_tcp_16bit_t.code = code;
+                break;
+            case coap_tcp_32bit:
+                pdu->hdr->coap_hdr_tcp_32bit_t.header_data[0] = COAP_TCP_LENGTH_FIELD_NUM_32_BIT << 4;
+                pdu->hdr->coap_hdr_tcp_32bit_t.header_data[5] = code;
+                break;
+            default:
+                debug("it has wrong type\n");
+        }
+
 #ifdef WITH_LWIP
         pdu->pbuf = p;
 #endif
@@ -132,14 +190,16 @@ coap_pdu_init(unsigned char type, unsigned char code, unsigned short id, size_t
 }
 
 coap_pdu_t *
-coap_new_pdu()
+coap_new_pdu(coap_transport_type transport)
 {
     coap_pdu_t *pdu;
 
 #ifndef WITH_CONTIKI
-    pdu = coap_pdu_init(0, 0, ntohs(COAP_INVALID_TID), COAP_MAX_PDU_SIZE);
+    pdu = coap_pdu_init(0, 0,
+                        ntohs(COAP_INVALID_TID),
+                        COAP_MAX_PDU_SIZE, transport);
 #else /* WITH_CONTIKI */
-    pdu = coap_pdu_init(0, 0, uip_ntohs(COAP_INVALID_TID), COAP_MAX_PDU_SIZE);
+    pdu = coap_pdu_init(0, 0, uip_ntohs(COAP_INVALID_TID), COAP_MAX_PDU_SIZE, transport);
 #endif /* WITH_CONTIKI */
 
 #ifndef NDEBUG
@@ -163,26 +223,256 @@ void coap_delete_pdu(coap_pdu_t *pdu)
 #endif
 }
 
-int coap_add_token(coap_pdu_t *pdu, size_t len, const unsigned char *data)
+coap_transport_type coap_get_tcp_header_type_from_size(unsigned int size)
+{
+    if (COAP_TCP_LENGTH_LIMIT_8_BIT < size && COAP_TCP_LENGTH_LIMIT_16_BIT >= size)
+    {
+        return coap_tcp_8bit;
+    }
+    else if (COAP_TCP_LENGTH_LIMIT_16_BIT < size && COAP_TCP_LENGTH_LIMIT_32_BIT >= size)
+    {
+        return coap_tcp_16bit;
+    }
+    else if (COAP_TCP_LENGTH_LIMIT_32_BIT < size)
+    {
+        return coap_tcp_32bit;
+    }
+    else
+    {
+        return coap_tcp;
+    }
+}
+
+coap_transport_type coap_get_tcp_header_type_from_initbyte(unsigned int length)
+{
+    coap_transport_type type;
+    switch(length)
+    {
+        case COAP_TCP_LENGTH_FIELD_NUM_8_BIT:
+            type = coap_tcp_8bit;
+            break;
+        case COAP_TCP_LENGTH_FIELD_NUM_16_BIT:
+            type = coap_tcp_16bit;
+            break;
+        case COAP_TCP_LENGTH_FIELD_NUM_32_BIT:
+            type = coap_tcp_32bit;
+            break;
+        default:
+            type = coap_tcp;
+    }
+    return type;
+}
+
+void coap_add_length(const coap_pdu_t *pdu, coap_transport_type transport, unsigned int length)
+{
+    assert(pdu);
+
+    switch(transport)
+    {
+        case coap_tcp_8bit:
+            if (length > COAP_TCP_LENGTH_FIELD_8_BIT)
+            {
+                pdu->hdr->coap_hdr_tcp_8bit_t.length_byte =
+                        length - COAP_TCP_LENGTH_FIELD_8_BIT;
+            }
+            break;
+        case coap_tcp_16bit:
+            if (length > COAP_TCP_LENGTH_FIELD_16_BIT)
+            {
+                pdu->hdr->coap_hdr_tcp_16bit_t.length_byte =
+                        length - COAP_TCP_LENGTH_FIELD_16_BIT;
+            }
+            break;
+        case coap_tcp_32bit:
+            if (length > COAP_TCP_LENGTH_FIELD_32_BIT)
+            {
+                unsigned int total_length = length - COAP_TCP_LENGTH_FIELD_32_BIT;
+                pdu->hdr->coap_hdr_tcp_32bit_t.header_data[1] = total_length >> 24;
+                pdu->hdr->coap_hdr_tcp_32bit_t.header_data[2] = (total_length >> 16) & 0x00ff;
+                pdu->hdr->coap_hdr_tcp_32bit_t.header_data[3] = (total_length >> 8) & 0x0000ff;
+                pdu->hdr->coap_hdr_tcp_32bit_t.header_data[4] = total_length & 0x000000ff;
+            }
+            break;
+        default:
+            debug("it has wrong type\n");
+    }
+}
+
+unsigned int coap_get_length(const coap_pdu_t *pdu, coap_transport_type transport)
+{
+    assert(pdu);
+
+    unsigned int length = 0;
+    unsigned int length_field_data = 0;
+    switch(transport)
+    {
+        case coap_tcp_8bit:
+            length = pdu->hdr->coap_hdr_tcp_8bit_t.length_byte + COAP_TCP_LENGTH_FIELD_8_BIT;
+            break;
+        case coap_tcp_16bit:
+            length_field_data =
+                    ((unsigned char *)(&pdu->hdr->coap_hdr_tcp_16bit_t))[2] << 8 |
+                    ((unsigned char *)(&pdu->hdr->coap_hdr_tcp_16bit_t))[1];
+            length = length_field_data + COAP_TCP_LENGTH_FIELD_16_BIT;
+            break;
+        case coap_tcp_32bit:
+            length_field_data =
+                    pdu->hdr->coap_hdr_tcp_32bit_t.header_data[1] << 24 |
+                    pdu->hdr->coap_hdr_tcp_32bit_t.header_data[2] << 16 |
+                    pdu->hdr->coap_hdr_tcp_32bit_t.header_data[3] << 8 |
+                    pdu->hdr->coap_hdr_tcp_32bit_t.header_data[4];
+            length = length_field_data + COAP_TCP_LENGTH_FIELD_32_BIT;
+            break;
+        default:
+            debug("it has wrong type\n");
+    }
+
+    return length;
+}
+
+void coap_add_code(const coap_pdu_t *pdu, coap_transport_type transport, unsigned int code)
+{
+    assert(pdu);
+
+    switch(transport)
+    {
+        case coap_udp:
+            pdu->hdr->coap_hdr_udp_t.code = COAP_RESPONSE_CODE(code);
+            break;
+        case coap_tcp:
+            pdu->hdr->coap_hdr_tcp_t.code = COAP_RESPONSE_CODE(code);
+            break;
+        case coap_tcp_8bit:
+            pdu->hdr->coap_hdr_tcp_8bit_t.code = COAP_RESPONSE_CODE(code);
+            break;
+        case coap_tcp_16bit:
+            pdu->hdr->coap_hdr_tcp_16bit_t.code = COAP_RESPONSE_CODE(code);
+            break;
+        case coap_tcp_32bit:
+            pdu->hdr->coap_hdr_tcp_32bit_t.header_data[5] = COAP_RESPONSE_CODE(code);
+            break;
+        default:
+            debug("it has wrong type\n");
+    }
+}
+
+unsigned int coap_get_code(const coap_pdu_t *pdu, coap_transport_type transport)
+{
+    assert(pdu);
+
+    unsigned int code = 0;
+    switch(transport)
+    {
+        case coap_udp:
+            code = pdu->hdr->coap_hdr_udp_t.code;
+            break;
+        case coap_tcp:
+            code = pdu->hdr->coap_hdr_tcp_t.code;
+            break;
+        case coap_tcp_8bit:
+            code = pdu->hdr->coap_hdr_tcp_8bit_t.code;
+            break;
+        case coap_tcp_16bit:
+            code = pdu->hdr->coap_hdr_tcp_16bit_t.code;
+            break;
+        case coap_tcp_32bit:
+            code = pdu->hdr->coap_hdr_tcp_32bit_t.header_data[5];
+            break;
+        default:
+            debug("it has wrong type\n");
+    }
+    return code;
+}
+
+int coap_add_token(coap_pdu_t *pdu, size_t len, const unsigned char *data,
+                   coap_transport_type transport)
 {
     const size_t HEADERLENGTH = len + 4;
     /* must allow for pdu == NULL as callers may rely on this */
     if (!pdu || len > 8 || pdu->max_size < HEADERLENGTH)
         return 0;
 
-    pdu->hdr->token_length = len;
+    unsigned char* token = NULL;
+    switch(transport)
+    {
+        case coap_udp:
+            pdu->hdr->coap_hdr_udp_t.token_length = len;
+            token = pdu->hdr->coap_hdr_udp_t.token;
+            pdu->length = HEADERLENGTH;
+            break;
+        case coap_tcp:
+            pdu->hdr->coap_hdr_tcp_t.token_length = len;
+            token = pdu->hdr->coap_hdr_tcp_t.token;
+            pdu->length = HEADERLENGTH;
+            break;
+        case coap_tcp_8bit:
+            pdu->hdr->coap_hdr_tcp_8bit_t.token_length = len;
+            token = pdu->hdr->coap_hdr_tcp_8bit_t.token;
+            pdu->length = HEADERLENGTH;
+            break;
+        case coap_tcp_16bit:
+            pdu->hdr->coap_hdr_tcp_16bit_t.token_length = len;
+            token = pdu->hdr->coap_hdr_tcp_16bit_t.token;
+            pdu->length = HEADERLENGTH;
+            break;
+        case coap_tcp_32bit:
+            pdu->hdr->coap_hdr_tcp_32bit_t.header_data[0] =
+                    pdu->hdr->coap_hdr_tcp_32bit_t.header_data[0] | len;
+            token = pdu->hdr->coap_hdr_tcp_32bit_t.token;
+            pdu->length = len + COAP_TCP_HEADER_32_BIT;
+            break;
+        default:
+            debug("it has wrong type\n");
+    }
+
     if (len)
-        memcpy(pdu->hdr->token, data, len);
+    {
+        memcpy(token, data, len);
+    }
+
     pdu->max_delta = 0;
-    pdu->length = HEADERLENGTH;
     pdu->data = NULL;
 
     return 1;
 }
 
+void coap_get_token(const coap_hdr_t *pdu_hdr, coap_transport_type transport,
+                    unsigned char **token, unsigned int *token_length)
+{
+    assert(pdu);
+    assert(token);
+    assert(token_length);
+
+    switch(transport)
+    {
+        case coap_udp:
+            *token_length = pdu_hdr->coap_hdr_udp_t.token_length;
+            *token = (unsigned char *)pdu_hdr->coap_hdr_udp_t.token;
+            break;
+        case coap_tcp:
+            *token_length = pdu_hdr->coap_hdr_tcp_t.token_length;
+            *token = (unsigned char *)pdu_hdr->coap_hdr_tcp_t.token;
+            break;
+        case coap_tcp_8bit:
+            *token_length = pdu_hdr->coap_hdr_tcp_8bit_t.token_length;
+            *token = (unsigned char *)pdu_hdr->coap_hdr_tcp_8bit_t.token;
+            break;
+        case coap_tcp_16bit:
+            *token_length = pdu_hdr->coap_hdr_tcp_16bit_t.token_length;
+            *token = (unsigned char *)pdu_hdr->coap_hdr_tcp_16bit_t.token;
+            break;
+        case coap_tcp_32bit:
+            *token_length = (pdu_hdr->coap_hdr_tcp_32bit_t.header_data[0]) & 0x0f;
+            *token = (unsigned char *)pdu_hdr->coap_hdr_tcp_32bit_t.token;
+            break;
+        default:
+            debug("it has wrong type\n");
+    }
+}
+
 /** @FIXME de-duplicate code with coap_add_option_later */
 size_t coap_add_option(coap_pdu_t *pdu, unsigned short type, unsigned int len,
-        const unsigned char *data)
+        const unsigned char *data, coap_transport_type transport)
 {
     size_t optsize;
     coap_opt_t *opt;
@@ -196,7 +486,24 @@ size_t coap_add_option(coap_pdu_t *pdu, unsigned short type, unsigned int len,
         return 0;
     }
 
-    opt = (unsigned char *) pdu->hdr + pdu->length;
+    switch(transport)
+    {
+        case coap_tcp:
+            opt = (unsigned char *) &(pdu->hdr->coap_hdr_tcp_t) + pdu->length;
+            break;
+        case coap_tcp_8bit:
+            opt = (unsigned char *) &(pdu->hdr->coap_hdr_tcp_8bit_t) + pdu->length;
+            break;
+        case coap_tcp_16bit:
+            opt = (unsigned char *) &(pdu->hdr->coap_hdr_tcp_16bit_t) + pdu->length;
+            break;
+        case coap_tcp_32bit:
+            opt = (unsigned char *) &(pdu->hdr->coap_hdr_tcp_32bit_t) + pdu->length;
+            break;
+        default:
+            opt = (unsigned char *) &(pdu->hdr->coap_hdr_udp_t) + pdu->length;
+            break;
+    }
 
     /* encode option and check length */
     optsize = coap_opt_encode(opt, pdu->max_size - pdu->length, type - pdu->max_delta, data, len);
@@ -368,10 +675,9 @@ static size_t next_option_safe(coap_opt_t **optp, size_t *length, coap_option_t*
     return optsize;
 }
 
-int coap_pdu_parse(unsigned char *data, size_t length, coap_pdu_t *pdu)
+int coap_pdu_parse(unsigned char *data, size_t length, coap_pdu_t *pdu,
+                   coap_transport_type transport)
 {
-    coap_opt_t *opt;
-
     assert(data);
     assert(pdu);
 
@@ -379,58 +685,133 @@ int coap_pdu_parse(unsigned char *data, size_t length, coap_pdu_t *pdu)
     {
         debug("insufficient space to store parsed PDU\n");
         printf("[COAP] insufficient space to store parsed PDU\n");
-        return 0;
+        return -1;
     }
 
-    if (length < sizeof(coap_hdr_t))
+    unsigned int headerSize = 0;
+    switch(transport)
+    {
+        case coap_tcp:
+            headerSize = COAP_TCP_HEADER_NO_FIELD;
+            break;
+        case coap_tcp_8bit:
+            headerSize = COAP_TCP_HEADER_8_BIT;
+            break;
+        case coap_tcp_16bit:
+            headerSize = COAP_TCP_HEADER_16_BIT;
+            break;
+        case coap_tcp_32bit:
+            headerSize = COAP_TCP_HEADER_32_BIT;
+            break;
+        default:
+            headerSize = sizeof(pdu->hdr->coap_hdr_udp_t);
+            break;
+    }
+
+    if (length < headerSize)
     {
         debug("discarded invalid PDU\n");
     }
 
-    pdu->hdr->version = data[0] >> 6;
-    pdu->hdr->type = (data[0] >> 4) & 0x03;
-    pdu->hdr->token_length = data[0] & 0x0f;
-    pdu->hdr->code = data[1];
-    /*
-     printf("[COAP] pdu - version : %d\n", pdu->hdr->version);
-     printf("[COAP] pdu - type : %d\n", pdu->hdr->type);
-     printf("[COAP] pdu - token_length : %d\n", pdu->hdr->token_length);
-     printf("[COAP] pdu - code : %d\n", pdu->hdr->code);
-     */
-    pdu->data = NULL;
+    coap_opt_t *opt = NULL;
+    unsigned int tokenLength = 0;
+    switch(transport)
+    {
+        case coap_tcp:
+            pdu->hdr->coap_hdr_tcp_t.message_length = data[0] >> 4;
+            pdu->hdr->coap_hdr_tcp_t.token_length = data[0] & 0x0f;
+            pdu->hdr->coap_hdr_tcp_t.code = data[1];
+            tokenLength = pdu->hdr->coap_hdr_tcp_t.token_length;
+            opt = (unsigned char *) (&(pdu->hdr->coap_hdr_tcp_t) + 1) + tokenLength;
+            break;
+        case coap_tcp_8bit:
+            pdu->hdr->coap_hdr_tcp_8bit_t.message_length = data[0] >> 4;
+            pdu->hdr->coap_hdr_tcp_8bit_t.token_length = data[0] & 0x0f;
+            pdu->hdr->coap_hdr_tcp_8bit_t.length_byte = data[1];
+            pdu->hdr->coap_hdr_tcp_8bit_t.code = data[2];
+            tokenLength = pdu->hdr->coap_hdr_tcp_8bit_t.token_length;
+            opt = (unsigned char *) (&(pdu->hdr->coap_hdr_tcp_8bit_t) + 1) + tokenLength;
+            break;
+        case coap_tcp_16bit:
+            pdu->hdr->coap_hdr_tcp_16bit_t.message_length = data[0] >> 4;
+            pdu->hdr->coap_hdr_tcp_16bit_t.token_length = data[0] & 0x0f;
+            pdu->hdr->coap_hdr_tcp_16bit_t.length_byte = (data[2] << 8 | data[1]);
+            pdu->hdr->coap_hdr_tcp_16bit_t.code = data[3];
+            tokenLength = pdu->hdr->coap_hdr_tcp_16bit_t.token_length;
+            opt = (unsigned char *) (&(pdu->hdr->coap_hdr_tcp_16bit_t) + 1) + tokenLength;
+            break;
+        case coap_tcp_32bit:
+            for (size_t i = 0 ; i < headerSize ; i++)
+            {
+                pdu->hdr->coap_hdr_tcp_32bit_t.header_data[i] = data[i];
+            }
+
+            tokenLength = data[0] & 0x0f;
+            opt = ((unsigned char *) &(pdu->hdr->coap_hdr_tcp_32bit_t)) +
+                    headerSize + tokenLength;
+            break;
+        default:
+            debug("it has wrong type\n");
+    }
+    pdu->length = length;
 
-    /* sanity checks */
-    if (pdu->hdr->code == 0)
+    if (coap_udp == transport)
     {
-        if (length != sizeof(coap_hdr_t) || pdu->hdr->token_length)
+        pdu->hdr->coap_hdr_udp_t.version = data[0] >> 6;
+        pdu->hdr->coap_hdr_udp_t.type = (data[0] >> 4) & 0x03;
+        pdu->hdr->coap_hdr_udp_t.token_length = data[0] & 0x0f;
+        pdu->hdr->coap_hdr_udp_t.code = data[1];
+        pdu->data = NULL;
+
+        tokenLength = pdu->hdr->coap_hdr_udp_t.token_length;
+
+        /* sanity checks */
+        if (pdu->hdr->coap_hdr_udp_t.code == 0)
         {
-            debug("coap_pdu_parse: empty message is not empty\n");
+            if (length != headerSize || tokenLength)
+            {
+                debug("coap_pdu_parse: empty message is not empty\n");
+                goto discard;
+            }
+        }
+
+        if (length < headerSize + tokenLength || tokenLength > 8)
+        {
+            debug("coap_pdu_parse: invalid Token\n");
             goto discard;
         }
-    }
 
-    if (length < sizeof(coap_hdr_t) + pdu->hdr->token_length || pdu->hdr->token_length > 8)
-    {
-        debug("coap_pdu_parse: invalid Token\n");
-        goto discard;
-    }
+        memcpy(&pdu->hdr->coap_hdr_udp_t.id, data + 2, 2);
 
-    /* Copy message id in network byte order, so we can easily write the
-     * response back to the network. */
-    memcpy(&pdu->hdr->id, data + 2, 2);
+        /* Finally calculate beginning of data block and thereby check integrity
+         * of the PDU structure. */
 
-    //printf("[COAP] pdu - id : %d\n", pdu->hdr->id);
+        /* append data (including the Token) to pdu structure */
+        memcpy(&(pdu->hdr->coap_hdr_udp_t) + 1, data + headerSize, length - headerSize);
 
-    /* append data (including the Token) to pdu structure */
-    memcpy(pdu->hdr + 1, data + sizeof(coap_hdr_t), length - sizeof(coap_hdr_t));
-    pdu->length = length;
+        /* skip header + token */
+        length -= (tokenLength + headerSize);
+        opt = (unsigned char *) (&(pdu->hdr->coap_hdr_udp_t) + 1) + tokenLength;
+    }
+    else // common for tcp header setting
+    {
+        pdu->data = NULL;
+
+        if (length < headerSize + tokenLength || tokenLength > 8)
+        {
+            debug("coap_pdu_parse: invalid Token\n");
+            goto discard;
+        }
+        /* Finally calculate beginning of data block and thereby check integrity
+         * of the PDU structure. */
 
-    /* Finally calculate beginning of data block and thereby check integrity
-     * of the PDU structure. */
+        /* append data (including the Token) to pdu structure */
+        memcpy(((unsigned char *) pdu->hdr) + headerSize,
+               data + headerSize, length - headerSize);
 
-    /* skip header + token */
-    length -= (pdu->hdr->token_length + sizeof(coap_hdr_t));
-    opt = (unsigned char *) (pdu->hdr + 1) + pdu->hdr->token_length;
+        /* skip header + token */
+        length -= (tokenLength + headerSize);
+    }
 
     while (length && *opt != COAP_PAYLOAD_START)
     {
@@ -457,7 +838,8 @@ int coap_pdu_parse(unsigned char *data, size_t length, coap_pdu_t *pdu)
         }
 
         debug(
-                "set data to %p (pdu ends at %p)\n", (unsigned char *)opt, (unsigned char *)pdu->hdr + pdu->length);
+                "set data to %p (pdu ends at %p)\n", (unsigned char *)opt,
+                (unsigned char *)pdu->hdr + pdu->length);
         pdu->data = (unsigned char *) opt;
         //printf("[COAP] pdu - data : %s\n", pdu->data);
     }