[JIRA IOT-738] fixed to calculate message length for option
[platform/upstream/iotivity.git] / resource / csdk / connectivity / lib / libcoap-4.1.1 / pdu.c
1 /* pdu.c -- CoAP message structure
2  *
3  * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
4  *
5  * This file is part of the CoAP library libcoap. Please see
6  * README for terms of use.
7  */
8
9 #include "config.h"
10
11 #if defined(HAVE_ASSERT_H) && !defined(assert)
12 # include <assert.h>
13 #endif
14
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #ifdef HAVE_ARPA_INET_H
19 #include <arpa/inet.h>
20 #endif
21
22 #include "debug.h"
23 #include "pdu.h"
24 #include "option.h"
25 #include "encode.h"
26
27 #ifdef WITH_ARDUINO
28 #include "util.h"
29 #endif
30
31 #ifdef WITH_CONTIKI
32 #include "memb.h"
33
34 #ifndef WITH_TCP
35 typedef unsigned char _pdu[sizeof(coap_pdu_t) + COAP_MAX_PDU_SIZE];
36
37 MEMB(pdu_storage, _pdu, COAP_PDU_MAXCNT);
38 #endif
39
40 void
41 coap_pdu_resources_init()
42 {
43     memb_init(&pdu_storage);
44 }
45 #else /* WITH_CONTIKI */
46 #include "mem.h"
47 #endif /* WITH_CONTIKI */
48
49 void coap_pdu_clear(coap_pdu_t *pdu, size_t size, coap_transport_type transport, unsigned int length)
50 {
51     assert(pdu);
52
53     memset(pdu, 0, sizeof(coap_pdu_t) + size);
54     pdu->max_size = size;
55     pdu->hdr = (coap_hdr_t *) ((unsigned char *) pdu + sizeof(coap_pdu_t));
56
57     if (coap_udp == transport)
58     {
59         pdu->hdr->coap_hdr_udp_t.version = COAP_DEFAULT_VERSION;
60         /* data is NULL unless explicitly set by coap_add_data() */
61         pdu->length = sizeof(pdu->hdr->coap_hdr_udp_t);
62     }
63 #ifdef WITH_TCP
64     else
65     {
66         /* data is NULL unless explicitly set by coap_add_data() */
67         pdu->length = length;
68     }
69 #endif
70 }
71
72 #ifdef WITH_LWIP
73 coap_pdu_t *
74 coap_pdu_from_pbuf(struct pbuf *pbuf)
75 {
76     LWIP_ASSERT("Can only deal with contiguous PBUFs", pbuf->tot_len == pbuf->len);
77     LWIP_ASSERT("coap_read needs to receive an exclusive copy of the incoming pbuf", pbuf->ref == 1);
78
79     void *data = pbuf->payload;
80     coap_pdu_t *result;
81
82     u8_t header_error = pbuf_header(pbuf, sizeof(coap_pdu_t));
83     LWIP_ASSERT("CoAP PDU header does not fit in existing header space", header_error == 0);
84
85     result = (coap_pdu_t *)pbuf->payload;
86
87     memset(result, 0, sizeof(coap_pdu_t));
88
89     result->max_size = pbuf->tot_len - sizeof(coap_pdu_t);
90     result->length = pbuf->tot_len - sizeof(coap_pdu_t);
91     result->hdr = data;
92     result->pbuf = pbuf;
93
94     return result;
95 }
96 #endif
97
98 coap_pdu_t *
99 coap_pdu_init(unsigned char type, unsigned char code, unsigned short id,
100               size_t size, coap_transport_type transport)
101 {
102     coap_pdu_t *pdu;
103 #ifdef WITH_LWIP
104     struct pbuf *p;
105 #endif
106
107     unsigned int length = 0;
108     switch(transport)
109     {
110         case coap_udp:
111             length = sizeof(pdu->hdr->coap_hdr_udp_t);
112             break;
113 #ifdef WITH_TCP
114         case coap_tcp:
115             length = COAP_TCP_HEADER_NO_FIELD;
116             break;
117         case coap_tcp_8bit:
118             length = COAP_TCP_HEADER_8_BIT;
119             break;
120         case coap_tcp_16bit:
121             length = COAP_TCP_HEADER_16_BIT;
122             break;
123         case coap_tcp_32bit:
124             length = COAP_TCP_HEADER_32_BIT;
125             break;
126 #endif
127         default:
128             debug("it has wrong type\n");
129     }
130
131 #ifndef WITH_TCP
132     assert(size <= COAP_MAX_PDU_SIZE);
133     /* Size must be large enough to fit the header. */
134     if (size < length || size > COAP_MAX_PDU_SIZE)
135         return NULL;
136 #endif
137
138     /* size must be large enough for hdr */
139 #if defined(WITH_POSIX) || defined(WITH_ARDUINO)
140     pdu = (coap_pdu_t *) coap_malloc(sizeof(coap_pdu_t) + size);
141 #endif
142 #ifdef WITH_CONTIKI
143     pdu = (coap_pdu_t *)memb_alloc(&pdu_storage);
144 #endif
145 #ifdef WITH_LWIP
146     p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
147     if (p != NULL)
148     {
149         u8_t header_error = pbuf_header(p, sizeof(coap_pdu_t));
150         /* we could catch that case and allocate larger memory in advance, but then
151          * again, we'd run into greater trouble with incoming packages anyway */
152         LWIP_ASSERT("CoAP PDU header does not fit in transport header", header_error == 0);
153         pdu = p->payload;
154     }
155     else
156     {
157         pdu = NULL;
158     }
159 #endif
160     if (pdu)
161     {
162         coap_pdu_clear(pdu, size, transport, length);
163
164         switch(transport)
165         {
166             case coap_udp:
167                 pdu->hdr->coap_hdr_udp_t.id = id;
168                 pdu->hdr->coap_hdr_udp_t.type = type;
169                 pdu->hdr->coap_hdr_udp_t.code = code;
170                 break;
171 #ifdef WITH_TCP
172             case coap_tcp:
173                 pdu->hdr->coap_hdr_tcp_t.message_length = 0;
174                 pdu->hdr->coap_hdr_tcp_t.code = code;
175                 break;
176             case coap_tcp_8bit:
177                 pdu->hdr->coap_hdr_tcp_8bit_t.message_length = COAP_TCP_LENGTH_FIELD_NUM_8_BIT;
178                 pdu->hdr->coap_hdr_tcp_8bit_t.length_byte = 0;
179                 pdu->hdr->coap_hdr_tcp_8bit_t.code = code;
180                 break;
181             case coap_tcp_16bit:
182                 pdu->hdr->coap_hdr_tcp_16bit_t.header_data[0] = COAP_TCP_LENGTH_FIELD_NUM_16_BIT << 4;
183                 pdu->hdr->coap_hdr_tcp_16bit_t.header_data[3] = code;
184                 break;
185             case coap_tcp_32bit:
186                 pdu->hdr->coap_hdr_tcp_32bit_t.header_data[0] = COAP_TCP_LENGTH_FIELD_NUM_32_BIT << 4;
187                 pdu->hdr->coap_hdr_tcp_32bit_t.header_data[5] = code;
188                 break;
189 #endif
190             default:
191                 debug("it has wrong type\n");
192         }
193
194 #ifdef WITH_LWIP
195         pdu->pbuf = p;
196 #endif
197     }
198     return pdu;
199 }
200
201 coap_pdu_t *
202 coap_new_pdu(coap_transport_type transport, unsigned int size)
203 {
204     coap_pdu_t *pdu;
205
206 #ifndef WITH_CONTIKI
207     pdu = coap_pdu_init(0, 0,
208                         ntohs(COAP_INVALID_TID),
209 #ifndef WITH_TCP
210                         COAP_MAX_PDU_SIZE,
211 #else
212                         size,
213 #endif
214                         transport);
215 #else /* WITH_CONTIKI */
216     pdu = coap_pdu_init(0, 0, uip_ntohs(COAP_INVALID_TID),
217 #ifndef WITH_TCP
218                         COAP_MAX_PDU_SIZE,
219 #else
220                         size,
221 #endif
222                         transport);
223 #endif /* WITH_CONTIKI */
224
225 #ifndef NDEBUG
226     if (!pdu)
227         coap_log(LOG_CRIT, "coap_new_pdu: cannot allocate memory for new PDU\n");
228 #endif
229     return pdu;
230 }
231
232 void coap_delete_pdu(coap_pdu_t *pdu)
233 {
234 #if defined(WITH_POSIX) || defined(WITH_ARDUINO)
235     coap_free( pdu );
236 #endif
237 #ifdef WITH_LWIP
238     if (pdu != NULL) /* accepting double free as the other implementation accept that too */
239         pbuf_free(pdu->pbuf);
240 #endif
241 #ifdef WITH_CONTIKI
242     memb_free(&pdu_storage, pdu);
243 #endif
244 }
245
246 #ifdef WITH_TCP
247 coap_transport_type coap_get_tcp_header_type_from_size(unsigned int size)
248 {
249     if (COAP_TCP_LENGTH_LIMIT_8_BIT < size && COAP_TCP_LENGTH_LIMIT_16_BIT >= size)
250     {
251         return coap_tcp_8bit;
252     }
253     else if (COAP_TCP_LENGTH_LIMIT_16_BIT < size && COAP_TCP_LENGTH_LIMIT_32_BIT >= size)
254     {
255         return coap_tcp_16bit;
256     }
257     else if (COAP_TCP_LENGTH_LIMIT_32_BIT < size)
258     {
259         return coap_tcp_32bit;
260     }
261     else
262     {
263         return coap_tcp;
264     }
265 }
266
267 coap_transport_type coap_get_tcp_header_type_from_initbyte(unsigned int length)
268 {
269     coap_transport_type type;
270     switch(length)
271     {
272         case COAP_TCP_LENGTH_FIELD_NUM_8_BIT:
273             type = coap_tcp_8bit;
274             break;
275         case COAP_TCP_LENGTH_FIELD_NUM_16_BIT:
276             type = coap_tcp_16bit;
277             break;
278         case COAP_TCP_LENGTH_FIELD_NUM_32_BIT:
279             type = coap_tcp_32bit;
280             break;
281         default:
282             type = coap_tcp;
283     }
284     return type;
285 }
286
287 void coap_add_length(const coap_pdu_t *pdu, coap_transport_type transport, unsigned int length)
288 {
289     assert(pdu);
290
291     switch(transport)
292     {
293         case coap_tcp:
294             pdu->hdr->coap_hdr_tcp_t.message_length = length;
295             break;
296         case coap_tcp_8bit:
297             if (length > COAP_TCP_LENGTH_FIELD_8_BIT)
298             {
299                 pdu->hdr->coap_hdr_tcp_8bit_t.length_byte =
300                         length - COAP_TCP_LENGTH_FIELD_8_BIT;
301             }
302             break;
303         case coap_tcp_16bit:
304             if (length > COAP_TCP_LENGTH_FIELD_16_BIT)
305             {
306                 unsigned int total_length = length - COAP_TCP_LENGTH_FIELD_16_BIT;
307                 pdu->hdr->coap_hdr_tcp_16bit_t.header_data[1] = (total_length >> 8) & 0x0000ff;
308                 pdu->hdr->coap_hdr_tcp_16bit_t.header_data[2] = total_length & 0x000000ff;
309             }
310             break;
311         case coap_tcp_32bit:
312             if (length > COAP_TCP_LENGTH_FIELD_32_BIT)
313             {
314                 unsigned int total_length = length - COAP_TCP_LENGTH_FIELD_32_BIT;
315                 pdu->hdr->coap_hdr_tcp_32bit_t.header_data[1] = total_length >> 24;
316                 pdu->hdr->coap_hdr_tcp_32bit_t.header_data[2] = (total_length >> 16) & 0x00ff;
317                 pdu->hdr->coap_hdr_tcp_32bit_t.header_data[3] = (total_length >> 8) & 0x0000ff;
318                 pdu->hdr->coap_hdr_tcp_32bit_t.header_data[4] = total_length & 0x000000ff;
319             }
320             break;
321         default:
322             debug("it has wrong type\n");
323     }
324 }
325
326 unsigned int coap_get_length_from_header(const unsigned char *header, coap_transport_type transport)
327 {
328     assert(header);
329
330     unsigned int length = 0;
331     unsigned int length_field_data = 0;
332     switch(transport)
333     {
334         case coap_tcp_8bit:
335             length = header[1] + COAP_TCP_LENGTH_FIELD_8_BIT;
336             break;
337         case coap_tcp_16bit:
338             length_field_data = (header[1] << 8 | header[2]);
339             length = length_field_data + COAP_TCP_LENGTH_FIELD_16_BIT;
340             break;
341         case coap_tcp_32bit:
342             length_field_data = header[1] << 24 | header[2] << 16 | header[3] << 8 | header[4];
343             length = length_field_data + COAP_TCP_LENGTH_FIELD_32_BIT;
344             break;
345         default:
346             debug("it has wrong type\n");
347     }
348
349     return length;
350 }
351
352 unsigned int coap_get_length(const coap_pdu_t *pdu, coap_transport_type transport)
353 {
354     assert(pdu);
355
356     unsigned int length = 0;
357     unsigned int length_field_data = 0;
358     switch(transport)
359     {
360         case coap_tcp:
361             length = pdu->hdr->coap_hdr_tcp_t.message_length;
362             break;
363         case coap_tcp_8bit:
364             length = pdu->hdr->coap_hdr_tcp_8bit_t.length_byte + COAP_TCP_LENGTH_FIELD_8_BIT;
365             break;
366         case coap_tcp_16bit:
367             length_field_data =
368                     pdu->hdr->coap_hdr_tcp_16bit_t.header_data[1] << 8 |
369                     pdu->hdr->coap_hdr_tcp_16bit_t.header_data[2];
370             length = length_field_data + COAP_TCP_LENGTH_FIELD_16_BIT;
371             break;
372         case coap_tcp_32bit:
373             length_field_data =
374                     pdu->hdr->coap_hdr_tcp_32bit_t.header_data[1] << 24 |
375                     pdu->hdr->coap_hdr_tcp_32bit_t.header_data[2] << 16 |
376                     pdu->hdr->coap_hdr_tcp_32bit_t.header_data[3] << 8 |
377                     pdu->hdr->coap_hdr_tcp_32bit_t.header_data[4];
378             length = length_field_data + COAP_TCP_LENGTH_FIELD_32_BIT;
379             break;
380         default:
381             debug("it has wrong type\n");
382     }
383
384     return length;
385 }
386
387 unsigned int coap_get_tcp_header_length(unsigned char *data)
388 {
389     assert(data);
390
391     unsigned int tokenLength =  data[0] & 0x0f;
392     coap_transport_type transport =
393             coap_get_tcp_header_type_from_initbyte(data[0] >> 4);
394     unsigned int length = 0;
395
396     length = coap_get_tcp_header_length_for_transport(transport) + tokenLength;
397     return length;
398 }
399
400 unsigned int coap_get_tcp_header_length_for_transport(coap_transport_type transport)
401 {
402     unsigned int length = 0;
403     switch(transport)
404     {
405         case coap_tcp:
406             length = COAP_TCP_HEADER_NO_FIELD;
407             break;
408         case coap_tcp_8bit:
409             length = COAP_TCP_HEADER_8_BIT;
410             break;
411         case coap_tcp_16bit:
412             length = COAP_TCP_HEADER_16_BIT;
413             break;
414         case coap_tcp_32bit:
415             length = COAP_TCP_HEADER_32_BIT;
416             break;
417         default:
418             debug("it has wrong type\n");
419     }
420
421     return length;
422 }
423
424 size_t coap_get_opt_header_length(unsigned short key, size_t length)
425 {
426     size_t headerLength = 0;
427
428     unsigned short optDeltaLength = 0;
429     if (COAP_OPTION_FIELD_8_BIT >= key)
430     {
431         optDeltaLength = 0;
432     }
433     else if (COAP_OPTION_FIELD_8_BIT < key && COAP_OPTION_FIELD_16_BIT >= key)
434     {
435         optDeltaLength = 1;
436     }
437     else if (COAP_OPTION_FIELD_16_BIT < key && COAP_OPTION_FIELD_32_BIT >= key)
438     {
439         optDeltaLength = 2;
440     }
441     else
442     {
443         printf("Error : Reserved for the Payload marker for Delta");
444         return 0;
445     }
446
447     size_t optLength = 0;
448     if (COAP_OPTION_FIELD_8_BIT >= length)
449     {
450         optLength = 0;
451     }
452     else if (COAP_OPTION_FIELD_8_BIT < length && COAP_OPTION_FIELD_16_BIT >= length)
453     {
454         optLength = 1;
455     }
456     else if (COAP_OPTION_FIELD_16_BIT < length && COAP_OPTION_FIELD_32_BIT >= length)
457     {
458         optLength = 2;
459     }
460     else
461     {
462         printf("Error : Reserved for the Payload marker for length");
463         return 0;
464     }
465
466     headerLength = length + optDeltaLength + optLength + 1;
467
468     return headerLength;
469 }
470
471 #endif
472
473 void coap_add_code(const coap_pdu_t *pdu, coap_transport_type transport, unsigned int code)
474 {
475     assert(pdu);
476
477     switch(transport)
478     {
479         case coap_udp:
480             pdu->hdr->coap_hdr_udp_t.code = COAP_RESPONSE_CODE(code);
481             break;
482 #ifdef WITH_TCP
483         case coap_tcp:
484             pdu->hdr->coap_hdr_tcp_t.code = COAP_RESPONSE_CODE(code);
485             break;
486         case coap_tcp_8bit:
487             pdu->hdr->coap_hdr_tcp_8bit_t.code = COAP_RESPONSE_CODE(code);
488             break;
489         case coap_tcp_16bit:
490             pdu->hdr->coap_hdr_tcp_16bit_t.header_data[3] = COAP_RESPONSE_CODE(code);
491             break;
492         case coap_tcp_32bit:
493             pdu->hdr->coap_hdr_tcp_32bit_t.header_data[5] = COAP_RESPONSE_CODE(code);
494             break;
495 #endif
496         default:
497             debug("it has wrong type\n");
498     }
499 }
500
501 unsigned int coap_get_code(const coap_pdu_t *pdu, coap_transport_type transport)
502 {
503     assert(pdu);
504
505     unsigned int code = 0;
506     switch(transport)
507     {
508         case coap_udp:
509             code = pdu->hdr->coap_hdr_udp_t.code;
510             break;
511 #ifdef WITH_TCP
512         case coap_tcp:
513             code = pdu->hdr->coap_hdr_tcp_t.code;
514             break;
515         case coap_tcp_8bit:
516             code = pdu->hdr->coap_hdr_tcp_8bit_t.code;
517             break;
518         case coap_tcp_16bit:
519             code = pdu->hdr->coap_hdr_tcp_16bit_t.header_data[3];
520             break;
521         case coap_tcp_32bit:
522             code = pdu->hdr->coap_hdr_tcp_32bit_t.header_data[5];
523             break;
524 #endif
525         default:
526             debug("it has wrong type\n");
527     }
528     return code;
529 }
530
531 int coap_add_token(coap_pdu_t *pdu, size_t len, const unsigned char *data,
532                    coap_transport_type transport)
533 {
534     const size_t HEADERLENGTH = len + 4;
535     /* must allow for pdu == NULL as callers may rely on this */
536     if (!pdu || len > 8 || pdu->max_size < HEADERLENGTH)
537         return 0;
538
539     unsigned char* token = NULL;
540     switch(transport)
541     {
542         case coap_udp:
543             pdu->hdr->coap_hdr_udp_t.token_length = len;
544             token = pdu->hdr->coap_hdr_udp_t.token;
545             pdu->length = HEADERLENGTH;
546             break;
547 #ifdef WITH_TCP
548         case coap_tcp:
549             pdu->hdr->coap_hdr_tcp_t.token_length = len;
550             token = pdu->hdr->coap_hdr_tcp_t.token;
551             pdu->length = len + COAP_TCP_HEADER_NO_FIELD;
552             break;
553         case coap_tcp_8bit:
554             pdu->hdr->coap_hdr_tcp_8bit_t.token_length = len;
555             token = pdu->hdr->coap_hdr_tcp_8bit_t.token;
556             pdu->length = len + COAP_TCP_HEADER_8_BIT;
557             break;
558         case coap_tcp_16bit:
559             pdu->hdr->coap_hdr_tcp_16bit_t.header_data[0] =
560                     pdu->hdr->coap_hdr_tcp_16bit_t.header_data[0] | len;
561             token = pdu->hdr->coap_hdr_tcp_16bit_t.token;
562             pdu->length = len + COAP_TCP_HEADER_16_BIT;
563             break;
564         case coap_tcp_32bit:
565             pdu->hdr->coap_hdr_tcp_32bit_t.header_data[0] =
566                     pdu->hdr->coap_hdr_tcp_32bit_t.header_data[0] | len;
567             token = pdu->hdr->coap_hdr_tcp_32bit_t.token;
568             pdu->length = len + COAP_TCP_HEADER_32_BIT;
569             break;
570 #endif
571         default:
572             debug("it has wrong type\n");
573     }
574
575     if (len)
576     {
577         memcpy(token, data, len);
578     }
579
580     pdu->max_delta = 0;
581     pdu->data = NULL;
582
583     return 1;
584 }
585
586 void coap_get_token(const coap_hdr_t *pdu_hdr, coap_transport_type transport,
587                     unsigned char **token, unsigned int *token_length)
588 {
589     assert(pdu_hdr);
590     assert(token);
591     assert(token_length);
592
593     switch(transport)
594     {
595         case coap_udp:
596             *token_length = pdu_hdr->coap_hdr_udp_t.token_length;
597             *token = (unsigned char *)pdu_hdr->coap_hdr_udp_t.token;
598             break;
599 #ifdef WITH_TCP
600         case coap_tcp:
601             *token_length = pdu_hdr->coap_hdr_tcp_t.token_length;
602             *token = (unsigned char *)pdu_hdr->coap_hdr_tcp_t.token;
603             break;
604         case coap_tcp_8bit:
605             *token_length = pdu_hdr->coap_hdr_tcp_8bit_t.token_length;
606             *token = (unsigned char *)pdu_hdr->coap_hdr_tcp_8bit_t.token;
607             break;
608         case coap_tcp_16bit:
609             *token_length = (pdu_hdr->coap_hdr_tcp_16bit_t.header_data[0]) & 0x0f;
610             *token = (unsigned char *)pdu_hdr->coap_hdr_tcp_16bit_t.token;
611             break;
612         case coap_tcp_32bit:
613             *token_length = (pdu_hdr->coap_hdr_tcp_32bit_t.header_data[0]) & 0x0f;
614             *token = (unsigned char *)pdu_hdr->coap_hdr_tcp_32bit_t.token;
615             break;
616 #endif
617         default:
618             debug("it has wrong type\n");
619     }
620 }
621
622 /** @FIXME de-duplicate code with coap_add_option_later */
623 size_t coap_add_option(coap_pdu_t *pdu, unsigned short type, unsigned int len,
624         const unsigned char *data, coap_transport_type transport)
625 {
626     size_t optsize;
627     coap_opt_t *opt;
628
629     assert(pdu);
630     pdu->data = NULL;
631
632     if (type < pdu->max_delta)
633     {
634         warn("coap_add_option: options are not in correct order\n");
635         return 0;
636     }
637
638     switch(transport)
639     {
640 #ifdef WITH_TCP
641         case coap_tcp:
642             opt = (unsigned char *) &(pdu->hdr->coap_hdr_tcp_t) + pdu->length;
643             break;
644         case coap_tcp_8bit:
645             opt = (unsigned char *) &(pdu->hdr->coap_hdr_tcp_8bit_t) + pdu->length;
646             break;
647         case coap_tcp_16bit:
648             opt = (unsigned char *) &(pdu->hdr->coap_hdr_tcp_16bit_t) + pdu->length;
649             break;
650         case coap_tcp_32bit:
651             opt = (unsigned char *) &(pdu->hdr->coap_hdr_tcp_32bit_t) + pdu->length;
652             break;
653 #endif
654         default:
655             opt = (unsigned char *) &(pdu->hdr->coap_hdr_udp_t) + pdu->length;
656             break;
657     }
658
659     /* encode option and check length */
660     optsize = coap_opt_encode(opt, pdu->max_size - pdu->length, type - pdu->max_delta, data, len);
661
662     if (!optsize)
663     {
664         warn("coap_add_option: cannot add option\n");
665         /* error */
666         return 0;
667     }
668     else
669     {
670         pdu->max_delta = type;
671         pdu->length += optsize;
672     }
673
674     return optsize;
675 }
676
677 /** @FIXME de-duplicate code with coap_add_option */
678 unsigned char*
679 coap_add_option_later(coap_pdu_t *pdu, unsigned short type, unsigned int len)
680 {
681     size_t optsize;
682     coap_opt_t *opt;
683
684     assert(pdu);
685     pdu->data = NULL;
686
687     if (type < pdu->max_delta)
688     {
689         warn("coap_add_option: options are not in correct order\n");
690         return NULL;
691     }
692
693     opt = (unsigned char *) pdu->hdr + pdu->length;
694
695     /* encode option and check length */
696     optsize = coap_opt_encode(opt, pdu->max_size - pdu->length, type - pdu->max_delta, NULL, len);
697
698     if (!optsize)
699     {
700         warn("coap_add_option: cannot add option\n");
701         /* error */
702         return NULL;
703     }
704     else
705     {
706         pdu->max_delta = type;
707         pdu->length += optsize;
708     }
709
710     return ((unsigned char*) opt) + optsize - len;
711 }
712
713 int coap_add_data(coap_pdu_t *pdu, unsigned int len, const unsigned char *data)
714 {
715     assert(pdu);
716     assert(pdu->data == NULL);
717
718     if (len == 0)
719         return 1;
720
721     if (pdu->length + len + 1 > pdu->max_size)
722     {
723         warn("coap_add_data: cannot add: data too large for PDU\n");
724         assert(pdu->data == NULL);
725         return 0;
726     }
727
728     pdu->data = (unsigned char *) pdu->hdr + pdu->length;
729     *pdu->data = COAP_PAYLOAD_START;
730     pdu->data++;
731
732     memcpy(pdu->data, data, len);
733     pdu->length += len + 1;
734     return 1;
735 }
736
737 int coap_get_data(const coap_pdu_t *pdu, size_t *len, unsigned char **data)
738 {
739     assert(pdu);
740     assert(len);
741     assert(data);
742
743     if (pdu->data)
744     {
745         *len = (unsigned char *) pdu->hdr + pdu->length - pdu->data;
746         *data = pdu->data;
747     }
748     else
749     { /* no data, clear everything */
750         *len = 0;
751         *data = NULL;
752     }
753
754     return *data != NULL;
755 }
756
757 #ifndef SHORT_ERROR_RESPONSE
758 typedef struct
759 {
760     unsigned char code;
761     char *phrase;
762 } error_desc_t;
763
764 /* if you change anything here, make sure, that the longest string does not
765  * exceed COAP_ERROR_PHRASE_LENGTH. */
766 error_desc_t coap_error[] =
767 {
768 { COAP_RESPONSE_CODE(65), "2.01 Created" },
769 { COAP_RESPONSE_CODE(66), "2.02 Deleted" },
770 { COAP_RESPONSE_CODE(67), "2.03 Valid" },
771 { COAP_RESPONSE_CODE(68), "2.04 Changed" },
772 { COAP_RESPONSE_CODE(69), "2.05 Content" },
773 { COAP_RESPONSE_CODE(400), "Bad Request" },
774 { COAP_RESPONSE_CODE(401), "Unauthorized" },
775 { COAP_RESPONSE_CODE(402), "Bad Option" },
776 { COAP_RESPONSE_CODE(403), "Forbidden" },
777 { COAP_RESPONSE_CODE(404), "Not Found" },
778 { COAP_RESPONSE_CODE(405), "Method Not Allowed" },
779 { COAP_RESPONSE_CODE(408), "Request Entity Incomplete" },
780 { COAP_RESPONSE_CODE(413), "Request Entity Too Large" },
781 { COAP_RESPONSE_CODE(415), "Unsupported Media Type" },
782 { COAP_RESPONSE_CODE(500), "Internal Server Error" },
783 { COAP_RESPONSE_CODE(501), "Not Implemented" },
784 { COAP_RESPONSE_CODE(502), "Bad Gateway" },
785 { COAP_RESPONSE_CODE(503), "Service Unavailable" },
786 { COAP_RESPONSE_CODE(504), "Gateway Timeout" },
787 { COAP_RESPONSE_CODE(505), "Proxying Not Supported" },
788 { 0, NULL } /* end marker */
789 };
790
791 char *
792 coap_response_phrase(unsigned char code)
793 {
794     int i;
795     for (i = 0; coap_error[i].code; ++i)
796     {
797         if (coap_error[i].code == code)
798             return coap_error[i].phrase;
799     }
800     return NULL;
801 }
802 #endif
803
804 /**
805  * Advances *optp to next option if still in PDU. This function
806  * returns the number of bytes opt has been advanced or @c 0
807  * on error.
808  */
809 static size_t next_option_safe(coap_opt_t **optp, size_t *length, coap_option_t* option)
810 {
811     //coap_option_t option;
812     size_t optsize;
813
814     assert(optp);
815     assert(*optp);
816     assert(length);
817     optsize = coap_opt_parse(*optp, *length, option);
818     if (optsize)
819     {
820         assert(optsize <= *length);
821
822         *optp += optsize;
823         *length -= optsize;
824     }
825
826     return optsize;
827 }
828
829 int coap_pdu_parse(unsigned char *data, size_t length, coap_pdu_t *pdu,
830                    coap_transport_type transport)
831 {
832     assert(data);
833     assert(pdu);
834
835     if (pdu->max_size < length)
836     {
837         debug("insufficient space to store parsed PDU\n");
838         printf("[COAP] insufficient space to store parsed PDU\n");
839         return -1;
840     }
841
842     unsigned int headerSize = 0;
843
844     if (coap_udp == transport)
845     {
846         headerSize = sizeof(pdu->hdr->coap_hdr_udp_t);
847     }
848 #ifdef WITH_TCP
849     else
850     {
851         headerSize = coap_get_tcp_header_length_for_transport(transport);
852     }
853 #endif
854
855     if (length < headerSize)
856     {
857         debug("discarded invalid PDU\n");
858     }
859
860     coap_opt_t *opt = NULL;
861     unsigned int tokenLength = 0;
862 #ifdef WITH_TCP
863     switch(transport)
864     {
865         case coap_udp:
866             break;
867         case coap_tcp:
868             pdu->hdr->coap_hdr_tcp_t.message_length = data[0] >> 4;
869             pdu->hdr->coap_hdr_tcp_t.token_length = data[0] & 0x0f;
870             pdu->hdr->coap_hdr_tcp_t.code = data[1];
871             tokenLength = pdu->hdr->coap_hdr_tcp_t.token_length;
872             opt = (unsigned char *) (&(pdu->hdr->coap_hdr_tcp_t) + 1) + tokenLength;
873             break;
874         case coap_tcp_8bit:
875             pdu->hdr->coap_hdr_tcp_8bit_t.message_length = data[0] >> 4;
876             pdu->hdr->coap_hdr_tcp_8bit_t.token_length = data[0] & 0x0f;
877             pdu->hdr->coap_hdr_tcp_8bit_t.length_byte = data[1];
878             pdu->hdr->coap_hdr_tcp_8bit_t.code = data[2];
879             tokenLength = pdu->hdr->coap_hdr_tcp_8bit_t.token_length;
880             opt = (unsigned char *) (&(pdu->hdr->coap_hdr_tcp_8bit_t))
881                     + tokenLength + COAP_TCP_HEADER_8_BIT;
882             break;
883         case coap_tcp_16bit:
884             for (size_t i = 0 ; i < headerSize ; i++)
885             {
886                 pdu->hdr->coap_hdr_tcp_16bit_t.header_data[i] = data[i];
887             }
888
889             tokenLength = data[0] & 0x0f;
890             opt = (unsigned char *) (&(pdu->hdr->coap_hdr_tcp_16bit_t) + 1) + tokenLength;
891             break;
892         case coap_tcp_32bit:
893             for (size_t i = 0 ; i < headerSize ; i++)
894             {
895                 pdu->hdr->coap_hdr_tcp_32bit_t.header_data[i] = data[i];
896             }
897
898             tokenLength = data[0] & 0x0f;
899             opt = ((unsigned char *) &(pdu->hdr->coap_hdr_tcp_32bit_t)) +
900                     headerSize + tokenLength;
901             break;
902         default:
903             printf("it has wrong type\n");
904     }
905 #endif
906     pdu->length = length;
907
908     if (coap_udp == transport)
909     {
910         pdu->hdr->coap_hdr_udp_t.version = data[0] >> 6;
911         pdu->hdr->coap_hdr_udp_t.type = (data[0] >> 4) & 0x03;
912         pdu->hdr->coap_hdr_udp_t.token_length = data[0] & 0x0f;
913         pdu->hdr->coap_hdr_udp_t.code = data[1];
914         pdu->data = NULL;
915
916         tokenLength = pdu->hdr->coap_hdr_udp_t.token_length;
917
918         /* sanity checks */
919         if (pdu->hdr->coap_hdr_udp_t.code == 0)
920         {
921             if (length != headerSize || tokenLength)
922             {
923                 debug("coap_pdu_parse: empty message is not empty\n");
924                 goto discard;
925             }
926         }
927
928         if (length < headerSize + tokenLength || tokenLength > 8)
929         {
930             debug("coap_pdu_parse: invalid Token\n");
931             goto discard;
932         }
933
934         memcpy(&pdu->hdr->coap_hdr_udp_t.id, data + 2, 2);
935
936         /* Finally calculate beginning of data block and thereby check integrity
937          * of the PDU structure. */
938
939         /* append data (including the Token) to pdu structure */
940         memcpy(&(pdu->hdr->coap_hdr_udp_t) + 1, data + headerSize, length - headerSize);
941
942         /* skip header + token */
943         length -= (tokenLength + headerSize);
944         opt = (unsigned char *) (&(pdu->hdr->coap_hdr_udp_t) + 1) + tokenLength;
945     }
946 #ifdef WITH_TCP
947     else // common for tcp header setting
948     {
949         pdu->data = NULL;
950
951         if (length < headerSize + tokenLength || tokenLength > 8)
952         {
953             debug("coap_pdu_parse: invalid Token\n");
954             goto discard;
955         }
956         /* Finally calculate beginning of data block and thereby check integrity
957          * of the PDU structure. */
958
959         /* append data (including the Token) to pdu structure */
960         memcpy(((unsigned char *) pdu->hdr) + headerSize,
961                data + headerSize, length - headerSize);
962
963         /* skip header + token */
964         length -= (tokenLength + headerSize);
965     }
966 #endif
967
968     while (length && *opt != COAP_PAYLOAD_START)
969     {
970         coap_option_t option;
971         memset(&option, 0, sizeof(coap_option_t));
972         if (!next_option_safe(&opt, (size_t *) &length, &option))
973         {
974             debug("coap_pdu_parse: drop\n");
975             goto discard;
976         }
977     }
978
979     /* end of packet or start marker */
980     if (length)
981     {
982         assert(*opt == COAP_PAYLOAD_START);
983         opt++;
984         length--;
985
986         if (!length)
987         {
988             debug("coap_pdu_parse: message ending in payload start marker\n");
989             goto discard;
990         }
991
992         debug(
993                 "set data to %p (pdu ends at %p)\n", (unsigned char *)opt,
994                 (unsigned char *)pdu->hdr + pdu->length);
995         pdu->data = (unsigned char *) opt;
996         //printf("[COAP] pdu - data : %s\n", pdu->data);
997     }
998
999     return 1;
1000
1001     discard: return 0;
1002 }