libcoap 4.3.0
coap_debug.c
Go to the documentation of this file.
1/* debug.c -- debug utilities
2 *
3 * Copyright (C) 2010--2012,2014--2019 Olaf Bergmann <bergmann@tzi.org> and others
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
11#include "coap3/coap_internal.h"
12
13#if defined(HAVE_STRNLEN) && defined(__GNUC__) && !defined(_GNU_SOURCE)
14#define _GNU_SOURCE 1
15#endif
16
17#include <stdarg.h>
18#include <stdio.h>
19#include <string.h>
20#include <ctype.h>
21
22#ifdef HAVE_ARPA_INET_H
23#include <arpa/inet.h>
24#endif
25#ifdef HAVE_WS2TCPIP_H
26#include <ws2tcpip.h>
27#endif
28
29#ifdef HAVE_TIME_H
30#include <time.h>
31#endif
32
33#ifdef WITH_LWIP
34# define fprintf(fd, ...) LWIP_PLATFORM_DIAG((__VA_ARGS__))
35# define fflush(...)
36#endif
37
38#ifdef WITH_CONTIKI
39# ifndef DEBUG
40# define DEBUG DEBUG_PRINT
41# endif /* DEBUG */
42#include "net/ip/uip-debug.h"
43#endif
44
45static coap_log_t maxlog = LOG_WARNING; /* default maximum log level */
46
47static int use_fprintf_for_show_pdu = 1; /* non zero to output with fprintf */
48
49const char *coap_package_name(void) {
50 return PACKAGE_NAME;
51}
52
53const char *coap_package_version(void) {
54 return PACKAGE_STRING;
55}
56
57void
58coap_set_show_pdu_output(int use_fprintf) {
59 use_fprintf_for_show_pdu = use_fprintf;
60}
61
64 return maxlog;
65}
66
67void
69 maxlog = level;
70}
71
72/* this array has the same order as the type log_t */
73static const char *loglevels[] = {
74 "EMRG", "ALRT", "CRIT", "ERR ", "WARN", "NOTE", "INFO", "DEBG", "????", "CIPH"
75};
76
77#ifdef HAVE_TIME_H
78
80print_timestamp(char *s, size_t len, coap_tick_t t) {
81 struct tm *tmp;
82 size_t lensofar;
83 time_t now = coap_ticks_to_rt(t);
84 tmp = localtime(&now);
85 lensofar = strftime(s, len, "%b %d %H:%M:%S", tmp);
86 if (len > lensofar + 4) {
87 lensofar += snprintf(&s[lensofar], len-lensofar, ".%03u",
88 (unsigned int)((coap_ticks_to_rt_us(t) % 1000000)/1000));
89 }
90 return lensofar;
91}
92
93#else /* alternative implementation: just print the timestamp */
94
96print_timestamp(char *s, size_t len, coap_tick_t t) {
97#ifdef HAVE_SNPRINTF
98 return snprintf(s, len, "%u.%03u",
99 (unsigned int)coap_ticks_to_rt(t),
100 (unsigned int)((coap_ticks_to_rt_us(t) % 1000000)/1000));
101#else /* HAVE_SNPRINTF */
102 /* @todo do manual conversion of timestamp */
103 return 0;
104#endif /* HAVE_SNPRINTF */
105}
106
107#endif /* HAVE_TIME_H */
108
109#ifndef HAVE_STRNLEN
118static inline size_t
119strnlen(const char *s, size_t maxlen) {
120 size_t n = 0;
121 while(*s++ && n < maxlen)
122 ++n;
123 return n;
124}
125#endif /* HAVE_STRNLEN */
126
127static size_t
128print_readable( const uint8_t *data, size_t len,
129 unsigned char *result, size_t buflen, int encode_always ) {
130 const uint8_t hex[] = "0123456789ABCDEF";
131 size_t cnt = 0;
132 assert(data || len == 0);
133
134 if (buflen == 0) { /* there is nothing we can do here but return */
135 return 0;
136 }
137
138 while (len) {
139 if (!encode_always && isprint(*data)) {
140 if (cnt+1 < buflen) { /* keep one byte for terminating zero */
141 *result++ = *data;
142 ++cnt;
143 } else {
144 break;
145 }
146 } else {
147 if (cnt+4 < buflen) { /* keep one byte for terminating zero */
148 *result++ = '\\';
149 *result++ = 'x';
150 *result++ = hex[(*data & 0xf0) >> 4];
151 *result++ = hex[*data & 0x0f];
152 cnt += 4;
153 } else
154 break;
155 }
156
157 ++data; --len;
158 }
159
160 *result = '\0'; /* add a terminating zero */
161 return cnt;
162}
163
164#ifndef min
165#define min(a,b) ((a) < (b) ? (a) : (b))
166#endif
167
168/*
169 * Returned buf is always NULL terminated.
170 * Returned size is number of characters, not including NULL terminator.
171 */
172size_t
173coap_print_addr(const coap_address_t *addr, unsigned char *buf, size_t len) {
174#if defined( HAVE_ARPA_INET_H ) || defined( HAVE_WS2TCPIP_H )
175 const void *addrptr = NULL;
176 in_port_t port;
177 unsigned char *p = buf;
178 size_t need_buf;
179
180 assert(buf);
181 assert(len);
182 buf[0] = '\000';
183
184 switch (addr->addr.sa.sa_family) {
185 case AF_INET:
186 if (len < INET_ADDRSTRLEN + 1) /* Include : */
187 return 0;
188 addrptr = &addr->addr.sin.sin_addr;
189 port = ntohs(addr->addr.sin.sin_port);
190 need_buf = INET_ADDRSTRLEN;
191 break;
192 case AF_INET6:
193 if (len < INET6_ADDRSTRLEN + 3) /* Include [ ] : */
194 return 0;
195
196 *p++ = '[';
197
198 addrptr = &addr->addr.sin6.sin6_addr;
199 port = ntohs(addr->addr.sin6.sin6_port);
200 need_buf = INET6_ADDRSTRLEN;
201
202 break;
203 default:
204 /* Include trailing NULL if possible */
205 memcpy(buf, "(unknown address type)", min(22+1, len));
206 buf[len-1] = '\000';
207 return min(22, len);
208 }
209
210 /* Cast needed for Windows, since it doesn't have the correct API signature. */
211 if (inet_ntop(addr->addr.sa.sa_family, addrptr, (char *)p,
212 min(len, need_buf)) == 0) {
213 perror("coap_print_addr");
214 buf[0] = '\000';
215 return 0;
216 }
217
218 p += strlen((char *)p);
219
220 if (addr->addr.sa.sa_family == AF_INET6) {
221 if (p + 1 < buf + len) {
222 *p++ = ']';
223 } else
224 return p - buf; /* Already NULL terminated */
225 }
226
227 /* Cannot rely on snprintf() return value for short buffers */
228 snprintf((char *)p, buf + len - p, ":%d", port);
229
230 return strlen((char *)buf);
231#else /* HAVE_ARPA_INET_H */
232# if WITH_CONTIKI
233 unsigned char *p = buf;
234 uint8_t i;
235# if NETSTACK_CONF_WITH_IPV6
236 const uint8_t hex[] = "0123456789ABCDEF";
237
238 assert(buf);
239 assert(len);
240 buf[0] = '\000';
241 if (len < 42)
242 return 0;
243
244 *p++ = '[';
245
246 for (i=0; i < 16; i += 2) {
247 if (i) {
248 *p++ = ':';
249 }
250 *p++ = hex[(addr->addr.u8[i] & 0xf0) >> 4];
251 *p++ = hex[(addr->addr.u8[i] & 0x0f)];
252 *p++ = hex[(addr->addr.u8[i+1] & 0xf0) >> 4];
253 *p++ = hex[(addr->addr.u8[i+1] & 0x0f)];
254 }
255 *p++ = ']';
256# else /* WITH_UIP6 */
257# warning "IPv4 network addresses will not be included in debug output"
258
259 if (len < 21) {
260 *p = '\000';
261 return 0;
262 }
263# endif /* WITH_UIP6 */
264 if (buf + len - p < 6) {
265 *p = '\000';
266 return p - buf;
267 }
268
269#ifdef HAVE_SNPRINTF
270 /* Cannot rely on snprintf() return value for short buffers */
271 snprintf((char *)p, buf + len - p, ":%d", uip_htons(addr->port));
272#else /* HAVE_SNPRINTF */
273 /* @todo manual conversion of port number */
274 *p = '\000';
275#endif /* HAVE_SNPRINTF */
276
277 return strlen((char *)p);
278# else /* WITH_CONTIKI */
279 /* TODO: output addresses manually */
280# warning "inet_ntop() not available, network addresses will not be included in debug output"
281# endif /* WITH_CONTIKI */
282 buf[0] = '\000';
283 return 0;
284#endif
285}
286
287#ifdef WITH_CONTIKI
288# define fprintf(fd, ...) { (void)fd; PRINTF(__VA_ARGS__); }
289# define fflush(...)
290
291# ifdef HAVE_VPRINTF
292# define vfprintf(fd, ...) { (void)fd; vprintf(__VA_ARGS__); }
293# else /* HAVE_VPRINTF */
294# define vfprintf(fd, ...) { (void)fd; PRINTF(__VA_ARGS__); }
295# endif /* HAVE_VPRINTF */
296#endif /* WITH_CONTIKI */
297
299static const char *
300msg_type_string(uint16_t t) {
301 static const char *types[] = { "CON", "NON", "ACK", "RST", "???" };
302
303 return types[min(t, sizeof(types)/sizeof(char *) - 1)];
304}
305
307static const char *
308msg_code_string(uint16_t c) {
309 static const char *methods[] = { "0.00", "GET", "POST", "PUT", "DELETE",
310 "FETCH", "PATCH", "iPATCH" };
311 static const char *signals[] = { "7.00", "CSM", "Ping", "Pong", "Release",
312 "Abort" };
313 static char buf[5];
314
315 if (c < sizeof(methods)/sizeof(const char *)) {
316 return methods[c];
317 } else if (c >= 224 && c - 224 < (int)(sizeof(signals)/sizeof(const char *))) {
318 return signals[c-224];
319 } else {
320 snprintf(buf, sizeof(buf), "%u.%02u", (c >> 5) & 0x7, c & 0x1f);
321 return buf;
322 }
323}
324
326static const char *
327msg_option_string(uint8_t code, uint16_t option_type) {
328 struct option_desc_t {
329 uint16_t type;
330 const char *name;
331 };
332
333 static struct option_desc_t options[] = {
334 { COAP_OPTION_IF_MATCH, "If-Match" },
335 { COAP_OPTION_URI_HOST, "Uri-Host" },
336 { COAP_OPTION_ETAG, "ETag" },
337 { COAP_OPTION_IF_NONE_MATCH, "If-None-Match" },
338 { COAP_OPTION_OBSERVE, "Observe" },
339 { COAP_OPTION_URI_PORT, "Uri-Port" },
340 { COAP_OPTION_LOCATION_PATH, "Location-Path" },
341 { COAP_OPTION_URI_PATH, "Uri-Path" },
342 { COAP_OPTION_CONTENT_FORMAT, "Content-Format" },
343 { COAP_OPTION_MAXAGE, "Max-Age" },
344 { COAP_OPTION_URI_QUERY, "Uri-Query" },
345 { COAP_OPTION_HOP_LIMIT, "Hop-Limit" },
346 { COAP_OPTION_ACCEPT, "Accept" },
347 { COAP_OPTION_LOCATION_QUERY, "Location-Query" },
348 { COAP_OPTION_BLOCK2, "Block2" },
349 { COAP_OPTION_BLOCK1, "Block1" },
350 { COAP_OPTION_SIZE2, "Size2" },
351 { COAP_OPTION_PROXY_URI, "Proxy-Uri" },
352 { COAP_OPTION_PROXY_SCHEME, "Proxy-Scheme" },
353 { COAP_OPTION_SIZE1, "Size1" },
354 { COAP_OPTION_NORESPONSE, "No-Response" }
355 };
356
357 static struct option_desc_t options_csm[] = {
358 { COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE, "Max-Message-Size" },
359 { COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER, "Block-wise-Transfer" }
360 };
361
362 static struct option_desc_t options_pingpong[] = {
363 { COAP_SIGNALING_OPTION_CUSTODY, "Custody" }
364 };
365
366 static struct option_desc_t options_release[] = {
367 { COAP_SIGNALING_OPTION_ALTERNATIVE_ADDRESS, "Alternative-Address" },
368 { COAP_SIGNALING_OPTION_HOLD_OFF, "Hold-Off" }
369 };
370
371 static struct option_desc_t options_abort[] = {
372 { COAP_SIGNALING_OPTION_BAD_CSM_OPTION, "Bad-CSM-Option" }
373 };
374
375 static char buf[6];
376 size_t i;
377
378 if (code == COAP_SIGNALING_CSM) {
379 for (i = 0; i < sizeof(options_csm)/sizeof(struct option_desc_t); i++) {
380 if (option_type == options_csm[i].type) {
381 return options_csm[i].name;
382 }
383 }
384 } else if (code == COAP_SIGNALING_PING || code == COAP_SIGNALING_PONG) {
385 for (i = 0; i < sizeof(options_pingpong)/sizeof(struct option_desc_t); i++) {
386 if (option_type == options_pingpong[i].type) {
387 return options_pingpong[i].name;
388 }
389 }
390 } else if (code == COAP_SIGNALING_RELEASE) {
391 for (i = 0; i < sizeof(options_release)/sizeof(struct option_desc_t); i++) {
392 if (option_type == options_release[i].type) {
393 return options_release[i].name;
394 }
395 }
396 } else if (code == COAP_SIGNALING_ABORT) {
397 for (i = 0; i < sizeof(options_abort)/sizeof(struct option_desc_t); i++) {
398 if (option_type == options_abort[i].type) {
399 return options_abort[i].name;
400 }
401 }
402 } else {
403 /* search option_type in list of known options */
404 for (i = 0; i < sizeof(options)/sizeof(struct option_desc_t); i++) {
405 if (option_type == options[i].type) {
406 return options[i].name;
407 }
408 }
409 }
410 /* unknown option type, just print to buf */
411 snprintf(buf, sizeof(buf), "%u", option_type);
412 return buf;
413}
414
415static unsigned int
416print_content_format(unsigned int format_type,
417 unsigned char *result, unsigned int buflen) {
418 struct desc_t {
419 unsigned int type;
420 const char *name;
421 };
422
423 static struct desc_t formats[] = {
424 { COAP_MEDIATYPE_TEXT_PLAIN, "text/plain" },
425 { COAP_MEDIATYPE_APPLICATION_LINK_FORMAT, "application/link-format" },
426 { COAP_MEDIATYPE_APPLICATION_XML, "application/xml" },
427 { COAP_MEDIATYPE_APPLICATION_OCTET_STREAM, "application/octet-stream" },
428 { COAP_MEDIATYPE_APPLICATION_RDF_XML, "application/rdf+xml" },
429 { COAP_MEDIATYPE_APPLICATION_EXI, "application/exi" },
430 { COAP_MEDIATYPE_APPLICATION_JSON, "application/json" },
431 { COAP_MEDIATYPE_APPLICATION_CBOR, "application/cbor" },
432 { COAP_MEDIATYPE_APPLICATION_CWT, "application/cwt" },
433 { COAP_MEDIATYPE_APPLICATION_COSE_SIGN, "application/cose; cose-type=\"cose-sign\"" },
434 { COAP_MEDIATYPE_APPLICATION_COSE_SIGN1, "application/cose; cose-type=\"cose-sign1\"" },
435 { COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT, "application/cose; cose-type=\"cose-encrypt\"" },
436 { COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT0, "application/cose; cose-type=\"cose-encrypt0\"" },
437 { COAP_MEDIATYPE_APPLICATION_COSE_MAC, "application/cose; cose-type=\"cose-mac\"" },
438 { COAP_MEDIATYPE_APPLICATION_COSE_MAC0, "application/cose; cose-type=\"cose-mac0\"" },
439 { COAP_MEDIATYPE_APPLICATION_COSE_KEY, "application/cose-key" },
440 { COAP_MEDIATYPE_APPLICATION_COSE_KEY_SET, "application/cose-key-set" },
441 { COAP_MEDIATYPE_APPLICATION_SENML_JSON, "application/senml+json" },
442 { COAP_MEDIATYPE_APPLICATION_SENSML_JSON, "application/sensml+json" },
443 { COAP_MEDIATYPE_APPLICATION_SENML_CBOR, "application/senml+cbor" },
444 { COAP_MEDIATYPE_APPLICATION_SENSML_CBOR, "application/sensml+cbor" },
445 { COAP_MEDIATYPE_APPLICATION_SENML_EXI, "application/senml-exi" },
446 { COAP_MEDIATYPE_APPLICATION_SENSML_EXI, "application/sensml-exi" },
447 { COAP_MEDIATYPE_APPLICATION_SENML_XML, "application/senml+xml" },
448 { COAP_MEDIATYPE_APPLICATION_SENSML_XML, "application/sensml+xml" },
449 { COAP_MEDIATYPE_APPLICATION_DOTS_CBOR, "application/dots+cbor" },
450 { 75, "application/dcaf+cbor" }
451 };
452
453 size_t i;
454
455 /* search format_type in list of known content formats */
456 for (i = 0; i < sizeof(formats)/sizeof(struct desc_t); i++) {
457 if (format_type == formats[i].type) {
458 return snprintf((char *)result, buflen, "%s", formats[i].name);
459 }
460 }
461
462 /* unknown content format, just print numeric value to buf */
463 return snprintf((char *)result, buflen, "%d", format_type);
464}
465
472is_binary(int content_format) {
473 return !(content_format == -1 ||
474 content_format == COAP_MEDIATYPE_TEXT_PLAIN ||
475 content_format == COAP_MEDIATYPE_APPLICATION_LINK_FORMAT ||
476 content_format == COAP_MEDIATYPE_APPLICATION_XML ||
477 content_format == COAP_MEDIATYPE_APPLICATION_JSON);
478}
479
480#define COAP_DO_SHOW_OUTPUT_LINE \
481 do { \
482 if (use_fprintf_for_show_pdu) { \
483 fprintf(COAP_DEBUG_FD, "%s", outbuf); \
484 } \
485 else { \
486 coap_log(level, "%s", outbuf); \
487 } \
488 } while (0)
489
490/*
491 * It is possible to override the output debug buffer size and hence control
492 * the amount of information printed out about a CoAP PDU.
493 * Note: Adding a byte may be insufficient to output the next byte of the PDU.
494 *
495 * This is done by the adding of a -DCOAP_DEBUG_BUF_SIZE=nnnn option to the
496 * CPPFLAGS parameter that is optionally used on the ./configure command line.
497 *
498 * E.g. ./configure CPPFLAGS="-DCOAP_DEBUG_BUF_SIZE=4096"
499 *
500 */
501
502#if COAP_DEBUG_BUF_SIZE < 5
503#error "COAP_DEBUG_BUF_SIZE must be at least 5, should be >= 32 to be useful"
504#endif /* COAP_DEBUG_BUF_SIZE < 5 */
505
506void
508#if COAP_CONSTRAINED_STACK
509 static coap_mutex_t static_show_pdu_mutex = COAP_MUTEX_INITIALIZER;
510 /* Proxy-Uri: can be 1034 bytes long */
511 static unsigned char buf[min(COAP_DEBUG_BUF_SIZE, 1035)];
512 static char outbuf[COAP_DEBUG_BUF_SIZE];
513#else /* ! COAP_CONSTRAINED_STACK */
514 /* Proxy-Uri: can be 1034 bytes long */
515 unsigned char buf[min(COAP_DEBUG_BUF_SIZE, 1035)];
516 char outbuf[COAP_DEBUG_BUF_SIZE];
517#endif /* ! COAP_CONSTRAINED_STACK */
518 size_t buf_len = 0; /* takes the number of bytes written to buf */
519 int encode = 0, have_options = 0, i;
520 coap_opt_iterator_t opt_iter;
521 coap_opt_t *option;
522 int content_format = -1;
523 size_t data_len;
524 const uint8_t *data;
525 uint32_t opt_len;
526 const uint8_t* opt_val;
527 size_t outbuflen = 0;
528
529 /* Save time if not needed */
530 if (level > coap_get_log_level())
531 return;
532
533#if COAP_CONSTRAINED_STACK
534 coap_mutex_lock(&static_show_pdu_mutex);
535#endif /* COAP_CONSTRAINED_STACK */
536
537 snprintf(outbuf, sizeof(outbuf), "v:%d t:%s c:%s i:%04x {",
539 msg_code_string(pdu->code), pdu->mid);
540
541 for (i = 0; i < pdu->token_length; i++) {
542 outbuflen = strlen(outbuf);
543 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen,
544 "%02x", pdu->token[i]);
545 }
546 outbuflen = strlen(outbuf);
547 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "}");
548
549 /* show options, if any */
551
552 outbuflen = strlen(outbuf);
553 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, " [");
554 while ((option = coap_option_next(&opt_iter))) {
555 buf[0] = '\000';
556 if (!have_options) {
557 have_options = 1;
558 } else {
559 outbuflen = strlen(outbuf);
560 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, ",");
561 }
562
563 if (pdu->code == COAP_SIGNALING_CODE_CSM) switch(opt_iter.number) {
565 buf_len = snprintf((char *)buf, sizeof(buf), "%u",
567 coap_opt_length(option)));
568 break;
569 default:
570 buf_len = 0;
571 break;
572 } else if (pdu->code == COAP_SIGNALING_CODE_PING
573 || pdu->code == COAP_SIGNALING_CODE_PONG) {
574 buf_len = 0;
575 } else if (pdu->code == COAP_SIGNALING_CODE_RELEASE) switch(opt_iter.number) {
577 buf_len = print_readable(coap_opt_value(option),
578 coap_opt_length(option),
579 buf, sizeof(buf), 0);
580 break;
582 buf_len = snprintf((char *)buf, sizeof(buf), "%u",
584 coap_opt_length(option)));
585 break;
586 default:
587 buf_len = 0;
588 break;
589 } else if (pdu->code == COAP_SIGNALING_CODE_ABORT) switch(opt_iter.number) {
591 buf_len = snprintf((char *)buf, sizeof(buf), "%u",
593 coap_opt_length(option)));
594 break;
595 default:
596 buf_len = 0;
597 break;
598 } else switch (opt_iter.number) {
601 content_format = (int)coap_decode_var_bytes(coap_opt_value(option),
602 coap_opt_length(option));
603
604 buf_len = print_content_format(content_format, buf, sizeof(buf));
605 break;
606
609 /* split block option into number/more/size where more is the
610 * letter M if set, the _ otherwise */
611 buf_len = snprintf((char *)buf, sizeof(buf), "%u/%c/%u",
612 coap_opt_block_num(option), /* block number */
613 COAP_OPT_BLOCK_MORE(option) ? 'M' : '_', /* M bit */
614 (1 << (COAP_OPT_BLOCK_SZX(option) + 4))); /* block size */
615
616 break;
617
624 /* show values as unsigned decimal value */
625 buf_len = snprintf((char *)buf, sizeof(buf), "%u",
627 coap_opt_length(option)));
628 break;
629
631 case COAP_OPTION_ETAG:
632 opt_len = coap_opt_length(option);
633 opt_val = coap_opt_value(option);
634 snprintf((char *)buf, sizeof(buf), "0x");
635 for (i = 0; (uint32_t)i < opt_len; i++) {
636 buf_len = strlen((char *)buf);
637 snprintf((char *)&buf[buf_len], sizeof(buf)-buf_len,
638 "%02x", opt_val[i]);
639 }
640 buf_len = strlen((char *)buf);
641 break;
642 default:
643 /* generic output function for all other option types */
644 if (opt_iter.number == COAP_OPTION_URI_PATH ||
645 opt_iter.number == COAP_OPTION_PROXY_URI ||
646 opt_iter.number == COAP_OPTION_URI_HOST ||
647 opt_iter.number == COAP_OPTION_LOCATION_PATH ||
649 opt_iter.number == COAP_OPTION_PROXY_SCHEME ||
650 opt_iter.number == COAP_OPTION_URI_QUERY) {
651 encode = 0;
652 } else {
653 encode = 1;
654 }
655
656 buf_len = print_readable(coap_opt_value(option),
657 coap_opt_length(option),
658 buf, sizeof(buf), encode);
659 }
660
661 outbuflen = strlen(outbuf);
662 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen,
663 " %s:%.*s", msg_option_string(pdu->code, opt_iter.number),
664 (int)buf_len, buf);
665 }
666
667 outbuflen = strlen(outbuf);
668 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, " ]");
669
670 if (coap_get_data(pdu, &data_len, &data)) {
671
672 outbuflen = strlen(outbuf);
673 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, " :: ");
674
675 if (is_binary(content_format) || !isprint(data[0])) {
676 size_t keep_data_len = data_len;
677 const uint8_t *keep_data = data;
678
679 outbuflen = strlen(outbuf);
680 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen,
681 "binary data length %zu\n", data_len);
683 /*
684 * Output hex dump of binary data as a continuous entry
685 */
686 outbuf[0] = '\000';
687 snprintf(outbuf, sizeof(outbuf), "<<");
688 while (data_len--) {
689 outbuflen = strlen(outbuf);
690 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen,
691 "%02x", *data++);
692 }
693 outbuflen = strlen(outbuf);
694 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, ">>");
695 data_len = keep_data_len;
696 data = keep_data;
697 outbuflen = strlen(outbuf);
698 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "\n");
700 /*
701 * Output ascii readable (if possible), immediately under the
702 * hex value of the character output above to help binary debugging
703 */
704 outbuf[0] = '\000';
705 snprintf(outbuf, sizeof(outbuf), "<<");
706 while (data_len--) {
707 outbuflen = strlen(outbuf);
708 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen,
709 "%c ", isprint (*data) ? *data : '.');
710 data++;
711 }
712 outbuflen = strlen(outbuf);
713 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, ">>");
714 } else {
715 size_t max_length;
716 outbuflen = strlen(outbuf);
717 max_length = sizeof(outbuf)-outbuflen;
718 if (max_length > 1) {
719 outbuf[outbuflen++] = '\'';
720 outbuf[outbuflen] = '\000';
721 max_length--;
722 }
723 if (max_length > 1) {
724 outbuflen += print_readable(data, data_len,
725 (unsigned char*)&outbuf[outbuflen],
726 max_length, 0);
727 }
728 /* print_readable may be handling unprintables - hence headroom of 4 */
729 if (outbuflen < sizeof(outbuf)-4-1) {
730 outbuf[outbuflen++] = '\'';
731 outbuf[outbuflen] = '\000';
732 }
733 }
734 }
735
736 outbuflen = strlen(outbuf);
737 if (outbuflen == sizeof(outbuf)-1) outbuflen--;
738 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "\n");
740
741#if COAP_CONSTRAINED_STACK
742 coap_mutex_unlock(&static_show_pdu_mutex);
743#endif /* COAP_CONSTRAINED_STACK */
744}
745
747{
748 char buffer[128];
749 coap_string_tls_version(buffer, sizeof(buffer));
750 coap_log(level, "%s\n", buffer);
751}
752
753char *coap_string_tls_version(char *buffer, size_t bufsize)
754{
756 char beta[8];
757 char sub[2];
758 char b_beta[8];
759 char b_sub[2];
760
761 switch (tls_version->type) {
763 snprintf(buffer, bufsize, "TLS Library: None");
764 break;
766 snprintf(buffer, bufsize, "TLS Library: TinyDTLS - runtime %lu.%lu.%lu, "
767 "libcoap built for %lu.%lu.%lu",
768 (unsigned long)(tls_version->version >> 16),
769 (unsigned long)((tls_version->version >> 8) & 0xff),
770 (unsigned long)(tls_version->version & 0xff),
771 (unsigned long)(tls_version->built_version >> 16),
772 (unsigned long)((tls_version->built_version >> 8) & 0xff),
773 (unsigned long)(tls_version->built_version & 0xff));
774 break;
776 switch (tls_version->version &0xf) {
777 case 0:
778 strcpy(beta, "-dev");
779 break;
780 case 0xf:
781 strcpy(beta, "");
782 break;
783 default:
784 strcpy(beta, "-beta");
785 beta[5] = (tls_version->version &0xf) + '0';
786 beta[6] = '\000';
787 break;
788 }
789 sub[0] = ((tls_version->version >> 4) & 0xff) ?
790 ((tls_version->version >> 4) & 0xff) + 'a' -1 : '\000';
791 sub[1] = '\000';
792 switch (tls_version->built_version &0xf) {
793 case 0:
794 strcpy(b_beta, "-dev");
795 break;
796 case 0xf:
797 strcpy(b_beta, "");
798 break;
799 default:
800 strcpy(b_beta, "-beta");
801 b_beta[5] = (tls_version->built_version &0xf) + '0';
802 b_beta[6] = '\000';
803 break;
804 }
805 b_sub[0] = ((tls_version->built_version >> 4) & 0xff) ?
806 ((tls_version->built_version >> 4) & 0xff) + 'a' -1 : '\000';
807 b_sub[1] = '\000';
808 snprintf(buffer, bufsize, "TLS Library: OpenSSL - runtime "
809 "%lu.%lu.%lu%s%s, libcoap built for %lu.%lu.%lu%s%s",
810 (unsigned long)(tls_version->version >> 28),
811 (unsigned long)((tls_version->version >> 20) & 0xff),
812 (unsigned long)((tls_version->version >> 12) & 0xff), sub, beta,
813 (unsigned long)(tls_version->built_version >> 28),
814 (unsigned long)((tls_version->built_version >> 20) & 0xff),
815 (unsigned long)((tls_version->built_version >> 12) & 0xff),
816 b_sub, b_beta);
817 break;
819 snprintf(buffer, bufsize, "TLS Library: GnuTLS - runtime %lu.%lu.%lu, "
820 "libcoap built for %lu.%lu.%lu",
821 (unsigned long)(tls_version->version >> 16),
822 (unsigned long)((tls_version->version >> 8) & 0xff),
823 (unsigned long)(tls_version->version & 0xff),
824 (unsigned long)(tls_version->built_version >> 16),
825 (unsigned long)((tls_version->built_version >> 8) & 0xff),
826 (unsigned long)(tls_version->built_version & 0xff));
827 break;
829 snprintf(buffer, bufsize, "TLS Library: Mbed TLS - runtime %lu.%lu.%lu, "
830 "libcoap built for %lu.%lu.%lu",
831 (unsigned long)(tls_version->version >> 24),
832 (unsigned long)((tls_version->version >> 16) & 0xff),
833 (unsigned long)((tls_version->version >> 8) & 0xff),
834 (unsigned long)(tls_version->built_version >> 24),
835 (unsigned long)((tls_version->built_version >> 16) & 0xff),
836 (unsigned long)((tls_version->built_version >> 8) & 0xff));
837 break;
838 default:
839 snprintf(buffer, bufsize, "Library type %d unknown", tls_version->type);
840 break;
841 }
842 return buffer;
843}
844
845char *coap_string_tls_support(char *buffer, size_t bufsize)
846{
848
849 switch (tls_version->type) {
851 snprintf(buffer, bufsize, "(No DTLS or TLS support)");
852 break;
854 snprintf(buffer, bufsize,
855 "(DTLS and no TLS support; PSK and RPK support)");
856 break;
858 snprintf(buffer, bufsize,
859 "(DTLS and TLS support; PSK, PKI, PKCS11 and no RPK support)");
860 break;
862 if (tls_version->version >= 0x030606)
863 snprintf(buffer, bufsize,
864 "(DTLS and TLS support; PSK, PKI, PKCS11 and RPK support)");
865 else
866 snprintf(buffer, bufsize,
867 "(DTLS and TLS support; PSK, PKI, PKCS11 and no RPK support)");
868 break;
870 snprintf(buffer, bufsize,
871 "(DTLS and no TLS support; PSK, PKI and no RPK support)");
872 break;
873 default:
874 buffer[0] = '\000';
875 break;
876 }
877 return buffer;
878}
879
881
883 log_handler = handler;
884}
885
886void
887coap_log_impl(coap_log_t level, const char *format, ...) {
888
889 if (maxlog < level)
890 return;
891
892 if (log_handler) {
893#if COAP_CONSTRAINED_STACK
894 static coap_mutex_t static_log_mutex = COAP_MUTEX_INITIALIZER;
895 static char message[COAP_DEBUG_BUF_SIZE];
896#else /* ! COAP_CONSTRAINED_STACK */
897 char message[COAP_DEBUG_BUF_SIZE];
898#endif /* ! COAP_CONSTRAINED_STACK */
899 va_list ap;
900 va_start(ap, format);
901#if COAP_CONSTRAINED_STACK
902 coap_mutex_lock(&static_log_mutex);
903#endif /* COAP_CONSTRAINED_STACK */
904
905 vsnprintf( message, sizeof(message), format, ap);
906 va_end(ap);
907 log_handler(level, message);
908#if COAP_CONSTRAINED_STACK
909 coap_mutex_unlock(&static_log_mutex);
910#endif /* COAP_CONSTRAINED_STACK */
911 } else {
912 char timebuf[32];
913 coap_tick_t now;
914 va_list ap;
915 FILE *log_fd;
916 size_t len;
917
918 log_fd = level <= LOG_CRIT ? COAP_ERR_FD : COAP_DEBUG_FD;
919
920 coap_ticks(&now);
921 len = print_timestamp(timebuf,sizeof(timebuf), now);
922 if (len)
923 fprintf(log_fd, "%.*s ", (int)len, timebuf);
924
925 if (level <= COAP_LOG_CIPHERS)
926 fprintf(log_fd, "%s ", loglevels[level]);
927
928 va_start(ap, format);
929 vfprintf(log_fd, format, ap);
930 va_end(ap);
931 fflush(log_fd);
932 }
933}
934
935static struct packet_num_interval {
936 int start;
937 int end;
940static int packet_loss_level = 0;
941static int send_packet_count = 0;
942
943int coap_debug_set_packet_loss(const char *loss_level) {
944 const char *p = loss_level;
945 char *end = NULL;
946 int n = (int)strtol(p, &end, 10), i = 0;
947 if (end == p || n < 0)
948 return 0;
949 if (*end == '%') {
950 if (n > 100)
951 n = 100;
952 packet_loss_level = n * 65536 / 100;
953 coap_log(LOG_DEBUG, "packet loss level set to %d%%\n", n);
954 } else {
955 if (n <= 0)
956 return 0;
957 while (i < 10) {
959 if (*end == '-') {
960 p = end + 1;
961 n = (int)strtol(p, &end, 10);
962 if (end == p || n <= 0)
963 return 0;
964 }
965 packet_loss_intervals[i++].end = n;
966 if (*end == 0)
967 break;
968 if (*end != ',')
969 return 0;
970 p = end + 1;
971 n = (int)strtol(p, &end, 10);
972 if (end == p || n <= 0)
973 return 0;
974 }
975 if (i == 10)
976 return 0;
978 }
980 return 1;
981}
982
986 int i;
987 for (i = 0; i < num_packet_loss_intervals; i++) {
990 coap_log(LOG_DEBUG, "Packet %u dropped\n", send_packet_count);
991 return 0;
992 }
993 }
994 }
995 if ( packet_loss_level > 0 ) {
996 uint16_t r = 0;
997 coap_prng( (uint8_t*)&r, 2 );
998 if ( r < packet_loss_level ) {
999 coap_log(LOG_DEBUG, "Packet %u dropped\n", send_packet_count);
1000 return 0;
1001 }
1002 }
1003 return 1;
1004}
static int packet_loss_level
Definition: coap_debug.c:940
static struct packet_num_interval packet_loss_intervals[10]
static int send_packet_count
Definition: coap_debug.c:941
int coap_debug_set_packet_loss(const char *loss_level)
Set the packet loss level for testing.
Definition: coap_debug.c:943
static coap_log_t maxlog
Definition: coap_debug.c:45
static coap_log_handler_t log_handler
Definition: coap_debug.c:880
COAP_STATIC_INLINE int is_binary(int content_format)
Returns 1 if the given content_format is either unknown or known to carry binary data.
Definition: coap_debug.c:472
static const char * msg_code_string(uint16_t c)
Returns a textual description of the method or response code.
Definition: coap_debug.c:308
#define COAP_DO_SHOW_OUTPUT_LINE
Definition: coap_debug.c:480
static size_t print_readable(const uint8_t *data, size_t len, unsigned char *result, size_t buflen, int encode_always)
Definition: coap_debug.c:128
static const char * msg_option_string(uint8_t code, uint16_t option_type)
Returns a textual description of the option name.
Definition: coap_debug.c:327
static size_t strnlen(const char *s, size_t maxlen)
A length-safe strlen() fake.
Definition: coap_debug.c:119
static const char * loglevels[]
Definition: coap_debug.c:73
COAP_STATIC_INLINE size_t print_timestamp(char *s, size_t len, coap_tick_t t)
Definition: coap_debug.c:96
#define min(a, b)
Definition: coap_debug.c:165
static const char * msg_type_string(uint16_t t)
Returns a textual description of the message type t.
Definition: coap_debug.c:300
static int use_fprintf_for_show_pdu
Definition: coap_debug.c:47
static int num_packet_loss_intervals
Definition: coap_debug.c:939
int coap_debug_send_packet(void)
Check to see whether a packet should be sent or not.
Definition: coap_debug.c:983
static unsigned int print_content_format(unsigned int format_type, unsigned char *result, unsigned int buflen)
Definition: coap_debug.c:416
Pulls together all the internal only header files.
#define INET6_ADDRSTRLEN
#define COAP_OPT_BLOCK_SZX(opt)
Returns the value of the SZX-field of a Block option opt.
Definition: block.h:57
#define COAP_OPT_BLOCK_MORE(opt)
Returns the value of the More-bit of a Block option opt.
Definition: block.h:53
unsigned int coap_opt_block_num(const coap_opt_t *block_opt)
Returns the value of field num in the given block option block_opt.
Definition: block.c:18
void coap_ticks(coap_tick_t *t)
Sets t to the internal time with COAP_TICKS_PER_SECOND resolution.
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition: coap_time.h:122
coap_time_t coap_ticks_to_rt(coap_tick_t t)
Helper function that converts coap ticks to wallclock time.
uint64_t coap_ticks_to_rt_us(coap_tick_t t)
Helper function that converts coap ticks to POSIX wallclock time in us.
int coap_prng(void *buf, size_t len)
Fills buf with len random bytes using the default pseudo random number generator.
Definition: coap_prng.c:87
coap_tls_version_t * coap_get_tls_library_version(void)
Determine the type and version of the underlying (D)TLS library.
Definition: coap_notls.c:27
@ COAP_TLS_LIBRARY_GNUTLS
Using GnuTLS library.
Definition: coap_dtls.h:56
@ COAP_TLS_LIBRARY_TINYDTLS
Using TinyDTLS library.
Definition: coap_dtls.h:54
@ COAP_TLS_LIBRARY_NOTLS
No DTLS library.
Definition: coap_dtls.h:53
@ COAP_TLS_LIBRARY_OPENSSL
Using OpenSSL library.
Definition: coap_dtls.h:55
@ COAP_TLS_LIBRARY_MBEDTLS
Using Mbed TLS library.
Definition: coap_dtls.h:57
unsigned int coap_decode_var_bytes(const uint8_t *buf, size_t len)
Decodes multiple-length byte sequences.
Definition: encode.c:31
void coap_set_log_handler(coap_log_handler_t handler)
Add a custom log callback handler.
Definition: coap_debug.c:882
coap_log_t coap_get_log_level(void)
Get the current logging level.
Definition: coap_debug.c:63
char * coap_string_tls_version(char *buffer, size_t bufsize)
Build a string containing the current (D)TLS library linked with and built for version.
Definition: coap_debug.c:753
void coap_show_pdu(coap_log_t level, const coap_pdu_t *pdu)
Display the contents of the specified pdu.
Definition: coap_debug.c:507
char * coap_string_tls_support(char *buffer, size_t bufsize)
Build a string containing the current (D)TLS library support.
Definition: coap_debug.c:845
#define COAP_ERR_FD
Used for output for LOG_CRIT to LOG_EMERG.
Definition: coap_debug.h:32
coap_log_t
Pre-defined log levels akin to what is used in syslog with LOG_CIPHERS added.
Definition: coap_debug.h:51
const char * coap_package_version(void)
Get the library package version.
Definition: coap_debug.c:53
void coap_set_log_level(coap_log_t level)
Sets the log level to the specified value.
Definition: coap_debug.c:68
void coap_log_impl(coap_log_t level, const char *format,...)
Writes the given text to COAP_ERR_FD (for level <= LOG_CRIT) or COAP_DEBUG_FD (for level >= LOG_ERR).
Definition: coap_debug.c:887
size_t coap_print_addr(const coap_address_t *addr, unsigned char *buf, size_t len)
Print the address into the defined buffer.
Definition: coap_debug.c:173
#define COAP_DEBUG_FD
Used for output for LOG_DEBUG to LOG_ERR.
Definition: coap_debug.h:25
void coap_show_tls_version(coap_log_t level)
Display the current (D)TLS library linked with and built for version.
Definition: coap_debug.c:746
void coap_set_show_pdu_output(int use_fprintf)
Defines the output mode for the coap_show_pdu() function.
Definition: coap_debug.c:58
const char * coap_package_name(void)
Get the library package name.
Definition: coap_debug.c:49
void(* coap_log_handler_t)(coap_log_t level, const char *message)
Logging callback handler definition.
Definition: coap_debug.h:103
#define coap_log(level,...)
Logging function.
Definition: coap_debug.h:152
@ LOG_CRIT
Critical.
Definition: coap_debug.h:54
@ LOG_WARNING
Warning.
Definition: coap_debug.h:56
@ LOG_DEBUG
Debug.
Definition: coap_debug.h:59
@ COAP_LOG_CIPHERS
CipherInfo.
Definition: coap_debug.h:60
coap_opt_t * coap_option_next(coap_opt_iterator_t *oi)
Updates the iterator oi to point to the next option.
Definition: option.c:148
uint32_t coap_opt_length(const coap_opt_t *opt)
Returns the length of the given option.
Definition: option.c:211
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.
Definition: option.c:112
#define COAP_OPT_ALL
Pre-defined filter that includes all options.
Definition: option.h:107
const uint8_t * coap_opt_value(const coap_opt_t *opt)
Returns a pointer to the value of the given option.
Definition: option.c:248
#define COAP_DEBUG_BUF_SIZE
#define COAP_DEFAULT_VERSION
#define COAP_OPTION_HOP_LIMIT
Definition: pdu.h:121
#define COAP_OPTION_NORESPONSE
Definition: pdu.h:130
#define COAP_OPTION_URI_HOST
Definition: pdu.h:108
#define COAP_OPTION_IF_MATCH
Definition: pdu.h:107
#define COAP_MEDIATYPE_APPLICATION_COSE_MAC
Definition: pdu.h:204
#define COAP_MEDIATYPE_APPLICATION_SENSML_EXI
Definition: pdu.h:216
#define COAP_MEDIATYPE_APPLICATION_CWT
Definition: pdu.h:197
#define COAP_OPTION_BLOCK2
Definition: pdu.h:124
#define COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT
Definition: pdu.h:202
#define COAP_MEDIATYPE_APPLICATION_RDF_XML
Definition: pdu.h:193
#define COAP_OPTION_CONTENT_FORMAT
Definition: pdu.h:116
#define COAP_SIGNALING_OPTION_ALTERNATIVE_ADDRESS
Definition: pdu.h:182
#define COAP_OPTION_SIZE2
Definition: pdu.h:126
#define COAP_MEDIATYPE_APPLICATION_SENSML_XML
Definition: pdu.h:218
#define COAP_MEDIATYPE_APPLICATION_COSE_SIGN
Definition: pdu.h:200
#define COAP_OPTION_BLOCK1
Definition: pdu.h:125
#define COAP_OPTION_PROXY_SCHEME
Definition: pdu.h:128
#define COAP_MEDIATYPE_APPLICATION_COSE_KEY_SET
Definition: pdu.h:208
#define COAP_MEDIATYPE_APPLICATION_SENML_CBOR
Definition: pdu.h:213
#define COAP_OPTION_URI_QUERY
Definition: pdu.h:120
#define COAP_MEDIATYPE_APPLICATION_COSE_KEY
Definition: pdu.h:207
#define COAP_MEDIATYPE_APPLICATION_COSE_SIGN1
Definition: pdu.h:201
#define COAP_OPTION_IF_NONE_MATCH
Definition: pdu.h:110
#define COAP_MEDIATYPE_APPLICATION_OCTET_STREAM
Definition: pdu.h:192
#define COAP_OPTION_LOCATION_PATH
Definition: pdu.h:113
#define COAP_OPTION_URI_PATH
Definition: pdu.h:115
#define COAP_MEDIATYPE_APPLICATION_SENML_EXI
Definition: pdu.h:215
#define COAP_MEDIATYPE_APPLICATION_CBOR
Definition: pdu.h:196
#define COAP_OPTION_SIZE1
Definition: pdu.h:129
#define COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT0
Definition: pdu.h:203
#define COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER
Definition: pdu.h:178
#define COAP_MEDIATYPE_TEXT_PLAIN
Definition: pdu.h:189
#define COAP_MEDIATYPE_APPLICATION_JSON
Definition: pdu.h:195
#define COAP_OPTION_LOCATION_QUERY
Definition: pdu.h:123
#define COAP_MEDIATYPE_APPLICATION_COSE_MAC0
Definition: pdu.h:205
#define COAP_MEDIATYPE_APPLICATION_SENML_JSON
Definition: pdu.h:211
#define COAP_MEDIATYPE_APPLICATION_EXI
Definition: pdu.h:194
#define COAP_SIGNALING_OPTION_CUSTODY
Definition: pdu.h:180
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: pdu.c:654
#define COAP_OPTION_URI_PORT
Definition: pdu.h:112
#define COAP_MEDIATYPE_APPLICATION_SENML_XML
Definition: pdu.h:217
#define COAP_OPTION_ACCEPT
Definition: pdu.h:122
#define COAP_MEDIATYPE_APPLICATION_DOTS_CBOR
Definition: pdu.h:221
#define COAP_OPTION_MAXAGE
Definition: pdu.h:119
#define COAP_OPTION_ETAG
Definition: pdu.h:109
#define COAP_MEDIATYPE_APPLICATION_SENSML_JSON
Definition: pdu.h:212
#define COAP_OPTION_PROXY_URI
Definition: pdu.h:127
#define COAP_OPTION_OBSERVE
Definition: pdu.h:111
#define COAP_SIGNALING_OPTION_HOLD_OFF
Definition: pdu.h:183
#define COAP_MEDIATYPE_APPLICATION_LINK_FORMAT
Definition: pdu.h:190
#define COAP_SIGNALING_OPTION_BAD_CSM_OPTION
Definition: pdu.h:185
#define COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE
Definition: pdu.h:177
#define COAP_MEDIATYPE_APPLICATION_XML
Definition: pdu.h:191
#define COAP_MEDIATYPE_APPLICATION_SENSML_CBOR
Definition: pdu.h:214
@ COAP_SIGNALING_CODE_ABORT
Definition: pdu.h:335
@ COAP_SIGNALING_CODE_CSM
Definition: pdu.h:331
@ COAP_SIGNALING_CODE_PING
Definition: pdu.h:332
@ COAP_SIGNALING_CODE_PONG
Definition: pdu.h:333
@ COAP_SIGNALING_CODE_RELEASE
Definition: pdu.h:334
@ COAP_SIGNALING_RELEASE
Definition: pdu.h:172
@ COAP_SIGNALING_CSM
Definition: pdu.h:169
@ COAP_SIGNALING_PONG
Definition: pdu.h:171
@ COAP_SIGNALING_PING
Definition: pdu.h:170
@ COAP_SIGNALING_ABORT
Definition: pdu.h:173
#define COAP_STATIC_INLINE
Definition: libcoap.h:40
uint8_t coap_opt_t
Use byte-oriented access methods here because sliding a complex struct coap_opt_t over the data buffe...
Definition: option.h:26
multi-purpose address abstraction
Definition: address.h:96
struct sockaddr_in sin
Definition: address.h:100
struct sockaddr_in6 sin6
Definition: address.h:101
struct sockaddr sa
Definition: address.h:99
union coap_address_t::@0 addr
Iterator to run through PDU options.
Definition: option.h:170
coap_option_num_t number
decoded option number
Definition: option.h:172
structure for CoAP PDUs token, if any, follows the fixed size header, then options until payload mark...
uint8_t * token
first byte of token, if any, or options
coap_pdu_code_t code
request method (value 1–31) or response code (value 64-255)
uint8_t token_length
length of Token
coap_mid_t mid
message id, if any, in regular host byte order
coap_pdu_type_t type
message type
The structure used for returning the underlying (D)TLS library information.
Definition: coap_dtls.h:64
uint64_t built_version
(D)TLS Built against Library Version
Definition: coap_dtls.h:67
coap_tls_library_t type
Library type.
Definition: coap_dtls.h:66
uint64_t version
(D)TLS runtime Library Version
Definition: coap_dtls.h:65