libcoap 4.3.3
coap_debug.c
Go to the documentation of this file.
1/* coap_debug.c -- debug utilities
2 *
3 * Copyright (C) 2010--2012,2014--2023 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
16#include "coap3/coap_internal.h"
17
18#if defined(HAVE_STRNLEN) && defined(__GNUC__) && !defined(_GNU_SOURCE)
19#define _GNU_SOURCE 1
20#endif
21
22#include <stdarg.h>
23#include <stdio.h>
24#include <string.h>
25#include <ctype.h>
26
27#ifdef HAVE_ARPA_INET_H
28#include <arpa/inet.h>
29#endif
30#ifdef HAVE_WS2TCPIP_H
31#include <ws2tcpip.h>
32#endif
33
34#ifdef HAVE_TIME_H
35#include <time.h>
36#endif
37
38#ifdef WITH_LWIP
39# define fprintf(fd, ...) LWIP_PLATFORM_DIAG((__VA_ARGS__))
40# define fflush(...)
41#endif
42
43#ifdef WITH_CONTIKI
44# define fprintf(fd, ...) { (void)fd; printf(__VA_ARGS__); }
45# define fflush(...)
46# define vfprintf(fd, ...) { (void)fd; printf(__VA_ARGS__); }
47
48# ifndef LOG_CONF_LEVEL_COAP
49# define LOG_CONF_LEVEL_COAP 2 /* = LOG_LEVEL_WARN */
50# endif
51static coap_log_t maxlog = LOG_CONF_LEVEL_COAP == 0 ? /* = LOG_LEVEL_NONE */
53 (LOG_CONF_LEVEL_COAP == 1 ? /* = LOG_LEVEL_ERR */
55 (LOG_CONF_LEVEL_COAP == 2 ? /* = LOG_LEVEL_WARN */
57 (LOG_CONF_LEVEL_COAP == 3 ? /* = LOG_LEVEL_INFO */
60#else /* WITH_CONTIKI */
61static coap_log_t maxlog = COAP_LOG_WARN; /* default maximum CoAP log level */
62#endif /* WITH_CONTIKI */
63
64static int use_fprintf_for_show_pdu = 1; /* non zero to output with fprintf */
65
66const char *
68 return PACKAGE_NAME;
69}
70
71const char *
73 return PACKAGE_STRING;
74}
75
76const char *
78#ifdef LIBCOAP_PACKAGE_BUILD
79 return LIBCOAP_PACKAGE_BUILD;
80#else /* !LIBCOAP_PACKAGE_BUILD */
81 return PACKAGE_STRING;
82#endif /* !LIBCOAP_PACKAGE_BUILD */
83}
84
85void
86coap_set_show_pdu_output(int use_fprintf) {
87 use_fprintf_for_show_pdu = use_fprintf;
88}
89
92 return maxlog;
93}
94
95void
97 if (level > COAP_MAX_LOGGING_LEVEL)
99 maxlog = level;
100}
101
102/* this array has the same order as the type coap_log_t with the (D)TLS
103 entries added to the list with a COAP_LOG_DTLS_BASE offset */
104static const char *loglevels[] = {
105 /* General logging */
106 "EMRG", "ALRT", "CRIT", "ERR ", "WARN", "NOTE", "INFO", "DEBG", "OSC ",
107 /* (D)TLS logging */
108 "Emrg", "Alrt", "Crit", "Err ", "Warn", "Note", "Info", "Debg"
109};
110
111#ifdef WITH_CONTIKI
112void
113coap_print_contiki_prefix(coap_log_t level) {
114 printf("[%s: COAP ] ", loglevels[level]);
115}
116#endif /* WITH_CONTIKI */
117
118#ifdef HAVE_TIME_H
119
121print_timestamp(char *s, size_t len, coap_tick_t t) {
122 struct tm *tmp;
123 size_t lensofar;
124 time_t now = coap_ticks_to_rt(t);
125 tmp = localtime(&now);
126 lensofar = strftime(s, len, "%b %d %H:%M:%S", tmp);
127 if (len > lensofar + 4) {
128 lensofar += snprintf(&s[lensofar], len-lensofar, ".%03u",
129 (unsigned int)((coap_ticks_to_rt_us(t) % 1000000)/1000));
130 }
131 return lensofar;
132}
133
134#else /* alternative implementation: just print the timestamp */
135
137print_timestamp(char *s, size_t len, coap_tick_t t) {
138#ifdef HAVE_SNPRINTF
139 return snprintf(s, len, "%u.%03u",
140 (unsigned int)coap_ticks_to_rt(t),
141 (unsigned int)((coap_ticks_to_rt_us(t) % 1000000)/1000));
142#else /* HAVE_SNPRINTF */
143 /* @todo do manual conversion of timestamp */
144 return 0;
145#endif /* HAVE_SNPRINTF */
146}
147
148#endif /* HAVE_TIME_H */
149
150#if !defined(HAVE_STRNLEN) && !defined(__MINGW32__)
159static inline size_t
160strnlen(const char *s, size_t maxlen) {
161 size_t n = 0;
162 while (*s++ && n < maxlen)
163 ++n;
164 return n;
165}
166#endif /* HAVE_STRNLEN && !__MINGW32__ */
167
168static size_t
169print_readable(const uint8_t *data, size_t len,
170 unsigned char *result, size_t buflen, int encode_always) {
171 const uint8_t hex[] = "0123456789ABCDEF";
172 size_t cnt = 0;
173 assert(data || len == 0);
174
175 if (buflen == 0) { /* there is nothing we can do here but return */
176 return 0;
177 }
178
179 while (len) {
180 if (!encode_always && isprint(*data)) {
181 if (cnt+1 < buflen) { /* keep one byte for terminating zero */
182 *result++ = *data;
183 ++cnt;
184 } else {
185 break;
186 }
187 } else {
188 if (cnt+4 < buflen) { /* keep one byte for terminating zero */
189 *result++ = '\\';
190 *result++ = 'x';
191 *result++ = hex[(*data & 0xf0) >> 4];
192 *result++ = hex[*data & 0x0f];
193 cnt += 4;
194 } else
195 break;
196 }
197
198 ++data;
199 --len;
200 }
201
202 *result = '\0'; /* add a terminating zero */
203 return cnt;
204}
205
206#ifndef min
207#define min(a,b) ((a) < (b) ? (a) : (b))
208#endif
209
210#ifndef INET6_ADDRSTRLEN
211#define INET6_ADDRSTRLEN 46
212#endif
213/*
214 * Returned buf is always NULL terminated.
215 * Returned size is number of characters, not including NULL terminator.
216 */
217size_t
218coap_print_addr(const coap_address_t *addr, unsigned char *buf, size_t len) {
219#if defined( HAVE_ARPA_INET_H ) || defined( HAVE_WS2TCPIP_H )
220 char scratch[INET6_ADDRSTRLEN];
221
222 assert(buf);
223 assert(len);
224 buf[0] = '\000';
225
226 switch (addr->addr.sa.sa_family) {
227#if COAP_IPV4_SUPPORT
228 case AF_INET:
229 snprintf((char *)buf, len, "%s:%d",
230 coap_print_ip_addr(addr, scratch, sizeof(scratch)),
231 ntohs(addr->addr.sin.sin_port));
232 break;
233#endif /* COAP_IPV4_SUPPORT */
234#if COAP_IPV6_SUPPORT
235 case AF_INET6:
236 snprintf((char *)buf, len, "[%s]:%d",
237 coap_print_ip_addr(addr, scratch, sizeof(scratch)),
238 ntohs(addr->addr.sin6.sin6_port));
239 break;
240#endif /* COAP_IPV6_SUPPORT */
241#if COAP_AF_UNIX_SUPPORT
242 case AF_UNIX:
243 snprintf((char *)buf, len, "'%s'", addr->addr.cun.sun_path);
244 break;
245#endif /* COAP_AF_UNIX_SUPPORT */
246 default:
247 /* Include trailing NULL if possible */
248 memcpy(buf, "(unknown address type)", min(22+1, len));
249 buf[len-1] = '\000';
250 break;
251 }
252 return strlen((char *)buf);
253
254#else /* HAVE_ARPA_INET_H */
255
256# if WITH_CONTIKI
257
258 char scratch[INET6_ADDRSTRLEN];
259#ifdef HAVE_SNPRINTF
260
261 snprintf((char *)buf, len, "[%s]:%d",
262 coap_print_ip_addr(addr, scratch, sizeof(scratch)),
264 return strlen((char *)buf);
265#else /* HAVE_SNPRINTF */
266 unsigned char *p = buf;
267# if NETSTACK_CONF_WITH_IPV6
268
269 assert(buf);
270 assert(len);
271 buf[0] = '\000';
272 if (len < 40 + 2 + 6)
273 return 0;
274
275 *p++ = '[';
276 memcpy(p, coap_print_ip_addr(addr, scratch, sizeof(scratch)), 40);
277 p += 40 - 1;
278 *p++ = ']';
279# else /* WITH_UIP6 */
280# warning "IPv4 network addresses will not be included in debug output"
281
282 if (len < 21) {
283 *p = '\000';
284 return 0;
285 }
286# endif /* WITH_UIP6 */
287
288 *p++ = ':';
289 *p++ = '0' + (coap_address_get_port(addr) / 10000) % 10;
290 *p++ = '0' + (coap_address_get_port(addr) / 1000) % 10;
291 *p++ = '0' + (coap_address_get_port(addr) / 100) % 10;
292 *p++ = '0' + (coap_address_get_port(addr) / 10) % 10;
293 *p++ = '0' + coap_address_get_port(addr) % 10;
294 *p = '\000';
295
296 return strlen((char *)buf);
297#endif /* HAVE_SNPRINTF */
298
299# elif WITH_LWIP
300
301 char scratch[INET6_ADDRSTRLEN];
302#ifdef HAVE_SNPRINTF
303
304 snprintf((char *)buf, len, "[%s]:%d",
305 coap_print_ip_addr(addr, scratch, sizeof(scratch)),
306 addr->port);
307 return strlen((char *)buf);
308#else /* HAVE_SNPRINTF */
309 unsigned char *p = buf;
310
311 assert(buf);
312 assert(len);
313 buf[0] = '\000';
314
315 switch (IP_GET_TYPE(addr->addr)) {
316 case IPADDR_TYPE_V4:
317 if (len < IP4ADDR_STRLEN_MAX + 6)
318 return 0;
319 memcpy(buf, coap_print_ip_addr(addr, scratch, sizeof(scratch)), IP4ADDR_STRLEN_MAX);
320 p += strlen((char *)buf);
321 break;
322#if LWIP_IPV6
323 case IPADDR_TYPE_V6:
324 case IPADDR_TYPE_ANY:
325 if (len < 40 + 2 + 6)
326 return 0;
327 *p++ = '[';
328 memcpy(p, coap_print_ip_addr(addr, scratch, sizeof(scratch)), 40);
329 p += strlen((char *)buf);
330 *p++ = ']';
331 break;
332#endif /* LWIP_IPV6 */
333 }
334
335 *p++ = ':';
336 *p++ = '0' + (addr->port / 10000) % 10;
337 *p++ = '0' + (addr->port / 1000) % 10;
338 *p++ = '0' + (addr->port / 100) % 10;
339 *p++ = '0' + (addr->port / 10) % 10;
340 *p++ = '0' + addr->port % 10;
341 *p = '\000';
342
343 return strlen((char *)buf);
344#endif /* HAVE_SNPRINTF */
345
346# else /* ! WITH_CONTIKI && ! WITH_LWIP */
347
348 (void)addr;
349 (void)len;
350
351 /* TODO: output addresses manually */
352# warning "inet_ntop() not available, network addresses will not be included in debug output"
353# endif /* ! WITH_CONTIKI && ! WITH_LWIP */
354 buf[0] = '\000';
355 return 0;
356#endif
357}
358
359/*
360 * Returned buf is always NULL terminated with as much as possible of the
361 * IP address filled in.
362 */
363const char *
364coap_print_ip_addr(const coap_address_t *addr, char *buf, size_t len) {
365#if defined( HAVE_ARPA_INET_H ) || defined( HAVE_WS2TCPIP_H )
366 const void *addrptr = NULL;
367
368 assert(buf);
369 assert(len);
370 buf[0] = '\000';
371
372 switch (addr->addr.sa.sa_family) {
373#if COAP_IPV4_SUPPORT
374 case AF_INET:
375 if (len < INET_ADDRSTRLEN)
376 return buf;
377 addrptr = &addr->addr.sin.sin_addr;
378 break;
379#endif /* COAP_IPV4_SUPPORT */
380#if COAP_IPV6_SUPPORT
381 case AF_INET6:
382 if (len < INET6_ADDRSTRLEN)
383 return buf;
384 addrptr = &addr->addr.sin6.sin6_addr;
385 break;
386#endif /* COAP_IPV6_SUPPORT */
387#if COAP_AF_UNIX_SUPPORT
388 case AF_UNIX:
389 snprintf(buf, len, "'%s'", addr->addr.cun.sun_path);
390 return buf;
391#endif /* COAP_AF_UNIX_SUPPORT */
392 default:
393 /* Include trailing NULL if possible */
394 memcpy(buf, "(unknown address type)", min(22+1, len));
395 buf[len-1] = '\000';
396 return buf;
397 }
398
399 /* Cast needed for Windows, since it doesn't have the correct API signature. */
400 if (inet_ntop(addr->addr.sa.sa_family, addrptr, (char *)buf, len) == 0) {
401 coap_log_err("coap_print_ip_addr: inet_ntop\n");
402 buf[0] = '\000';
403 return buf;
404 }
405 return buf;
406
407#else /* HAVE_ARPA_INET_H */
408
409# if WITH_CONTIKI
410 char *p = buf;
411 uint8_t i;
412# if NETSTACK_CONF_WITH_IPV6
413 const char hex[] = "0123456789ABCDEF";
414
415 assert(buf);
416 assert(len);
417 buf[0] = '\000';
418 if (len < 40)
419 return 0;
420
421 for (i=0; i < 16; i += 2) {
422 if (i) {
423 *p++ = ':';
424 }
425 *p++ = hex[(addr->addr.u8[i] & 0xf0) >> 4];
426 *p++ = hex[(addr->addr.u8[i] & 0x0f)];
427 *p++ = hex[(addr->addr.u8[i+1] & 0xf0) >> 4];
428 *p++ = hex[(addr->addr.u8[i+1] & 0x0f)];
429 }
430 *p = '\000';
431# else /* WITH_UIP6 */
432# warning "IPv4 network addresses will not be included in debug output"
433
434 if (len < 21) {
435 return buf;
436 }
437# endif /* WITH_UIP6 */
438 return buf;
439
440# elif WITH_LWIP
441
442 assert(buf);
443 assert(len);
444 buf[0] = '\000';
445
446 switch (IP_GET_TYPE(&addr->addr)) {
447#if LWIP_IPV4
448 case IPADDR_TYPE_V4:
449 if (len < IP4ADDR_STRLEN_MAX)
450 return buf;
451 memcpy(buf, ip4addr_ntoa(ip_2_ip4(&addr->addr)), IP4ADDR_STRLEN_MAX);
452 break;
453#endif /* LWIP_IPV4 */
454#if LWIP_IPV6
455 case IPADDR_TYPE_V6:
456 case IPADDR_TYPE_ANY:
457 if (len < 40)
458 return buf;
459#if LWIP_IPV4
460 memcpy(buf, ip6addr_ntoa(&addr->addr.u_addr.ip6), 40);
461#else /* LWIP_IPV4 */
462 memcpy(buf, ip6addr_ntoa(&addr->addr), 40);
463#endif /* LWIP_IPV4 */
464 break;
465#endif /* LWIP_IPV6 */
466 }
467 return buf;
468
469# else /* ! WITH_CONTIKI && ! WITH_LWIP */
470
471 (void)addr;
472 (void)len;
473
474 /* TODO: output addresses manually */
475# warning "inet_ntop() not available, network addresses will not be included in debug output"
476# endif /* WITH_CONTIKI */
477 buf[0] = '\000';
478 return buf;
479#endif
480}
481
483static const char *
484msg_type_string(uint16_t t) {
485 static const char *types[] = { "CON", "NON", "ACK", "RST", "???" };
486
487 return types[min(t, sizeof(types)/sizeof(char *) - 1)];
488}
489
491static const char *
492msg_code_string(uint16_t c) {
493 static const char *methods[] = { "0.00", "GET", "POST", "PUT", "DELETE",
494 "FETCH", "PATCH", "iPATCH"
495 };
496 static const char *signals[] = { "7.00", "CSM", "Ping", "Pong", "Release",
497 "Abort"
498 };
499 static char buf[5];
500
501 if (c < sizeof(methods)/sizeof(const char *)) {
502 return methods[c];
503 } else if (c >= 224 && c - 224 < (int)(sizeof(signals)/sizeof(const char *))) {
504 return signals[c-224];
505 } else {
506 snprintf(buf, sizeof(buf), "%u.%02u", (c >> 5) & 0x7, c & 0x1f);
507 return buf;
508 }
509}
510
512static const char *
513msg_option_string(uint8_t code, uint16_t option_type) {
514 struct option_desc_t {
515 uint16_t type;
516 const char *name;
517 };
518
519 static struct option_desc_t options[] = {
520 { COAP_OPTION_IF_MATCH, "If-Match" },
521 { COAP_OPTION_URI_HOST, "Uri-Host" },
522 { COAP_OPTION_ETAG, "ETag" },
523 { COAP_OPTION_IF_NONE_MATCH, "If-None-Match" },
524 { COAP_OPTION_OBSERVE, "Observe" },
525 { COAP_OPTION_URI_PORT, "Uri-Port" },
526 { COAP_OPTION_LOCATION_PATH, "Location-Path" },
527 { COAP_OPTION_OSCORE, "Oscore" },
528 { COAP_OPTION_URI_PATH, "Uri-Path" },
529 { COAP_OPTION_CONTENT_FORMAT, "Content-Format" },
530 { COAP_OPTION_MAXAGE, "Max-Age" },
531 { COAP_OPTION_URI_QUERY, "Uri-Query" },
532 { COAP_OPTION_HOP_LIMIT, "Hop-Limit" },
533 { COAP_OPTION_ACCEPT, "Accept" },
534 { COAP_OPTION_LOCATION_QUERY, "Location-Query" },
535 { COAP_OPTION_BLOCK2, "Block2" },
536 { COAP_OPTION_BLOCK1, "Block1" },
537 { COAP_OPTION_SIZE2, "Size2" },
538 { COAP_OPTION_PROXY_URI, "Proxy-Uri" },
539 { COAP_OPTION_PROXY_SCHEME, "Proxy-Scheme" },
540 { COAP_OPTION_SIZE1, "Size1" },
541 { COAP_OPTION_ECHO, "Echo" },
542 { COAP_OPTION_NORESPONSE, "No-Response" },
543 { COAP_OPTION_RTAG, "Request-Tag" },
544 { COAP_OPTION_Q_BLOCK1, "Q-Block1" },
545 { COAP_OPTION_Q_BLOCK2, "Q-Block2" }
546 };
547
548 static struct option_desc_t options_csm[] = {
549 { COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE, "Max-Message-Size" },
550 { COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER, "Block-Wise-Transfer" },
551 { COAP_SIGNALING_OPTION_EXTENDED_TOKEN_LENGTH, "Extended-Token-Length" }
552 };
553
554 static struct option_desc_t options_pingpong[] = {
555 { COAP_SIGNALING_OPTION_CUSTODY, "Custody" }
556 };
557
558 static struct option_desc_t options_release[] = {
559 { COAP_SIGNALING_OPTION_ALTERNATIVE_ADDRESS, "Alternative-Address" },
560 { COAP_SIGNALING_OPTION_HOLD_OFF, "Hold-Off" }
561 };
562
563 static struct option_desc_t options_abort[] = {
564 { COAP_SIGNALING_OPTION_BAD_CSM_OPTION, "Bad-CSM-Option" }
565 };
566
567 static char buf[6];
568 size_t i;
569
570 if (code == COAP_SIGNALING_CSM) {
571 for (i = 0; i < sizeof(options_csm)/sizeof(struct option_desc_t); i++) {
572 if (option_type == options_csm[i].type) {
573 return options_csm[i].name;
574 }
575 }
576 } else if (code == COAP_SIGNALING_PING || code == COAP_SIGNALING_PONG) {
577 for (i = 0; i < sizeof(options_pingpong)/sizeof(struct option_desc_t); i++) {
578 if (option_type == options_pingpong[i].type) {
579 return options_pingpong[i].name;
580 }
581 }
582 } else if (code == COAP_SIGNALING_RELEASE) {
583 for (i = 0; i < sizeof(options_release)/sizeof(struct option_desc_t); i++) {
584 if (option_type == options_release[i].type) {
585 return options_release[i].name;
586 }
587 }
588 } else if (code == COAP_SIGNALING_ABORT) {
589 for (i = 0; i < sizeof(options_abort)/sizeof(struct option_desc_t); i++) {
590 if (option_type == options_abort[i].type) {
591 return options_abort[i].name;
592 }
593 }
594 } else {
595 /* search option_type in list of known options */
596 for (i = 0; i < sizeof(options)/sizeof(struct option_desc_t); i++) {
597 if (option_type == options[i].type) {
598 return options[i].name;
599 }
600 }
601 }
602 /* unknown option type, just print to buf */
603 snprintf(buf, sizeof(buf), "%u", option_type);
604 return buf;
605}
606
607static unsigned int
608print_content_format(unsigned int format_type,
609 unsigned char *result, unsigned int buflen) {
610 struct desc_t {
611 unsigned int type;
612 const char *name;
613 };
614
615 static struct desc_t formats[] = {
616 { COAP_MEDIATYPE_TEXT_PLAIN, "text/plain" },
617 { COAP_MEDIATYPE_APPLICATION_LINK_FORMAT, "application/link-format" },
618 { COAP_MEDIATYPE_APPLICATION_XML, "application/xml" },
619 { COAP_MEDIATYPE_APPLICATION_OCTET_STREAM, "application/octet-stream" },
620 { COAP_MEDIATYPE_APPLICATION_RDF_XML, "application/rdf+xml" },
621 { COAP_MEDIATYPE_APPLICATION_EXI, "application/exi" },
622 { COAP_MEDIATYPE_APPLICATION_JSON, "application/json" },
623 { COAP_MEDIATYPE_APPLICATION_CBOR, "application/cbor" },
624 { COAP_MEDIATYPE_APPLICATION_CWT, "application/cwt" },
625 { COAP_MEDIATYPE_APPLICATION_COAP_GROUP_JSON, "application/coap-group+json" },
626 { COAP_MEDIATYPE_APPLICATION_COSE_SIGN, "application/cose; cose-type=\"cose-sign\"" },
627 { COAP_MEDIATYPE_APPLICATION_COSE_SIGN1, "application/cose; cose-type=\"cose-sign1\"" },
628 { COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT, "application/cose; cose-type=\"cose-encrypt\"" },
629 { COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT0, "application/cose; cose-type=\"cose-encrypt0\"" },
630 { COAP_MEDIATYPE_APPLICATION_COSE_MAC, "application/cose; cose-type=\"cose-mac\"" },
631 { COAP_MEDIATYPE_APPLICATION_COSE_MAC0, "application/cose; cose-type=\"cose-mac0\"" },
632 { COAP_MEDIATYPE_APPLICATION_COSE_KEY, "application/cose-key" },
633 { COAP_MEDIATYPE_APPLICATION_COSE_KEY_SET, "application/cose-key-set" },
634 { COAP_MEDIATYPE_APPLICATION_SENML_JSON, "application/senml+json" },
635 { COAP_MEDIATYPE_APPLICATION_SENSML_JSON, "application/sensml+json" },
636 { COAP_MEDIATYPE_APPLICATION_SENML_CBOR, "application/senml+cbor" },
637 { COAP_MEDIATYPE_APPLICATION_SENSML_CBOR, "application/sensml+cbor" },
638 { COAP_MEDIATYPE_APPLICATION_SENML_EXI, "application/senml-exi" },
639 { COAP_MEDIATYPE_APPLICATION_SENSML_EXI, "application/sensml-exi" },
640 { COAP_MEDIATYPE_APPLICATION_SENML_XML, "application/senml+xml" },
641 { COAP_MEDIATYPE_APPLICATION_SENSML_XML, "application/sensml+xml" },
642 { COAP_MEDIATYPE_APPLICATION_DOTS_CBOR, "application/dots+cbor" },
643 { COAP_MEDIATYPE_APPLICATION_ACE_CBOR, "application/ace+cbor" },
644 { COAP_MEDIATYPE_APPLICATION_MB_CBOR_SEQ, "application/missing-blocks+cbor-seq" },
645 { COAP_MEDIATYPE_APPLICATION_OSCORE, "application/oscore" },
646 { 75, "application/dcaf+cbor" }
647 };
648
649 size_t i;
650
651 /* search format_type in list of known content formats */
652 for (i = 0; i < sizeof(formats)/sizeof(struct desc_t); i++) {
653 if (format_type == formats[i].type) {
654 return snprintf((char *)result, buflen, "%s", formats[i].name);
655 }
656 }
657
658 /* unknown content format, just print numeric value to buf */
659 return snprintf((char *)result, buflen, "%d", format_type);
660}
661
668is_binary(int content_format) {
669 return !(content_format == -1 ||
670 content_format == COAP_MEDIATYPE_TEXT_PLAIN ||
671 content_format == COAP_MEDIATYPE_APPLICATION_LINK_FORMAT ||
672 content_format == COAP_MEDIATYPE_APPLICATION_XML ||
673 content_format == COAP_MEDIATYPE_APPLICATION_JSON);
674}
675
676#define COAP_DO_SHOW_OUTPUT_LINE \
677 do { \
678 if (use_fprintf_for_show_pdu) { \
679 fprintf(COAP_DEBUG_FD, "%s", outbuf); \
680 } \
681 else { \
682 coap_log(level, "%s", outbuf); \
683 } \
684 } while (0)
685
686/*
687 * It is possible to override the output debug buffer size and hence control
688 * the amount of information printed out about a CoAP PDU.
689 * Note: Adding a byte may be insufficient to output the next byte of the PDU.
690 *
691 * This is done by the adding of a -DCOAP_DEBUG_BUF_SIZE=nnnn option to the
692 * CPPFLAGS parameter that is optionally used on the ./configure command line.
693 *
694 * E.g. ./configure CPPFLAGS="-DCOAP_DEBUG_BUF_SIZE=4096"
695 *
696 */
697
698#if COAP_DEBUG_BUF_SIZE < 5
699#error "COAP_DEBUG_BUF_SIZE must be at least 5, should be >= 32 to be useful"
700#endif /* COAP_DEBUG_BUF_SIZE < 5 */
701
702void
704#if COAP_CONSTRAINED_STACK
705 /* Proxy-Uri: can be 1034 bytes long */
706 /* buf and outbuf protected by mutex m_show_pdu */
707 static unsigned char buf[min(COAP_DEBUG_BUF_SIZE, 1035)];
708 static char outbuf[COAP_DEBUG_BUF_SIZE];
709#else /* ! COAP_CONSTRAINED_STACK */
710 /* Proxy-Uri: can be 1034 bytes long */
711 unsigned char buf[min(COAP_DEBUG_BUF_SIZE, 1035)];
712 char outbuf[COAP_DEBUG_BUF_SIZE];
713#endif /* ! COAP_CONSTRAINED_STACK */
714 size_t buf_len = 0; /* takes the number of bytes written to buf */
715 int encode = 0, have_options = 0;
716 uint32_t i;
717 coap_opt_iterator_t opt_iter;
718 coap_opt_t *option;
719 int content_format = -1;
720 size_t data_len;
721 const uint8_t *data;
722 uint32_t opt_len;
723 const uint8_t *opt_val;
724 size_t outbuflen = 0;
725 int is_oscore_payload = 0;
726
727 /* Save time if not needed */
728 if (level > coap_get_log_level())
729 return;
730
731#if COAP_CONSTRAINED_STACK
732 coap_mutex_lock(&m_show_pdu);
733#endif /* COAP_CONSTRAINED_STACK */
734
735 if (!pdu->session || COAP_PROTO_NOT_RELIABLE(pdu->session->proto)) {
736 snprintf(outbuf, sizeof(outbuf), "v:%d t:%s c:%s i:%04x {",
738 msg_code_string(pdu->code), pdu->mid);
739 } else if (pdu->session->proto == COAP_PROTO_WS ||
740 pdu->session->proto == COAP_PROTO_WSS) {
741 if (pdu->type != COAP_MESSAGE_CON)
742 coap_log_alert("WebSocket: type != CON\n");
743 snprintf(outbuf, sizeof(outbuf), "v:WebSocket c:%s {",
744 msg_code_string(pdu->code));
745 } else {
746 if (pdu->type != COAP_MESSAGE_CON)
747 coap_log_alert("Reliable: type != CON\n");
748 snprintf(outbuf, sizeof(outbuf), "v:Reliable c:%s {",
749 msg_code_string(pdu->code));
750 }
751
752 for (i = 0; i < pdu->actual_token.length; i++) {
753 outbuflen = strlen(outbuf);
754 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen,
755 "%02x", pdu->actual_token.s[i]);
756 }
757 outbuflen = strlen(outbuf);
758 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "}");
759
760 /* show options, if any */
762
763 outbuflen = strlen(outbuf);
764 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, " [");
765 while ((option = coap_option_next(&opt_iter))) {
766 buf[0] = '\000';
767 if (!have_options) {
768 have_options = 1;
769 } else {
770 outbuflen = strlen(outbuf);
771 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, ",");
772 }
773
774 if (pdu->code == COAP_SIGNALING_CODE_CSM) {
775 switch (opt_iter.number) {
778 buf_len = snprintf((char *)buf, sizeof(buf), "%u",
780 coap_opt_length(option)));
781 break;
782 default:
783 buf_len = 0;
784 break;
785 }
786 } else if (pdu->code == COAP_SIGNALING_CODE_PING ||
788 buf_len = 0;
789 } else if (pdu->code == COAP_SIGNALING_CODE_RELEASE) {
790 switch (opt_iter.number) {
792 buf_len = print_readable(coap_opt_value(option),
793 coap_opt_length(option),
794 buf, sizeof(buf), 0);
795 break;
797 buf_len = snprintf((char *)buf, sizeof(buf), "%u",
799 coap_opt_length(option)));
800 break;
801 default:
802 buf_len = 0;
803 break;
804 }
805 } else if (pdu->code == COAP_SIGNALING_CODE_ABORT) {
806 switch (opt_iter.number) {
808 buf_len = snprintf((char *)buf, sizeof(buf), "%u",
810 coap_opt_length(option)));
811 break;
812 default:
813 buf_len = 0;
814 break;
815 }
816 } else {
817 switch (opt_iter.number) {
820 content_format = (int)coap_decode_var_bytes(coap_opt_value(option),
821 coap_opt_length(option));
822
823 buf_len = print_content_format(content_format, buf, sizeof(buf));
824 break;
825
830 /* split block option into number/more/size where more is the
831 * letter M if set, the _ otherwise */
832 if (COAP_OPT_BLOCK_SZX(option) == 7) {
833 if (coap_get_data(pdu, &data_len, &data))
834 buf_len = snprintf((char *)buf, sizeof(buf), "%u/%c/BERT(%zu)",
835 coap_opt_block_num(option), /* block number */
836 COAP_OPT_BLOCK_MORE(option) ? 'M' : '_', /* M bit */
837 data_len);
838 else
839 buf_len = snprintf((char *)buf, sizeof(buf), "%u/%c/BERT",
840 coap_opt_block_num(option), /* block number */
841 COAP_OPT_BLOCK_MORE(option) ? 'M' : '_'); /* M bit */
842 } else {
843 buf_len = snprintf((char *)buf, sizeof(buf), "%u/%c/%u",
844 coap_opt_block_num(option), /* block number */
845 COAP_OPT_BLOCK_MORE(option) ? 'M' : '_', /* M bit */
846 (1 << (COAP_OPT_BLOCK_SZX(option) + 4))); /* block size */
847 }
848
849 break;
850
852 opt_len = coap_opt_length(option);
853 buf[0] = '\000';
854 if (opt_len) {
855 size_t ofs = 1;
856 size_t cnt;
857
858 opt_val = coap_opt_value(option);
859 if (opt_val[0] & 0x20) {
860 /* Group Flag */
861 snprintf((char *)buf, sizeof(buf), "grp");
862 }
863 if (opt_val[0] & 0x07) {
864 /* Partial IV */
865 cnt = opt_val[0] & 0x07;
866 if (cnt > opt_len - ofs)
867 goto no_more;
868 buf_len = strlen((char *)buf);
869 snprintf((char *)&buf[buf_len], sizeof(buf)-buf_len, "%spIV=0x",
870 buf_len ? "," : "");
871 for (i = 0; (uint32_t)i < cnt; i++) {
872 buf_len = strlen((char *)buf);
873 snprintf((char *)&buf[buf_len], sizeof(buf)-buf_len,
874 "%02x", opt_val[ofs + i]);
875 }
876 ofs += cnt;
877 }
878 if (opt_val[0] & 0x10) {
879 /* kid context */
880 if (ofs >= opt_len)
881 goto no_more;
882 cnt = opt_val[ofs];
883 if (cnt > opt_len - ofs - 1)
884 goto no_more;
885 ofs++;
886 buf_len = strlen((char *)buf);
887 snprintf((char *)&buf[buf_len], sizeof(buf)-buf_len, "%skc=0x",
888 buf_len ? "," : "");
889 for (i = 0; (uint32_t)i < cnt; i++) {
890 buf_len = strlen((char *)buf);
891 snprintf((char *)&buf[buf_len], sizeof(buf)-buf_len,
892 "%02x", opt_val[ofs + i]);
893 }
894 ofs += cnt;
895 }
896 if (opt_val[0] & 0x08) {
897 /* kid */
898 if (ofs >= opt_len)
899 goto no_more;
900 cnt = opt_len - ofs;
901 buf_len = strlen((char *)buf);
902 snprintf((char *)&buf[buf_len], sizeof(buf)-buf_len, "%skid=0x",
903 buf_len ? "," : "");
904 for (i = 0; (uint32_t)i < cnt; i++) {
905 buf_len = strlen((char *)buf);
906 snprintf((char *)&buf[buf_len], sizeof(buf)-buf_len,
907 "%02x", opt_val[ofs + i]);
908 }
909 }
910 }
911no_more:
912 buf_len = strlen((char *)buf);
913 is_oscore_payload = 1;
914 break;
915
922 if (coap_opt_length(option)) {
923 /* show values as unsigned decimal value */
924 buf_len = snprintf((char *)buf, sizeof(buf), "%u",
926 coap_opt_length(option)));
927 }
928 break;
929
931 case COAP_OPTION_ETAG:
932 case COAP_OPTION_ECHO:
934 case COAP_OPTION_RTAG:
935 opt_len = coap_opt_length(option);
936 opt_val = coap_opt_value(option);
937 snprintf((char *)buf, sizeof(buf), "0x");
938 for (i = 0; (uint32_t)i < opt_len; i++) {
939 buf_len = strlen((char *)buf);
940 snprintf((char *)&buf[buf_len], sizeof(buf)-buf_len,
941 "%02x", opt_val[i]);
942 }
943 buf_len = strlen((char *)buf);
944 break;
945 default:
946 /* generic output function for all other option types */
947 if (opt_iter.number == COAP_OPTION_URI_PATH ||
948 opt_iter.number == COAP_OPTION_PROXY_URI ||
949 opt_iter.number == COAP_OPTION_URI_HOST ||
950 opt_iter.number == COAP_OPTION_LOCATION_PATH ||
952 opt_iter.number == COAP_OPTION_PROXY_SCHEME ||
953 opt_iter.number == COAP_OPTION_URI_QUERY) {
954 encode = 0;
955 } else {
956 encode = 1;
957 }
958 buf_len = print_readable(coap_opt_value(option),
959 coap_opt_length(option),
960 buf, sizeof(buf), encode);
961 }
962 }
963 outbuflen = strlen(outbuf);
964 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen,
965 " %s:%.*s", msg_option_string(pdu->code, opt_iter.number),
966 (int)buf_len, buf);
967 }
968
969 outbuflen = strlen(outbuf);
970 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, " ]");
971
972 if (coap_get_data(pdu, &data_len, &data)) {
973
974 outbuflen = strlen(outbuf);
975 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, " :: ");
976
977 if (is_binary(content_format) || !isprint(data[0]) || is_oscore_payload) {
978 size_t keep_data_len = data_len;
979 const uint8_t *keep_data = data;
980
981 outbuflen = strlen(outbuf);
982 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen,
983 "binary data length %zu\n", data_len);
985 /*
986 * Output hex dump of binary data as a continuous entry
987 */
988 outbuf[0] = '\000';
989 snprintf(outbuf, sizeof(outbuf), "<<");
990 while (data_len--) {
991 outbuflen = strlen(outbuf);
992 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen,
993 "%02x", *data++);
994 }
995 outbuflen = strlen(outbuf);
996 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, ">>");
997 data_len = keep_data_len;
998 data = keep_data;
999 outbuflen = strlen(outbuf);
1000 if (outbuflen == sizeof(outbuf)-1)
1001 outbuflen--;
1002 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "\n");
1004 /*
1005 * Output ascii readable (if possible), immediately under the
1006 * hex value of the character output above to help binary debugging
1007 */
1008 outbuf[0] = '\000';
1009 snprintf(outbuf, sizeof(outbuf), "<<");
1010 while (data_len--) {
1011 outbuflen = strlen(outbuf);
1012 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen,
1013 "%c ", isprint(*data) ? *data : '.');
1014 data++;
1015 }
1016 outbuflen = strlen(outbuf);
1017 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, ">>");
1018 } else {
1019 size_t max_length;
1020
1021 outbuflen = strlen(outbuf);
1022 max_length = sizeof(outbuf)-outbuflen;
1023 if (max_length > 1) {
1024 outbuf[outbuflen++] = '\'';
1025 outbuf[outbuflen] = '\000';
1026 max_length--;
1027 }
1028 if (max_length > 1) {
1029 outbuflen += print_readable(data, data_len,
1030 (unsigned char *)&outbuf[outbuflen],
1031 max_length, 0);
1032 }
1033 /* print_readable may be handling unprintables - hence headroom of 4 */
1034 if (outbuflen < sizeof(outbuf)-4-1) {
1035 outbuf[outbuflen++] = '\'';
1036 outbuf[outbuflen] = '\000';
1037 }
1038 }
1039 }
1040
1041 outbuflen = strlen(outbuf);
1042 if (outbuflen == sizeof(outbuf)-1)
1043 outbuflen--;
1044 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "\n");
1046
1047#if COAP_CONSTRAINED_STACK
1048 coap_mutex_unlock(&m_show_pdu);
1049#endif /* COAP_CONSTRAINED_STACK */
1050}
1051
1052void
1054 char buffer[128];
1055 coap_string_tls_version(buffer, sizeof(buffer));
1056 coap_log(level, "%s\n", buffer);
1057}
1058
1059char *
1060coap_string_tls_version(char *buffer, size_t bufsize) {
1062 char beta[8];
1063 char sub[2];
1064 char b_beta[8];
1065 char b_sub[2];
1066
1067 switch (tls_version->type) {
1069 snprintf(buffer, bufsize, "TLS Library: None");
1070 break;
1072 snprintf(buffer, bufsize, "TLS Library: TinyDTLS - runtime %lu.%lu.%lu, "
1073 "libcoap built for %lu.%lu.%lu",
1074 (unsigned long)(tls_version->version >> 16),
1075 (unsigned long)((tls_version->version >> 8) & 0xff),
1076 (unsigned long)(tls_version->version & 0xff),
1077 (unsigned long)(tls_version->built_version >> 16),
1078 (unsigned long)((tls_version->built_version >> 8) & 0xff),
1079 (unsigned long)(tls_version->built_version & 0xff));
1080 break;
1082 switch (tls_version->version &0xf) {
1083 case 0:
1084 strcpy(beta, "-dev");
1085 break;
1086 case 0xf:
1087 strcpy(beta, "");
1088 break;
1089 default:
1090 strcpy(beta, "-beta");
1091 beta[5] = (tls_version->version &0xf) + '0';
1092 beta[6] = '\000';
1093 break;
1094 }
1095 sub[0] = ((tls_version->version >> 4) & 0xff) ?
1096 ((tls_version->version >> 4) & 0xff) + 'a' -1 : '\000';
1097 sub[1] = '\000';
1098 switch (tls_version->built_version &0xf) {
1099 case 0:
1100 strcpy(b_beta, "-dev");
1101 break;
1102 case 0xf:
1103 strcpy(b_beta, "");
1104 break;
1105 default:
1106 strcpy(b_beta, "-beta");
1107 b_beta[5] = (tls_version->built_version &0xf) + '0';
1108 b_beta[6] = '\000';
1109 break;
1110 }
1111 b_sub[0] = ((tls_version->built_version >> 4) & 0xff) ?
1112 ((tls_version->built_version >> 4) & 0xff) + 'a' -1 : '\000';
1113 b_sub[1] = '\000';
1114 snprintf(buffer, bufsize, "TLS Library: OpenSSL - runtime "
1115 "%lu.%lu.%lu%s%s, libcoap built for %lu.%lu.%lu%s%s",
1116 (unsigned long)(tls_version->version >> 28),
1117 (unsigned long)((tls_version->version >> 20) & 0xff),
1118 (unsigned long)((tls_version->version >> 12) & 0xff), sub, beta,
1119 (unsigned long)(tls_version->built_version >> 28),
1120 (unsigned long)((tls_version->built_version >> 20) & 0xff),
1121 (unsigned long)((tls_version->built_version >> 12) & 0xff),
1122 b_sub, b_beta);
1123 break;
1125 snprintf(buffer, bufsize, "TLS Library: GnuTLS - runtime %lu.%lu.%lu, "
1126 "libcoap built for %lu.%lu.%lu",
1127 (unsigned long)(tls_version->version >> 16),
1128 (unsigned long)((tls_version->version >> 8) & 0xff),
1129 (unsigned long)(tls_version->version & 0xff),
1130 (unsigned long)(tls_version->built_version >> 16),
1131 (unsigned long)((tls_version->built_version >> 8) & 0xff),
1132 (unsigned long)(tls_version->built_version & 0xff));
1133 break;
1135 snprintf(buffer, bufsize, "TLS Library: Mbed TLS - runtime %lu.%lu.%lu, "
1136 "libcoap built for %lu.%lu.%lu",
1137 (unsigned long)(tls_version->version >> 24),
1138 (unsigned long)((tls_version->version >> 16) & 0xff),
1139 (unsigned long)((tls_version->version >> 8) & 0xff),
1140 (unsigned long)(tls_version->built_version >> 24),
1141 (unsigned long)((tls_version->built_version >> 16) & 0xff),
1142 (unsigned long)((tls_version->built_version >> 8) & 0xff));
1143 break;
1144 default:
1145 snprintf(buffer, bufsize, "Library type %d unknown", tls_version->type);
1146 break;
1147 }
1148 return buffer;
1149}
1150
1151char *
1152coap_string_tls_support(char *buffer, size_t bufsize) {
1153 const int have_tls = coap_tls_is_supported();
1154 const int have_dtls = coap_dtls_is_supported();
1155 const int have_psk = coap_dtls_psk_is_supported();
1156 const int have_pki = coap_dtls_pki_is_supported();
1157 const int have_pkcs11 = coap_dtls_pkcs11_is_supported();
1158 const int have_rpk = coap_dtls_rpk_is_supported();
1159 const int have_oscore = coap_oscore_is_supported();
1160 const int have_ws = coap_ws_is_supported();
1161
1162 if (have_dtls == 0 && have_tls == 0) {
1163 snprintf(buffer, bufsize, "(No DTLS or TLS support)");
1164 return buffer;
1165 }
1166 snprintf(buffer, bufsize,
1167 "(%sDTLS and %sTLS support; %sPSK, %sPKI, %sPKCS11, and %sRPK support)\n(%sOSCORE)\n(%sWebSockets)",
1168 have_dtls ? "" : "No ",
1169 have_tls ? "" : "no ",
1170 have_psk ? "" : "no ",
1171 have_pki ? "" : "no ",
1172 have_pkcs11 ? "" : "no ",
1173 have_rpk ? "" : "no ",
1174 have_oscore ? "Have " : "No ",
1175 have_ws ? "Have " : "No ");
1176 return buffer;
1177}
1178
1180
1181void
1183 log_handler = handler;
1184}
1185
1186void
1187coap_log_impl(coap_log_t level, const char *format, ...) {
1188
1189 if (log_handler) {
1190#if COAP_CONSTRAINED_STACK
1191 /* message protected by mutex m_log_impl */
1192 static char message[COAP_DEBUG_BUF_SIZE];
1193#else /* ! COAP_CONSTRAINED_STACK */
1194 char message[COAP_DEBUG_BUF_SIZE];
1195#endif /* ! COAP_CONSTRAINED_STACK */
1196 va_list ap;
1197 va_start(ap, format);
1198#if COAP_CONSTRAINED_STACK
1199 coap_mutex_lock(&m_log_impl);
1200#endif /* COAP_CONSTRAINED_STACK */
1201
1202 vsnprintf(message, sizeof(message), format, ap);
1203 va_end(ap);
1204 log_handler(level, message);
1205#if COAP_CONSTRAINED_STACK
1206 coap_mutex_unlock(&m_log_impl);
1207#endif /* COAP_CONSTRAINED_STACK */
1208 } else {
1209 char timebuf[32];
1210 coap_tick_t now;
1211 va_list ap;
1212 FILE *log_fd;
1213 size_t len;
1214
1215 log_fd = level <= COAP_LOG_CRIT ? COAP_ERR_FD : COAP_DEBUG_FD;
1216
1217 coap_ticks(&now);
1218 len = print_timestamp(timebuf,sizeof(timebuf), now);
1219 if (len)
1220 fprintf(log_fd, "%.*s ", (int)len, timebuf);
1221
1222 if (level >= sizeof(loglevels)/sizeof(loglevels[0])) {
1223 fprintf(log_fd, "%4d ", level);
1224 } else {
1225 fprintf(log_fd, "%s ", loglevels[level]);
1226 }
1227
1228 va_start(ap, format);
1229 vfprintf(log_fd, format, ap);
1230 va_end(ap);
1231 fflush(log_fd);
1232 }
1233}
1234
1235static struct packet_num_interval {
1237 int end;
1240static int packet_loss_level = 0;
1241static int send_packet_count = 0;
1242
1243int
1244coap_debug_set_packet_loss(const char *loss_level) {
1245 const char *p = loss_level;
1246 char *end = NULL;
1247 int n = (int)strtol(p, &end, 10), i = 0;
1248 if (end == p || n < 0)
1249 return 0;
1250 if (*end == '%') {
1251 if (n > 100)
1252 n = 100;
1253 packet_loss_level = n * 65536 / 100;
1254 coap_log_debug("packet loss level set to %d%%\n", n);
1255 } else {
1256 if (n <= 0)
1257 return 0;
1258 while (i < 10) {
1260 if (*end == '-') {
1261 p = end + 1;
1262 n = (int)strtol(p, &end, 10);
1263 if (end == p || n <= 0)
1264 return 0;
1265 }
1266 packet_loss_intervals[i++].end = n;
1267 if (*end == 0)
1268 break;
1269 if (*end != ',')
1270 return 0;
1271 p = end + 1;
1272 n = (int)strtol(p, &end, 10);
1273 if (end == p || n <= 0)
1274 return 0;
1275 }
1276 if (i == 10)
1277 return 0;
1279 }
1281 return 1;
1282}
1283
1284int
1287 if (num_packet_loss_intervals > 0) {
1288 int i;
1289 for (i = 0; i < num_packet_loss_intervals; i++) {
1290 if (send_packet_count >= packet_loss_intervals[i].start &&
1292 coap_log_debug("Packet %u dropped\n", send_packet_count);
1293 return 0;
1294 }
1295 }
1296 }
1297 if (packet_loss_level > 0) {
1298 uint16_t r = 0;
1299 coap_prng((uint8_t *)&r, 2);
1300 if (r < packet_loss_level) {
1301 coap_log_debug("Packet %u dropped\n", send_packet_count);
1302 return 0;
1303 }
1304 }
1305 return 1;
1306}
uint16_t coap_address_get_port(const coap_address_t *addr)
Returns the port from addr in host byte order.
Definition: coap_address.c:38
static int packet_loss_level
Definition: coap_debug.c:1240
static struct packet_num_interval packet_loss_intervals[10]
static int send_packet_count
Definition: coap_debug.c:1241
int coap_debug_set_packet_loss(const char *loss_level)
Set the packet loss level for testing.
Definition: coap_debug.c:1244
static coap_log_t maxlog
Definition: coap_debug.c:61
static coap_log_handler_t log_handler
Definition: coap_debug.c:1179
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:668
static const char * msg_code_string(uint16_t c)
Returns a textual description of the method or response code.
Definition: coap_debug.c:492
#define COAP_DO_SHOW_OUTPUT_LINE
Definition: coap_debug.c:676
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:169
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:513
static size_t strnlen(const char *s, size_t maxlen)
A length-safe strlen() fake.
Definition: coap_debug.c:160
static const char * loglevels[]
Definition: coap_debug.c:104
COAP_STATIC_INLINE size_t print_timestamp(char *s, size_t len, coap_tick_t t)
Definition: coap_debug.c:137
#define min(a, b)
Definition: coap_debug.c:207
static const char * msg_type_string(uint16_t t)
Returns a textual description of the message type t.
Definition: coap_debug.c:484
static int use_fprintf_for_show_pdu
Definition: coap_debug.c:64
static int num_packet_loss_intervals
Definition: coap_debug.c:1239
int coap_debug_send_packet(void)
Check to see whether a packet should be sent or not.
Definition: coap_debug.c:1285
static unsigned int print_content_format(unsigned int format_type, unsigned char *result, unsigned int buflen)
Definition: coap_debug.c:608
#define INET6_ADDRSTRLEN
Definition: coap_debug.c:211
Pulls together all the internal only header files.
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:26
#define COAP_OPT_BLOCK_SZX(opt)
Returns the value of the SZX-field of a Block option opt.
Definition: coap_block.h:92
#define COAP_OPT_BLOCK_MORE(opt)
Returns the value of the More-bit of a Block option opt.
Definition: coap_block.h:88
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: coap_block.c:39
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition: coap_time.h:144
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:140
void coap_ticks(coap_tick_t *)
Returns the current value of an internal tick counter.
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:69
int coap_dtls_psk_is_supported(void)
Check whether (D)TLS PSK is available.
Definition: coap_notls.c:37
int coap_tls_is_supported(void)
Check whether TLS is available.
Definition: coap_notls.c:28
int coap_dtls_is_supported(void)
Check whether DTLS is available.
Definition: coap_notls.c:23
int coap_dtls_pki_is_supported(void)
Check whether (D)TLS PKI is available.
Definition: coap_notls.c:46
int coap_dtls_rpk_is_supported(void)
Check whether (D)TLS RPK is available.
Definition: coap_notls.c:64
int coap_dtls_pkcs11_is_supported(void)
Check whether (D)TLS PKCS11 is available.
Definition: coap_notls.c:55
@ COAP_TLS_LIBRARY_GNUTLS
Using GnuTLS library.
Definition: coap_dtls.h:96
@ COAP_TLS_LIBRARY_TINYDTLS
Using TinyDTLS library.
Definition: coap_dtls.h:94
@ COAP_TLS_LIBRARY_NOTLS
No DTLS library.
Definition: coap_dtls.h:93
@ COAP_TLS_LIBRARY_OPENSSL
Using OpenSSL library.
Definition: coap_dtls.h:95
@ COAP_TLS_LIBRARY_MBEDTLS
Using Mbed TLS library.
Definition: coap_dtls.h:97
unsigned int coap_decode_var_bytes(const uint8_t *buf, size_t len)
Decodes multiple-length byte sequences.
Definition: coap_encode.c:38
void coap_set_log_handler(coap_log_handler_t handler)
Add a custom log callback handler.
Definition: coap_debug.c:1182
#define coap_log_debug(...)
Definition: coap_debug.h:120
coap_log_t coap_get_log_level(void)
Get the current logging level.
Definition: coap_debug.c:91
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:1060
#define coap_log_alert(...)
Definition: coap_debug.h:84
void coap_show_pdu(coap_log_t level, const coap_pdu_t *pdu)
Display the contents of the specified pdu.
Definition: coap_debug.c:703
char * coap_string_tls_support(char *buffer, size_t bufsize)
Build a string containing the current (D)TLS library support.
Definition: coap_debug.c:1152
#define COAP_MAX_LOGGING_LEVEL
Definition: coap_debug.h:42
#define COAP_ERR_FD
Used for output for COAP_LOG_CRIT to COAP_LOG_EMERG.
Definition: coap_debug.h:38
coap_log_t
Logging type.
Definition: coap_debug.h:50
const char * coap_package_version(void)
Get the library package version.
Definition: coap_debug.c:72
void coap_set_log_level(coap_log_t level)
Sets the log level to the specified value.
Definition: coap_debug.c:96
void coap_log_impl(coap_log_t level, const char *format,...)
Writes the given text to COAP_ERR_FD (for level <= COAP_LOG_CRIT) or COAP_DEBUG_FD (for level >= COAP...
Definition: coap_debug.c:1187
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:218
#define COAP_DEBUG_FD
Used for output for COAP_LOG_OSCORE to COAP_LOG_ERR.
Definition: coap_debug.h:31
const char * coap_package_build(void)
Get the library package build.
Definition: coap_debug.c:77
const char * coap_print_ip_addr(const coap_address_t *addr, char *buf, size_t len)
Print the IP address into the defined buffer.
Definition: coap_debug.c:364
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:1053
void coap_set_show_pdu_output(int use_fprintf)
Defines the output mode for the coap_show_pdu() function.
Definition: coap_debug.c:86
#define coap_log_err(...)
Definition: coap_debug.h:96
const char * coap_package_name(void)
Get the library package name.
Definition: coap_debug.c:67
void(* coap_log_handler_t)(coap_log_t level, const char *message)
Logging callback handler definition.
Definition: coap_debug.h:202
#define coap_log(level,...)
Logging function.
Definition: coap_debug.h:277
@ COAP_LOG_INFO
Definition: coap_debug.h:57
@ COAP_LOG_EMERG
Definition: coap_debug.h:51
@ COAP_LOG_DEBUG
Definition: coap_debug.h:58
@ COAP_LOG_CRIT
Definition: coap_debug.h:53
@ COAP_LOG_ERR
Definition: coap_debug.h:54
@ COAP_LOG_WARN
Definition: coap_debug.h:55
coap_opt_t * coap_option_next(coap_opt_iterator_t *oi)
Updates the iterator oi to point to the next option.
Definition: coap_option.c:153
uint32_t coap_opt_length(const coap_opt_t *opt)
Returns the length of the given option.
Definition: coap_option.c:212
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: coap_option.c:117
#define COAP_OPT_ALL
Pre-defined filter that includes all options.
Definition: coap_option.h:108
const uint8_t * coap_opt_value(const coap_opt_t *opt)
Returns a pointer to the value of the given option.
Definition: coap_option.c:249
int coap_oscore_is_supported(void)
Check whether OSCORE is available.
Definition: coap_oscore.c:2104
#define COAP_DEFAULT_VERSION
#define COAP_OPTION_HOP_LIMIT
Definition: coap_pdu.h:129
#define COAP_OPTION_NORESPONSE
Definition: coap_pdu.h:141
#define COAP_OPTION_URI_HOST
Definition: coap_pdu.h:116
#define COAP_OPTION_IF_MATCH
Definition: coap_pdu.h:115
#define COAP_MEDIATYPE_APPLICATION_COSE_MAC
Definition: coap_pdu.h:223
#define COAP_MEDIATYPE_APPLICATION_SENSML_EXI
Definition: coap_pdu.h:235
#define COAP_MEDIATYPE_APPLICATION_CWT
Definition: coap_pdu.h:213
#define COAP_OPTION_BLOCK2
Definition: coap_pdu.h:133
#define COAP_MEDIATYPE_APPLICATION_MB_CBOR_SEQ
Definition: coap_pdu.h:246
#define COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT
Definition: coap_pdu.h:221
#define COAP_MEDIATYPE_APPLICATION_RDF_XML
Definition: coap_pdu.h:209
#define COAP_OPTION_CONTENT_FORMAT
Definition: coap_pdu.h:124
#define COAP_SIGNALING_OPTION_ALTERNATIVE_ADDRESS
Definition: coap_pdu.h:197
#define COAP_OPTION_SIZE2
Definition: coap_pdu.h:135
#define COAP_MEDIATYPE_APPLICATION_SENSML_XML
Definition: coap_pdu.h:237
#define COAP_MEDIATYPE_APPLICATION_COSE_SIGN
Definition: coap_pdu.h:219
#define COAP_OPTION_BLOCK1
Definition: coap_pdu.h:134
#define COAP_OPTION_Q_BLOCK1
Definition: coap_pdu.h:131
#define COAP_OPTION_PROXY_SCHEME
Definition: coap_pdu.h:138
#define COAP_MEDIATYPE_APPLICATION_COSE_KEY_SET
Definition: coap_pdu.h:227
#define COAP_MEDIATYPE_APPLICATION_OSCORE
Definition: coap_pdu.h:249
#define COAP_MEDIATYPE_APPLICATION_SENML_CBOR
Definition: coap_pdu.h:232
#define COAP_OPTION_URI_QUERY
Definition: coap_pdu.h:128
#define COAP_MEDIATYPE_APPLICATION_COSE_KEY
Definition: coap_pdu.h:226
#define COAP_MEDIATYPE_APPLICATION_COSE_SIGN1
Definition: coap_pdu.h:220
#define COAP_OPTION_IF_NONE_MATCH
Definition: coap_pdu.h:118
#define COAP_MEDIATYPE_APPLICATION_OCTET_STREAM
Definition: coap_pdu.h:208
#define COAP_OPTION_LOCATION_PATH
Definition: coap_pdu.h:121
#define COAP_OPTION_URI_PATH
Definition: coap_pdu.h:123
#define COAP_SIGNALING_OPTION_EXTENDED_TOKEN_LENGTH
Definition: coap_pdu.h:191
#define COAP_MEDIATYPE_APPLICATION_SENML_EXI
Definition: coap_pdu.h:234
#define COAP_OPTION_OSCORE
Definition: coap_pdu.h:122
#define COAP_MEDIATYPE_APPLICATION_CBOR
Definition: coap_pdu.h:212
#define COAP_OPTION_SIZE1
Definition: coap_pdu.h:139
#define COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT0
Definition: coap_pdu.h:222
#define COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER
Definition: coap_pdu.h:190
#define COAP_MEDIATYPE_TEXT_PLAIN
Definition: coap_pdu.h:205
#define COAP_MEDIATYPE_APPLICATION_JSON
Definition: coap_pdu.h:211
#define COAP_OPTION_LOCATION_QUERY
Definition: coap_pdu.h:132
#define COAP_MEDIATYPE_APPLICATION_COSE_MAC0
Definition: coap_pdu.h:224
#define COAP_MEDIATYPE_APPLICATION_ACE_CBOR
Definition: coap_pdu.h:243
#define COAP_OPTION_Q_BLOCK2
Definition: coap_pdu.h:136
#define COAP_MEDIATYPE_APPLICATION_SENML_JSON
Definition: coap_pdu.h:230
#define COAP_MEDIATYPE_APPLICATION_EXI
Definition: coap_pdu.h:210
#define COAP_SIGNALING_OPTION_CUSTODY
Definition: coap_pdu.h:194
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:797
#define COAP_OPTION_RTAG
Definition: coap_pdu.h:142
#define COAP_MEDIATYPE_APPLICATION_COAP_GROUP_JSON
Definition: coap_pdu.h:216
#define COAP_OPTION_URI_PORT
Definition: coap_pdu.h:120
#define COAP_MEDIATYPE_APPLICATION_SENML_XML
Definition: coap_pdu.h:236
#define COAP_OPTION_ACCEPT
Definition: coap_pdu.h:130
#define COAP_MEDIATYPE_APPLICATION_DOTS_CBOR
Definition: coap_pdu.h:240
#define COAP_OPTION_MAXAGE
Definition: coap_pdu.h:127
#define COAP_OPTION_ETAG
Definition: coap_pdu.h:117
#define COAP_MEDIATYPE_APPLICATION_SENSML_JSON
Definition: coap_pdu.h:231
#define COAP_OPTION_PROXY_URI
Definition: coap_pdu.h:137
#define COAP_OPTION_OBSERVE
Definition: coap_pdu.h:119
#define COAP_SIGNALING_OPTION_HOLD_OFF
Definition: coap_pdu.h:198
#define COAP_OPTION_ECHO
Definition: coap_pdu.h:140
#define COAP_MEDIATYPE_APPLICATION_LINK_FORMAT
Definition: coap_pdu.h:206
#define COAP_SIGNALING_OPTION_BAD_CSM_OPTION
Definition: coap_pdu.h:201
#define COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE
Definition: coap_pdu.h:189
#define COAP_MEDIATYPE_APPLICATION_XML
Definition: coap_pdu.h:207
#define COAP_MEDIATYPE_APPLICATION_SENSML_CBOR
Definition: coap_pdu.h:233
@ COAP_PROTO_WS
Definition: coap_pdu.h:310
@ COAP_PROTO_WSS
Definition: coap_pdu.h:311
@ COAP_SIGNALING_CODE_ABORT
Definition: coap_pdu.h:361
@ COAP_SIGNALING_CODE_CSM
Definition: coap_pdu.h:357
@ COAP_SIGNALING_CODE_PING
Definition: coap_pdu.h:358
@ COAP_SIGNALING_CODE_PONG
Definition: coap_pdu.h:359
@ COAP_SIGNALING_CODE_RELEASE
Definition: coap_pdu.h:360
@ COAP_MESSAGE_CON
Definition: coap_pdu.h:65
@ COAP_SIGNALING_RELEASE
Definition: coap_pdu.h:184
@ COAP_SIGNALING_CSM
Definition: coap_pdu.h:181
@ COAP_SIGNALING_PONG
Definition: coap_pdu.h:183
@ COAP_SIGNALING_PING
Definition: coap_pdu.h:182
@ COAP_SIGNALING_ABORT
Definition: coap_pdu.h:185
#define COAP_PROTO_NOT_RELIABLE(p)
Definition: coap_session.h:36
int coap_ws_is_supported(void)
Check whether WebSockets is available.
Definition: coap_ws.c:935
#define COAP_STATIC_INLINE
Definition: libcoap.h:53
Multi-purpose address abstraction.
Definition: coap_address.h:109
struct sockaddr_in sin
Definition: coap_address.h:113
struct coap_sockaddr_un cun
Definition: coap_address.h:115
struct sockaddr_in6 sin6
Definition: coap_address.h:114
struct sockaddr sa
Definition: coap_address.h:112
union coap_address_t::@0 addr
size_t length
length of binary data
Definition: coap_str.h:65
const uint8_t * s
read-only binary data
Definition: coap_str.h:66
Iterator to run through PDU options.
Definition: coap_option.h:168
coap_option_num_t number
decoded option number
Definition: coap_option.h:170
structure for CoAP PDUs
coap_pdu_code_t code
request method (value 1–31) or response code (value 64-255)
coap_bin_const_t actual_token
Actual token in pdu.
coap_mid_t mid
message id, if any, in regular host byte order
coap_session_t * session
Session responsible for PDU or NULL.
coap_pdu_type_t type
message type
coap_proto_t proto
protocol used
char sun_path[COAP_UNIX_PATH_MAX]
Definition: coap_address.h:105
The structure used for returning the underlying (D)TLS library information.
Definition: coap_dtls.h:104
uint64_t built_version
(D)TLS Built against Library Version
Definition: coap_dtls.h:107
coap_tls_library_t type
Library type.
Definition: coap_dtls.h:106
uint64_t version
(D)TLS runtime Library Version
Definition: coap_dtls.h:105