libcoap  4.2.0
pdu.c
Go to the documentation of this file.
1 /* pdu.c -- CoAP message structure
2  *
3  * Copyright (C) 2010--2016 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 "coap_config.h"
10 
11 #if defined(HAVE_ASSERT_H) && !defined(assert)
12 # include <assert.h>
13 #endif
14 
15 #if defined(HAVE_LIMITS_H)
16 #include <limits.h>
17 #endif
18 
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #ifdef HAVE_ARPA_INET_H
23 #include <arpa/inet.h>
24 #endif
25 #ifdef HAVE_WINSOCK2_H
26 #include <winsock2.h>
27 #endif
28 
29 #include "libcoap.h"
30 #include "coap_debug.h"
31 #include "pdu.h"
32 #include "option.h"
33 #include "encode.h"
34 #include "mem.h"
35 #include "coap_session.h"
36 
37 #ifndef min
38 #define min(a,b) ((a) < (b) ? (a) : (b))
39 #endif
40 
41 #ifndef max
42 #define max(a,b) ((a) > (b) ? (a) : (b))
43 #endif
44 
45 void
46 coap_pdu_clear(coap_pdu_t *pdu, size_t size) {
47  assert(pdu);
48  assert(pdu->token);
50  if (pdu->alloc_size > size)
51  pdu->alloc_size = size;
52  pdu->type = 0;
53  pdu->code = 0;
54  pdu->hdr_size = 0;
55  pdu->token_length = 0;
56  pdu->tid = 0;
57  pdu->max_delta = 0;
58  pdu->max_size = size;
59  pdu->used_size = 0;
60  pdu->data = NULL;
61 }
62 
63 #ifdef WITH_LWIP
64 coap_pdu_t *
65 coap_pdu_from_pbuf( struct pbuf *pbuf )
66 {
67  coap_pdu_t *pdu;
68 
69  if (pbuf == NULL) return NULL;
70 
71  LWIP_ASSERT("Can only deal with contiguous PBUFs", pbuf->tot_len == pbuf->len);
72  LWIP_ASSERT("coap_read needs to receive an exclusive copy of the incoming pbuf", pbuf->ref == 1);
73 
74  pdu = coap_malloc_type(COAP_PDU, sizeof(coap_pdu_t) );
75  if (!pdu) {
76  pbuf_free(pbuf);
77  return NULL;
78  }
79 
81  pdu->pbuf = pbuf;
82  pdu->token = (uint8_t *)pbuf->payload + pdu->max_hdr_size;
83  pdu->alloc_size = pbuf->tot_len - pdu->max_hdr_size;
84  coap_pdu_clear(pdu, pdu->alloc_size);
85 
86  return pdu;
87 }
88 #endif
89 
90 coap_pdu_t *
91 coap_pdu_init(uint8_t type, uint8_t code, uint16_t tid, size_t size) {
92  coap_pdu_t *pdu;
93 
94  pdu = coap_malloc_type(COAP_PDU, sizeof(coap_pdu_t));
95  if (!pdu) return NULL;
96 
97 #if defined(WITH_CONTIKI) || defined(WITH_LWIP)
99  if (size > COAP_MAX_MESSAGE_SIZE_TCP16 + 4)
100  return NULL;
102 #else
104 #endif
105 
106 #ifdef WITH_LWIP
107  pdu->pbuf = pbuf_alloc(PBUF_TRANSPORT, size + pdu->max_hdr_size, PBUF_RAM);
108  if (pdu->pbuf == NULL) {
109  coap_free_type(COAP_PDU, pdu);
110  return NULL;
111  }
112  pdu->token = (uint8_t *)pdu->pbuf->payload + pdu->max_hdr_size;
113 #else /* WITH_LWIP */
114  uint8_t *buf;
115  pdu->alloc_size = min(size, 256);
117  if (buf == NULL) {
118  coap_free_type(COAP_PDU, pdu);
119  return NULL;
120  }
121  pdu->token = buf + pdu->max_hdr_size;
122 #endif /* WITH_LWIP */
123  coap_pdu_clear(pdu, size);
124  pdu->tid = tid;
125  pdu->type = type;
126  pdu->code = code;
127  return pdu;
128 }
129 
130 coap_pdu_t *
131 coap_new_pdu(const struct coap_session_t *session) {
132  coap_pdu_t *pdu = coap_pdu_init(0, 0, 0, coap_session_max_pdu_size(session));
133 #ifndef NDEBUG
134  if (!pdu)
135  coap_log(LOG_CRIT, "coap_new_pdu: cannot allocate memory for new PDU\n");
136 #endif
137  return pdu;
138 }
139 
140 void
142  if (pdu != NULL) {
143 #ifdef WITH_LWIP
144  pbuf_free(pdu->pbuf);
145 #else
146  if (pdu->token != NULL)
148 #endif
149  coap_free_type(COAP_PDU, pdu);
150  }
151 }
152 
153 int
154 coap_pdu_resize(coap_pdu_t *pdu, size_t new_size) {
155  if (new_size > pdu->alloc_size) {
156 #if !defined(WITH_LWIP) && !defined(WITH_CONTIKI)
157  uint8_t *new_hdr;
158  size_t offset;
159 #endif
160  if (pdu->max_size && new_size > pdu->max_size) {
161  coap_log(LOG_WARNING, "coap_pdu_resize: pdu too big\n");
162  return 0;
163  }
164 #if !defined(WITH_LWIP) && !defined(WITH_CONTIKI)
165  if (pdu->data != NULL) {
166  assert(pdu->data > pdu->token);
167  offset = pdu->data - pdu->token;
168  } else {
169  offset = 0;
170  }
171  new_hdr = (uint8_t*)realloc(pdu->token - pdu->max_hdr_size, new_size + pdu->max_hdr_size);
172  if (new_hdr == NULL) {
173  coap_log(LOG_WARNING, "coap_pdu_resize: realloc failed\n");
174  return 0;
175  }
176  pdu->token = new_hdr + pdu->max_hdr_size;
177  if (offset > 0)
178  pdu->data = pdu->token + offset;
179  else
180  pdu->data = NULL;
181 #endif
182  }
183  pdu->alloc_size = new_size;
184  return 1;
185 }
186 
187 static int
188 coap_pdu_check_resize(coap_pdu_t *pdu, size_t size) {
189  if (size > pdu->alloc_size) {
190  size_t new_size = max(256, pdu->alloc_size * 2);
191  while (size > new_size)
192  new_size *= 2;
193  if (pdu->max_size && new_size > pdu->max_size) {
194  new_size = pdu->max_size;
195  if (new_size < size)
196  return 0;
197  }
198  if (!coap_pdu_resize(pdu, new_size))
199  return 0;
200  }
201  return 1;
202 }
203 
204 int
205 coap_add_token(coap_pdu_t *pdu, size_t len, const uint8_t *data) {
206  /* must allow for pdu == NULL as callers may rely on this */
207  if (!pdu || len > 8)
208  return 0;
209 
210  if (pdu->used_size) {
212  "coap_add_token: The token must defined first. Token ignored\n");
213  return 0;
214  }
215  if (!coap_pdu_check_resize(pdu, len))
216  return 0;
217  pdu->token_length = (uint8_t)len;
218  if (len)
219  memcpy(pdu->token, data, len);
220  pdu->max_delta = 0;
221  pdu->used_size = len;
222  pdu->data = NULL;
223 
224  return 1;
225 }
226 
227 /* FIXME: de-duplicate code with coap_add_option_later */
228 size_t
229 coap_add_option(coap_pdu_t *pdu, uint16_t type, size_t len, const uint8_t *data) {
230  size_t optsize;
231  coap_opt_t *opt;
232 
233  assert(pdu);
234  pdu->data = NULL;
235 
236  if (type < pdu->max_delta) {
238  "coap_add_option: options are not in correct order\n");
239  return 0;
240  }
241 
242  if (!coap_pdu_check_resize(pdu,
243  pdu->used_size + coap_opt_encode_size(type - pdu->max_delta, len)))
244  return 0;
245 
246  opt = pdu->token + pdu->used_size;
247 
248  /* encode option and check length */
249  optsize = coap_opt_encode(opt, pdu->alloc_size - pdu->used_size,
250  type - pdu->max_delta, data, len);
251 
252  if (!optsize) {
253  coap_log(LOG_WARNING, "coap_add_option: cannot add option\n");
254  /* error */
255  return 0;
256  } else {
257  pdu->max_delta = type;
258  pdu->used_size += optsize;
259  }
260 
261  return optsize;
262 }
263 
264 /* FIXME: de-duplicate code with coap_add_option */
265 uint8_t*
266 coap_add_option_later(coap_pdu_t *pdu, uint16_t type, size_t len) {
267  size_t optsize;
268  coap_opt_t *opt;
269 
270  assert(pdu);
271  pdu->data = NULL;
272 
273  if (type < pdu->max_delta) {
275  "coap_add_option: options are not in correct order\n");
276  return NULL;
277  }
278 
279  if (!coap_pdu_check_resize(pdu,
280  pdu->used_size + coap_opt_encode_size(type - pdu->max_delta, len)))
281  return 0;
282 
283  opt = pdu->token + pdu->used_size;
284 
285  /* encode option and check length */
286  optsize = coap_opt_encode(opt, pdu->alloc_size - pdu->used_size,
287  type - pdu->max_delta, NULL, len);
288 
289  if (!optsize) {
290  coap_log(LOG_WARNING, "coap_add_option: cannot add option\n");
291  /* error */
292  return NULL;
293  } else {
294  pdu->max_delta = type;
295  pdu->used_size += (uint16_t)optsize;
296  }
297 
298  return opt + optsize - len;
299 }
300 
301 int
302 coap_add_data(coap_pdu_t *pdu, size_t len, const uint8_t *data) {
303  if (len == 0) {
304  return 1;
305  } else {
306  uint8_t *payload = coap_add_data_after(pdu, len);
307  if (payload != NULL)
308  memcpy(payload, data, len);
309  return payload != NULL;
310  }
311 }
312 
313 uint8_t *
314 coap_add_data_after(coap_pdu_t *pdu, size_t len) {
315  assert(pdu);
316  assert(pdu->data == NULL);
317 
318  pdu->data = NULL;
319 
320  if (len == 0)
321  return NULL;
322 
323  if (!coap_pdu_resize(pdu, pdu->used_size + len + 1))
324  return 0;
325  pdu->token[pdu->used_size++] = COAP_PAYLOAD_START;
326  pdu->data = pdu->token + pdu->used_size;
327  pdu->used_size += len;
328  return pdu->data;
329 }
330 
331 int
332 coap_get_data(const coap_pdu_t *pdu, size_t *len, uint8_t **data) {
333  assert(pdu);
334  assert(len);
335  assert(data);
336 
337  *data = pdu->data;
338  if(pdu->data == NULL) {
339  *len = 0;
340  return 0;
341  }
342 
343  *len = pdu->used_size - (pdu->data - pdu->token);
344 
345  return 1;
346 }
347 
348 #ifndef SHORT_ERROR_RESPONSE
349 typedef struct {
350  unsigned char code;
351  const char *phrase;
352 } error_desc_t;
353 
354 /* if you change anything here, make sure, that the longest string does not
355  * exceed COAP_ERROR_PHRASE_LENGTH. */
357  { COAP_RESPONSE_CODE(201), "Created" },
358  { COAP_RESPONSE_CODE(202), "Deleted" },
359  { COAP_RESPONSE_CODE(203), "Valid" },
360  { COAP_RESPONSE_CODE(204), "Changed" },
361  { COAP_RESPONSE_CODE(205), "Content" },
362  { COAP_RESPONSE_CODE(231), "Continue" },
363  { COAP_RESPONSE_CODE(400), "Bad Request" },
364  { COAP_RESPONSE_CODE(401), "Unauthorized" },
365  { COAP_RESPONSE_CODE(402), "Bad Option" },
366  { COAP_RESPONSE_CODE(403), "Forbidden" },
367  { COAP_RESPONSE_CODE(404), "Not Found" },
368  { COAP_RESPONSE_CODE(405), "Method Not Allowed" },
369  { COAP_RESPONSE_CODE(406), "Not Acceptable" },
370  { COAP_RESPONSE_CODE(408), "Request Entity Incomplete" },
371  { COAP_RESPONSE_CODE(412), "Precondition Failed" },
372  { COAP_RESPONSE_CODE(413), "Request Entity Too Large" },
373  { COAP_RESPONSE_CODE(415), "Unsupported Content-Format" },
374  { COAP_RESPONSE_CODE(500), "Internal Server Error" },
375  { COAP_RESPONSE_CODE(501), "Not Implemented" },
376  { COAP_RESPONSE_CODE(502), "Bad Gateway" },
377  { COAP_RESPONSE_CODE(503), "Service Unavailable" },
378  { COAP_RESPONSE_CODE(504), "Gateway Timeout" },
379  { COAP_RESPONSE_CODE(505), "Proxying Not Supported" },
380  { 0, NULL } /* end marker */
381 };
382 
383 const char *
384 coap_response_phrase(unsigned char code) {
385  int i;
386  for (i = 0; coap_error[i].code; ++i) {
387  if (coap_error[i].code == code)
388  return coap_error[i].phrase;
389  }
390  return NULL;
391 }
392 #endif
393 
399 static size_t
401  coap_option_t option;
402  size_t optsize;
403 
404  assert(optp); assert(*optp);
405  assert(length);
406 
407  optsize = coap_opt_parse(*optp, *length, &option);
408  if (optsize) {
409  assert(optsize <= *length);
410 
411  *optp += optsize;
412  *length -= optsize;
413  }
414 
415  return optsize;
416 }
417 
418 size_t
420  const uint8_t *data) {
421  assert(data);
422  size_t header_size = 0;
423 
424  if (proto == COAP_PROTO_TCP || proto==COAP_PROTO_TLS) {
425  uint8_t len = *data >> 4;
426  if (len < 13)
427  header_size = 2;
428  else if (len==13)
429  header_size = 3;
430  else if (len==14)
431  header_size = 4;
432  else
433  header_size = 6;
434  } else if (proto == COAP_PROTO_UDP || proto==COAP_PROTO_DTLS) {
435  header_size = 4;
436  }
437 
438  return header_size;
439 }
440 
441 size_t
443  const uint8_t *data,
444  size_t length) {
445  assert(data);
446  assert(proto == COAP_PROTO_TCP || proto == COAP_PROTO_TLS);
447  assert(coap_pdu_parse_header_size(proto, data) <= length );
448 
449  size_t size = 0;
450 
451  if ((proto == COAP_PROTO_TCP || proto==COAP_PROTO_TLS) && length >= 1) {
452  uint8_t len = *data >> 4;
453  if (len < 13) {
454  size = len;
455  } else if (length >= 2) {
456  if (len==13) {
457  size = (size_t)data[1] + COAP_MESSAGE_SIZE_OFFSET_TCP8;
458  } else if (length >= 3) {
459  if (len==14) {
460  size = ((size_t)data[1] << 8) + data[2] + COAP_MESSAGE_SIZE_OFFSET_TCP16;
461  } else if (length >= 5) {
462  size = ((size_t)data[1] << 24) + ((size_t)data[2] << 16)
463  + ((size_t)data[3] << 8) + data[4] + COAP_MESSAGE_SIZE_OFFSET_TCP32;
464  }
465  }
466  }
467  size += data[0] & 0x0f;
468  }
469 
470  return size;
471 }
472 
473 int
475  uint8_t *hdr = pdu->token - pdu->hdr_size;
476  if (proto == COAP_PROTO_UDP || proto == COAP_PROTO_DTLS) {
477  assert(pdu->hdr_size == 4);
478  if ((hdr[0] >> 6) != COAP_DEFAULT_VERSION) {
479  coap_log(LOG_DEBUG, "coap_pdu_parse: UDP version not supported\n");
480  return 0;
481  }
482  pdu->type = (hdr[0] >> 4) & 0x03;
483  pdu->token_length = hdr[0] & 0x0f;
484  pdu->code = hdr[1];
485  pdu->tid = (uint16_t)hdr[2] << 8 | hdr[3];
486  } else if (proto == COAP_PROTO_TCP || proto == COAP_PROTO_TLS) {
487  assert(pdu->hdr_size >= 2 && pdu->hdr_size <= 6);
488  pdu->type = COAP_MESSAGE_CON;
489  pdu->token_length = hdr[0] & 0x0f;
490  pdu->code = hdr[pdu->hdr_size-1];
491  pdu->tid = 0;
492  } else {
493  coap_log(LOG_DEBUG, "coap_pdu_parse: unsupported protocol\n");
494  return 0;
495  }
496  if (pdu->token_length > pdu->alloc_size) {
497  /* Invalid PDU provided - not wise to assert here though */
498  coap_log(LOG_DEBUG, "coap_pdu_parse: PDU header token size broken\n");
499  pdu->token_length = (uint8_t)pdu->alloc_size;
500  return 0;
501  }
502  return 1;
503 }
504 
505 int
507 
508  /* sanity checks */
509  if (pdu->code == 0) {
510  if (pdu->used_size != 0 || pdu->token_length) {
511  coap_log(LOG_DEBUG, "coap_pdu_parse: empty message is not empty\n");
512  return 0;
513  }
514  }
515 
516  if (pdu->token_length > pdu->used_size || pdu->token_length > 8) {
517  coap_log(LOG_DEBUG, "coap_pdu_parse: invalid Token\n");
518  return 0;
519  }
520 
521  if (pdu->code == 0) {
522  /* empty packet */
523  pdu->used_size = 0;
524  pdu->data = NULL;
525  } else {
526  /* skip header + token */
527  coap_opt_t *opt = pdu->token + pdu->token_length;
528  size_t length = pdu->used_size - pdu->token_length;
529 
530  while (length > 0 && *opt != COAP_PAYLOAD_START) {
531  if ( !next_option_safe( &opt, (size_t *)&length ) ) {
532  coap_log(LOG_DEBUG, "coap_pdu_parse: missing payload start code\n");
533  return 0;
534  }
535  }
536 
537  if (length > 0) {
538  assert(*opt == COAP_PAYLOAD_START);
539  opt++; length--;
540 
541  if (length == 0) {
543  "coap_pdu_parse: message ending in payload start marker\n");
544  return 0;
545  }
546  }
547  if (length > 0)
548  pdu->data = (uint8_t*)opt;
549  else
550  pdu->data = NULL;
551  }
552 
553  return 1;
554 }
555 
556 int
558  const uint8_t *data,
559  size_t length,
560  coap_pdu_t *pdu)
561 {
562  size_t hdr_size;
563 
564  if (length == 0)
565  return 0;
566  hdr_size = coap_pdu_parse_header_size(proto, data);
567  if (!hdr_size || hdr_size > length)
568  return 0;
569  if (hdr_size > pdu->max_hdr_size)
570  return 0;
571  if (!coap_pdu_resize(pdu, length - hdr_size))
572  return 0;
573 #ifndef WITH_LWIP
574  memcpy(pdu->token - hdr_size, data, length);
575 #endif
576  pdu->hdr_size = (uint8_t)hdr_size;
577  pdu->used_size = length - hdr_size;
578  return coap_pdu_parse_header(pdu, proto) && coap_pdu_parse_opt(pdu);
579 }
580 
581 size_t
583  if (proto == COAP_PROTO_UDP || proto == COAP_PROTO_DTLS) {
584  assert(pdu->max_hdr_size >= 4);
585  if (pdu->max_hdr_size < 4) {
587  "coap_pdu_encode_header: not enough space for UDP-style header\n");
588  return 0;
589  }
590  pdu->token[-4] = COAP_DEFAULT_VERSION << 6
591  | pdu->type << 4
592  | pdu->token_length;
593  pdu->token[-3] = pdu->code;
594  pdu->token[-2] = (uint8_t)(pdu->tid >> 8);
595  pdu->token[-1] = (uint8_t)(pdu->tid);
596  pdu->hdr_size = 4;
597  } else if (proto == COAP_PROTO_TCP || proto == COAP_PROTO_TLS) {
598  size_t len;
599  assert(pdu->used_size >= pdu->token_length);
600  if (pdu->used_size < pdu->token_length) {
601  coap_log(LOG_WARNING, "coap_pdu_encode_header: corrupted PDU\n");
602  return 0;
603  }
604  len = pdu->used_size - pdu->token_length;
605  if (len <= COAP_MAX_MESSAGE_SIZE_TCP0) {
606  assert(pdu->max_hdr_size >= 2);
607  if (pdu->max_hdr_size < 2) {
609  "coap_pdu_encode_header: not enough space for TCP0 header\n");
610  return 0;
611  }
612  pdu->token[-2] = (uint8_t)len << 4
613  | pdu->token_length;
614  pdu->token[-1] = pdu->code;
615  pdu->hdr_size = 2;
616  } else if (len <= COAP_MAX_MESSAGE_SIZE_TCP8) {
617  assert(pdu->max_hdr_size >= 3);
618  if (pdu->max_hdr_size < 3) {
620  "coap_pdu_encode_header: not enough space for TCP8 header\n");
621  return 0;
622  }
623  pdu->token[-3] = 13 << 4 | pdu->token_length;
624  pdu->token[-2] = (uint8_t)(len - COAP_MESSAGE_SIZE_OFFSET_TCP8);
625  pdu->token[-1] = pdu->code;
626  pdu->hdr_size = 3;
627  } else if (len <= COAP_MAX_MESSAGE_SIZE_TCP16) {
628  assert(pdu->max_hdr_size >= 4);
629  if (pdu->max_hdr_size < 4) {
631  "coap_pdu_encode_header: not enough space for TCP16 header\n");
632  return 0;
633  }
634  pdu->token[-4] = 14 << 4 | pdu->token_length;
635  pdu->token[-3] = (uint8_t)((len - COAP_MESSAGE_SIZE_OFFSET_TCP16) >> 8);
636  pdu->token[-2] = (uint8_t)(len - COAP_MESSAGE_SIZE_OFFSET_TCP16);
637  pdu->token[-1] = pdu->code;
638  pdu->hdr_size = 4;
639  } else {
640  assert(pdu->max_hdr_size >= 6);
641  if (pdu->max_hdr_size < 6) {
643  "coap_pdu_encode_header: not enough space for TCP32 header\n");
644  return 0;
645  }
646  pdu->token[-6] = 15 << 4 | pdu->token_length;
647  pdu->token[-5] = (uint8_t)((len - COAP_MESSAGE_SIZE_OFFSET_TCP32) >> 24);
648  pdu->token[-4] = (uint8_t)((len - COAP_MESSAGE_SIZE_OFFSET_TCP32) >> 16);
649  pdu->token[-3] = (uint8_t)((len - COAP_MESSAGE_SIZE_OFFSET_TCP32) >> 8);
650  pdu->token[-2] = (uint8_t)(len - COAP_MESSAGE_SIZE_OFFSET_TCP32);
651  pdu->token[-1] = pdu->code;
652  pdu->hdr_size = 6;
653  }
654  } else {
655  coap_log(LOG_WARNING, "coap_pdu_encode_header: unsupported protocol\n");
656  }
657  return pdu->hdr_size;
658 }
uint8_t type
message type
Definition: pdu.h:288
uint8_t code
request method (value 1–10) or response code (value 40-255)
Definition: pdu.h:289
size_t length
the option value length
Definition: option.h:411
#define max(a, b)
Definition: pdu.c:42
uint8_t coap_opt_t
Use byte-oriented access methods here because sliding a complex struct coap_opt_t over the data buffe...
Definition: option.h:25
coap_pdu_t * coap_new_pdu(const struct coap_session_t *session)
Creates a new CoAP PDU.
Definition: pdu.c:131
uint8_t coap_proto_t
Definition: pdu.h:339
int coap_add_data(coap_pdu_t *pdu, size_t len, const uint8_t *data)
Adds given data to the pdu that is passed as first parameter.
Definition: pdu.c:302
#define COAP_RESPONSE_CODE(N)
Definition: pdu.h:132
uint8_t * coap_add_data_after(coap_pdu_t *pdu, size_t len)
Adds given data to the pdu that is passed as first parameter but does not copyt it.
Definition: pdu.c:314
static size_t next_option_safe(coap_opt_t **optp, size_t *length)
Advances *optp to next option if still in PDU.
Definition: pdu.c:400
const char * phrase
Definition: pdu.c:351
#define COAP_MAX_MESSAGE_SIZE_TCP8
Definition: pdu.h:42
#define COAP_PROTO_DTLS
Definition: pdu.h:345
int coap_pdu_parse_header(coap_pdu_t *pdu, coap_proto_t proto)
Decode the protocol specific header for the specified PDU.
Definition: pdu.c:474
size_t coap_session_max_pdu_size(const coap_session_t *session)
Get maximum acceptable PDU size.
Definition: coap_session.c:189
int coap_pdu_parse_opt(coap_pdu_t *pdu)
Verify consistency in the given CoAP PDU structure and locate the data.
Definition: pdu.c:506
Debug.
Definition: coap_debug.h:49
#define COAP_MAX_MESSAGE_SIZE_TCP16
Definition: pdu.h:43
Helpers for handling options in CoAP PDUs.
#define COAP_MESSAGE_SIZE_OFFSET_TCP16
Definition: pdu.h:37
static int coap_pdu_check_resize(coap_pdu_t *pdu, size_t size)
Definition: pdu.c:188
void coap_pdu_clear(coap_pdu_t *pdu, size_t size)
Clears any contents from pdu and resets used_size, and data pointers.
Definition: pdu.c:46
int coap_add_token(coap_pdu_t *pdu, size_t len, const uint8_t *data)
Adds token of length len to pdu.
Definition: pdu.c:205
int coap_pdu_resize(coap_pdu_t *pdu, size_t new_size)
Dynamically grows the size of pdu to new_size.
Definition: pdu.c:154
#define COAP_MESSAGE_SIZE_OFFSET_TCP32
Definition: pdu.h:38
#define COAP_PROTO_UDP
Definition: pdu.h:344
size_t coap_opt_encode_size(uint16_t delta, size_t length)
Compute storage bytes needed for an option with given delta and length.
Definition: option.c:388
size_t coap_pdu_encode_header(coap_pdu_t *pdu, coap_proto_t proto)
Compose the protocol specific header for the specified PDU.
Definition: pdu.c:582
#define COAP_DEFAULT_VERSION
Definition: pdu.h:64
structure for CoAP PDUs token, if any, follows the fixed size header, then options until payload mark...
Definition: pdu.h:287
uint8_t * data
first byte of payload, if any
Definition: pdu.h:299
Warning.
Definition: coap_debug.h:46
error_desc_t coap_error[]
Definition: pdu.c:356
Representation of CoAP options.
Definition: option.h:31
#define assert(...)
Definition: mem.c:18
uint8_t * data
the option data
Definition: option.h:412
#define min(a, b)
Definition: pdu.c:38
size_t used_size
used bytes of storage for token, options and payload
Definition: pdu.h:296
size_t alloc_size
allocated storage for token, options and payload
Definition: pdu.h:295
#define COAP_MESSAGE_SIZE_OFFSET_TCP8
Definition: pdu.h:36
uint8_t * coap_add_option_later(coap_pdu_t *pdu, uint16_t type, size_t len)
Adds option of given type to pdu that is passed as first parameter, but does not write a value...
Definition: pdu.c:266
uint8_t * token
first byte of token, if any, or options
Definition: pdu.h:298
size_t max_size
maximum size for token, options and payload, or zero for variable size pdu
Definition: pdu.h:297
size_t coap_opt_parse(const coap_opt_t *opt, size_t length, coap_option_t *result)
Parses the option pointed to by opt into result.
Definition: option.c:46
#define COAP_MESSAGE_CON
Definition: pdu.h:72
#define COAP_PROTO_TLS
Definition: pdu.h:347
int coap_get_data(const coap_pdu_t *pdu, size_t *len, uint8_t **data)
Retrieves the length and data pointer of specified PDU.
Definition: pdu.c:332
size_t coap_add_option(coap_pdu_t *pdu, uint16_t type, size_t len, const uint8_t *data)
Adds option of given type to pdu that is passed as first parameter.
Definition: pdu.c:229
Pre-defined constants that reflect defaults for CoAP.
void coap_delete_pdu(coap_pdu_t *pdu)
Dispose of an CoAP PDU and frees associated storage.
Definition: pdu.c:141
uint16_t max_delta
highest option number
Definition: pdu.h:294
const char * coap_response_phrase(unsigned char code)
Returns a human-readable response phrase for the specified CoAP response code.
Definition: pdu.c:384
#define COAP_PAYLOAD_START
Definition: pdu.h:257
int coap_pdu_parse(coap_proto_t proto, const uint8_t *data, size_t length, coap_pdu_t *pdu)
Parses data into the CoAP PDU structure given in result.
Definition: pdu.c:557
size_t coap_opt_encode(coap_opt_t *opt, size_t maxlen, uint16_t delta, const uint8_t *val, size_t length)
Encodes option with given delta into opt.
Definition: option.c:409
unsigned char code
Definition: pdu.c:350
#define COAP_MAX_MESSAGE_SIZE_TCP0
Definition: pdu.h:41
uint8_t max_hdr_size
space reserved for protocol-specific header
Definition: pdu.h:290
#define COAP_PDU_MAX_TCP_HEADER_SIZE
Definition: pdu.h:318
void * coap_malloc_type(coap_memory_tag_t type, size_t size)
Allocates a chunk of size bytes and returns a pointer to the newly allocated memory.
uint8_t hdr_size
actaul size used for protocol-specific header
Definition: pdu.h:291
size_t coap_pdu_parse_header_size(coap_proto_t proto, const uint8_t *data)
Interprets data to determine the number of bytes in the header.
Definition: pdu.c:419
#define coap_log(level,...)
Logging function.
Definition: coap_debug.h:122
coap_pdu_t * coap_pdu_init(uint8_t type, uint8_t code, uint16_t tid, size_t size)
Creates a new CoAP PDU with at least enough storage space for the given size maximum message size...
Definition: pdu.c:91
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
unsigned char uint8_t
Definition: uthash.h:79
uint8_t token_length
length of Token
Definition: pdu.h:292
Critical.
Definition: coap_debug.h:44
Definition: mem.h:37
#define COAP_PROTO_TCP
Definition: pdu.h:346
#define COAP_PDU_MAX_UDP_HEADER_SIZE
Definition: pdu.h:317
uint16_t tid
transaction id, if any, in regular host byte order
Definition: pdu.h:293
size_t coap_pdu_parse_size(coap_proto_t proto, const uint8_t *data, size_t length)
Parses data to extract the message size.
Definition: pdu.c:442