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