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