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