libcoap 4.3.5-develop-783b531
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 %u not known for fallback\n", value);
311 return NULL;
312 }
313 } else {
314 if (drop_options) {
315 if (coap_option_filter_get(drop_options, opt_iter.number))
316 continue;
317 }
318 if (!coap_insert_option(pdu, opt_iter.number,
319 coap_opt_length(option),
320 coap_opt_value(option)))
321 goto fail;
322 }
323 }
324 }
325 return pdu;
326
327fail:
329 return NULL;
330}
331
332
333/*
334 * The new size does not include the coap header (max_hdr_size)
335 */
336int
337coap_pdu_resize(coap_pdu_t *pdu, size_t new_size) {
338 if (new_size > pdu->alloc_size) {
339 /* Expanding the PDU usage */
340#if !defined(WITH_LWIP)
341 uint8_t *new_hdr;
342#else /* WITH_LWIP */
343 struct pbuf *new_hdr;
344#endif /* WITH_LWIP */
345 size_t offset;
346
347 if (pdu->max_size && new_size > pdu->max_size) {
348 coap_log_warn("coap_pdu_resize: pdu too big\n");
349 return 0;
350 }
351 if (pdu->data != NULL) {
352 assert(pdu->data > pdu->token);
353 offset = pdu->data - pdu->token;
354 } else {
355 offset = 0;
356 }
357#if !defined(WITH_LWIP)
358 new_hdr = (uint8_t *)coap_realloc_type(COAP_PDU_BUF,
359 pdu->token - pdu->max_hdr_size,
360 new_size + pdu->max_hdr_size);
361#else /* WITH_LWIP */
362 new_hdr = pbuf_alloc(PBUF_TRANSPORT, new_size + pdu->max_hdr_size, PBUF_RAM);
363#endif /* WITH_LWIP */
364 if (new_hdr == NULL) {
365 coap_log_warn("coap_pdu_resize: realloc failed\n");
366 return 0;
367 }
368#if !defined(WITH_LWIP)
369 pdu->token = new_hdr + pdu->max_hdr_size;
370#else /* WITH_LWIP */
371 memcpy(new_hdr->payload, pdu->pbuf->payload, pdu->pbuf->len);
372 pbuf_free(pdu->pbuf);
373 pdu->pbuf = new_hdr;
374 pdu->token = (uint8_t *)pdu->pbuf->payload + pdu->max_hdr_size;
375#endif /* WITH_LWIP */
376 if (offset > 0)
377 pdu->data = pdu->token + offset;
378 else
379 pdu->data = NULL;
381 pdu->actual_token.s = &pdu->token[0];
383 pdu->actual_token.s = &pdu->token[1];
384 else
385 pdu->actual_token.s = &pdu->token[2];
386 pdu->alloc_size = new_size;
387 }
388 return 1;
389}
390
391int
393 if (size > pdu->alloc_size) {
394 size_t new_size = max(256, pdu->alloc_size * 2);
395 while (size > new_size)
396 new_size *= 2;
397 if (pdu->max_size && new_size > pdu->max_size) {
398 new_size = pdu->max_size;
399 if (new_size < size)
400 return 0;
401 }
402 if (!coap_pdu_resize(pdu, new_size))
403 return 0;
404 }
405 return 1;
406}
407
408int
409coap_add_token(coap_pdu_t *pdu, size_t len, const uint8_t *data) {
410 size_t bias = 0;
411
412 /* must allow for pdu == NULL as callers may rely on this */
413 if (!pdu)
414 return 0;
415
416 if (pdu->used_size) {
417 coap_log_warn("coap_add_token: The token must defined first. Token ignored\n");
418 return 0;
419 }
420 pdu->actual_token.length = len;
421 if (len < COAP_TOKEN_EXT_1B_BIAS) {
422 bias = 0;
423 } else if (len < COAP_TOKEN_EXT_2B_BIAS) {
424 bias = 1;
425 } else if (len <= COAP_TOKEN_EXT_MAX) {
426 bias = 2;
427 } else {
428 coap_log_warn("coap_add_token: Token size too large. Token ignored\n");
429 return 0;
430 }
431 if (!coap_pdu_check_resize(pdu, len + bias)) {
432 coap_log_warn("coap_add_token: Insufficient space for token. Token ignored\n");
433 return 0;
434 }
435
436 pdu->actual_token.length = len;
437 pdu->actual_token.s = &pdu->token[bias];
438 pdu->e_token_length = (uint32_t)(len + bias);
439 if (len) {
440 switch (bias) {
441 case 0:
442 memcpy(pdu->token, data, len);
443 break;
444 case 1:
445 pdu->token[0] = (uint8_t)(len - COAP_TOKEN_EXT_1B_BIAS);
446 memcpy(&pdu->token[1], data, len);
447 break;
448 case 2:
449 pdu->token[0] = (uint8_t)((len - COAP_TOKEN_EXT_2B_BIAS) >> 8);
450 pdu->token[1] = (uint8_t)((len - COAP_TOKEN_EXT_2B_BIAS) & 0xff);
451 memcpy(&pdu->token[2], data, len);
452 break;
453 default:
454 break;
455 }
456 }
457 pdu->max_opt = 0;
458 pdu->used_size = len + bias;
459 pdu->data = NULL;
460
461 return 1;
462}
463
464/* It is assumed that coap_encode_var_safe8() has been called to reduce data */
465int
466coap_update_token(coap_pdu_t *pdu, size_t len, const uint8_t *data) {
467 size_t bias = 0;
468 size_t old_len;
469
470 /* must allow for pdu == NULL as callers may rely on this */
471 if (!pdu)
472 return 0;
473
474 if (pdu->used_size == 0) {
475 return coap_add_token(pdu, len, data);
476 }
477
478 old_len = pdu->e_token_length;
479
480 if (len < COAP_TOKEN_EXT_1B_BIAS) {
481 bias = 0;
482 } else if (len < COAP_TOKEN_EXT_2B_BIAS) {
483 bias = 1;
484 } else if (len <= COAP_TOKEN_EXT_MAX) {
485 bias = 2;
486 } else {
487 coap_log_warn("coap_add_token: Token size too large. Token ignored\n");
488 return 0;
489 }
490 if ((len + bias) == pdu->e_token_length) {
491 /* Easy case - just data has changed */
492 } else if ((len + bias) > pdu->e_token_length) {
493 if (!coap_pdu_check_resize(pdu,
494 pdu->used_size + (len + bias) - pdu->e_token_length)) {
495 coap_log_warn("Failed to update token\n");
496 return 0;
497 }
498 memmove(&pdu->token[(len + bias) - pdu->e_token_length],
499 pdu->token, pdu->used_size);
500 pdu->used_size += len + bias - pdu->e_token_length;
501 if (pdu->data) {
502 pdu->data += (len + bias) - pdu->e_token_length;
503 }
504 } else {
505 pdu->used_size -= pdu->e_token_length - (len + bias);
506 memmove(pdu->token, &pdu->token[pdu->e_token_length - (len + bias)], pdu->used_size);
507 if (pdu->data) {
508 pdu->data -= pdu->e_token_length - (len + bias);
509 }
510 }
511
512 pdu->actual_token.length = len;
513 pdu->actual_token.s = &pdu->token[bias];
514 pdu->e_token_length = (uint8_t)(len + bias);
515 if (len) {
516 switch (bias) {
517 case 0:
518 if (memcmp(pdu->token, data, len) != 0)
519 memcpy(pdu->token, data, len);
520 break;
521 case 1:
522 pdu->token[0] = (uint8_t)(len - COAP_TOKEN_EXT_1B_BIAS);
523 memcpy(&pdu->token[1], data, len);
524 break;
525 case 2:
526 pdu->token[0] = (uint8_t)((len - COAP_TOKEN_EXT_2B_BIAS) >> 8);
527 pdu->token[1] = (uint8_t)((len - COAP_TOKEN_EXT_2B_BIAS) & 0xff);
528 memcpy(&pdu->token[2], data, len);
529 break;
530 default:
531 break;
532 }
533 }
534 if (old_len != pdu->e_token_length && pdu->hdr_size && pdu->session)
535 /* Need to fix up the header */
536 if (!coap_pdu_encode_header(pdu, pdu->session->proto))
537 return 0;
538 return 1;
539}
540
541int
543 coap_opt_iterator_t opt_iter;
544 coap_opt_t *option;
545 coap_opt_t *next_option = NULL;
546 size_t opt_delta;
547 coap_option_t decode_this;
548 coap_option_t decode_next;
549
550 /* Need to locate where in current options to remove this one */
552 while ((option = coap_option_next(&opt_iter))) {
553 if (opt_iter.number == number) {
554 /* Found option to delete */
555 break;
556 }
557 }
558 if (!option)
559 return 0;
560
561 if (!coap_opt_parse(option, pdu->used_size - (option - pdu->token),
562 &decode_this))
563 return 0;
564
565 next_option = coap_option_next(&opt_iter);
566 if (next_option) {
567 if (!coap_opt_parse(next_option,
568 pdu->used_size - (next_option - pdu->token),
569 &decode_next))
570 return 0;
571 opt_delta = decode_this.delta + decode_next.delta;
572 if (opt_delta < 13) {
573 /* can simply update the delta of next option */
574 next_option[0] = (next_option[0] & 0x0f) + (coap_opt_t)(opt_delta << 4);
575 } else if (opt_delta < 269 && decode_next.delta < 13) {
576 /* next option delta size increase */
577 next_option -= 1;
578 next_option[0] = (next_option[1] & 0x0f) + (13 << 4);
579 next_option[1] = (coap_opt_t)(opt_delta - 13);
580 } else if (opt_delta < 269) {
581 /* can simply update the delta of next option */
582 next_option[1] = (coap_opt_t)(opt_delta - 13);
583 } else if (decode_next.delta < 13) { /* opt_delta >= 269 */
584 /* next option delta size increase */
585 if (next_option - option < 2) {
586 /* Need to shuffle everything up by 1 before decrement */
587 if (!coap_pdu_check_resize(pdu, pdu->used_size + 1))
588 return 0;
589 /* Possible a re-size took place with a realloc() */
590 /* Need to rediscover this and next options */
592 while ((option = coap_option_next(&opt_iter))) {
593 if (opt_iter.number == number) {
594 /* Found option to delete */
595 break;
596 }
597 }
598 next_option = coap_option_next(&opt_iter);
599 assert(option != NULL);
600 assert(next_option != NULL);
601 memmove(&next_option[1], next_option,
602 pdu->used_size - (next_option - pdu->token));
603 pdu->used_size++;
604 if (pdu->data)
605 pdu->data++;
606 next_option++;
607 }
608 next_option -= 2;
609 next_option[0] = (next_option[2] & 0x0f) + (14 << 4);
610 next_option[1] = (coap_opt_t)((opt_delta - 269) >> 8);
611 next_option[2] = (opt_delta - 269) & 0xff;
612 } else if (decode_next.delta < 269) { /* opt_delta >= 269 */
613 /* next option delta size increase */
614 next_option -= 1;
615 next_option[0] = (next_option[1] & 0x0f) + (14 << 4);
616 next_option[1] = (coap_opt_t)((opt_delta - 269) >> 8);
617 next_option[2] = (opt_delta - 269) & 0xff;
618 } else { /* decode_next.delta >= 269 && opt_delta >= 269 */
619 next_option[1] = (coap_opt_t)((opt_delta - 269) >> 8);
620 next_option[2] = (opt_delta - 269) & 0xff;
621 }
622 } else {
623 next_option = option + coap_opt_encode_size(decode_this.delta,
624 coap_opt_length(option));
625 pdu->max_opt -= decode_this.delta;
626 }
627 if (pdu->used_size - (next_option - pdu->token))
628 memmove(option, next_option, pdu->used_size - (next_option - pdu->token));
629 pdu->used_size -= next_option - option;
630 if (pdu->data)
631 pdu->data -= next_option - option;
632 return 1;
633}
634
635int
637 /* Validate that the option is repeatable */
638 switch (number) {
639 /* Ignore list of genuine repeatable */
641 case COAP_OPTION_ETAG:
647 case COAP_OPTION_RTAG:
648 break;
649 /* Protest at the known non-repeatable options and ignore them */
668 case COAP_OPTION_ECHO:
670 coap_log_info("Option number %d is not defined as repeatable - dropped\n",
671 number);
672 return 0;
673 default:
674 coap_log_info("Option number %d is not defined as repeatable\n",
675 number);
676 /* Accepting it after warning as there may be user defineable options */
677 break;
678 }
679 return 1;
680}
681
682size_t
684 const uint8_t *data) {
685 coap_opt_iterator_t opt_iter;
686 coap_opt_t *option;
687 uint16_t prev_number = 0;
688 size_t shift;
689 size_t opt_delta;
690 coap_option_t decode;
691 size_t shrink = 0;
692
693 if (number >= pdu->max_opt)
694 return coap_add_option_internal(pdu, number, len, data);
695
696 /* Need to locate where in current options to insert this one */
698 while ((option = coap_option_next(&opt_iter))) {
699 if (opt_iter.number > number) {
700 /* Found where to insert */
701 break;
702 }
703 prev_number = opt_iter.number;
704 }
705 if (option == NULL) {
706 /* Code is broken somewhere */
707 coap_log_warn("coap_insert_option: Broken max_opt\n");
708 return 0;
709 }
710
711 /* size of option inc header to insert */
712 shift = coap_opt_encode_size(number - prev_number, len);
713
714 /* size of next option (header may shrink in size as delta changes */
715 if (!coap_opt_parse(option, pdu->used_size - (option - pdu->token), &decode))
716 return 0;
717 opt_delta = opt_iter.number - number;
718 if (opt_delta == 0) {
719 if (!coap_option_check_repeatable(number))
720 return 0;
721 }
722
723 if (!coap_pdu_check_resize(pdu,
724 pdu->used_size + shift - shrink))
725 return 0;
726
727 /* Possible a re-size took place with a realloc() */
728 /* Need to locate where in current options to insert this one */
730 while ((option = coap_option_next(&opt_iter))) {
731 if (opt_iter.number > number) {
732 /* Found where to insert */
733 break;
734 }
735 }
736 assert(option != NULL);
737
738 if (decode.delta < 13) {
739 /* can simply patch in the new delta of next option */
740 option[0] = (option[0] & 0x0f) + (coap_opt_t)(opt_delta << 4);
741 } else if (decode.delta < 269 && opt_delta < 13) {
742 /* option header is going to shrink by one byte */
743 option[1] = (option[0] & 0x0f) + (coap_opt_t)(opt_delta << 4);
744 shrink = 1;
745 } else if (decode.delta < 269 && opt_delta < 269) {
746 /* can simply patch in the new delta of next option */
747 option[1] = (coap_opt_t)(opt_delta - 13);
748 } else if (opt_delta < 13) {
749 /* option header is going to shrink by two bytes */
750 option[2] = (option[0] & 0x0f) + (coap_opt_t)(opt_delta << 4);
751 shrink = 2;
752 } else if (opt_delta < 269) {
753 /* option header is going to shrink by one bytes */
754 option[1] = (option[0] & 0x0f) + 0xd0;
755 option[2] = (coap_opt_t)(opt_delta - 13);
756 shrink = 1;
757 } else {
758 /* can simply patch in the new delta of next option */
759 option[1] = (coap_opt_t)((opt_delta - 269) >> 8);
760 option[2] = (opt_delta - 269) & 0xff;
761 }
762
763 memmove(&option[shift], &option[shrink],
764 pdu->used_size - (option - pdu->token) - shrink);
765 if (!coap_opt_encode(option, pdu->alloc_size - pdu->used_size,
766 number - prev_number, data, len))
767 return 0;
768
769 if (shift >= shrink) {
770 pdu->used_size += shift - shrink;
771 if (pdu->data)
772 pdu->data += shift - shrink;
773 } else {
774 pdu->used_size -= shrink - shift;
775 if (pdu->data)
776 pdu->data -= shrink - shift;
777 }
778 return shift;
779}
780
781size_t
783 const uint8_t *data) {
784 coap_opt_iterator_t opt_iter;
785 coap_opt_t *option;
786 coap_option_t decode;
787 size_t new_length = 0;
788 size_t old_length = 0;
789
790 option = coap_check_option(pdu, number, &opt_iter);
791 if (!option)
792 return coap_insert_option(pdu, number, len, data);
793
794 old_length = coap_opt_parse(option, (size_t)-1, &decode);
795 if (old_length == 0)
796 return 0;
797 new_length = coap_opt_encode_size(decode.delta, len);
798
799 if (new_length > old_length) {
800 if (!coap_pdu_check_resize(pdu,
801 pdu->used_size + new_length - old_length))
802 return 0;
803 /* Possible a re-size took place with a realloc() */
804 option = coap_check_option(pdu, number, &opt_iter);
805 }
806
807 if (new_length != old_length)
808 memmove(&option[new_length], &option[old_length],
809 pdu->used_size - (option - pdu->token) - old_length);
810
811 if (!coap_opt_encode(option, new_length,
812 decode.delta, data, len))
813 return 0;
814
815 if (new_length >= old_length) {
816 pdu->used_size += new_length - old_length;
817 if (pdu->data)
818 pdu->data += new_length - old_length;
819 } else {
820 pdu->used_size -= old_length - new_length;
821 if (pdu->data)
822 pdu->data -= old_length - new_length;
823 }
824 return 1;
825}
826
827size_t
829 const uint8_t *data) {
830 if (pdu->data) {
831 coap_log_warn("coap_add_optlist_pdu: PDU already contains data\n");
832 return 0;
833 }
834 return coap_add_option_internal(pdu, number, len, data);
835}
836
837size_t
839 const uint8_t *data) {
840 size_t optsize;
841 coap_opt_t *opt;
842
843 assert(pdu);
844
845 if (number == pdu->max_opt) {
846 if (!coap_option_check_repeatable(number))
847 return 0;
848 }
849
850 if (COAP_PDU_IS_REQUEST(pdu) &&
851 (number == COAP_OPTION_PROXY_URI ||
852 number == COAP_OPTION_PROXY_SCHEME)) {
853 /*
854 * Need to check whether there is a hop-limit option. If not, it needs
855 * to be inserted by default (RFC 8768).
856 */
857 coap_opt_iterator_t opt_iter;
858
859 if (coap_check_option(pdu, COAP_OPTION_HOP_LIMIT, &opt_iter) == NULL) {
860 size_t hop_limit = COAP_OPTION_HOP_LIMIT;
861
862 coap_insert_option(pdu, COAP_OPTION_HOP_LIMIT, 1, (uint8_t *)&hop_limit);
863 }
864 }
865
866 if (number < pdu->max_opt) {
867 coap_log_debug("coap_add_option: options are not in correct order\n");
868 return coap_insert_option(pdu, number, len, data);
869 }
870
871 optsize = coap_opt_encode_size(number - pdu->max_opt, len);
872 if (!coap_pdu_check_resize(pdu,
873 pdu->used_size + optsize))
874 return 0;
875
876 if (pdu->data) {
877 /* include option delimiter */
878 memmove(&pdu->data[optsize-1], &pdu->data[-1],
879 pdu->used_size - (pdu->data - pdu->token) + 1);
880 opt = pdu->data -1;
881 pdu->data += optsize;
882 } else {
883 opt = pdu->token + pdu->used_size;
884 }
885
886 /* encode option and check length */
887 optsize = coap_opt_encode(opt, pdu->alloc_size - pdu->used_size,
888 number - pdu->max_opt, data, len);
889
890 if (!optsize) {
891 coap_log_warn("coap_add_option: cannot add option\n");
892 /* error */
893 return 0;
894 } else {
895 pdu->max_opt = number;
896 pdu->used_size += optsize;
897 }
898
899 return optsize;
900}
901
902int
903coap_add_data(coap_pdu_t *pdu, size_t len, const uint8_t *data) {
904 if (len == 0) {
905 return 1;
906 } else {
907 uint8_t *payload = coap_add_data_after(pdu, len);
908 if (payload != NULL)
909 memcpy(payload, data, len);
910 return payload != NULL;
911 }
912}
913
914uint8_t *
916 assert(pdu);
917 if (pdu->data) {
918 coap_log_warn("coap_add_data: PDU already contains data\n");
919 return 0;
920 }
921
922 if (len == 0)
923 return NULL;
924
925 if (!coap_pdu_resize(pdu, pdu->used_size + len + 1))
926 return 0;
927 pdu->token[pdu->used_size++] = COAP_PAYLOAD_START;
928 pdu->data = pdu->token + pdu->used_size;
929 pdu->used_size += len;
930 return pdu->data;
931}
932
933int
934coap_get_data(const coap_pdu_t *pdu, size_t *len, const uint8_t **data) {
935 size_t offset;
936 size_t total;
937
938 return coap_get_data_large(pdu, len, data, &offset, &total);
939}
940
941int
942coap_get_data_large(const coap_pdu_t *pdu, size_t *len, const uint8_t **data,
943 size_t *offset, size_t *total) {
944 assert(pdu);
945 assert(len);
946 assert(data);
947
948 *offset = pdu->body_offset;
949 *total = pdu->body_total;
950 if (pdu->body_data) {
951 *data = pdu->body_data;
952 *len = pdu->body_length;
953 return 1;
954 }
955 *data = pdu->data;
956 if (pdu->data == NULL) {
957 *len = 0;
958 *total = 0;
959 return 0;
960 }
961
962 *len = pdu->used_size - (pdu->data - pdu->token);
963 if (*total == 0)
964 *total = *len;
965
966 return 1;
967}
968
969#ifndef SHORT_ERROR_RESPONSE
970typedef struct {
971 unsigned char code;
972 const char *phrase;
974
975/* if you change anything here, make sure, that the longest string does not
976 * exceed COAP_ERROR_PHRASE_LENGTH. */
978 { COAP_RESPONSE_CODE(201), "Created" },
979 { COAP_RESPONSE_CODE(202), "Deleted" },
980 { COAP_RESPONSE_CODE(203), "Valid" },
981 { COAP_RESPONSE_CODE(204), "Changed" },
982 { COAP_RESPONSE_CODE(205), "Content" },
983 { COAP_RESPONSE_CODE(231), "Continue" },
984 { COAP_RESPONSE_CODE(400), "Bad Request" },
985 { COAP_RESPONSE_CODE(401), "Unauthorized" },
986 { COAP_RESPONSE_CODE(402), "Bad Option" },
987 { COAP_RESPONSE_CODE(403), "Forbidden" },
988 { COAP_RESPONSE_CODE(404), "Not Found" },
989 { COAP_RESPONSE_CODE(405), "Method Not Allowed" },
990 { COAP_RESPONSE_CODE(406), "Not Acceptable" },
991 { COAP_RESPONSE_CODE(408), "Request Entity Incomplete" },
992 { COAP_RESPONSE_CODE(409), "Conflict" },
993 { COAP_RESPONSE_CODE(412), "Precondition Failed" },
994 { COAP_RESPONSE_CODE(413), "Request Entity Too Large" },
995 { COAP_RESPONSE_CODE(415), "Unsupported Content-Format" },
996 { COAP_RESPONSE_CODE(422), "Unprocessable" },
997 { COAP_RESPONSE_CODE(429), "Too Many Requests" },
998 { COAP_RESPONSE_CODE(500), "Internal Server Error" },
999 { COAP_RESPONSE_CODE(501), "Not Implemented" },
1000 { COAP_RESPONSE_CODE(502), "Bad Gateway" },
1001 { COAP_RESPONSE_CODE(503), "Service Unavailable" },
1002 { COAP_RESPONSE_CODE(504), "Gateway Timeout" },
1003 { COAP_RESPONSE_CODE(505), "Proxying Not Supported" },
1004 { COAP_RESPONSE_CODE(508), "Hop Limit Reached" },
1005 { 0, NULL } /* end marker */
1006};
1007
1008const char *
1009coap_response_phrase(unsigned char code) {
1010 int i;
1011 for (i = 0; coap_error[i].code; ++i) {
1012 if (coap_error[i].code == code)
1013 return coap_error[i].phrase;
1014 }
1015 return NULL;
1016}
1017#endif
1018
1024static size_t
1025next_option_safe(coap_opt_t **optp, size_t *length, uint16_t *max_opt) {
1026 coap_option_t option;
1027 size_t optsize;
1028
1029 assert(optp);
1030 assert(*optp);
1031 assert(length);
1032
1033 optsize = coap_opt_parse(*optp, *length, &option);
1034 assert(optsize <= *length);
1035
1036 /* signal an error if this option would exceed the
1037 * allowed number space */
1038 if ((uint32_t)(*max_opt) + option.delta > COAP_MAX_OPT) {
1039 return 0;
1040 }
1041 *max_opt += option.delta;
1042 *optp += optsize;
1043 *length -= optsize;
1044
1045 return optsize;
1046}
1047
1048size_t
1050 const uint8_t *data) {
1051 assert(data);
1052 size_t header_size = 0;
1053
1054 if (proto == COAP_PROTO_TCP || proto==COAP_PROTO_TLS) {
1055 uint8_t len = *data >> 4;
1056 if (len < 13)
1057 header_size = 2;
1058 else if (len==13)
1059 header_size = 3;
1060 else if (len==14)
1061 header_size = 4;
1062 else
1063 header_size = 6;
1064 } else if (proto == COAP_PROTO_WS || proto==COAP_PROTO_WSS) {
1065 header_size = 2;
1066 } else if (proto == COAP_PROTO_UDP || proto==COAP_PROTO_DTLS) {
1067 header_size = 4;
1068 }
1069
1070 return header_size;
1071}
1072
1073#if !COAP_DISABLE_TCP
1074/*
1075 * strm
1076 * return +ve PDU size including token
1077 * 0 PDU does not parse
1078 */
1079size_t
1081 const uint8_t *data,
1082 size_t length) {
1083 assert(data);
1084 assert(proto == COAP_PROTO_TCP || proto == COAP_PROTO_TLS ||
1085 proto == COAP_PROTO_WS || proto == COAP_PROTO_WSS);
1086 assert(coap_pdu_parse_header_size(proto, data) <= length);
1087
1088 size_t size = 0;
1089 const uint8_t *token_start = NULL;
1090
1091 if ((proto == COAP_PROTO_TCP || proto == COAP_PROTO_TLS) && length >= 1) {
1092 uint8_t len = *data >> 4;
1093 uint8_t tkl = *data & 0x0f;
1094
1095 if (len < 13) {
1096 size = len;
1097 token_start = &data[2];
1098 } else if (length >= 2) {
1099 if (len==13) {
1100 size = (size_t)data[1] + COAP_MESSAGE_SIZE_OFFSET_TCP8;
1101 token_start = &data[3];
1102 } else if (length >= 3) {
1103 if (len==14) {
1104 size = ((size_t)data[1] << 8) + data[2] + COAP_MESSAGE_SIZE_OFFSET_TCP16;
1105 token_start = &data[4];
1106 } else if (length >= 5) {
1107 size = ((size_t)data[1] << 24) + ((size_t)data[2] << 16)
1108 + ((size_t)data[3] << 8) + data[4] + COAP_MESSAGE_SIZE_OFFSET_TCP32;
1109 token_start = &data[6];
1110 }
1111 }
1112 }
1113 if (token_start) {
1114 /* account for the token length */
1115 if (tkl < COAP_TOKEN_EXT_1B_TKL) {
1116 size += tkl;
1117 } else if (tkl == COAP_TOKEN_EXT_1B_TKL) {
1118 size += token_start[0] + COAP_TOKEN_EXT_1B_BIAS + 1;
1119 } else if (tkl == COAP_TOKEN_EXT_2B_TKL) {
1120 size += ((uint16_t)token_start[0] << 8) + token_start[1] +
1122 } else {
1123 /* Invalid at this point - caught later as undersized */
1124 }
1125 }
1126 }
1127
1128 return size;
1129}
1130#endif /* ! COAP_DISABLE_TCP */
1131
1132int
1134 uint8_t *hdr = pdu->token - pdu->hdr_size;
1135 uint8_t e_token_length;
1136
1137 if (proto == COAP_PROTO_UDP || proto == COAP_PROTO_DTLS) {
1138 assert(pdu->hdr_size == 4);
1139 if ((hdr[0] >> 6) != COAP_DEFAULT_VERSION) {
1140 coap_log_debug("coap_pdu_parse: UDP version not supported\n");
1141 return 0;
1142 }
1143 pdu->type = (hdr[0] >> 4) & 0x03;
1144 pdu->code = hdr[1];
1145 pdu->mid = (uint16_t)hdr[2] << 8 | hdr[3];
1146 } else if (proto == COAP_PROTO_TCP || proto == COAP_PROTO_TLS) {
1147 assert(pdu->hdr_size >= 2 && pdu->hdr_size <= 6);
1148 pdu->type = COAP_MESSAGE_CON;
1149 pdu->code = hdr[pdu->hdr_size-1];
1150 pdu->mid = 0;
1151 } else if (proto == COAP_PROTO_WS || proto == COAP_PROTO_WSS) {
1152 assert(pdu->hdr_size == 2);
1153 pdu->type = COAP_MESSAGE_CON;
1154 pdu->code = hdr[pdu->hdr_size-1];
1155 pdu->mid = 0;
1156 } else {
1157 coap_log_debug("coap_pdu_parse: unsupported protocol\n");
1158 return 0;
1159 }
1160
1161 e_token_length = hdr[0] & 0x0f;
1162 if (e_token_length < COAP_TOKEN_EXT_1B_TKL) {
1163 pdu->e_token_length = e_token_length;
1165 pdu->actual_token.s = &pdu->token[0];
1166 } else if (e_token_length == COAP_TOKEN_EXT_1B_TKL) {
1167 pdu->e_token_length = pdu->token[0] + COAP_TOKEN_EXT_1B_BIAS + 1;
1168 pdu->actual_token.length = pdu->e_token_length - 1;
1169 pdu->actual_token.s = &pdu->token[1];
1170 } else if (e_token_length == COAP_TOKEN_EXT_2B_TKL) {
1171 pdu->e_token_length = ((uint16_t)pdu->token[0] << 8) + pdu->token[1] +
1173 pdu->actual_token.length = pdu->e_token_length - 2;
1174 pdu->actual_token.s = &pdu->token[2];
1175 }
1176 if (pdu->e_token_length > pdu->alloc_size || e_token_length == 15) {
1177 /* Invalid PDU provided - not wise to assert here though */
1178 coap_log_debug("coap_pdu_parse: PDU header token size broken\n");
1179 pdu->e_token_length = 0;
1180 pdu->actual_token.length = 0;
1181 return 0;
1182 }
1183 return 1;
1184}
1185
1186static int
1188 switch ((coap_pdu_signaling_proto_t)pdu->code) {
1189 case COAP_SIGNALING_CSM:
1190 switch (pdu->max_opt) {
1192 if (len > 4)
1193 goto bad;
1194 break;
1196 if (len > 0)
1197 goto bad;
1198 break;
1200 if (len > 3)
1201 goto bad;
1202 break;
1203 default:
1204 if (pdu->max_opt & 0x01)
1205 goto bad; /* Critical */
1206 }
1207 break;
1210 switch (pdu->max_opt) {
1212 if (len > 0)
1213 goto bad;
1214 break;
1215 default:
1216 if (pdu->max_opt & 0x01)
1217 goto bad; /* Critical */
1218 }
1219 break;
1221 switch (pdu->max_opt) {
1223 if (len < 1 || len > 255)
1224 goto bad;
1225 break;
1227 if (len > 3)
1228 goto bad;
1229 break;
1230 default:
1231 if (pdu->max_opt & 0x01)
1232 goto bad; /* Critical */
1233 }
1234 break;
1236 switch (pdu->max_opt) {
1238 if (len > 2)
1239 goto bad;
1240 break;
1241 default:
1242 if (pdu->max_opt & 0x01)
1243 goto bad; /* Critical */
1244 }
1245 break;
1246 default:
1247 ;
1248 }
1249 return 1;
1250bad:
1251 return 0;
1252}
1253
1254static int
1256 int res = 1;
1257
1258 switch (pdu->max_opt) {
1260 if (len > 8)
1261 res = 0;
1262 break;
1264 if (len < 1 || len > 255)
1265 res = 0;
1266 break;
1267 case COAP_OPTION_ETAG:
1268 if (len < 1 || len > 8)
1269 res = 0;
1270 break;
1272 if (len != 0)
1273 res = 0;
1274 break;
1276 if (len > 3)
1277 res = 0;
1278 break;
1280 if (len > 2)
1281 res = 0;
1282 break;
1284 if (len > 255)
1285 res = 0;
1286 break;
1287 case COAP_OPTION_OSCORE:
1288 if (len > 255)
1289 res = 0;
1290 break;
1292 if (len > 255)
1293 res = 0;
1294 break;
1296 if (len > 2)
1297 res = 0;
1298 break;
1299 case COAP_OPTION_MAXAGE:
1300 if (len > 4)
1301 res = 0;
1302 break;
1304 if (len < 1 || len > 255)
1305 res = 0;
1306 break;
1308 if (len != 1)
1309 res = 0;
1310 break;
1311 case COAP_OPTION_ACCEPT:
1312 if (len > 2)
1313 res = 0;
1314 break;
1316 if (len > 3)
1317 res = 0;
1318 break;
1320 if (len > 255)
1321 res = 0;
1322 break;
1323 case COAP_OPTION_EDHOC:
1324 if (len != 0)
1325 res = 0;
1326 break;
1327 case COAP_OPTION_BLOCK2:
1328 if (len > 3)
1329 res = 0;
1330 break;
1331 case COAP_OPTION_BLOCK1:
1332 if (len > 3)
1333 res = 0;
1334 break;
1335 case COAP_OPTION_SIZE2:
1336 if (len > 4)
1337 res = 0;
1338 break;
1340 if (len > 3)
1341 res = 0;
1342 break;
1344 if (len < 1 || len > 1034)
1345 res = 0;
1346 break;
1348 if (len < 1 || len > 255)
1349 res = 0;
1350 break;
1351 case COAP_OPTION_SIZE1:
1352 if (len > 4)
1353 res = 0;
1354 break;
1355 case COAP_OPTION_ECHO:
1356 if (len > 40)
1357 res = 0;
1358 break;
1360 if (len > 1)
1361 res = 0;
1362 break;
1363 case COAP_OPTION_RTAG:
1364 if (len > 8)
1365 res = 0;
1366 break;
1367 default:
1368 ;
1369 }
1370 return res;
1371}
1372
1373static int
1374write_prefix(char **obp, size_t *len, const char *prf, size_t prflen) {
1375 /* Make sure space for null terminating byte */
1376 if (*len < prflen +1) {
1377 return 0;
1378 }
1379
1380 memcpy(*obp, prf, prflen);
1381 *obp += prflen;
1382 *len -= prflen;
1383 return 1;
1384}
1385
1386static int
1387write_char(char **obp, size_t *len, int c, int printable) {
1388 /* Make sure space for null terminating byte */
1389 if (*len < 2 +1) {
1390 return 0;
1391 }
1392
1393 if (!printable) {
1394 const uint8_t hex[] = "0123456789abcdef";
1395 (*obp)[0] = hex[(c & 0xf0) >> 4];
1396 (*obp)[1] = hex[c & 0x0f];
1397 } else {
1398 (*obp)[0] = isprint(c) ? c : '.';
1399 (*obp)[1] = ' ';
1400 }
1401 *obp += 2;
1402 *len -= 2;
1403 return 1;
1404}
1405
1406int
1408 int good = 1;
1409
1410 coap_option_filter_clear(error_opts);
1411
1412 /* sanity checks */
1413 if (pdu->code == 0) {
1414 if (pdu->used_size != 0 || pdu->e_token_length) {
1415 coap_log_debug("coap_pdu_parse: empty message is not empty\n");
1416 return 0;
1417 }
1418 }
1419
1420 if (pdu->e_token_length > pdu->used_size) {
1421 coap_log_debug("coap_pdu_parse: invalid Token\n");
1422 return 0;
1423 }
1424
1425 pdu->max_opt = 0;
1426 if (pdu->code == 0) {
1427 /* empty packet */
1428 pdu->used_size = 0;
1429 pdu->data = NULL;
1430 } else {
1431 /* skip header + token */
1432 coap_opt_t *opt = pdu->token + pdu->e_token_length;
1433 size_t length = pdu->used_size - pdu->e_token_length;
1434
1435 while (length > 0 && *opt != COAP_PAYLOAD_START) {
1436#if (COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_WARN)
1437 coap_opt_t *opt_last = opt;
1438#endif
1439 size_t optsize = next_option_safe(&opt, &length, &pdu->max_opt);
1440 const uint32_t len =
1441 optsize ? coap_opt_length((const uint8_t *)opt - optsize) : 0;
1442 if (optsize == 0) {
1443 coap_log_debug("coap_pdu_parse: %d.%02d: offset %u malformed option\n",
1444 pdu->code >> 5, pdu->code & 0x1F,
1445 (int)(opt_last - pdu->token - pdu->e_token_length));
1446 coap_option_filter_set(error_opts, pdu->max_opt);
1447 good = 0;
1448 break;
1449 }
1450 if (COAP_PDU_IS_SIGNALING(pdu) ?
1451 !coap_pdu_parse_opt_csm(pdu, len) :
1452 !coap_pdu_parse_opt_base(pdu, len)) {
1453 coap_log_warn("coap_pdu_parse: %d.%02d: offset %u option %u has bad length %" PRIu32 "\n",
1454 pdu->code >> 5, pdu->code & 0x1F,
1455 (int)(opt_last - pdu->token - pdu->e_token_length), pdu->max_opt,
1456 len);
1457 coap_option_filter_set(error_opts, pdu->max_opt);
1458 good = 0;
1459 }
1460 }
1461
1462 if (!good) {
1463 /*
1464 * Dump the options in the PDU for analysis, space separated except
1465 * error options which are prefixed by *
1466 * Two rows - hex and ascii (if printable)
1467 */
1468 static char outbuf[COAP_DEBUG_BUF_SIZE];
1469 char *obp;
1470 size_t tlen;
1471 size_t outbuflen;
1472 int i;
1473 int ok;
1474
1475 for (i = 0; i < 2; i++) {
1476 opt = pdu->token + pdu->e_token_length;
1477 length = pdu->used_size - pdu->e_token_length;
1478 pdu->max_opt = 0;
1479
1480 outbuflen = sizeof(outbuf);
1481 obp = outbuf;
1482 ok = write_prefix(&obp, &outbuflen, "O: ", 3);
1483 /*
1484 * Not safe to check for 'ok' here as a lot of variables may get
1485 * partially changed due to lack of outbuflen */
1486 while (length > 0 && *opt != COAP_PAYLOAD_START) {
1487 coap_opt_t *opt_last = opt;
1488 size_t optsize = next_option_safe(&opt, &length, &pdu->max_opt);
1489 const uint32_t len =
1490 optsize ? coap_opt_length((const uint8_t *)opt - optsize) : 0;
1491 if (!optsize || (COAP_PDU_IS_SIGNALING(pdu) ?
1492 !coap_pdu_parse_opt_csm(pdu, len) :
1493 !coap_pdu_parse_opt_base(pdu, len))) {
1494 ok = ok && write_prefix(&obp, &outbuflen, "*", 1);
1495 if (!optsize) {
1496 /* Skip to end of options to output all data */
1497 opt = pdu->token + pdu->used_size;
1498 length = 0;
1499 }
1500 } else {
1501 ok = ok && write_prefix(&obp, &outbuflen, " ", 1);
1502 }
1503 tlen = opt - opt_last;
1504 while (tlen) {
1505 tlen--;
1506 ok = ok && write_char(&obp, &outbuflen, *opt_last, i);
1507 opt_last++;
1508 }
1509 }
1510 if (length && *opt == COAP_PAYLOAD_START) {
1511 write_char(&obp, &outbuflen, *opt, i);
1512 }
1513 /* write_*() always leaves a spare byte to null terminate */
1514 *obp = '\000';
1515 coap_log_debug("%s\n", outbuf);
1516 }
1517 }
1518
1519 if (length > 0) {
1520 assert(*opt == COAP_PAYLOAD_START);
1521 opt++;
1522 length--;
1523
1524 if (length == 0) {
1525 coap_log_debug("coap_pdu_parse: message ending in payload start marker\n");
1526 return 0;
1527 }
1528 }
1529 if (length > 0)
1530 pdu->data = (uint8_t *)opt;
1531 else
1532 pdu->data = NULL;
1533 }
1534
1535 return good;
1536}
1537
1538int
1540 const uint8_t *data,
1541 size_t length,
1542 coap_pdu_t *pdu) {
1543 coap_opt_filter_t error_opts;
1544
1545 return coap_pdu_parse2(proto, data, length, pdu, &error_opts);
1546}
1547
1548int
1550 const uint8_t *data,
1551 size_t length,
1552 coap_pdu_t *pdu,
1553 coap_opt_filter_t *error_opts) {
1554 size_t hdr_size;
1555
1556 if (length == 0)
1557 return 0;
1558 hdr_size = coap_pdu_parse_header_size(proto, data);
1559 if (!hdr_size || hdr_size > length)
1560 return 0;
1561 if (hdr_size > pdu->max_hdr_size)
1562 return 0;
1563 if (!coap_pdu_resize(pdu, length - hdr_size))
1564 return 0;
1565 if (pdu->token - hdr_size != data)
1566 memcpy(pdu->token - hdr_size, data, length);
1567 pdu->hdr_size = (uint8_t)hdr_size;
1568 pdu->used_size = length - hdr_size;
1569 return coap_pdu_parse_header(pdu, proto) && coap_pdu_parse_opt(pdu, error_opts);
1570}
1571
1572size_t
1574 uint8_t e_token_length;
1575
1577 e_token_length = (uint8_t)pdu->actual_token.length;
1578 } else if (pdu->actual_token.length < COAP_TOKEN_EXT_2B_BIAS) {
1579 e_token_length = COAP_TOKEN_EXT_1B_TKL;
1580 } else if (pdu->actual_token.length <= COAP_TOKEN_EXT_MAX) {
1581 e_token_length = COAP_TOKEN_EXT_2B_TKL;
1582 } else {
1583 coap_log_warn("coap_add_token: Token size too large. PDU ignored\n");
1584 return 0;
1585 }
1586 if (COAP_PROTO_NOT_RELIABLE(proto)) {
1587 assert(pdu->max_hdr_size >= 4);
1588 if (pdu->max_hdr_size < 4) {
1589 coap_log_warn("coap_pdu_encode_header: not enough space for UDP-style header\n");
1590 return 0;
1591 }
1592 pdu->token[-4] = COAP_DEFAULT_VERSION << 6
1593 | pdu->type << 4
1594 | e_token_length;
1595 pdu->token[-3] = pdu->code;
1596 pdu->token[-2] = (uint8_t)(pdu->mid >> 8);
1597 pdu->token[-1] = (uint8_t)(pdu->mid);
1598 pdu->hdr_size = 4;
1599#if !COAP_DISABLE_TCP
1600 } else if (COAP_PROTO_RELIABLE(proto)) {
1601 size_t len;
1602 assert(pdu->used_size >= pdu->e_token_length);
1603 if (pdu->used_size < pdu->e_token_length) {
1604 coap_log_warn("coap_pdu_encode_header: corrupted PDU\n");
1605 return 0;
1606 }
1607
1608 /* A lot of the reliable code assumes type is CON */
1609 if (pdu->type != COAP_MESSAGE_CON)
1610 pdu->type = COAP_MESSAGE_CON;
1611
1612 if (proto == COAP_PROTO_WS || proto == COAP_PROTO_WSS)
1613 len = 0;
1614 else
1615 len = pdu->used_size - pdu->e_token_length;
1616 if (len <= COAP_MAX_MESSAGE_SIZE_TCP0) {
1617 assert(pdu->max_hdr_size >= 2);
1618 if (pdu->max_hdr_size < 2) {
1619 coap_log_warn("coap_pdu_encode_header: not enough space for TCP0 header\n");
1620 return 0;
1621 }
1622 pdu->token[-2] = (uint8_t)len << 4
1623 | e_token_length;
1624 pdu->token[-1] = pdu->code;
1625 pdu->hdr_size = 2;
1626 } else if (len <= COAP_MAX_MESSAGE_SIZE_TCP8) {
1627 assert(pdu->max_hdr_size >= 3);
1628 if (pdu->max_hdr_size < 3) {
1629 coap_log_warn("coap_pdu_encode_header: not enough space for TCP8 header\n");
1630 return 0;
1631 }
1632 pdu->token[-3] = 13 << 4 | e_token_length;
1633 pdu->token[-2] = (uint8_t)(len - COAP_MESSAGE_SIZE_OFFSET_TCP8);
1634 pdu->token[-1] = pdu->code;
1635 pdu->hdr_size = 3;
1636 } else if (len <= COAP_MAX_MESSAGE_SIZE_TCP16) {
1637 assert(pdu->max_hdr_size >= 4);
1638 if (pdu->max_hdr_size < 4) {
1639 coap_log_warn("coap_pdu_encode_header: not enough space for TCP16 header\n");
1640 return 0;
1641 }
1642 pdu->token[-4] = 14 << 4 | e_token_length;
1643 pdu->token[-3] = (uint8_t)((len - COAP_MESSAGE_SIZE_OFFSET_TCP16) >> 8);
1644 pdu->token[-2] = (uint8_t)(len - COAP_MESSAGE_SIZE_OFFSET_TCP16);
1645 pdu->token[-1] = pdu->code;
1646 pdu->hdr_size = 4;
1647 } else {
1648 assert(pdu->max_hdr_size >= 6);
1649 if (pdu->max_hdr_size < 6) {
1650 coap_log_warn("coap_pdu_encode_header: not enough space for TCP32 header\n");
1651 return 0;
1652 }
1653 pdu->token[-6] = 15 << 4 | e_token_length;
1654 pdu->token[-5] = (uint8_t)((len - COAP_MESSAGE_SIZE_OFFSET_TCP32) >> 24);
1655 pdu->token[-4] = (uint8_t)((len - COAP_MESSAGE_SIZE_OFFSET_TCP32) >> 16);
1656 pdu->token[-3] = (uint8_t)((len - COAP_MESSAGE_SIZE_OFFSET_TCP32) >> 8);
1657 pdu->token[-2] = (uint8_t)(len - COAP_MESSAGE_SIZE_OFFSET_TCP32);
1658 pdu->token[-1] = pdu->code;
1659 pdu->hdr_size = 6;
1660 }
1661#endif /* ! COAP_DISABLE_TCP */
1662 } else {
1663 coap_log_warn("coap_pdu_encode_header: unsupported protocol\n");
1664 }
1665 return pdu->hdr_size;
1666}
1667
1670 return pdu->code;
1671}
1672
1673void
1675#ifndef RIOT_VERSION
1676 assert(code <= 0xff);
1677#endif /* RIOT_VERSION */
1678 pdu->code = code;
1679}
1680
1683 return pdu->type;
1684}
1685
1686void
1688 assert(type <= 0x3);
1689 pdu->type = type;
1690}
1691
1694 return pdu->actual_token;
1695}
1696
1699 return pdu->mid;
1700}
1701
1702void
1704#if (UINT_MAX > 65535)
1705 assert(mid >= 0 && mid <= 0xffff);
1706#endif /* UINT_MAX > 65535 */
1707 pdu->mid = mid;
1708}
1709
1710coap_pdu_t *
1712 if (pdu != NULL) {
1713 ++pdu->ref;
1714 }
1715 return pdu;
1716}
1717
1718coap_pdu_t *
1720 coap_pdu_t *pdu_rw = NULL;
1721
1722 if (pdu != NULL) {
1723
1724 /* Need to do this to not get a compiler warning about const parameters */
1725 memcpy(&pdu_rw, &pdu, sizeof(pdu_rw));
1726 ++pdu_rw->ref;
1727 }
1728 return pdu_rw;
1729}
#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:1025
static int coap_pdu_parse_opt_csm(coap_pdu_t *pdu, uint16_t len)
Definition coap_pdu.c:1187
error_desc_t coap_error[]
Definition coap_pdu.c:977
static int write_prefix(char **obp, size_t *len, const char *prf, size_t prflen)
Definition coap_pdu.c:1374
static int coap_pdu_parse_opt_base(coap_pdu_t *pdu, uint16_t len)
Definition coap_pdu.c:1255
#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:1387
#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:1711
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:683
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:542
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:466
#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:1407
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:1133
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:1049
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:636
#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:782
#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:1573
#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:1549
#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:392
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:1080
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:1719
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:337
#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:838
#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:1669
#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:1009
#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:915
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:1674
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:409
#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:1687
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:828
#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:1682
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:934
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:1539
#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:1703
#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:942
#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:1698
#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:903
coap_bin_const_t coap_pdu_get_token(const coap_pdu_t *pdu)
Gets the token associated with pdu.
Definition coap_pdu.c:1693
@ 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:971
const char * phrase
Definition coap_pdu.c:972