libcoap 4.3.5-develop-e3f8cd0
Loading...
Searching...
No Matches
coap_pdu.c
Go to the documentation of this file.
1/* coap_pdu.c -- CoAP PDU handling
2 *
3 * Copyright (C) 2010--2026 Olaf Bergmann <bergmann@tzi.org>
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 *
7 * This file is part of the CoAP library libcoap. Please see
8 * README for terms of use.
9 */
10
17
18#if defined(HAVE_LIMITS_H)
19#include <limits.h>
20#endif
21
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25#ifndef __ZEPHYR__
26#ifdef HAVE_ARPA_INET_H
27#include <arpa/inet.h>
28#endif
29#ifdef HAVE_WINSOCK2_H
30#include <winsock2.h>
31#endif
32#endif /* !__ZEPHYR__ */
33
34#include <ctype.h>
35
36#ifndef min
37#define min(a,b) ((a) < (b) ? (a) : (b))
38#endif
39
40#ifndef max
41#define max(a,b) ((a) > (b) ? (a) : (b))
42#endif
43
44void
45coap_pdu_clear(coap_pdu_t *pdu, size_t size) {
46 assert(pdu);
47 assert(pdu->token);
49 if (pdu->alloc_size > size)
50 pdu->alloc_size = size;
51 pdu->type = 0;
52 pdu->code = 0;
53 pdu->ref = 0;
54 pdu->hdr_size = 0;
55 pdu->actual_token.length = 0;
56 pdu->e_token_length = 0;
57 pdu->crit_opt = 0;
58 pdu->mid = 0;
59 pdu->max_opt = 0;
60 pdu->max_size = size;
61 pdu->used_size = 0;
62 pdu->data = NULL;
63 pdu->body_data = NULL;
64 pdu->body_length = 0;
65 pdu->body_offset = 0;
66 pdu->body_total = 0;
67 pdu->lg_xmit = NULL;
68 pdu->session = NULL;
69 pdu->data_free = NULL;
70}
71
72#ifdef WITH_LWIP
74coap_pdu_from_pbuf(struct pbuf *pbuf) {
75 coap_pdu_t *pdu;
76
77 if (pbuf == NULL)
78 return NULL;
79
80 LWIP_ASSERT("Can only deal with contiguous PBUFs (increase PBUF_POOL_BUFSIZE)",
81 pbuf->tot_len == pbuf->len);
82 LWIP_ASSERT("coap_io_do_io needs to receive an exclusive copy of the incoming pbuf",
83 pbuf->ref == 1);
84
85 pdu = coap_malloc_type(COAP_PDU, sizeof(coap_pdu_t));
86 if (!pdu) {
87 pbuf_free(pbuf);
88 return NULL;
89 }
90
92 pdu->pbuf = pbuf;
93 pdu->token = (uint8_t *)pbuf->payload + pdu->max_hdr_size;
94 pdu->alloc_size = pbuf->tot_len - pdu->max_hdr_size;
95 coap_pdu_clear(pdu, pdu->alloc_size);
96
97 return pdu;
98}
99#endif /* LWIP */
100
103 size_t size) {
104 coap_pdu_t *pdu;
105
106#ifndef RIOT_VERSION
107 assert(type <= 0x3);
108 assert(code <= 0xff);
109 assert(mid >= 0 && mid <= 0xffff);
110#endif /* RIOT_VERSION */
111
112#if defined(WITH_LWIP) && MEMP_USE_CUSTOM_POOLS
113#if MEMP_STATS
114 /* Reserve 1 PDU for a response packet */
115 if (memp_pools[MEMP_COAP_PDU]->stats->used + 1 >=
116 memp_pools[MEMP_COAP_PDU]->stats->avail) {
117 memp_pools[MEMP_COAP_PDU]->stats->err++;
118 return NULL;
119 }
120#endif /* MEMP_STATS */
121#endif /* LWIP && MEMP_USE_CUSTOM_POOLS */
122 pdu = coap_malloc_type(COAP_PDU, sizeof(coap_pdu_t));
123 if (!pdu)
124 return NULL;
125
126#if COAP_DEFAULT_MAX_PDU_RX_SIZE <= COAP_MAX_MESSAGE_SIZE_TCP16
127 /* on TCP, the CoAP header will also have a maximum length of 4 bytes */
129#else
131#endif
132 if (size > ((size_t)COAP_DEFAULT_MAX_PDU_RX_SIZE - pdu->max_hdr_size)) {
134 return NULL;
135 }
136
137 pdu->alloc_size = min(size, COAP_DEFAULT_MTU);
138#ifdef WITH_LWIP
139 pdu->pbuf = pbuf_alloc(PBUF_TRANSPORT, pdu->alloc_size + pdu->max_hdr_size, PBUF_RAM);
140 if (pdu->pbuf == NULL) {
142 return NULL;
143 }
144 pdu->token = (uint8_t *)pdu->pbuf->payload + pdu->max_hdr_size;
145#else /* WITH_LWIP */
146 uint8_t *buf;
148 if (buf == NULL) {
150 return NULL;
151 }
152 pdu->token = buf + pdu->max_hdr_size;
153#endif /* WITH_LWIP */
154 coap_pdu_clear(pdu, size);
155 pdu->mid = mid;
156 pdu->type = type;
157 pdu->code = code;
158 return pdu;
159}
160
163 coap_session_t *session) {
164 coap_pdu_t *pdu;
165
166 coap_lock_lock(return NULL);
167 pdu = coap_new_pdu_lkd(type, code, session);
169 return pdu;
170}
171
174 coap_session_t *session) {
175 coap_pdu_t *pdu;
176
178 pdu = coap_pdu_init(type, code, coap_new_message_id_lkd(session),
180 if (!pdu)
181 coap_log_crit("coap_new_pdu: cannot allocate memory for new PDU (size = %" PRIuS ")\n",
183 return pdu;
184}
185
186COAP_API void
192
193void
195 if (pdu != NULL) {
196 if (pdu->ref) {
197 pdu->ref--;
198 return;
199 }
200#ifdef WITH_LWIP
201 pbuf_free(pdu->pbuf);
202#else
203 if (pdu->token != NULL)
205#endif
208 }
209}
210
213 coap_session_t *session,
214 size_t token_length,
215 const uint8_t *token,
216 coap_opt_filter_t *drop_options) {
217 coap_pdu_t *new_pdu;
218
219 coap_lock_lock(return NULL);
220 new_pdu = coap_pdu_duplicate_lkd(old_pdu,
221 session,
222 token_length,
223 token,
224 drop_options, COAP_BOOL_FALSE);
226 return new_pdu;
227}
228
229
230/*
231 * Note: This does not include any data, just the token and options
232 */
235 coap_session_t *session,
236 size_t token_length,
237 const uint8_t *token,
238 coap_opt_filter_t *drop_options,
239 coap_bool_t expand_opt_abb) {
240#if COAP_CLIENT_SUPPORT
241 uint8_t doing_first = session->doing_first;
242#endif /* COAP_CLIENT_SUPPORT */
243 coap_pdu_t *pdu;
244
246 /*
247 * Need to make sure that coap_session_max_pdu_size_lkd() immediately
248 * returns, rather than wait for the first CSM response from remote
249 * that indicates BERT size (TCP/TLS only) as this may be called early
250 * the OSCORE logic.
251 */
252#if COAP_CLIENT_SUPPORT
253 session->doing_first = 0;
254#endif /* COAP_CLIENT_SUPPORT */
255 pdu = coap_pdu_init(old_pdu->type, old_pdu->code,
257 max(old_pdu->max_size,
259#if COAP_CLIENT_SUPPORT
260 /* Restore any pending waits */
261 session->doing_first = doing_first;
262#endif /* COAP_CLIENT_SUPPORT */
263 if (pdu == NULL)
264 return NULL;
265
266 coap_add_token(pdu, token_length, token);
267 pdu->lg_xmit = old_pdu->lg_xmit;
268
269 if (drop_options == NULL && expand_opt_abb == COAP_BOOL_FALSE) {
270 /* Drop COAP_PAYLOAD_START as well if data */
271 size_t length = old_pdu->used_size - old_pdu->e_token_length -
272 (old_pdu->data ?
273 old_pdu->used_size - (old_pdu->data - old_pdu->token) +1 : 0);
274 if (!coap_pdu_resize(pdu, length + pdu->e_token_length))
275 goto fail;
276 /* Copy the options but not any data across */
277 memcpy(pdu->token + pdu->e_token_length,
278 old_pdu->token + old_pdu->e_token_length, length);
279 pdu->used_size += length;
280 pdu->max_opt = old_pdu->max_opt;
281 } else {
282 /* Copy across all the options the slow way */
283 coap_opt_iterator_t opt_iter;
284 coap_opt_t *option;
285
286 coap_option_iterator_init(old_pdu, &opt_iter, COAP_OPT_ALL);
287 while ((option = coap_option_next(&opt_iter))) {
288 if (opt_iter.number == COAP_OPTION_URI_PATH_ABB && expand_opt_abb == COAP_BOOL_TRUE) {
289 uint32_t value;
290 const char *exp;
291
293 coap_opt_length(option));
295 if (exp) {
296 while (exp) {
297 const char *next = strchr(exp, '/');
298
300 next ? (int)(next - exp) : (int)strlen(exp),
301 (const uint8_t *)exp))
302 goto fail;
303 if (next)
304 exp = next + 1;
305 else
306 exp = NULL;
307 }
308 } else {
310 coap_log_info("coap_pdu_duplicate: Uri-Path-Abbrev value %" PRIu32 " not known for fallback\n",
311 value);
312 return NULL;
313 }
314 } else {
315 if (drop_options) {
316 if (coap_option_filter_get(drop_options, opt_iter.number))
317 continue;
318 }
319 if (!coap_insert_option(pdu, opt_iter.number,
320 coap_opt_length(option),
321 coap_opt_value(option)))
322 goto fail;
323 }
324 }
325 }
326 return pdu;
327
328fail:
330 return NULL;
331}
332
333
334/*
335 * The new size does not include the coap header (max_hdr_size)
336 */
337int
338coap_pdu_resize(coap_pdu_t *pdu, size_t new_size) {
339 if (new_size > pdu->alloc_size) {
340 /* Expanding the PDU usage */
341#if !defined(WITH_LWIP)
342 uint8_t *new_hdr;
343#else /* WITH_LWIP */
344 struct pbuf *new_hdr;
345#endif /* WITH_LWIP */
346 size_t offset;
347
348 if (pdu->max_size && new_size > pdu->max_size) {
349 coap_log_warn("coap_pdu_resize: pdu too big\n");
350 return 0;
351 }
352 if (pdu->data != NULL) {
353 assert(pdu->data > pdu->token);
354 offset = pdu->data - pdu->token;
355 } else {
356 offset = 0;
357 }
358#if !defined(WITH_LWIP)
359 new_hdr = (uint8_t *)coap_realloc_type(COAP_PDU_BUF,
360 pdu->token - pdu->max_hdr_size,
361 new_size + pdu->max_hdr_size);
362#else /* WITH_LWIP */
363 new_hdr = pbuf_alloc(PBUF_TRANSPORT, new_size + pdu->max_hdr_size, PBUF_RAM);
364#endif /* WITH_LWIP */
365 if (new_hdr == NULL) {
366 coap_log_warn("coap_pdu_resize: realloc failed\n");
367 return 0;
368 }
369#if !defined(WITH_LWIP)
370 pdu->token = new_hdr + pdu->max_hdr_size;
371#else /* WITH_LWIP */
372 memcpy(new_hdr->payload, pdu->pbuf->payload, pdu->pbuf->len);
373 pbuf_free(pdu->pbuf);
374 pdu->pbuf = new_hdr;
375 pdu->token = (uint8_t *)pdu->pbuf->payload + pdu->max_hdr_size;
376#endif /* WITH_LWIP */
377 if (offset > 0)
378 pdu->data = pdu->token + offset;
379 else
380 pdu->data = NULL;
382 pdu->actual_token.s = &pdu->token[0];
384 pdu->actual_token.s = &pdu->token[1];
385 else
386 pdu->actual_token.s = &pdu->token[2];
387 pdu->alloc_size = new_size;
388 }
389 return 1;
390}
391
392int
394 if (size > pdu->alloc_size) {
395 size_t new_size = max(256, pdu->alloc_size * 2);
396 while (size > new_size)
397 new_size *= 2;
398 if (pdu->max_size && new_size > pdu->max_size) {
399 new_size = pdu->max_size;
400 if (new_size < size)
401 return 0;
402 }
403 if (!coap_pdu_resize(pdu, new_size))
404 return 0;
405 }
406 return 1;
407}
408
409int
410coap_add_token(coap_pdu_t *pdu, size_t len, const uint8_t *data) {
411 size_t bias = 0;
412
413 /* must allow for pdu == NULL as callers may rely on this */
414 if (!pdu)
415 return 0;
416
417 if (pdu->used_size) {
418 coap_log_warn("coap_add_token: The token must defined first. Token ignored\n");
419 return 0;
420 }
421 pdu->actual_token.length = len;
422 if (len < COAP_TOKEN_EXT_1B_BIAS) {
423 bias = 0;
424 } else if (len < COAP_TOKEN_EXT_2B_BIAS) {
425 bias = 1;
426 } else if (len <= COAP_TOKEN_EXT_MAX) {
427 bias = 2;
428 } else {
429 coap_log_warn("coap_add_token: Token size too large. Token ignored\n");
430 return 0;
431 }
432 if (!coap_pdu_check_resize(pdu, len + bias)) {
433 coap_log_warn("coap_add_token: Insufficient space for token. Token ignored\n");
434 return 0;
435 }
436
437 pdu->actual_token.length = len;
438 pdu->actual_token.s = &pdu->token[bias];
439 pdu->e_token_length = (uint32_t)(len + bias);
440 if (len) {
441 switch (bias) {
442 case 0:
443 memcpy(pdu->token, data, len);
444 break;
445 case 1:
446 pdu->token[0] = (uint8_t)(len - COAP_TOKEN_EXT_1B_BIAS);
447 memcpy(&pdu->token[1], data, len);
448 break;
449 case 2:
450 pdu->token[0] = (uint8_t)((len - COAP_TOKEN_EXT_2B_BIAS) >> 8);
451 pdu->token[1] = (uint8_t)((len - COAP_TOKEN_EXT_2B_BIAS) & 0xff);
452 memcpy(&pdu->token[2], data, len);
453 break;
454 default:
455 break;
456 }
457 }
458 pdu->max_opt = 0;
459 pdu->used_size = len + bias;
460 pdu->data = NULL;
461
462 return 1;
463}
464
465/* It is assumed that coap_encode_var_safe8() has been called to reduce data */
466int
467coap_update_token(coap_pdu_t *pdu, size_t len, const uint8_t *data) {
468 size_t bias = 0;
469 size_t old_len;
470
471 /* must allow for pdu == NULL as callers may rely on this */
472 if (!pdu)
473 return 0;
474
475 if (pdu->used_size == 0) {
476 return coap_add_token(pdu, len, data);
477 }
478
479 old_len = pdu->e_token_length;
480
481 if (len < COAP_TOKEN_EXT_1B_BIAS) {
482 bias = 0;
483 } else if (len < COAP_TOKEN_EXT_2B_BIAS) {
484 bias = 1;
485 } else if (len <= COAP_TOKEN_EXT_MAX) {
486 bias = 2;
487 } else {
488 coap_log_warn("coap_add_token: Token size too large. Token ignored\n");
489 return 0;
490 }
491 if ((len + bias) == pdu->e_token_length) {
492 /* Easy case - just data has changed */
493 } else if ((len + bias) > pdu->e_token_length) {
494 if (!coap_pdu_check_resize(pdu,
495 pdu->used_size + (len + bias) - pdu->e_token_length)) {
496 coap_log_warn("Failed to update token\n");
497 return 0;
498 }
499 memmove(&pdu->token[(len + bias) - pdu->e_token_length],
500 pdu->token, pdu->used_size);
501 pdu->used_size += len + bias - pdu->e_token_length;
502 if (pdu->data) {
503 pdu->data += (len + bias) - pdu->e_token_length;
504 }
505 } else {
506 pdu->used_size -= pdu->e_token_length - (len + bias);
507 memmove(pdu->token, &pdu->token[pdu->e_token_length - (len + bias)], pdu->used_size);
508 if (pdu->data) {
509 pdu->data -= pdu->e_token_length - (len + bias);
510 }
511 }
512
513 pdu->actual_token.length = len;
514 pdu->actual_token.s = &pdu->token[bias];
515 pdu->e_token_length = (uint8_t)(len + bias);
516 if (len) {
517 switch (bias) {
518 case 0:
519 if (memcmp(pdu->token, data, len) != 0)
520 memcpy(pdu->token, data, len);
521 break;
522 case 1:
523 pdu->token[0] = (uint8_t)(len - COAP_TOKEN_EXT_1B_BIAS);
524 memcpy(&pdu->token[1], data, len);
525 break;
526 case 2:
527 pdu->token[0] = (uint8_t)((len - COAP_TOKEN_EXT_2B_BIAS) >> 8);
528 pdu->token[1] = (uint8_t)((len - COAP_TOKEN_EXT_2B_BIAS) & 0xff);
529 memcpy(&pdu->token[2], data, len);
530 break;
531 default:
532 break;
533 }
534 }
535 if (old_len != pdu->e_token_length && pdu->hdr_size && pdu->session)
536 /* Need to fix up the header */
537 if (!coap_pdu_encode_header(pdu, pdu->session->proto))
538 return 0;
539 return 1;
540}
541
542int
544 coap_opt_iterator_t opt_iter;
545 coap_opt_t *option;
546 coap_opt_t *next_option = NULL;
547 size_t opt_delta;
548 coap_option_t decode_this;
549 coap_option_t decode_next;
550
551 /* Need to locate where in current options to remove this one */
553 while ((option = coap_option_next(&opt_iter))) {
554 if (opt_iter.number == number) {
555 /* Found option to delete */
556 break;
557 }
558 }
559 if (!option)
560 return 0;
561
562 if (!coap_opt_parse(option, pdu->used_size - (option - pdu->token),
563 &decode_this))
564 return 0;
565
566 next_option = coap_option_next(&opt_iter);
567 if (next_option) {
568 if (!coap_opt_parse(next_option,
569 pdu->used_size - (next_option - pdu->token),
570 &decode_next))
571 return 0;
572 opt_delta = decode_this.delta + decode_next.delta;
573 if (opt_delta < 13) {
574 /* can simply update the delta of next option */
575 next_option[0] = (next_option[0] & 0x0f) + (coap_opt_t)(opt_delta << 4);
576 } else if (opt_delta < 269 && decode_next.delta < 13) {
577 /* next option delta size increase */
578 next_option -= 1;
579 next_option[0] = (next_option[1] & 0x0f) + (13 << 4);
580 next_option[1] = (coap_opt_t)(opt_delta - 13);
581 } else if (opt_delta < 269) {
582 /* can simply update the delta of next option */
583 next_option[1] = (coap_opt_t)(opt_delta - 13);
584 } else if (decode_next.delta < 13) { /* opt_delta >= 269 */
585 /* next option delta size increase */
586 if (next_option - option < 2) {
587 /* Need to shuffle everything up by 1 before decrement */
588 if (!coap_pdu_check_resize(pdu, pdu->used_size + 1))
589 return 0;
590 /* Possible a re-size took place with a realloc() */
591 /* Need to rediscover this and next options */
593 while ((option = coap_option_next(&opt_iter))) {
594 if (opt_iter.number == number) {
595 /* Found option to delete */
596 break;
597 }
598 }
599 next_option = coap_option_next(&opt_iter);
600 assert(option != NULL);
601 assert(next_option != NULL);
602 memmove(&next_option[1], next_option,
603 pdu->used_size - (next_option - pdu->token));
604 pdu->used_size++;
605 if (pdu->data)
606 pdu->data++;
607 next_option++;
608 }
609 next_option -= 2;
610 next_option[0] = (next_option[2] & 0x0f) + (14 << 4);
611 next_option[1] = (coap_opt_t)((opt_delta - 269) >> 8);
612 next_option[2] = (opt_delta - 269) & 0xff;
613 } else if (decode_next.delta < 269) { /* opt_delta >= 269 */
614 /* next option delta size increase */
615 next_option -= 1;
616 next_option[0] = (next_option[1] & 0x0f) + (14 << 4);
617 next_option[1] = (coap_opt_t)((opt_delta - 269) >> 8);
618 next_option[2] = (opt_delta - 269) & 0xff;
619 } else { /* decode_next.delta >= 269 && opt_delta >= 269 */
620 next_option[1] = (coap_opt_t)((opt_delta - 269) >> 8);
621 next_option[2] = (opt_delta - 269) & 0xff;
622 }
623 } else {
624 next_option = option + coap_opt_encode_size(decode_this.delta,
625 coap_opt_length(option));
626 pdu->max_opt -= decode_this.delta;
627 }
628 if (pdu->used_size - (next_option - pdu->token))
629 memmove(option, next_option, pdu->used_size - (next_option - pdu->token));
630 pdu->used_size -= next_option - option;
631 if (pdu->data)
632 pdu->data -= next_option - option;
633 return 1;
634}
635
636int
638 /* Validate that the option is repeatable */
639 switch (number) {
640 /* Ignore list of genuine repeatable */
642 case COAP_OPTION_ETAG:
648 case COAP_OPTION_RTAG:
649 break;
650 /* Protest at the known non-repeatable options and ignore them */
669 case COAP_OPTION_ECHO:
671 coap_log_info("Option number %d is not defined as repeatable - dropped\n",
672 number);
673 return 0;
674 default:
675 coap_log_info("Option number %d is not defined as repeatable\n",
676 number);
677 /* Accepting it after warning as there may be user defineable options */
678 break;
679 }
680 return 1;
681}
682
683size_t
685 const uint8_t *data) {
686 coap_opt_iterator_t opt_iter;
687 coap_opt_t *option;
688 uint16_t prev_number = 0;
689 size_t shift;
690 size_t opt_delta;
691 coap_option_t decode;
692 size_t shrink = 0;
693
694 if (number >= pdu->max_opt)
695 return coap_add_option_internal(pdu, number, len, data);
696
697 /* Need to locate where in current options to insert this one */
699 while ((option = coap_option_next(&opt_iter))) {
700 if (opt_iter.number > number) {
701 /* Found where to insert */
702 break;
703 }
704 prev_number = opt_iter.number;
705 }
706 if (option == NULL) {
707 /* Code is broken somewhere */
708 coap_log_warn("coap_insert_option: Broken max_opt\n");
709 return 0;
710 }
711
712 /* size of option inc header to insert */
713 shift = coap_opt_encode_size(number - prev_number, len);
714
715 /* size of next option (header may shrink in size as delta changes */
716 if (!coap_opt_parse(option, pdu->used_size - (option - pdu->token), &decode))
717 return 0;
718 opt_delta = opt_iter.number - number;
719 if (opt_delta == 0) {
720 if (!coap_option_check_repeatable(number))
721 return 0;
722 }
723
724 if (!coap_pdu_check_resize(pdu,
725 pdu->used_size + shift - shrink))
726 return 0;
727
728 /* Possible a re-size took place with a realloc() */
729 /* Need to locate where in current options to insert this one */
731 while ((option = coap_option_next(&opt_iter))) {
732 if (opt_iter.number > number) {
733 /* Found where to insert */
734 break;
735 }
736 }
737 assert(option != NULL);
738
739 if (decode.delta < 13) {
740 /* can simply patch in the new delta of next option */
741 option[0] = (option[0] & 0x0f) + (coap_opt_t)(opt_delta << 4);
742 } else if (decode.delta < 269 && opt_delta < 13) {
743 /* option header is going to shrink by one byte */
744 option[1] = (option[0] & 0x0f) + (coap_opt_t)(opt_delta << 4);
745 shrink = 1;
746 } else if (decode.delta < 269 && opt_delta < 269) {
747 /* can simply patch in the new delta of next option */
748 option[1] = (coap_opt_t)(opt_delta - 13);
749 } else if (opt_delta < 13) {
750 /* option header is going to shrink by two bytes */
751 option[2] = (option[0] & 0x0f) + (coap_opt_t)(opt_delta << 4);
752 shrink = 2;
753 } else if (opt_delta < 269) {
754 /* option header is going to shrink by one bytes */
755 option[1] = (option[0] & 0x0f) + 0xd0;
756 option[2] = (coap_opt_t)(opt_delta - 13);
757 shrink = 1;
758 } else {
759 /* can simply patch in the new delta of next option */
760 option[1] = (coap_opt_t)((opt_delta - 269) >> 8);
761 option[2] = (opt_delta - 269) & 0xff;
762 }
763
764 memmove(&option[shift], &option[shrink],
765 pdu->used_size - (option - pdu->token) - shrink);
766 if (!coap_opt_encode(option, pdu->alloc_size - pdu->used_size,
767 number - prev_number, data, len))
768 return 0;
769
770 if (shift >= shrink) {
771 pdu->used_size += shift - shrink;
772 if (pdu->data)
773 pdu->data += shift - shrink;
774 } else {
775 pdu->used_size -= shrink - shift;
776 if (pdu->data)
777 pdu->data -= shrink - shift;
778 }
779 return shift;
780}
781
782size_t
784 const uint8_t *data) {
785 coap_opt_iterator_t opt_iter;
786 coap_opt_t *option;
787 coap_option_t decode;
788 size_t new_length = 0;
789 size_t old_length = 0;
790
791 option = coap_check_option(pdu, number, &opt_iter);
792 if (!option)
793 return coap_insert_option(pdu, number, len, data);
794
795 old_length = coap_opt_parse(option, (size_t)-1, &decode);
796 if (old_length == 0)
797 return 0;
798 new_length = coap_opt_encode_size(decode.delta, len);
799
800 if (new_length > old_length) {
801 if (!coap_pdu_check_resize(pdu,
802 pdu->used_size + new_length - old_length))
803 return 0;
804 /* Possible a re-size took place with a realloc() */
805 option = coap_check_option(pdu, number, &opt_iter);
806 }
807
808 if (new_length != old_length)
809 memmove(&option[new_length], &option[old_length],
810 pdu->used_size - (option - pdu->token) - old_length);
811
812 if (!coap_opt_encode(option, new_length,
813 decode.delta, data, len))
814 return 0;
815
816 if (new_length >= old_length) {
817 pdu->used_size += new_length - old_length;
818 if (pdu->data)
819 pdu->data += new_length - old_length;
820 } else {
821 pdu->used_size -= old_length - new_length;
822 if (pdu->data)
823 pdu->data -= old_length - new_length;
824 }
825 return 1;
826}
827
828size_t
830 const uint8_t *data) {
831 if (pdu->data) {
832 coap_log_warn("coap_add_optlist_pdu: PDU already contains data\n");
833 return 0;
834 }
835 return coap_add_option_internal(pdu, number, len, data);
836}
837
838size_t
840 const uint8_t *data) {
841 size_t optsize;
842 coap_opt_t *opt;
843
844 assert(pdu);
845
846 if (number == pdu->max_opt) {
847 if (!coap_option_check_repeatable(number))
848 return 0;
849 }
850
851 if (COAP_PDU_IS_REQUEST(pdu) &&
852 (number == COAP_OPTION_PROXY_URI ||
853 number == COAP_OPTION_PROXY_SCHEME)) {
854 /*
855 * Need to check whether there is a hop-limit option. If not, it needs
856 * to be inserted by default (RFC 8768).
857 */
858 coap_opt_iterator_t opt_iter;
859
860 if (coap_check_option(pdu, COAP_OPTION_HOP_LIMIT, &opt_iter) == NULL) {
861 size_t hop_limit = COAP_OPTION_HOP_LIMIT;
862
863 coap_insert_option(pdu, COAP_OPTION_HOP_LIMIT, 1, (uint8_t *)&hop_limit);
864 }
865 }
866
867 if (number < pdu->max_opt) {
868 coap_log_debug("coap_add_option: options are not in correct order\n");
869 return coap_insert_option(pdu, number, len, data);
870 }
871
872 optsize = coap_opt_encode_size(number - pdu->max_opt, len);
873 if (!coap_pdu_check_resize(pdu,
874 pdu->used_size + optsize))
875 return 0;
876
877 if (pdu->data) {
878 /* include option delimiter */
879 memmove(&pdu->data[optsize-1], &pdu->data[-1],
880 pdu->used_size - (pdu->data - pdu->token) + 1);
881 opt = pdu->data -1;
882 pdu->data += optsize;
883 } else {
884 opt = pdu->token + pdu->used_size;
885 }
886
887 /* encode option and check length */
888 optsize = coap_opt_encode(opt, pdu->alloc_size - pdu->used_size,
889 number - pdu->max_opt, data, len);
890
891 if (!optsize) {
892 coap_log_warn("coap_add_option: cannot add option\n");
893 /* error */
894 return 0;
895 } else {
896 pdu->max_opt = number;
897 pdu->used_size += optsize;
898 }
899
900 return optsize;
901}
902
903int
904coap_add_data(coap_pdu_t *pdu, size_t len, const uint8_t *data) {
905 if (len == 0) {
906 return 1;
907 } else {
908 uint8_t *payload = coap_add_data_after(pdu, len);
909 if (payload != NULL)
910 memcpy(payload, data, len);
911 return payload != NULL;
912 }
913}
914
915uint8_t *
917 assert(pdu);
918 if (pdu->data) {
919 coap_log_warn("coap_add_data: PDU already contains data\n");
920 return 0;
921 }
922
923 if (len == 0)
924 return NULL;
925
926 if (!coap_pdu_resize(pdu, pdu->used_size + len + 1))
927 return 0;
928 pdu->token[pdu->used_size++] = COAP_PAYLOAD_START;
929 pdu->data = pdu->token + pdu->used_size;
930 pdu->used_size += len;
931 return pdu->data;
932}
933
934int
935coap_get_data(const coap_pdu_t *pdu, size_t *len, const uint8_t **data) {
936 size_t offset;
937 size_t total;
938
939 return coap_get_data_large(pdu, len, data, &offset, &total);
940}
941
942int
943coap_get_data_large(const coap_pdu_t *pdu, size_t *len, const uint8_t **data,
944 size_t *offset, size_t *total) {
945 assert(pdu);
946 assert(len);
947 assert(data);
948
949 *offset = pdu->body_offset;
950 *total = pdu->body_total;
951 if (pdu->body_data) {
952 *data = pdu->body_data;
953 *len = pdu->body_length;
954 return 1;
955 }
956 *data = pdu->data;
957 if (pdu->data == NULL) {
958 *len = 0;
959 *total = 0;
960 return 0;
961 }
962
963 *len = pdu->used_size - (pdu->data - pdu->token);
964 if (*total == 0)
965 *total = *len;
966
967 return 1;
968}
969
970#ifndef SHORT_ERROR_RESPONSE
971typedef struct {
972 unsigned char code;
973 const char *phrase;
975
976/* if you change anything here, make sure, that the longest string does not
977 * exceed COAP_ERROR_PHRASE_LENGTH. */
979 { COAP_RESPONSE_CODE(201), "Created" },
980 { COAP_RESPONSE_CODE(202), "Deleted" },
981 { COAP_RESPONSE_CODE(203), "Valid" },
982 { COAP_RESPONSE_CODE(204), "Changed" },
983 { COAP_RESPONSE_CODE(205), "Content" },
984 { COAP_RESPONSE_CODE(231), "Continue" },
985 { COAP_RESPONSE_CODE(400), "Bad Request" },
986 { COAP_RESPONSE_CODE(401), "Unauthorized" },
987 { COAP_RESPONSE_CODE(402), "Bad Option" },
988 { COAP_RESPONSE_CODE(403), "Forbidden" },
989 { COAP_RESPONSE_CODE(404), "Not Found" },
990 { COAP_RESPONSE_CODE(405), "Method Not Allowed" },
991 { COAP_RESPONSE_CODE(406), "Not Acceptable" },
992 { COAP_RESPONSE_CODE(408), "Request Entity Incomplete" },
993 { COAP_RESPONSE_CODE(409), "Conflict" },
994 { COAP_RESPONSE_CODE(412), "Precondition Failed" },
995 { COAP_RESPONSE_CODE(413), "Request Entity Too Large" },
996 { COAP_RESPONSE_CODE(415), "Unsupported Content-Format" },
997 { COAP_RESPONSE_CODE(422), "Unprocessable" },
998 { COAP_RESPONSE_CODE(429), "Too Many Requests" },
999 { COAP_RESPONSE_CODE(500), "Internal Server Error" },
1000 { COAP_RESPONSE_CODE(501), "Not Implemented" },
1001 { COAP_RESPONSE_CODE(502), "Bad Gateway" },
1002 { COAP_RESPONSE_CODE(503), "Service Unavailable" },
1003 { COAP_RESPONSE_CODE(504), "Gateway Timeout" },
1004 { COAP_RESPONSE_CODE(505), "Proxying Not Supported" },
1005 { COAP_RESPONSE_CODE(508), "Hop Limit Reached" },
1006 { 0, NULL } /* end marker */
1007};
1008
1009const char *
1010coap_response_phrase(unsigned char code) {
1011 int i;
1012 for (i = 0; coap_error[i].code; ++i) {
1013 if (coap_error[i].code == code)
1014 return coap_error[i].phrase;
1015 }
1016 return NULL;
1017}
1018#endif
1019
1025static size_t
1026next_option_safe(coap_opt_t **optp, size_t *length, uint16_t *max_opt) {
1027 coap_option_t option;
1028 size_t optsize;
1029
1030 assert(optp);
1031 assert(*optp);
1032 assert(length);
1033
1034 optsize = coap_opt_parse(*optp, *length, &option);
1035 assert(optsize <= *length);
1036
1037 /* signal an error if this option would exceed the
1038 * allowed number space */
1039 if ((uint32_t)(*max_opt) + option.delta > COAP_MAX_OPT) {
1040 return 0;
1041 }
1042 *max_opt += option.delta;
1043 *optp += optsize;
1044 *length -= optsize;
1045
1046 return optsize;
1047}
1048
1049size_t
1051 const uint8_t *data) {
1052 assert(data);
1053 size_t header_size = 0;
1054
1055 if (proto == COAP_PROTO_TCP || proto==COAP_PROTO_TLS) {
1056 uint8_t len = *data >> 4;
1057 if (len < 13)
1058 header_size = 2;
1059 else if (len==13)
1060 header_size = 3;
1061 else if (len==14)
1062 header_size = 4;
1063 else
1064 header_size = 6;
1065 } else if (proto == COAP_PROTO_WS || proto==COAP_PROTO_WSS) {
1066 header_size = 2;
1067 } else if (proto == COAP_PROTO_UDP || proto==COAP_PROTO_DTLS) {
1068 header_size = 4;
1069 }
1070
1071 return header_size;
1072}
1073
1074#if !COAP_DISABLE_TCP
1075/*
1076 * strm
1077 * return +ve PDU size including token
1078 * 0 PDU does not parse
1079 */
1080size_t
1082 const uint8_t *data,
1083 size_t length) {
1084 assert(data);
1085 assert(proto == COAP_PROTO_TCP || proto == COAP_PROTO_TLS ||
1086 proto == COAP_PROTO_WS || proto == COAP_PROTO_WSS);
1087 assert(coap_pdu_parse_header_size(proto, data) <= length);
1088
1089 size_t size = 0;
1090 const uint8_t *token_start = NULL;
1091
1092 if ((proto == COAP_PROTO_TCP || proto == COAP_PROTO_TLS) && length >= 1) {
1093 uint8_t len = *data >> 4;
1094 uint8_t tkl = *data & 0x0f;
1095
1096 if (len < 13) {
1097 size = len;
1098 token_start = &data[2];
1099 } else if (length >= 2) {
1100 if (len==13) {
1101 size = (size_t)data[1] + COAP_MESSAGE_SIZE_OFFSET_TCP8;
1102 token_start = &data[3];
1103 } else if (length >= 3) {
1104 if (len==14) {
1105 size = ((size_t)data[1] << 8) + data[2] + COAP_MESSAGE_SIZE_OFFSET_TCP16;
1106 token_start = &data[4];
1107 } else if (length >= 5) {
1108 size = ((size_t)data[1] << 24) + ((size_t)data[2] << 16)
1109 + ((size_t)data[3] << 8) + data[4] + COAP_MESSAGE_SIZE_OFFSET_TCP32;
1110 token_start = &data[6];
1111 }
1112 }
1113 }
1114 if (token_start) {
1115 /* account for the token length */
1116 if (tkl < COAP_TOKEN_EXT_1B_TKL) {
1117 size += tkl;
1118 } else if (tkl == COAP_TOKEN_EXT_1B_TKL) {
1119 size += token_start[0] + COAP_TOKEN_EXT_1B_BIAS + 1;
1120 } else if (tkl == COAP_TOKEN_EXT_2B_TKL) {
1121 size += ((uint16_t)token_start[0] << 8) + token_start[1] +
1123 } else {
1124 /* Invalid at this point - caught later as undersized */
1125 }
1126 }
1127 }
1128
1129 return size;
1130}
1131#endif /* ! COAP_DISABLE_TCP */
1132
1133int
1135 uint8_t *hdr = pdu->token - pdu->hdr_size;
1136 uint8_t e_token_length;
1137
1138 if (proto == COAP_PROTO_UDP || proto == COAP_PROTO_DTLS) {
1139 assert(pdu->hdr_size == 4);
1140 if ((hdr[0] >> 6) != COAP_DEFAULT_VERSION) {
1141 coap_log_debug("coap_pdu_parse: UDP version not supported\n");
1142 return 0;
1143 }
1144 pdu->type = (hdr[0] >> 4) & 0x03;
1145 pdu->code = hdr[1];
1146 pdu->mid = (uint16_t)hdr[2] << 8 | hdr[3];
1147 } else if (proto == COAP_PROTO_TCP || proto == COAP_PROTO_TLS) {
1148 assert(pdu->hdr_size >= 2 && pdu->hdr_size <= 6);
1149 pdu->type = COAP_MESSAGE_CON;
1150 pdu->code = hdr[pdu->hdr_size-1];
1151 pdu->mid = 0;
1152 } else if (proto == COAP_PROTO_WS || proto == COAP_PROTO_WSS) {
1153 assert(pdu->hdr_size == 2);
1154 pdu->type = COAP_MESSAGE_CON;
1155 pdu->code = hdr[pdu->hdr_size-1];
1156 pdu->mid = 0;
1157 } else {
1158 coap_log_debug("coap_pdu_parse: unsupported protocol\n");
1159 return 0;
1160 }
1161
1162 e_token_length = hdr[0] & 0x0f;
1163 if (e_token_length < COAP_TOKEN_EXT_1B_TKL) {
1164 pdu->e_token_length = e_token_length;
1166 pdu->actual_token.s = &pdu->token[0];
1167 } else if (e_token_length == COAP_TOKEN_EXT_1B_TKL) {
1168 pdu->e_token_length = pdu->token[0] + COAP_TOKEN_EXT_1B_BIAS + 1;
1169 pdu->actual_token.length = pdu->e_token_length - 1;
1170 pdu->actual_token.s = &pdu->token[1];
1171 } else if (e_token_length == COAP_TOKEN_EXT_2B_TKL) {
1172 pdu->e_token_length = ((uint16_t)pdu->token[0] << 8) + pdu->token[1] +
1174 pdu->actual_token.length = pdu->e_token_length - 2;
1175 pdu->actual_token.s = &pdu->token[2];
1176 }
1177 if (pdu->e_token_length > pdu->alloc_size || e_token_length == 15) {
1178 /* Invalid PDU provided - not wise to assert here though */
1179 coap_log_debug("coap_pdu_parse: PDU header token size broken\n");
1180 pdu->e_token_length = 0;
1181 pdu->actual_token.length = 0;
1182 return 0;
1183 }
1184 return 1;
1185}
1186
1187static int
1189 switch ((coap_pdu_signaling_proto_t)pdu->code) {
1190 case COAP_SIGNALING_CSM:
1191 switch (pdu->max_opt) {
1193 if (len > 4)
1194 goto bad;
1195 break;
1197 if (len > 0)
1198 goto bad;
1199 break;
1201 if (len > 3)
1202 goto bad;
1203 break;
1204 default:
1205 if (pdu->max_opt & 0x01)
1206 goto bad; /* Critical */
1207 }
1208 break;
1211 switch (pdu->max_opt) {
1213 if (len > 0)
1214 goto bad;
1215 break;
1216 default:
1217 if (pdu->max_opt & 0x01)
1218 goto bad; /* Critical */
1219 }
1220 break;
1222 switch (pdu->max_opt) {
1224 if (len < 1 || len > 255)
1225 goto bad;
1226 break;
1228 if (len > 3)
1229 goto bad;
1230 break;
1231 default:
1232 if (pdu->max_opt & 0x01)
1233 goto bad; /* Critical */
1234 }
1235 break;
1237 switch (pdu->max_opt) {
1239 if (len > 2)
1240 goto bad;
1241 break;
1242 default:
1243 if (pdu->max_opt & 0x01)
1244 goto bad; /* Critical */
1245 }
1246 break;
1247 default:
1248 ;
1249 }
1250 return 1;
1251bad:
1252 return 0;
1253}
1254
1255static int
1257 int res = 1;
1258
1259 switch (pdu->max_opt) {
1261 if (len > 8)
1262 res = 0;
1263 break;
1265 if (len < 1 || len > 255)
1266 res = 0;
1267 break;
1268 case COAP_OPTION_ETAG:
1269 if (len < 1 || len > 8)
1270 res = 0;
1271 break;
1273 if (len != 0)
1274 res = 0;
1275 break;
1277 if (len > 3)
1278 res = 0;
1279 break;
1281 if (len > 2)
1282 res = 0;
1283 break;
1285 if (len > 255)
1286 res = 0;
1287 break;
1288 case COAP_OPTION_OSCORE:
1289 if (len > 255)
1290 res = 0;
1291 break;
1293 if (len > 255)
1294 res = 0;
1295 break;
1297 if (len > 2)
1298 res = 0;
1299 break;
1300 case COAP_OPTION_MAXAGE:
1301 if (len > 4)
1302 res = 0;
1303 break;
1305 if (len < 1 || len > 255)
1306 res = 0;
1307 break;
1309 if (len != 1)
1310 res = 0;
1311 break;
1312 case COAP_OPTION_ACCEPT:
1313 if (len > 2)
1314 res = 0;
1315 break;
1317 if (len > 3)
1318 res = 0;
1319 break;
1321 if (len > 255)
1322 res = 0;
1323 break;
1324 case COAP_OPTION_EDHOC:
1325 if (len != 0)
1326 res = 0;
1327 break;
1328 case COAP_OPTION_BLOCK2:
1329 if (len > 3)
1330 res = 0;
1331 break;
1332 case COAP_OPTION_BLOCK1:
1333 if (len > 3)
1334 res = 0;
1335 break;
1336 case COAP_OPTION_SIZE2:
1337 if (len > 4)
1338 res = 0;
1339 break;
1341 if (len > 3)
1342 res = 0;
1343 break;
1345 if (len < 1 || len > 1034)
1346 res = 0;
1347 break;
1349 if (len < 1 || len > 255)
1350 res = 0;
1351 break;
1352 case COAP_OPTION_SIZE1:
1353 if (len > 4)
1354 res = 0;
1355 break;
1356 case COAP_OPTION_ECHO:
1357 if (len > 40)
1358 res = 0;
1359 break;
1361 if (len > 1)
1362 res = 0;
1363 break;
1364 case COAP_OPTION_RTAG:
1365 if (len > 8)
1366 res = 0;
1367 break;
1368 default:
1369 ;
1370 }
1371 return res;
1372}
1373
1374static int
1375write_prefix(char **obp, size_t *len, const char *prf, size_t prflen) {
1376 /* Make sure space for null terminating byte */
1377 if (*len < prflen +1) {
1378 return 0;
1379 }
1380
1381 memcpy(*obp, prf, prflen);
1382 *obp += prflen;
1383 *len -= prflen;
1384 return 1;
1385}
1386
1387static int
1388write_char(char **obp, size_t *len, int c, int printable) {
1389 /* Make sure space for null terminating byte */
1390 if (*len < 2 +1) {
1391 return 0;
1392 }
1393
1394 if (!printable) {
1395 const uint8_t hex[] = "0123456789abcdef";
1396 (*obp)[0] = hex[(c & 0xf0) >> 4];
1397 (*obp)[1] = hex[c & 0x0f];
1398 } else {
1399 (*obp)[0] = isprint(c) ? c : '.';
1400 (*obp)[1] = ' ';
1401 }
1402 *obp += 2;
1403 *len -= 2;
1404 return 1;
1405}
1406
1407int
1409 int good = 1;
1410
1411 coap_option_filter_clear(error_opts);
1412
1413 /* sanity checks */
1414 if (pdu->code == 0) {
1415 if (pdu->used_size != 0 || pdu->e_token_length) {
1416 coap_log_debug("coap_pdu_parse: empty message is not empty\n");
1417 return 0;
1418 }
1419 }
1420
1421 if (pdu->e_token_length > pdu->used_size) {
1422 coap_log_debug("coap_pdu_parse: invalid Token\n");
1423 return 0;
1424 }
1425
1426 pdu->max_opt = 0;
1427 if (pdu->code == 0) {
1428 /* empty packet */
1429 pdu->used_size = 0;
1430 pdu->data = NULL;
1431 } else {
1432 /* skip header + token */
1433 coap_opt_t *opt = pdu->token + pdu->e_token_length;
1434 size_t length = pdu->used_size - pdu->e_token_length;
1435
1436 while (length > 0 && *opt != COAP_PAYLOAD_START) {
1437#if (COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_WARN)
1438 coap_opt_t *opt_last = opt;
1439#endif
1440 size_t optsize = next_option_safe(&opt, &length, &pdu->max_opt);
1441 const uint32_t len =
1442 optsize ? coap_opt_length((const uint8_t *)opt - optsize) : 0;
1443 if (optsize == 0) {
1444 coap_log_debug("coap_pdu_parse: %d.%02d: offset %u malformed option\n",
1445 pdu->code >> 5, pdu->code & 0x1F,
1446 (int)(opt_last - pdu->token - pdu->e_token_length));
1447 coap_option_filter_set(error_opts, pdu->max_opt);
1448 good = 0;
1449 break;
1450 }
1451 if (COAP_PDU_IS_SIGNALING(pdu) ?
1452 !coap_pdu_parse_opt_csm(pdu, len) :
1453 !coap_pdu_parse_opt_base(pdu, len)) {
1454 coap_log_warn("coap_pdu_parse: %d.%02d: offset %u option %u has bad length %" PRIu32 "\n",
1455 pdu->code >> 5, pdu->code & 0x1F,
1456 (int)(opt_last - pdu->token - pdu->e_token_length), pdu->max_opt,
1457 len);
1458 coap_option_filter_set(error_opts, pdu->max_opt);
1459 good = 0;
1460 }
1461 }
1462
1463 if (!good) {
1464 /*
1465 * Dump the options in the PDU for analysis, space separated except
1466 * error options which are prefixed by *
1467 * Two rows - hex and ascii (if printable)
1468 */
1469 static char outbuf[COAP_DEBUG_BUF_SIZE];
1470 char *obp;
1471 size_t tlen;
1472 size_t outbuflen;
1473 int i;
1474 int ok;
1475
1476 for (i = 0; i < 2; i++) {
1477 opt = pdu->token + pdu->e_token_length;
1478 length = pdu->used_size - pdu->e_token_length;
1479 pdu->max_opt = 0;
1480
1481 outbuflen = sizeof(outbuf);
1482 obp = outbuf;
1483 ok = write_prefix(&obp, &outbuflen, "O: ", 3);
1484 /*
1485 * Not safe to check for 'ok' here as a lot of variables may get
1486 * partially changed due to lack of outbuflen */
1487 while (length > 0 && *opt != COAP_PAYLOAD_START) {
1488 coap_opt_t *opt_last = opt;
1489 size_t optsize = next_option_safe(&opt, &length, &pdu->max_opt);
1490 const uint32_t len =
1491 optsize ? coap_opt_length((const uint8_t *)opt - optsize) : 0;
1492 if (!optsize || (COAP_PDU_IS_SIGNALING(pdu) ?
1493 !coap_pdu_parse_opt_csm(pdu, len) :
1494 !coap_pdu_parse_opt_base(pdu, len))) {
1495 ok = ok && write_prefix(&obp, &outbuflen, "*", 1);
1496 if (!optsize) {
1497 /* Skip to end of options to output all data */
1498 opt = pdu->token + pdu->used_size;
1499 length = 0;
1500 }
1501 } else {
1502 ok = ok && write_prefix(&obp, &outbuflen, " ", 1);
1503 }
1504 tlen = opt - opt_last;
1505 while (tlen) {
1506 tlen--;
1507 ok = ok && write_char(&obp, &outbuflen, *opt_last, i);
1508 opt_last++;
1509 }
1510 }
1511 if (length && *opt == COAP_PAYLOAD_START) {
1512 write_char(&obp, &outbuflen, *opt, i);
1513 }
1514 /* write_*() always leaves a spare byte to null terminate */
1515 *obp = '\000';
1516 coap_log_debug("%s\n", outbuf);
1517 }
1518 }
1519
1520 if (length > 0) {
1521 assert(*opt == COAP_PAYLOAD_START);
1522 opt++;
1523 length--;
1524
1525 if (length == 0) {
1526 coap_log_debug("coap_pdu_parse: message ending in payload start marker\n");
1527 return 0;
1528 }
1529 }
1530 if (length > 0)
1531 pdu->data = (uint8_t *)opt;
1532 else
1533 pdu->data = NULL;
1534 }
1535
1536 return good;
1537}
1538
1539int
1541 const uint8_t *data,
1542 size_t length,
1543 coap_pdu_t *pdu) {
1544 coap_opt_filter_t error_opts;
1545
1546 return coap_pdu_parse2(proto, data, length, pdu, &error_opts);
1547}
1548
1549int
1551 const uint8_t *data,
1552 size_t length,
1553 coap_pdu_t *pdu,
1554 coap_opt_filter_t *error_opts) {
1555 size_t hdr_size;
1556
1557 if (length == 0)
1558 return 0;
1559 hdr_size = coap_pdu_parse_header_size(proto, data);
1560 if (!hdr_size || hdr_size > length)
1561 return 0;
1562 if (hdr_size > pdu->max_hdr_size)
1563 return 0;
1564 if (!coap_pdu_resize(pdu, length - hdr_size))
1565 return 0;
1566 if (pdu->token - hdr_size != data)
1567 memcpy(pdu->token - hdr_size, data, length);
1568 pdu->hdr_size = (uint8_t)hdr_size;
1569 pdu->used_size = length - hdr_size;
1570 return coap_pdu_parse_header(pdu, proto) && coap_pdu_parse_opt(pdu, error_opts);
1571}
1572
1573size_t
1575 uint8_t e_token_length;
1576
1578 e_token_length = (uint8_t)pdu->actual_token.length;
1579 } else if (pdu->actual_token.length < COAP_TOKEN_EXT_2B_BIAS) {
1580 e_token_length = COAP_TOKEN_EXT_1B_TKL;
1581 } else if (pdu->actual_token.length <= COAP_TOKEN_EXT_MAX) {
1582 e_token_length = COAP_TOKEN_EXT_2B_TKL;
1583 } else {
1584 coap_log_warn("coap_add_token: Token size too large. PDU ignored\n");
1585 return 0;
1586 }
1587 if (COAP_PROTO_NOT_RELIABLE(proto)) {
1588 assert(pdu->max_hdr_size >= 4);
1589 if (pdu->max_hdr_size < 4) {
1590 coap_log_warn("coap_pdu_encode_header: not enough space for UDP-style header\n");
1591 return 0;
1592 }
1593 pdu->token[-4] = COAP_DEFAULT_VERSION << 6
1594 | pdu->type << 4
1595 | e_token_length;
1596 pdu->token[-3] = pdu->code;
1597 pdu->token[-2] = (uint8_t)(pdu->mid >> 8);
1598 pdu->token[-1] = (uint8_t)(pdu->mid);
1599 pdu->hdr_size = 4;
1600#if !COAP_DISABLE_TCP
1601 } else if (COAP_PROTO_RELIABLE(proto)) {
1602 size_t len;
1603 assert(pdu->used_size >= pdu->e_token_length);
1604 if (pdu->used_size < pdu->e_token_length) {
1605 coap_log_warn("coap_pdu_encode_header: corrupted PDU\n");
1606 return 0;
1607 }
1608
1609 /* A lot of the reliable code assumes type is CON */
1610 if (pdu->type != COAP_MESSAGE_CON)
1611 pdu->type = COAP_MESSAGE_CON;
1612
1613 if (proto == COAP_PROTO_WS || proto == COAP_PROTO_WSS)
1614 len = 0;
1615 else
1616 len = pdu->used_size - pdu->e_token_length;
1617 if (len <= COAP_MAX_MESSAGE_SIZE_TCP0) {
1618 assert(pdu->max_hdr_size >= 2);
1619 if (pdu->max_hdr_size < 2) {
1620 coap_log_warn("coap_pdu_encode_header: not enough space for TCP0 header\n");
1621 return 0;
1622 }
1623 pdu->token[-2] = (uint8_t)len << 4
1624 | e_token_length;
1625 pdu->token[-1] = pdu->code;
1626 pdu->hdr_size = 2;
1627 } else if (len <= COAP_MAX_MESSAGE_SIZE_TCP8) {
1628 assert(pdu->max_hdr_size >= 3);
1629 if (pdu->max_hdr_size < 3) {
1630 coap_log_warn("coap_pdu_encode_header: not enough space for TCP8 header\n");
1631 return 0;
1632 }
1633 pdu->token[-3] = 13 << 4 | e_token_length;
1634 pdu->token[-2] = (uint8_t)(len - COAP_MESSAGE_SIZE_OFFSET_TCP8);
1635 pdu->token[-1] = pdu->code;
1636 pdu->hdr_size = 3;
1637 } else if (len <= COAP_MAX_MESSAGE_SIZE_TCP16) {
1638 assert(pdu->max_hdr_size >= 4);
1639 if (pdu->max_hdr_size < 4) {
1640 coap_log_warn("coap_pdu_encode_header: not enough space for TCP16 header\n");
1641 return 0;
1642 }
1643 pdu->token[-4] = 14 << 4 | e_token_length;
1644 pdu->token[-3] = (uint8_t)((len - COAP_MESSAGE_SIZE_OFFSET_TCP16) >> 8);
1645 pdu->token[-2] = (uint8_t)(len - COAP_MESSAGE_SIZE_OFFSET_TCP16);
1646 pdu->token[-1] = pdu->code;
1647 pdu->hdr_size = 4;
1648 } else {
1649 assert(pdu->max_hdr_size >= 6);
1650 if (pdu->max_hdr_size < 6) {
1651 coap_log_warn("coap_pdu_encode_header: not enough space for TCP32 header\n");
1652 return 0;
1653 }
1654 pdu->token[-6] = 15 << 4 | e_token_length;
1655 pdu->token[-5] = (uint8_t)((len - COAP_MESSAGE_SIZE_OFFSET_TCP32) >> 24);
1656 pdu->token[-4] = (uint8_t)((len - COAP_MESSAGE_SIZE_OFFSET_TCP32) >> 16);
1657 pdu->token[-3] = (uint8_t)((len - COAP_MESSAGE_SIZE_OFFSET_TCP32) >> 8);
1658 pdu->token[-2] = (uint8_t)(len - COAP_MESSAGE_SIZE_OFFSET_TCP32);
1659 pdu->token[-1] = pdu->code;
1660 pdu->hdr_size = 6;
1661 }
1662#endif /* ! COAP_DISABLE_TCP */
1663 } else {
1664 coap_log_warn("coap_pdu_encode_header: unsupported protocol\n");
1665 }
1666 return pdu->hdr_size;
1667}
1668
1671 return pdu->code;
1672}
1673
1674void
1676#ifndef RIOT_VERSION
1677 assert(code <= 0xff);
1678#endif /* RIOT_VERSION */
1679 pdu->code = code;
1680}
1681
1684 return pdu->type;
1685}
1686
1687void
1689 assert(type <= 0x3);
1690 pdu->type = type;
1691}
1692
1695 return pdu->actual_token;
1696}
1697
1700 return pdu->mid;
1701}
1702
1703void
1705#if (UINT_MAX > 65535)
1706 assert(mid >= 0 && mid <= 0xffff);
1707#endif /* UINT_MAX > 65535 */
1708 pdu->mid = mid;
1709}
1710
1711coap_pdu_t *
1713 if (pdu != NULL) {
1714 ++pdu->ref;
1715 }
1716 return pdu;
1717}
1718
1719coap_pdu_t *
1721 coap_pdu_t *pdu_rw = NULL;
1722
1723 if (pdu != NULL) {
1724
1725 /* Need to do this to not get a compiler warning about const parameters */
1726 memcpy(&pdu_rw, &pdu, sizeof(pdu_rw));
1727 ++pdu_rw->ref;
1728 }
1729 return pdu_rw;
1730}
#define PRIuS
#define PRIu32
Library specific build wrapper for coap_internal.h.
#define COAP_API
@ COAP_PDU
Definition coap_mem.h:40
@ COAP_PDU_BUF
Definition coap_mem.h:41
void * coap_realloc_type(coap_memory_tag_t type, void *p, size_t size)
Reallocates a chunk p of bytes created by coap_malloc_type() or coap_realloc_type() and returns a poi...
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.
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
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 coap_option.c:41
#define NULL
Definition coap_option.h:30
uint16_t coap_option_num_t
Definition coap_option.h:37
uint8_t coap_opt_t
Use byte-oriented access methods here because sliding a complex struct coap_opt_t over the data buffe...
Definition coap_option.h:43
static size_t next_option_safe(coap_opt_t **optp, size_t *length, uint16_t *max_opt)
Advances *optp to next option if still in PDU.
Definition coap_pdu.c:1026
static int coap_pdu_parse_opt_csm(coap_pdu_t *pdu, uint16_t len)
Definition coap_pdu.c:1188
error_desc_t coap_error[]
Definition coap_pdu.c:978
static int write_prefix(char **obp, size_t *len, const char *prf, size_t prflen)
Definition coap_pdu.c:1375
static int coap_pdu_parse_opt_base(coap_pdu_t *pdu, uint16_t len)
Definition coap_pdu.c:1256
#define min(a, b)
Definition coap_pdu.c:37
static int write_char(char **obp, size_t *len, int c, int printable)
Definition coap_pdu.c:1388
#define max(a, b)
Definition coap_pdu.c:41
uint16_t coap_new_message_id_lkd(coap_session_t *session)
Returns a new message id and updates session->tx_mid accordingly.
unsigned int coap_decode_var_bytes(const uint8_t *buf, size_t len)
Decodes multiple-length byte sequences.
Definition coap_encode.c:38
#define coap_lock_unlock()
Dummy for no thread-safe code.
#define coap_lock_check_locked()
Dummy for no thread-safe code.
#define coap_lock_lock(failed)
Dummy for no thread-safe code.
#define coap_log_debug(...)
Definition coap_debug.h:126
#define coap_log_info(...)
Definition coap_debug.h:114
#define coap_log_warn(...)
Definition coap_debug.h:108
#define coap_log_crit(...)
Definition coap_debug.h:96
coap_opt_t * coap_option_next(coap_opt_iterator_t *oi)
Updates the iterator oi to point to the next option.
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.
uint32_t coap_opt_length(const coap_opt_t *opt)
Returns the length of the given option.
coap_opt_iterator_t * coap_option_iterator_init(const coap_pdu_t *pdu, coap_opt_iterator_t *oi, const coap_opt_filter_t *filter)
Initializes the given option iterator oi to point to the beginning of the pdu's option list.
size_t coap_opt_encode_size(uint16_t delta, size_t length)
Compute storage bytes needed for an option with given delta and length.
#define COAP_OPT_ALL
Pre-defined filter that includes all options.
void coap_option_filter_clear(coap_opt_filter_t *filter)
Clears filter filter.
coap_opt_t * coap_check_option(const coap_pdu_t *pdu, coap_option_num_t number, coap_opt_iterator_t *oi)
Retrieves the first option of number number from pdu.
const uint8_t * coap_opt_value(const coap_opt_t *opt)
Returns a pointer to the value of the given option.
int coap_option_filter_get(coap_opt_filter_t *filter, coap_option_num_t option)
Checks if number is contained in filter.
int coap_option_filter_set(coap_opt_filter_t *filter, coap_option_num_t option)
Sets the corresponding entry for number in filter.
#define COAP_MESSAGE_SIZE_OFFSET_TCP8
coap_pdu_t * coap_pdu_reference_lkd(coap_pdu_t *pdu)
Increment reference counter on a pdu to stop it prematurely getting freed off when coap_delete_pdu() ...
Definition coap_pdu.c:1712
void coap_delete_pdu_lkd(coap_pdu_t *pdu)
Dispose of an CoAP PDU and free off associated storage.
Definition coap_pdu.c:194
#define COAP_DEBUG_BUF_SIZE
#define COAP_TOKEN_EXT_2B_TKL
size_t coap_insert_option(coap_pdu_t *pdu, coap_option_num_t number, size_t len, const uint8_t *data)
Inserts option of given number in the pdu with the appropriate data.
Definition coap_pdu.c:684
int coap_remove_option(coap_pdu_t *pdu, coap_option_num_t number)
Removes (first) option of given number from the pdu.
Definition coap_pdu.c:543
int coap_update_token(coap_pdu_t *pdu, size_t len, const uint8_t *data)
Updates token in pdu with length len and data.
Definition coap_pdu.c:467
#define COAP_TOKEN_EXT_1B_BIAS
#define COAP_PDU_MAX_UDP_HEADER_SIZE
int coap_pdu_parse_opt(coap_pdu_t *pdu, coap_opt_filter_t *error_opts)
Verify consistency in the given CoAP PDU structure and locate the data.
Definition coap_pdu.c:1408
int coap_pdu_parse_header(coap_pdu_t *pdu, coap_proto_t proto)
Decode the protocol specific header for the specified PDU.
Definition coap_pdu.c:1134
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 coap_pdu.c:1050
coap_pdu_t * coap_new_pdu_lkd(coap_pdu_type_t type, coap_pdu_code_t code, coap_session_t *session)
Creates a new CoAP PDU.
Definition coap_pdu.c:173
#define COAP_PDU_MAX_TCP_HEADER_SIZE
#define COAP_MAX_MESSAGE_SIZE_TCP8
#define COAP_DEFAULT_MAX_PDU_RX_SIZE
#define COAP_PDU_IS_SIGNALING(pdu)
#define COAP_TOKEN_EXT_2B_BIAS
#define COAP_MAX_MESSAGE_SIZE_TCP0
int coap_option_check_repeatable(coap_option_num_t number)
Check whether the option is allowed to be repeated or not.
Definition coap_pdu.c:637
#define COAP_MESSAGE_SIZE_OFFSET_TCP16
void coap_pdu_clear(coap_pdu_t *pdu, size_t size)
Clears any contents from pdu and resets used_size, and data pointers.
Definition coap_pdu.c:45
coap_pdu_t * coap_pdu_duplicate_lkd(const coap_pdu_t *old_pdu, coap_session_t *session, size_t token_length, const uint8_t *token, coap_opt_filter_t *drop_options, coap_bool_t expand_opt_abb)
Duplicate an existing PDU.
Definition coap_pdu.c:234
#define COAP_MESSAGE_SIZE_OFFSET_TCP32
size_t coap_update_option(coap_pdu_t *pdu, coap_option_num_t number, size_t len, const uint8_t *data)
Updates existing first option of given number in the pdu with the new data.
Definition coap_pdu.c:783
#define COAP_TOKEN_EXT_1B_TKL
size_t coap_pdu_encode_header(coap_pdu_t *pdu, coap_proto_t proto)
Compose the protocol specific header for the specified PDU.
Definition coap_pdu.c:1574
#define COAP_DEFAULT_VERSION
int coap_pdu_parse2(coap_proto_t proto, const uint8_t *data, size_t length, coap_pdu_t *pdu, coap_opt_filter_t *error_opts)
Parses data into the CoAP PDU structure given in result.
Definition coap_pdu.c:1550
#define COAP_PAYLOAD_START
int coap_pdu_check_resize(coap_pdu_t *pdu, size_t size)
Dynamically grows the size of pdu to new_size if needed.
Definition coap_pdu.c:393
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 coap_pdu.c:1081
coap_pdu_t * coap_const_pdu_reference_lkd(const coap_pdu_t *pdu)
Increment reference counter on a const pdu to stop it prematurely getting freed off when coap_delete_...
Definition coap_pdu.c:1720
int coap_pdu_resize(coap_pdu_t *pdu, size_t new_size)
Dynamically grows the size of pdu to new_size.
Definition coap_pdu.c:338
#define COAP_PDU_IS_REQUEST(pdu)
#define COAP_MAX_MESSAGE_SIZE_TCP16
size_t coap_add_option_internal(coap_pdu_t *pdu, coap_option_num_t number, size_t len, const uint8_t *data)
Adds option of given number to pdu that is passed as first parameter.
Definition coap_pdu.c:839
#define COAP_OPTION_HOP_LIMIT
Definition coap_pdu.h:136
#define COAP_OPTION_NORESPONSE
Definition coap_pdu.h:149
#define COAP_OPTION_URI_HOST
Definition coap_pdu.h:122
#define COAP_OPTION_IF_MATCH
Definition coap_pdu.h:121
coap_pdu_code_t coap_pdu_get_code(const coap_pdu_t *pdu)
Gets the PDU code associated with pdu.
Definition coap_pdu.c:1670
#define COAP_OPTION_BLOCK2
Definition coap_pdu.h:141
const char * coap_response_phrase(unsigned char code)
Returns a human-readable response phrase for the specified CoAP response code.
Definition coap_pdu.c:1010
#define COAP_OPTION_CONTENT_FORMAT
Definition coap_pdu.h:130
#define COAP_SIGNALING_OPTION_ALTERNATIVE_ADDRESS
Definition coap_pdu.h:209
#define COAP_OPTION_SIZE2
Definition coap_pdu.h:143
#define COAP_OPTION_BLOCK1
Definition coap_pdu.h:142
#define COAP_OPTION_Q_BLOCK1
Definition coap_pdu.h:138
#define COAP_OPTION_PROXY_SCHEME
Definition coap_pdu.h:146
COAP_API void coap_delete_pdu(coap_pdu_t *pdu)
Dispose of an CoAP PDU and free off associated storage.
Definition coap_pdu.c:187
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.
Definition coap_pdu.c:916
coap_bool_t
Definition coap_pdu.h:377
#define COAP_OPTION_URI_QUERY
Definition coap_pdu.h:135
void coap_pdu_set_code(coap_pdu_t *pdu, coap_pdu_code_t code)
Sets the PDU code in the pdu.
Definition coap_pdu.c:1675
int coap_mid_t
coap_mid_t is used to store the CoAP Message ID of a CoAP PDU.
Definition coap_pdu.h:267
COAP_API coap_pdu_t * coap_pdu_duplicate(const coap_pdu_t *old_pdu, coap_session_t *session, size_t token_length, const uint8_t *token, coap_opt_filter_t *drop_options)
Duplicate an existing PDU.
Definition coap_pdu.c:212
#define COAP_OPTION_IF_NONE_MATCH
Definition coap_pdu.h:124
#define COAP_OPTION_LOCATION_PATH
Definition coap_pdu.h:127
#define COAP_TOKEN_EXT_MAX
Definition coap_pdu.h:62
#define COAP_OPTION_URI_PATH
Definition coap_pdu.h:129
#define COAP_SIGNALING_OPTION_EXTENDED_TOKEN_LENGTH
Definition coap_pdu.h:203
#define COAP_RESPONSE_CODE(N)
Definition coap_pdu.h:164
coap_proto_t
CoAP protocol types Note: coap_layers_coap[] needs updating if extended.
Definition coap_pdu.h:317
coap_pdu_code_t
Set of codes available for a PDU.
Definition coap_pdu.h:331
#define COAP_OPTION_OSCORE
Definition coap_pdu.h:128
#define COAP_OPTION_SIZE1
Definition coap_pdu.h:147
coap_pdu_type_t
CoAP PDU message type definitions.
Definition coap_pdu.h:70
#define COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER
Definition coap_pdu.h:202
int coap_add_token(coap_pdu_t *pdu, size_t len, const uint8_t *data)
Adds token of length len to pdu.
Definition coap_pdu.c:410
#define COAP_OPTION_LOCATION_QUERY
Definition coap_pdu.h:139
void coap_pdu_set_type(coap_pdu_t *pdu, coap_pdu_type_t type)
Sets the PDU type in the pdu.
Definition coap_pdu.c:1688
size_t coap_add_option(coap_pdu_t *pdu, coap_option_num_t number, size_t len, const uint8_t *data)
Adds option of given number to pdu that is passed as first parameter.
Definition coap_pdu.c:829
#define COAP_OPTION_Q_BLOCK2
Definition coap_pdu.h:144
#define COAP_SIGNALING_OPTION_CUSTODY
Definition coap_pdu.h:206
coap_pdu_signaling_proto_t
Definition coap_pdu.h:192
coap_pdu_type_t coap_pdu_get_type(const coap_pdu_t *pdu)
Gets the PDU type associated with pdu.
Definition coap_pdu.c:1683
int coap_get_data(const coap_pdu_t *pdu, size_t *len, const uint8_t **data)
Retrieves the length and data pointer of specified PDU.
Definition coap_pdu.c:935
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 coap_pdu.c:1540
#define COAP_MAX_OPT
the highest option number we know
Definition coap_pdu.h:155
void coap_pdu_set_mid(coap_pdu_t *pdu, coap_mid_t mid)
Sets the message id in the pdu.
Definition coap_pdu.c:1704
#define COAP_OPTION_RTAG
Definition coap_pdu.h:150
#define COAP_OPTION_URI_PATH_ABB
Definition coap_pdu.h:131
COAP_API coap_pdu_t * coap_new_pdu(coap_pdu_type_t type, coap_pdu_code_t code, coap_session_t *session)
Creates a new CoAP PDU.
Definition coap_pdu.c:162
#define COAP_OPTION_URI_PORT
Definition coap_pdu.h:126
coap_pdu_t * coap_pdu_init(coap_pdu_type_t type, coap_pdu_code_t code, coap_mid_t mid, size_t size)
Creates a new CoAP PDU with at least enough storage space for the given size maximum message size.
Definition coap_pdu.c:102
#define COAP_OPTION_EDHOC
Definition coap_pdu.h:140
#define COAP_OPTION_ACCEPT
Definition coap_pdu.h:137
int coap_get_data_large(const coap_pdu_t *pdu, size_t *len, const uint8_t **data, size_t *offset, size_t *total)
Retrieves the data from a PDU, with support for large bodies of data that spans multiple PDUs.
Definition coap_pdu.c:943
#define COAP_DEFAULT_MTU
Definition coap_pdu.h:43
coap_mid_t coap_pdu_get_mid(const coap_pdu_t *pdu)
Gets the message id associated with pdu.
Definition coap_pdu.c:1699
#define COAP_OPTION_MAXAGE
Definition coap_pdu.h:134
#define COAP_OPTION_ETAG
Definition coap_pdu.h:123
#define COAP_OPTION_PROXY_URI
Definition coap_pdu.h:145
#define COAP_OPTION_OBSERVE
Definition coap_pdu.h:125
#define COAP_SIGNALING_OPTION_HOLD_OFF
Definition coap_pdu.h:210
#define COAP_OPTION_ECHO
Definition coap_pdu.h:148
#define COAP_SIGNALING_OPTION_BAD_CSM_OPTION
Definition coap_pdu.h:213
#define COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE
Definition coap_pdu.h:201
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 coap_pdu.c:904
coap_bin_const_t coap_pdu_get_token(const coap_pdu_t *pdu)
Gets the token associated with pdu.
Definition coap_pdu.c:1694
@ COAP_BOOL_FALSE
Definition coap_pdu.h:378
@ COAP_BOOL_TRUE
Definition coap_pdu.h:379
@ COAP_PROTO_WS
Definition coap_pdu.h:323
@ COAP_PROTO_DTLS
Definition coap_pdu.h:320
@ COAP_PROTO_UDP
Definition coap_pdu.h:319
@ COAP_PROTO_TLS
Definition coap_pdu.h:322
@ COAP_PROTO_WSS
Definition coap_pdu.h:324
@ COAP_PROTO_TCP
Definition coap_pdu.h:321
@ COAP_MESSAGE_CON
Definition coap_pdu.h:71
@ COAP_SIGNALING_RELEASE
Definition coap_pdu.h:196
@ COAP_SIGNALING_CSM
Definition coap_pdu.h:193
@ COAP_SIGNALING_PONG
Definition coap_pdu.h:195
@ COAP_SIGNALING_PING
Definition coap_pdu.h:194
@ COAP_SIGNALING_ABORT
Definition coap_pdu.h:197
size_t coap_session_max_pdu_size_lkd(const coap_session_t *session)
Get maximum acceptable PDU size.
#define COAP_PROTO_NOT_RELIABLE(p)
#define COAP_PROTO_RELIABLE(p)
void coap_delete_binary(coap_binary_t *s)
Deletes the given coap_binary_t object and releases any memory allocated.
Definition coap_str.c:114
coap_upa_chain_t * coap_upa_server_mapping_chain
Definition coap_uri.c:33
const char * coap_map_abbrev_uri_path(coap_upa_chain_t *chain, uint32_t value)
Determine the expanded Uri-Path-Abbrev option value.
Definition coap_uri.c:1154
CoAP binary data definition with const data.
Definition coap_str.h:65
size_t length
length of binary data
Definition coap_str.h:66
const uint8_t * s
read-only binary data
Definition coap_str.h:67
Iterator to run through PDU options.
coap_option_num_t number
decoded option number
Representation of CoAP options.
Definition coap_option.h:49
uint16_t delta
Definition coap_option.h:50
structure for CoAP PDUs
uint8_t max_hdr_size
space reserved for protocol-specific header
uint16_t max_opt
highest option number in PDU
uint8_t * token
first byte of token (or extended length bytes prefix), if any, or options
coap_lg_xmit_t * lg_xmit
Holds ptr to lg_xmit if sending a set of blocks.
size_t body_length
Holds body data length.
size_t max_size
maximum size for token, options and payload, or zero for variable size pdu
const uint8_t * body_data
Holds ptr to re-assembled data or NULL.
size_t body_offset
Holds body data offset.
unsigned ref
reference count
coap_pdu_code_t code
request method (value 1–31) or response code (value 64-255)
uint8_t hdr_size
actual size used for protocol-specific header (0 until header is encoded)
coap_bin_const_t actual_token
Actual token in pdu.
uint8_t * data
first byte of payload, if any
coap_mid_t mid
message id, if any, in regular host byte order
uint32_t e_token_length
length of Token space (includes leading extended bytes
size_t used_size
used bytes of storage for token, options and payload
uint8_t crit_opt
Set if unknown critical option for proxy.
coap_binary_t * data_free
Data to be freed off by coap_delete_pdu()
size_t alloc_size
allocated storage for token, options and payload
coap_session_t * session
Session responsible for PDU or NULL.
size_t body_total
Holds body data total size.
coap_pdu_type_t type
message type
Abstraction of virtual session that can be attached to coap_context_t (client) or coap_endpoint_t (se...
coap_proto_t proto
protocol used
unsigned char code
Definition coap_pdu.c:972
const char * phrase
Definition coap_pdu.c:973