Loading...
Searching...
No Matches
coap_debug.c
Go to the documentation of this file.
/* coap_debug.c -- debug utilities
*
* Copyright (C) 2010--2012,2014--2023 Olaf Bergmann <bergmann@tzi.org> and others
*
* SPDX-License-Identifier: BSD-2-Clause
*
* This file is part of the CoAP library libcoap. Please see
* README for terms of use.
*/
#include "coap3/coap_internal.h"
#if defined(HAVE_STRNLEN) && defined(__GNUC__) && !defined(_GNU_SOURCE)
#define _GNU_SOURCE 1
#endif
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_WS2TCPIP_H
#include <ws2tcpip.h>
#endif
#ifdef HAVE_TIME_H
#include <time.h>
#endif
#ifdef WITH_LWIP
# define fprintf(fd, ...) LWIP_PLATFORM_DIAG((__VA_ARGS__))
# define fflush(...)
#endif
#ifdef WITH_CONTIKI
# define fprintf(fd, ...) { (void)fd; printf(__VA_ARGS__); }
# define fflush(...)
# define vfprintf(fd, ...) { (void)fd; printf(__VA_ARGS__); }
# ifndef LOG_CONF_LEVEL_COAP
# define LOG_CONF_LEVEL_COAP 2 /* = LOG_LEVEL_WARN */
# endif
static coap_log_t maxlog = LOG_CONF_LEVEL_COAP == 0 ? /* = LOG_LEVEL_NONE */
COAP_LOG_EMERG :
(LOG_CONF_LEVEL_COAP == 1 ? /* = LOG_LEVEL_ERR */
COAP_LOG_ERR :
(LOG_CONF_LEVEL_COAP == 2 ? /* = LOG_LEVEL_WARN */
COAP_LOG_WARN :
(LOG_CONF_LEVEL_COAP == 3 ? /* = LOG_LEVEL_INFO */
COAP_LOG_INFO :
COAP_LOG_DEBUG)));
#else /* WITH_CONTIKI */
static coap_log_t maxlog = COAP_LOG_WARN; /* default maximum CoAP log level */
#endif /* WITH_CONTIKI */
static int use_fprintf_for_show_pdu = 1; /* non zero to output with fprintf */
const char *
coap_package_name(void) {
return PACKAGE_NAME;
}
const char *
coap_package_version(void) {
return PACKAGE_STRING;
}
const char *
coap_package_build(void) {
#ifdef LIBCOAP_PACKAGE_BUILD
return LIBCOAP_PACKAGE_BUILD;
#else /* !LIBCOAP_PACKAGE_BUILD */
return PACKAGE_STRING;
#endif /* !LIBCOAP_PACKAGE_BUILD */
}
void
coap_set_show_pdu_output(int use_fprintf) {
use_fprintf_for_show_pdu = use_fprintf;
}
coap_log_t
coap_get_log_level(void) {
return maxlog;
}
void
coap_set_log_level(coap_log_t level) {
if (level > COAP_MAX_LOGGING_LEVEL)
level = COAP_MAX_LOGGING_LEVEL;
maxlog = level;
}
/* this array has the same order as the type coap_log_t with the (D)TLS
entries added to the list with a COAP_LOG_DTLS_BASE offset */
static const char *loglevels[] = {
/* General logging */
"EMRG", "ALRT", "CRIT", "ERR ", "WARN", "NOTE", "INFO", "DEBG", "OSC ",
/* (D)TLS logging */
"Emrg", "Alrt", "Crit", "Err ", "Warn", "Note", "Info", "Debg"
};
#ifdef WITH_CONTIKI
void
coap_print_contiki_prefix(coap_log_t level) {
printf("[%s: COAP ] ", loglevels[level]);
}
#endif /* WITH_CONTIKI */
#ifdef HAVE_TIME_H
COAP_STATIC_INLINE size_t
print_timestamp(char *s, size_t len, coap_tick_t t) {
struct tm *tmp;
size_t lensofar;
time_t now = coap_ticks_to_rt(t);
tmp = localtime(&now);
lensofar = strftime(s, len, "%b %d %H:%M:%S", tmp);
if (len > lensofar + 4) {
lensofar += snprintf(&s[lensofar], len-lensofar, ".%03u",
(unsigned int)((coap_ticks_to_rt_us(t) % 1000000)/1000));
}
return lensofar;
}
#else /* alternative implementation: just print the timestamp */
COAP_STATIC_INLINE size_t
print_timestamp(char *s, size_t len, coap_tick_t t) {
#ifdef HAVE_SNPRINTF
return snprintf(s, len, "%u.%03u",
(unsigned int)coap_ticks_to_rt(t),
(unsigned int)((coap_ticks_to_rt_us(t) % 1000000)/1000));
#else /* HAVE_SNPRINTF */
/* @todo do manual conversion of timestamp */
return 0;
#endif /* HAVE_SNPRINTF */
}
#endif /* HAVE_TIME_H */
#if !defined(HAVE_STRNLEN) && !defined(__MINGW32__)
static inline size_t
strnlen(const char *s, size_t maxlen) {
size_t n = 0;
while (*s++ && n < maxlen)
++n;
return n;
}
#endif /* HAVE_STRNLEN && !__MINGW32__ */
static size_t
print_readable(const uint8_t *data, size_t len,
unsigned char *result, size_t buflen, int encode_always) {
const uint8_t hex[] = "0123456789ABCDEF";
size_t cnt = 0;
assert(data || len == 0);
if (buflen == 0) { /* there is nothing we can do here but return */
return 0;
}
while (len) {
if (!encode_always && isprint(*data)) {
if (cnt+1 < buflen) { /* keep one byte for terminating zero */
*result++ = *data;
++cnt;
} else {
break;
}
} else {
if (cnt+4 < buflen) { /* keep one byte for terminating zero */
*result++ = '\\';
*result++ = 'x';
*result++ = hex[(*data & 0xf0) >> 4];
*result++ = hex[*data & 0x0f];
cnt += 4;
} else
break;
}
++data;
--len;
}
*result = '\0'; /* add a terminating zero */
return cnt;
}
#ifndef min
#define min(a,b) ((a) < (b) ? (a) : (b))
#endif
#ifndef INET6_ADDRSTRLEN
#define INET6_ADDRSTRLEN 46
#endif
/*
* Returned buf is always NULL terminated.
* Returned size is number of characters, not including NULL terminator.
*/
size_t
coap_print_addr(const coap_address_t *addr, unsigned char *buf, size_t len) {
#if defined( HAVE_ARPA_INET_H ) || defined( HAVE_WS2TCPIP_H )
char scratch[INET6_ADDRSTRLEN];
assert(buf);
assert(len);
buf[0] = '\000';
switch (addr->addr.sa.sa_family) {
#if COAP_IPV4_SUPPORT
case AF_INET:
snprintf((char *)buf, len, "%s:%d",
coap_print_ip_addr(addr, scratch, sizeof(scratch)),
coap_address_get_port(addr));
break;
#endif /* COAP_IPV4_SUPPORT */
#if COAP_IPV6_SUPPORT
case AF_INET6:
snprintf((char *)buf, len, "[%s]:%d",
coap_print_ip_addr(addr, scratch, sizeof(scratch)),
coap_address_get_port(addr));
break;
#endif /* COAP_IPV6_SUPPORT */
#if COAP_AF_UNIX_SUPPORT
case AF_UNIX:
snprintf((char *)buf, len, "'%s'", addr->addr.cun.sun_path);
break;
#endif /* COAP_AF_UNIX_SUPPORT */
default:
/* Include trailing NULL if possible */
memcpy(buf, "(unknown address type)", min(22+1, len));
buf[len-1] = '\000';
break;
}
return strlen((char *)buf);
#else /* HAVE_ARPA_INET_H */
# if WITH_CONTIKI
char scratch[INET6_ADDRSTRLEN];
#ifdef HAVE_SNPRINTF
snprintf((char *)buf, len, "[%s]:%d",
coap_print_ip_addr(addr, scratch, sizeof(scratch)),
coap_address_get_port(addr));
return strlen((char *)buf);
#else /* HAVE_SNPRINTF */
unsigned char *p = buf;
# if NETSTACK_CONF_WITH_IPV6
assert(buf);
assert(len);
buf[0] = '\000';
if (len < 40 + 2 + 6)
return 0;
*p++ = '[';
memcpy(p, coap_print_ip_addr(addr, scratch, sizeof(scratch)), 40);
p += 40 - 1;
*p++ = ']';
# else /* WITH_UIP6 */
# warning "IPv4 network addresses will not be included in debug output"
if (len < 21) {
*p = '\000';
return 0;
}
# endif /* WITH_UIP6 */
*p++ = ':';
*p++ = '0' + (coap_address_get_port(addr) / 10000) % 10;
*p++ = '0' + (coap_address_get_port(addr) / 1000) % 10;
*p++ = '0' + (coap_address_get_port(addr) / 100) % 10;
*p++ = '0' + (coap_address_get_port(addr) / 10) % 10;
*p++ = '0' + coap_address_get_port(addr) % 10;
*p = '\000';
return strlen((char *)buf);
#endif /* HAVE_SNPRINTF */
# elif WITH_LWIP
char scratch[INET6_ADDRSTRLEN];
#ifdef HAVE_SNPRINTF
snprintf((char *)buf, len, "[%s]:%d",
coap_print_ip_addr(addr, scratch, sizeof(scratch)),
addr->port);
return strlen((char *)buf);
#else /* HAVE_SNPRINTF */
unsigned char *p = buf;
assert(buf);
assert(len);
buf[0] = '\000';
switch (IP_GET_TYPE(addr->addr)) {
case IPADDR_TYPE_V4:
if (len < IP4ADDR_STRLEN_MAX + 6)
return 0;
memcpy(buf, coap_print_ip_addr(addr, scratch, sizeof(scratch)), IP4ADDR_STRLEN_MAX);
p += strlen((char *)buf);
break;
#if LWIP_IPV6
case IPADDR_TYPE_V6:
case IPADDR_TYPE_ANY:
if (len < 40 + 2 + 6)
return 0;
*p++ = '[';
memcpy(p, coap_print_ip_addr(addr, scratch, sizeof(scratch)), 40);
p += strlen((char *)buf);
*p++ = ']';
break;
#endif /* LWIP_IPV6 */
}
*p++ = ':';
*p++ = '0' + (addr->port / 10000) % 10;
*p++ = '0' + (addr->port / 1000) % 10;
*p++ = '0' + (addr->port / 100) % 10;
*p++ = '0' + (addr->port / 10) % 10;
*p++ = '0' + addr->port % 10;
*p = '\000';
return strlen((char *)buf);
#endif /* HAVE_SNPRINTF */
# else /* ! WITH_CONTIKI && ! WITH_LWIP */
(void)addr;
(void)len;
/* TODO: output addresses manually */
# warning "inet_ntop() not available, network addresses will not be included in debug output"
# endif /* ! WITH_CONTIKI && ! WITH_LWIP */
buf[0] = '\000';
return 0;
#endif
}
/*
* Returned buf is always NULL terminated with as much as possible of the
* IP address filled in.
*/
const char *
coap_print_ip_addr(const coap_address_t *addr, char *buf, size_t len) {
#if defined( HAVE_ARPA_INET_H ) || defined( HAVE_WS2TCPIP_H )
const void *addrptr = NULL;
assert(buf);
assert(len);
buf[0] = '\000';
switch (addr->addr.sa.sa_family) {
#if COAP_IPV4_SUPPORT
case AF_INET:
if (len < INET_ADDRSTRLEN)
return buf;
addrptr = &addr->addr.sin.sin_addr;
break;
#endif /* COAP_IPV4_SUPPORT */
#if COAP_IPV6_SUPPORT
case AF_INET6:
if (len < INET6_ADDRSTRLEN)
return buf;
addrptr = &addr->addr.sin6.sin6_addr;
break;
#endif /* COAP_IPV6_SUPPORT */
#if COAP_AF_UNIX_SUPPORT
case AF_UNIX:
snprintf(buf, len, "'%s'", addr->addr.cun.sun_path);
return buf;
#endif /* COAP_AF_UNIX_SUPPORT */
default:
/* Include trailing NULL if possible */
memcpy(buf, "(unknown address type)", min(22+1, len));
buf[len-1] = '\000';
return buf;
}
/* Cast needed for Windows, since it doesn't have the correct API signature. */
if (inet_ntop(addr->addr.sa.sa_family, addrptr, (char *)buf, len) == 0) {
coap_log_err("coap_print_ip_addr: inet_ntop\n");
buf[0] = '\000';
return buf;
}
return buf;
#else /* HAVE_ARPA_INET_H */
# if WITH_CONTIKI
char *p = buf;
uint8_t i;
# if NETSTACK_CONF_WITH_IPV6
const char hex[] = "0123456789ABCDEF";
assert(buf);
assert(len);
buf[0] = '\000';
if (len < 40)
return 0;
for (i=0; i < 16; i += 2) {
if (i) {
*p++ = ':';
}
*p++ = hex[(addr->addr.u8[i] & 0xf0) >> 4];
*p++ = hex[(addr->addr.u8[i] & 0x0f)];
*p++ = hex[(addr->addr.u8[i+1] & 0xf0) >> 4];
*p++ = hex[(addr->addr.u8[i+1] & 0x0f)];
}
*p = '\000';
# else /* WITH_UIP6 */
# warning "IPv4 network addresses will not be included in debug output"
if (len < 21) {
return buf;
}
# endif /* WITH_UIP6 */
return buf;
# elif WITH_LWIP
assert(buf);
assert(len);
buf[0] = '\000';
switch (IP_GET_TYPE(&addr->addr)) {
#if LWIP_IPV4
case IPADDR_TYPE_V4:
if (len < IP4ADDR_STRLEN_MAX)
return buf;
memcpy(buf, ip4addr_ntoa(ip_2_ip4(&addr->addr)), IP4ADDR_STRLEN_MAX);
break;
#endif /* LWIP_IPV4 */
#if LWIP_IPV6
case IPADDR_TYPE_V6:
case IPADDR_TYPE_ANY:
if (len < 40)
return buf;
#if LWIP_IPV4
memcpy(buf, ip6addr_ntoa(&addr->addr.u_addr.ip6), 40);
#else /* LWIP_IPV4 */
memcpy(buf, ip6addr_ntoa(&addr->addr), 40);
#endif /* LWIP_IPV4 */
break;
#endif /* LWIP_IPV6 */
}
return buf;
# else /* ! WITH_CONTIKI && ! WITH_LWIP */
(void)addr;
(void)len;
/* TODO: output addresses manually */
# warning "inet_ntop() not available, network addresses will not be included in debug output"
# endif /* WITH_CONTIKI */
buf[0] = '\000';
return buf;
#endif
}
static const char *
msg_type_string(uint16_t t) {
static const char *types[] = { "CON", "NON", "ACK", "RST", "???" };
return types[min(t, sizeof(types)/sizeof(char *) - 1)];
}
static const char *
msg_code_string(uint16_t c) {
static const char *methods[] = { "0.00", "GET", "POST", "PUT", "DELETE",
"FETCH", "PATCH", "iPATCH"
};
static const char *signals[] = { "7.00", "CSM", "Ping", "Pong", "Release",
"Abort"
};
static char buf[5];
if (c < sizeof(methods)/sizeof(const char *)) {
return methods[c];
} else if (c >= 224 && c - 224 < (int)(sizeof(signals)/sizeof(const char *))) {
return signals[c-224];
} else {
snprintf(buf, sizeof(buf), "%u.%02u", (c >> 5) & 0x7, c & 0x1f);
return buf;
}
}
static const char *
msg_option_string(uint8_t code, uint16_t option_type) {
struct option_desc_t {
uint16_t type;
const char *name;
};
static struct option_desc_t options[] = {
{ COAP_OPTION_IF_MATCH, "If-Match" },
{ COAP_OPTION_URI_HOST, "Uri-Host" },
{ COAP_OPTION_ETAG, "ETag" },
{ COAP_OPTION_IF_NONE_MATCH, "If-None-Match" },
{ COAP_OPTION_OBSERVE, "Observe" },
{ COAP_OPTION_URI_PORT, "Uri-Port" },
{ COAP_OPTION_LOCATION_PATH, "Location-Path" },
{ COAP_OPTION_OSCORE, "Oscore" },
{ COAP_OPTION_URI_PATH, "Uri-Path" },
{ COAP_OPTION_CONTENT_FORMAT, "Content-Format" },
{ COAP_OPTION_MAXAGE, "Max-Age" },
{ COAP_OPTION_URI_QUERY, "Uri-Query" },
{ COAP_OPTION_HOP_LIMIT, "Hop-Limit" },
{ COAP_OPTION_ACCEPT, "Accept" },
{ COAP_OPTION_LOCATION_QUERY, "Location-Query" },
{ COAP_OPTION_BLOCK2, "Block2" },
{ COAP_OPTION_BLOCK1, "Block1" },
{ COAP_OPTION_SIZE2, "Size2" },
{ COAP_OPTION_PROXY_URI, "Proxy-Uri" },
{ COAP_OPTION_PROXY_SCHEME, "Proxy-Scheme" },
{ COAP_OPTION_SIZE1, "Size1" },
{ COAP_OPTION_ECHO, "Echo" },
{ COAP_OPTION_NORESPONSE, "No-Response" },
{ COAP_OPTION_RTAG, "Request-Tag" },
{ COAP_OPTION_Q_BLOCK1, "Q-Block1" },
{ COAP_OPTION_Q_BLOCK2, "Q-Block2" }
};
static struct option_desc_t options_csm[] = {
{ COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE, "Max-Message-Size" },
{ COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER, "Block-Wise-Transfer" },
{ COAP_SIGNALING_OPTION_EXTENDED_TOKEN_LENGTH, "Extended-Token-Length" }
};
static struct option_desc_t options_pingpong[] = {
{ COAP_SIGNALING_OPTION_CUSTODY, "Custody" }
};
static struct option_desc_t options_release[] = {
{ COAP_SIGNALING_OPTION_ALTERNATIVE_ADDRESS, "Alternative-Address" },
{ COAP_SIGNALING_OPTION_HOLD_OFF, "Hold-Off" }
};
static struct option_desc_t options_abort[] = {
{ COAP_SIGNALING_OPTION_BAD_CSM_OPTION, "Bad-CSM-Option" }
};
static char buf[6];
size_t i;
if (code == COAP_SIGNALING_CSM) {
for (i = 0; i < sizeof(options_csm)/sizeof(struct option_desc_t); i++) {
if (option_type == options_csm[i].type) {
return options_csm[i].name;
}
}
} else if (code == COAP_SIGNALING_PING || code == COAP_SIGNALING_PONG) {
for (i = 0; i < sizeof(options_pingpong)/sizeof(struct option_desc_t); i++) {
if (option_type == options_pingpong[i].type) {
return options_pingpong[i].name;
}
}
} else if (code == COAP_SIGNALING_RELEASE) {
for (i = 0; i < sizeof(options_release)/sizeof(struct option_desc_t); i++) {
if (option_type == options_release[i].type) {
return options_release[i].name;
}
}
} else if (code == COAP_SIGNALING_ABORT) {
for (i = 0; i < sizeof(options_abort)/sizeof(struct option_desc_t); i++) {
if (option_type == options_abort[i].type) {
return options_abort[i].name;
}
}
} else {
/* search option_type in list of known options */
for (i = 0; i < sizeof(options)/sizeof(struct option_desc_t); i++) {
if (option_type == options[i].type) {
return options[i].name;
}
}
}
/* unknown option type, just print to buf */
snprintf(buf, sizeof(buf), "%u", option_type);
return buf;
}
static unsigned int
print_content_format(unsigned int format_type,
unsigned char *result, unsigned int buflen) {
struct desc_t {
unsigned int type;
const char *name;
};
static struct desc_t formats[] = {
{ COAP_MEDIATYPE_TEXT_PLAIN, "text/plain" },
{ COAP_MEDIATYPE_APPLICATION_LINK_FORMAT, "application/link-format" },
{ COAP_MEDIATYPE_APPLICATION_XML, "application/xml" },
{ COAP_MEDIATYPE_APPLICATION_OCTET_STREAM, "application/octet-stream" },
{ COAP_MEDIATYPE_APPLICATION_RDF_XML, "application/rdf+xml" },
{ COAP_MEDIATYPE_APPLICATION_EXI, "application/exi" },
{ COAP_MEDIATYPE_APPLICATION_JSON, "application/json" },
{ COAP_MEDIATYPE_APPLICATION_CBOR, "application/cbor" },
{ COAP_MEDIATYPE_APPLICATION_CWT, "application/cwt" },
{ COAP_MEDIATYPE_APPLICATION_COAP_GROUP_JSON, "application/coap-group+json" },
{ COAP_MEDIATYPE_APPLICATION_COSE_SIGN, "application/cose; cose-type=\"cose-sign\"" },
{ COAP_MEDIATYPE_APPLICATION_COSE_SIGN1, "application/cose; cose-type=\"cose-sign1\"" },
{ COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT, "application/cose; cose-type=\"cose-encrypt\"" },
{ COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT0, "application/cose; cose-type=\"cose-encrypt0\"" },
{ COAP_MEDIATYPE_APPLICATION_COSE_MAC, "application/cose; cose-type=\"cose-mac\"" },
{ COAP_MEDIATYPE_APPLICATION_COSE_MAC0, "application/cose; cose-type=\"cose-mac0\"" },
{ COAP_MEDIATYPE_APPLICATION_COSE_KEY, "application/cose-key" },
{ COAP_MEDIATYPE_APPLICATION_COSE_KEY_SET, "application/cose-key-set" },
{ COAP_MEDIATYPE_APPLICATION_SENML_JSON, "application/senml+json" },
{ COAP_MEDIATYPE_APPLICATION_SENSML_JSON, "application/sensml+json" },
{ COAP_MEDIATYPE_APPLICATION_SENML_CBOR, "application/senml+cbor" },
{ COAP_MEDIATYPE_APPLICATION_SENSML_CBOR, "application/sensml+cbor" },
{ COAP_MEDIATYPE_APPLICATION_SENML_EXI, "application/senml-exi" },
{ COAP_MEDIATYPE_APPLICATION_SENSML_EXI, "application/sensml-exi" },
{ COAP_MEDIATYPE_APPLICATION_SENML_XML, "application/senml+xml" },
{ COAP_MEDIATYPE_APPLICATION_SENSML_XML, "application/sensml+xml" },
{ COAP_MEDIATYPE_APPLICATION_DOTS_CBOR, "application/dots+cbor" },
{ COAP_MEDIATYPE_APPLICATION_ACE_CBOR, "application/ace+cbor" },
{ COAP_MEDIATYPE_APPLICATION_MB_CBOR_SEQ, "application/missing-blocks+cbor-seq" },
{ COAP_MEDIATYPE_APPLICATION_OSCORE, "application/oscore" },
{ 75, "application/dcaf+cbor" }
};
size_t i;
/* search format_type in list of known content formats */
for (i = 0; i < sizeof(formats)/sizeof(struct desc_t); i++) {
if (format_type == formats[i].type) {
return snprintf((char *)result, buflen, "%s", formats[i].name);
}
}
/* unknown content format, just print numeric value to buf */
return snprintf((char *)result, buflen, "%d", format_type);
}
COAP_STATIC_INLINE int
is_binary(int content_format) {
return !(content_format == -1 ||
content_format == COAP_MEDIATYPE_TEXT_PLAIN ||
content_format == COAP_MEDIATYPE_APPLICATION_LINK_FORMAT ||
content_format == COAP_MEDIATYPE_APPLICATION_XML ||
content_format == COAP_MEDIATYPE_APPLICATION_JSON);
}
#define COAP_DO_SHOW_OUTPUT_LINE \
do { \
if (use_fprintf_for_show_pdu) { \
fprintf(COAP_DEBUG_FD, "%s", outbuf); \
} \
else { \
coap_log(level, "%s", outbuf); \
} \
} while (0)
/*
* It is possible to override the output debug buffer size and hence control
* the amount of information printed out about a CoAP PDU.
* Note: Adding a byte may be insufficient to output the next byte of the PDU.
*
* This is done by the adding of a -DCOAP_DEBUG_BUF_SIZE=nnnn option to the
* CPPFLAGS parameter that is optionally used on the ./configure command line.
*
* E.g. ./configure CPPFLAGS="-DCOAP_DEBUG_BUF_SIZE=4096"
*
*/
#if COAP_DEBUG_BUF_SIZE < 5
#error "COAP_DEBUG_BUF_SIZE must be at least 5, should be >= 32 to be useful"
#endif /* COAP_DEBUG_BUF_SIZE < 5 */
void
coap_show_pdu(coap_log_t level, const coap_pdu_t *pdu) {
#if COAP_CONSTRAINED_STACK
/* Proxy-Uri: can be 1034 bytes long */
/* buf and outbuf protected by mutex m_show_pdu */
static unsigned char buf[min(COAP_DEBUG_BUF_SIZE, 1035)];
static char outbuf[COAP_DEBUG_BUF_SIZE];
#else /* ! COAP_CONSTRAINED_STACK */
/* Proxy-Uri: can be 1034 bytes long */
unsigned char buf[min(COAP_DEBUG_BUF_SIZE, 1035)];
char outbuf[COAP_DEBUG_BUF_SIZE];
#endif /* ! COAP_CONSTRAINED_STACK */
size_t buf_len = 0; /* takes the number of bytes written to buf */
int encode = 0, have_options = 0;
uint32_t i;
coap_opt_iterator_t opt_iter;
coap_opt_t *option;
int content_format = -1;
size_t data_len;
const uint8_t *data;
uint32_t opt_len;
const uint8_t *opt_val;
size_t outbuflen = 0;
int is_oscore_payload = 0;
/* Save time if not needed */
if (level > coap_get_log_level())
return;
#if COAP_CONSTRAINED_STACK
coap_mutex_lock(&m_show_pdu);
#endif /* COAP_CONSTRAINED_STACK */
if (!pdu->session || COAP_PROTO_NOT_RELIABLE(pdu->session->proto)) {
snprintf(outbuf, sizeof(outbuf), "v:%d t:%s c:%s i:%04x {",
COAP_DEFAULT_VERSION, msg_type_string(pdu->type),
msg_code_string(pdu->code), pdu->mid);
} else if (pdu->session->proto == COAP_PROTO_WS ||
pdu->session->proto == COAP_PROTO_WSS) {
if (pdu->type != COAP_MESSAGE_CON)
coap_log_alert("WebSocket: type != CON\n");
snprintf(outbuf, sizeof(outbuf), "v:WebSocket c:%s {",
msg_code_string(pdu->code));
} else {
if (pdu->type != COAP_MESSAGE_CON)
coap_log_alert("Reliable: type != CON\n");
snprintf(outbuf, sizeof(outbuf), "v:Reliable c:%s {",
msg_code_string(pdu->code));
}
for (i = 0; i < pdu->actual_token.length; i++) {
outbuflen = strlen(outbuf);
snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen,
"%02x", pdu->actual_token.s[i]);
}
outbuflen = strlen(outbuf);
snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "}");
/* show options, if any */
coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL);
outbuflen = strlen(outbuf);
snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, " [");
while ((option = coap_option_next(&opt_iter))) {
buf[0] = '\000';
if (!have_options) {
have_options = 1;
} else {
outbuflen = strlen(outbuf);
snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, ",");
}
if (pdu->code == COAP_SIGNALING_CODE_CSM) {
switch (opt_iter.number) {
case COAP_SIGNALING_OPTION_EXTENDED_TOKEN_LENGTH:
case COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE:
buf_len = snprintf((char *)buf, sizeof(buf), "%u",
coap_decode_var_bytes(coap_opt_value(option),
coap_opt_length(option)));
break;
default:
buf_len = 0;
break;
}
} else if (pdu->code == COAP_SIGNALING_CODE_PING ||
pdu->code == COAP_SIGNALING_CODE_PONG) {
buf_len = 0;
} else if (pdu->code == COAP_SIGNALING_CODE_RELEASE) {
switch (opt_iter.number) {
case COAP_SIGNALING_OPTION_ALTERNATIVE_ADDRESS:
buf_len = print_readable(coap_opt_value(option),
coap_opt_length(option),
buf, sizeof(buf), 0);
break;
case COAP_SIGNALING_OPTION_HOLD_OFF:
buf_len = snprintf((char *)buf, sizeof(buf), "%u",
coap_decode_var_bytes(coap_opt_value(option),
coap_opt_length(option)));
break;
default:
buf_len = 0;
break;
}
} else if (pdu->code == COAP_SIGNALING_CODE_ABORT) {
switch (opt_iter.number) {
case COAP_SIGNALING_OPTION_BAD_CSM_OPTION:
buf_len = snprintf((char *)buf, sizeof(buf), "%u",
coap_decode_var_bytes(coap_opt_value(option),
coap_opt_length(option)));
break;
default:
buf_len = 0;
break;
}
} else {
switch (opt_iter.number) {
case COAP_OPTION_CONTENT_FORMAT:
case COAP_OPTION_ACCEPT:
content_format = (int)coap_decode_var_bytes(coap_opt_value(option),
coap_opt_length(option));
buf_len = print_content_format(content_format, buf, sizeof(buf));
break;
case COAP_OPTION_BLOCK1:
case COAP_OPTION_BLOCK2:
case COAP_OPTION_Q_BLOCK1:
case COAP_OPTION_Q_BLOCK2:
/* split block option into number/more/size where more is the
* letter M if set, the _ otherwise */
if (COAP_OPT_BLOCK_SZX(option) == 7) {
if (coap_get_data(pdu, &data_len, &data))
buf_len = snprintf((char *)buf, sizeof(buf), "%u/%c/BERT(%zu)",
coap_opt_block_num(option), /* block number */
COAP_OPT_BLOCK_MORE(option) ? 'M' : '_', /* M bit */
data_len);
else
buf_len = snprintf((char *)buf, sizeof(buf), "%u/%c/BERT",
coap_opt_block_num(option), /* block number */
COAP_OPT_BLOCK_MORE(option) ? 'M' : '_'); /* M bit */
} else {
buf_len = snprintf((char *)buf, sizeof(buf), "%u/%c/%u",
coap_opt_block_num(option), /* block number */
COAP_OPT_BLOCK_MORE(option) ? 'M' : '_', /* M bit */
(1 << (COAP_OPT_BLOCK_SZX(option) + 4))); /* block size */
}
break;
case COAP_OPTION_OSCORE:
opt_len = coap_opt_length(option);
buf[0] = '\000';
if (opt_len) {
size_t ofs = 1;
size_t cnt;
opt_val = coap_opt_value(option);
if (opt_val[0] & 0x20) {
/* Group Flag */
snprintf((char *)buf, sizeof(buf), "grp");
}
if (opt_val[0] & 0x07) {
/* Partial IV */
cnt = opt_val[0] & 0x07;
if (cnt > opt_len - ofs)
goto no_more;
buf_len = strlen((char *)buf);
snprintf((char *)&buf[buf_len], sizeof(buf)-buf_len, "%spIV=0x",
buf_len ? "," : "");
for (i = 0; (uint32_t)i < cnt; i++) {
buf_len = strlen((char *)buf);
snprintf((char *)&buf[buf_len], sizeof(buf)-buf_len,
"%02x", opt_val[ofs + i]);
}
ofs += cnt;
}
if (opt_val[0] & 0x10) {
/* kid context */
if (ofs >= opt_len)
goto no_more;
cnt = opt_val[ofs];
if (cnt > opt_len - ofs - 1)
goto no_more;
ofs++;
buf_len = strlen((char *)buf);
snprintf((char *)&buf[buf_len], sizeof(buf)-buf_len, "%skc=0x",
buf_len ? "," : "");
for (i = 0; (uint32_t)i < cnt; i++) {
buf_len = strlen((char *)buf);
snprintf((char *)&buf[buf_len], sizeof(buf)-buf_len,
"%02x", opt_val[ofs + i]);
}
ofs += cnt;
}
if (opt_val[0] & 0x08) {
/* kid */
if (ofs >= opt_len)
goto no_more;
cnt = opt_len - ofs;
buf_len = strlen((char *)buf);
snprintf((char *)&buf[buf_len], sizeof(buf)-buf_len, "%skid=0x",
buf_len ? "," : "");
for (i = 0; (uint32_t)i < cnt; i++) {
buf_len = strlen((char *)buf);
snprintf((char *)&buf[buf_len], sizeof(buf)-buf_len,
"%02x", opt_val[ofs + i]);
}
}
}
no_more:
buf_len = strlen((char *)buf);
is_oscore_payload = 1;
break;
case COAP_OPTION_URI_PORT:
case COAP_OPTION_MAXAGE:
case COAP_OPTION_OBSERVE:
case COAP_OPTION_SIZE1:
case COAP_OPTION_SIZE2:
case COAP_OPTION_HOP_LIMIT:
if (coap_opt_length(option)) {
/* show values as unsigned decimal value */
buf_len = snprintf((char *)buf, sizeof(buf), "%u",
coap_decode_var_bytes(coap_opt_value(option),
coap_opt_length(option)));
}
break;
case COAP_OPTION_IF_MATCH:
case COAP_OPTION_ETAG:
case COAP_OPTION_ECHO:
case COAP_OPTION_NORESPONSE:
case COAP_OPTION_RTAG:
opt_len = coap_opt_length(option);
opt_val = coap_opt_value(option);
snprintf((char *)buf, sizeof(buf), "0x");
for (i = 0; (uint32_t)i < opt_len; i++) {
buf_len = strlen((char *)buf);
snprintf((char *)&buf[buf_len], sizeof(buf)-buf_len,
"%02x", opt_val[i]);
}
buf_len = strlen((char *)buf);
break;
default:
/* generic output function for all other option types */
if (opt_iter.number == COAP_OPTION_URI_PATH ||
opt_iter.number == COAP_OPTION_PROXY_URI ||
opt_iter.number == COAP_OPTION_URI_HOST ||
opt_iter.number == COAP_OPTION_LOCATION_PATH ||
opt_iter.number == COAP_OPTION_LOCATION_QUERY ||
opt_iter.number == COAP_OPTION_PROXY_SCHEME ||
opt_iter.number == COAP_OPTION_URI_QUERY) {
encode = 0;
} else {
encode = 1;
}
buf_len = print_readable(coap_opt_value(option),
coap_opt_length(option),
buf, sizeof(buf), encode);
}
}
outbuflen = strlen(outbuf);
snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen,
" %s:%.*s", msg_option_string(pdu->code, opt_iter.number),
(int)buf_len, buf);
}
outbuflen = strlen(outbuf);
snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, " ]");
if (coap_get_data(pdu, &data_len, &data)) {
outbuflen = strlen(outbuf);
snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, " :: ");
if (is_binary(content_format) || !isprint(data[0]) || is_oscore_payload) {
size_t keep_data_len = data_len;
const uint8_t *keep_data = data;
outbuflen = strlen(outbuf);
snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen,
"binary data length %zu\n", data_len);
COAP_DO_SHOW_OUTPUT_LINE;
/*
* Output hex dump of binary data as a continuous entry
*/
outbuf[0] = '\000';
snprintf(outbuf, sizeof(outbuf), "<<");
while (data_len--) {
outbuflen = strlen(outbuf);
snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen,
"%02x", *data++);
}
outbuflen = strlen(outbuf);
snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, ">>");
data_len = keep_data_len;
data = keep_data;
outbuflen = strlen(outbuf);
if (outbuflen == sizeof(outbuf)-1)
outbuflen--;
snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "\n");
COAP_DO_SHOW_OUTPUT_LINE;
/*
* Output ascii readable (if possible), immediately under the
* hex value of the character output above to help binary debugging
*/
outbuf[0] = '\000';
snprintf(outbuf, sizeof(outbuf), "<<");
while (data_len--) {
outbuflen = strlen(outbuf);
snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen,
"%c ", isprint(*data) ? *data : '.');
data++;
}
outbuflen = strlen(outbuf);
snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, ">>");
} else {
size_t max_length;
outbuflen = strlen(outbuf);
max_length = sizeof(outbuf)-outbuflen;
if (max_length > 1) {
outbuf[outbuflen++] = '\'';
outbuf[outbuflen] = '\000';
max_length--;
}
if (max_length > 1) {
outbuflen += print_readable(data, data_len,
(unsigned char *)&outbuf[outbuflen],
max_length, 0);
}
/* print_readable may be handling unprintables - hence headroom of 4 */
if (outbuflen < sizeof(outbuf)-4-1) {
outbuf[outbuflen++] = '\'';
outbuf[outbuflen] = '\000';
}
}
}
outbuflen = strlen(outbuf);
if (outbuflen == sizeof(outbuf)-1)
outbuflen--;
snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "\n");
COAP_DO_SHOW_OUTPUT_LINE;
#if COAP_CONSTRAINED_STACK
coap_mutex_unlock(&m_show_pdu);
#endif /* COAP_CONSTRAINED_STACK */
}
void
coap_show_tls_version(coap_log_t level) {
char buffer[128];
coap_string_tls_version(buffer, sizeof(buffer));
coap_log(level, "%s\n", buffer);
}
char *
coap_string_tls_version(char *buffer, size_t bufsize) {
coap_tls_version_t *tls_version = coap_get_tls_library_version();
char beta[8];
char sub[2];
char b_beta[8];
char b_sub[2];
switch (tls_version->type) {
case COAP_TLS_LIBRARY_NOTLS:
snprintf(buffer, bufsize, "TLS Library: None");
break;
case COAP_TLS_LIBRARY_TINYDTLS:
snprintf(buffer, bufsize, "TLS Library: TinyDTLS - runtime %lu.%lu.%lu, "
"libcoap built for %lu.%lu.%lu",
(unsigned long)(tls_version->version >> 16),
(unsigned long)((tls_version->version >> 8) & 0xff),
(unsigned long)(tls_version->version & 0xff),
(unsigned long)(tls_version->built_version >> 16),
(unsigned long)((tls_version->built_version >> 8) & 0xff),
(unsigned long)(tls_version->built_version & 0xff));
break;
case COAP_TLS_LIBRARY_OPENSSL:
switch (tls_version->version &0xf) {
case 0:
strcpy(beta, "-dev");
break;
case 0xf:
strcpy(beta, "");
break;
default:
strcpy(beta, "-beta");
beta[5] = (tls_version->version &0xf) + '0';
beta[6] = '\000';
break;
}
sub[0] = ((tls_version->version >> 4) & 0xff) ?
((tls_version->version >> 4) & 0xff) + 'a' -1 : '\000';
sub[1] = '\000';
switch (tls_version->built_version &0xf) {
case 0:
strcpy(b_beta, "-dev");
break;
case 0xf:
strcpy(b_beta, "");
break;
default:
strcpy(b_beta, "-beta");
b_beta[5] = (tls_version->built_version &0xf) + '0';
b_beta[6] = '\000';
break;
}
b_sub[0] = ((tls_version->built_version >> 4) & 0xff) ?
((tls_version->built_version >> 4) & 0xff) + 'a' -1 : '\000';
b_sub[1] = '\000';
snprintf(buffer, bufsize, "TLS Library: OpenSSL - runtime "
"%lu.%lu.%lu%s%s, libcoap built for %lu.%lu.%lu%s%s",
(unsigned long)(tls_version->version >> 28),
(unsigned long)((tls_version->version >> 20) & 0xff),
(unsigned long)((tls_version->version >> 12) & 0xff), sub, beta,
(unsigned long)(tls_version->built_version >> 28),
(unsigned long)((tls_version->built_version >> 20) & 0xff),
(unsigned long)((tls_version->built_version >> 12) & 0xff),
b_sub, b_beta);
break;
case COAP_TLS_LIBRARY_GNUTLS:
snprintf(buffer, bufsize, "TLS Library: GnuTLS - runtime %lu.%lu.%lu, "
"libcoap built for %lu.%lu.%lu",
(unsigned long)(tls_version->version >> 16),
(unsigned long)((tls_version->version >> 8) & 0xff),
(unsigned long)(tls_version->version & 0xff),
(unsigned long)(tls_version->built_version >> 16),
(unsigned long)((tls_version->built_version >> 8) & 0xff),
(unsigned long)(tls_version->built_version & 0xff));
break;
case COAP_TLS_LIBRARY_MBEDTLS:
snprintf(buffer, bufsize, "TLS Library: Mbed TLS - runtime %lu.%lu.%lu, "
"libcoap built for %lu.%lu.%lu",
(unsigned long)(tls_version->version >> 24),
(unsigned long)((tls_version->version >> 16) & 0xff),
(unsigned long)((tls_version->version >> 8) & 0xff),
(unsigned long)(tls_version->built_version >> 24),
(unsigned long)((tls_version->built_version >> 16) & 0xff),
(unsigned long)((tls_version->built_version >> 8) & 0xff));
break;
default:
snprintf(buffer, bufsize, "Library type %d unknown", tls_version->type);
break;
}
return buffer;
}
char *
coap_string_tls_support(char *buffer, size_t bufsize) {
const int have_tls = coap_tls_is_supported();
const int have_dtls = coap_dtls_is_supported();
const int have_psk = coap_dtls_psk_is_supported();
const int have_pki = coap_dtls_pki_is_supported();
const int have_pkcs11 = coap_dtls_pkcs11_is_supported();
const int have_rpk = coap_dtls_rpk_is_supported();
const int have_oscore = coap_oscore_is_supported();
const int have_ws = coap_ws_is_supported();
if (have_dtls == 0 && have_tls == 0) {
snprintf(buffer, bufsize, "(No DTLS or TLS support)");
return buffer;
}
snprintf(buffer, bufsize,
"(%sDTLS and %sTLS support; %sPSK, %sPKI, %sPKCS11, and %sRPK support)\n(%sOSCORE)\n(%sWebSockets)",
have_dtls ? "" : "No ",
have_tls ? "" : "no ",
have_psk ? "" : "no ",
have_pki ? "" : "no ",
have_pkcs11 ? "" : "no ",
have_rpk ? "" : "no ",
have_oscore ? "Have " : "No ",
have_ws ? "Have " : "No ");
return buffer;
}
static coap_log_handler_t log_handler = NULL;
void
coap_set_log_handler(coap_log_handler_t handler) {
log_handler = handler;
}
void
coap_log_impl(coap_log_t level, const char *format, ...) {
if (log_handler) {
#if COAP_CONSTRAINED_STACK
/* message protected by mutex m_log_impl */
static char message[COAP_DEBUG_BUF_SIZE];
#else /* ! COAP_CONSTRAINED_STACK */
char message[COAP_DEBUG_BUF_SIZE];
#endif /* ! COAP_CONSTRAINED_STACK */
va_list ap;
va_start(ap, format);
#if COAP_CONSTRAINED_STACK
coap_mutex_lock(&m_log_impl);
#endif /* COAP_CONSTRAINED_STACK */
vsnprintf(message, sizeof(message), format, ap);
va_end(ap);
log_handler(level, message);
#if COAP_CONSTRAINED_STACK
coap_mutex_unlock(&m_log_impl);
#endif /* COAP_CONSTRAINED_STACK */
} else {
char timebuf[32];
coap_tick_t now;
va_list ap;
FILE *log_fd;
size_t len;
log_fd = level <= COAP_LOG_CRIT ? COAP_ERR_FD : COAP_DEBUG_FD;
coap_ticks(&now);
len = print_timestamp(timebuf,sizeof(timebuf), now);
if (len)
fprintf(log_fd, "%.*s ", (int)len, timebuf);
if (level >= sizeof(loglevels)/sizeof(loglevels[0])) {
fprintf(log_fd, "%4d ", level);
} else {
fprintf(log_fd, "%s ", loglevels[level]);
}
va_start(ap, format);
vfprintf(log_fd, format, ap);
va_end(ap);
fflush(log_fd);
}
}
static struct packet_num_interval {
int start;
int end;
} packet_loss_intervals[10];
static int num_packet_loss_intervals = 0;
static int packet_loss_level = 0;
static int send_packet_count = 0;
int
coap_debug_set_packet_loss(const char *loss_level) {
const char *p = loss_level;
char *end = NULL;
int n = (int)strtol(p, &end, 10), i = 0;
if (end == p || n < 0)
return 0;
if (*end == '%') {
if (n > 100)
n = 100;
packet_loss_level = n * 65536 / 100;
coap_log_debug("packet loss level set to %d%%\n", n);
} else {
if (n <= 0)
return 0;
while (i < 10) {
packet_loss_intervals[i].start = n;
if (*end == '-') {
p = end + 1;
n = (int)strtol(p, &end, 10);
if (end == p || n <= 0)
return 0;
}
packet_loss_intervals[i++].end = n;
if (*end == 0)
break;
if (*end != ',')
return 0;
p = end + 1;
n = (int)strtol(p, &end, 10);
if (end == p || n <= 0)
return 0;
}
if (i == 10)
return 0;
num_packet_loss_intervals = i;
}
send_packet_count = 0;
return 1;
}
int
coap_debug_send_packet(void) {
++send_packet_count;
if (num_packet_loss_intervals > 0) {
int i;
for (i = 0; i < num_packet_loss_intervals; i++) {
if (send_packet_count >= packet_loss_intervals[i].start &&
send_packet_count <= packet_loss_intervals[i].end) {
coap_log_debug("Packet %u dropped\n", send_packet_count);
return 0;
}
}
}
if (packet_loss_level > 0) {
uint16_t r = 0;
coap_prng((uint8_t *)&r, 2);
if (r < packet_loss_level) {
coap_log_debug("Packet %u dropped\n", send_packet_count);
return 0;
}
}
return 1;
}
void
coap_debug_reset(void) {
maxlog = COAP_LOG_WARN;
use_fprintf_for_show_pdu = 1;
num_packet_loss_intervals = 0;
packet_loss_level = 0;
send_packet_count = 0;
}
coap_address_get_port
uint16_t coap_address_get_port(const coap_address_t *addr)
Returns the port from addr in host byte order.
Definition coap_address.c:44
packet_loss_level
static int packet_loss_level
Definition coap_debug.c:1240
packet_loss_intervals
static struct packet_num_interval packet_loss_intervals[10]
send_packet_count
static int send_packet_count
Definition coap_debug.c:1241
coap_debug_set_packet_loss
int coap_debug_set_packet_loss(const char *loss_level)
Set the packet loss level for testing.
Definition coap_debug.c:1244
maxlog
static coap_log_t maxlog
Definition coap_debug.c:61
log_handler
static coap_log_handler_t log_handler
Definition coap_debug.c:1179
is_binary
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
msg_code_string
static const char * msg_code_string(uint16_t c)
Returns a textual description of the method or response code.
Definition coap_debug.c:492
COAP_DO_SHOW_OUTPUT_LINE
#define COAP_DO_SHOW_OUTPUT_LINE
Definition coap_debug.c:676
print_readable
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
msg_option_string
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
strnlen
static size_t strnlen(const char *s, size_t maxlen)
A length-safe strlen() fake.
Definition coap_debug.c:160
loglevels
static const char * loglevels[]
Definition coap_debug.c:104
print_timestamp
COAP_STATIC_INLINE size_t print_timestamp(char *s, size_t len, coap_tick_t t)
Definition coap_debug.c:137
min
#define min(a, b)
Definition coap_debug.c:207
msg_type_string
static const char * msg_type_string(uint16_t t)
Returns a textual description of the message type t.
Definition coap_debug.c:484
use_fprintf_for_show_pdu
static int use_fprintf_for_show_pdu
Definition coap_debug.c:64
num_packet_loss_intervals
static int num_packet_loss_intervals
Definition coap_debug.c:1239
coap_debug_send_packet
int coap_debug_send_packet(void)
Check to see whether a packet should be sent or not.
Definition coap_debug.c:1285
coap_debug_reset
void coap_debug_reset(void)
Reset all the defined logging parameters.
Definition coap_debug.c:1309
print_content_format
static unsigned int print_content_format(unsigned int format_type, unsigned char *result, unsigned int buflen)
Definition coap_debug.c:608
INET6_ADDRSTRLEN
#define INET6_ADDRSTRLEN
Definition coap_debug.c:211
coap_internal.h
Pulls together all the internal only header files.
coap_opt_t
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
COAP_OPT_BLOCK_SZX
#define COAP_OPT_BLOCK_SZX(opt)
Returns the value of the SZX-field of a Block option opt.
Definition coap_block.h:92
COAP_OPT_BLOCK_MORE
#define COAP_OPT_BLOCK_MORE(opt)
Returns the value of the More-bit of a Block option opt.
Definition coap_block.h:88
coap_opt_block_num
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
coap_tick_t
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition coap_time.h:144
coap_ticks_to_rt
coap_time_t coap_ticks_to_rt(coap_tick_t t)
Helper function that converts coap ticks to wallclock time.
coap_ticks_to_rt_us
uint64_t coap_ticks_to_rt_us(coap_tick_t t)
Helper function that converts coap ticks to POSIX wallclock time in us.
coap_prng
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
coap_ticks
void coap_ticks(coap_tick_t *)
Returns the current value of an internal tick counter.
coap_get_tls_library_version
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
coap_dtls_psk_is_supported
int coap_dtls_psk_is_supported(void)
Check whether (D)TLS PSK is available.
Definition coap_notls.c:37
coap_tls_is_supported
int coap_tls_is_supported(void)
Check whether TLS is available.
Definition coap_notls.c:28
coap_dtls_is_supported
int coap_dtls_is_supported(void)
Check whether DTLS is available.
Definition coap_notls.c:23
coap_dtls_pki_is_supported
int coap_dtls_pki_is_supported(void)
Check whether (D)TLS PKI is available.
Definition coap_notls.c:46
coap_dtls_rpk_is_supported
int coap_dtls_rpk_is_supported(void)
Check whether (D)TLS RPK is available.
Definition coap_notls.c:64
coap_dtls_pkcs11_is_supported
int coap_dtls_pkcs11_is_supported(void)
Check whether (D)TLS PKCS11 is available.
Definition coap_notls.c:55
COAP_TLS_LIBRARY_GNUTLS
@ COAP_TLS_LIBRARY_GNUTLS
Using GnuTLS library.
Definition coap_dtls.h:96
COAP_TLS_LIBRARY_TINYDTLS
@ COAP_TLS_LIBRARY_TINYDTLS
Using TinyDTLS library.
Definition coap_dtls.h:94
COAP_TLS_LIBRARY_NOTLS
@ COAP_TLS_LIBRARY_NOTLS
No DTLS library.
Definition coap_dtls.h:93
COAP_TLS_LIBRARY_OPENSSL
@ COAP_TLS_LIBRARY_OPENSSL
Using OpenSSL library.
Definition coap_dtls.h:95
COAP_TLS_LIBRARY_MBEDTLS
@ COAP_TLS_LIBRARY_MBEDTLS
Using Mbed TLS library.
Definition coap_dtls.h:97
coap_decode_var_bytes
unsigned int coap_decode_var_bytes(const uint8_t *buf, size_t len)
Decodes multiple-length byte sequences.
Definition coap_encode.c:38
coap_set_log_handler
void coap_set_log_handler(coap_log_handler_t handler)
Add a custom log callback handler.
Definition coap_debug.c:1182
coap_log_debug
#define coap_log_debug(...)
Definition coap_debug.h:120
coap_get_log_level
coap_log_t coap_get_log_level(void)
Get the current logging level.
Definition coap_debug.c:91
coap_string_tls_version
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
coap_log_alert
#define coap_log_alert(...)
Definition coap_debug.h:84
coap_show_pdu
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
coap_string_tls_support
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
COAP_MAX_LOGGING_LEVEL
#define COAP_MAX_LOGGING_LEVEL
Definition coap_debug.h:42
COAP_ERR_FD
#define COAP_ERR_FD
Used for output for COAP_LOG_CRIT to COAP_LOG_EMERG.
Definition coap_debug.h:38
coap_log_t
coap_log_t
Logging type.
Definition coap_debug.h:50
coap_package_version
const char * coap_package_version(void)
Get the library package version.
Definition coap_debug.c:72
coap_set_log_level
void coap_set_log_level(coap_log_t level)
Sets the log level to the specified value.
Definition coap_debug.c:96
coap_log_impl
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
coap_print_addr
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
COAP_DEBUG_FD
#define COAP_DEBUG_FD
Used for output for COAP_LOG_OSCORE to COAP_LOG_ERR.
Definition coap_debug.h:31
coap_package_build
const char * coap_package_build(void)
Get the library package build.
Definition coap_debug.c:77
coap_print_ip_addr
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
coap_show_tls_version
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
coap_set_show_pdu_output
void coap_set_show_pdu_output(int use_fprintf)
Defines the output mode for the coap_show_pdu() function.
Definition coap_debug.c:86
coap_log_err
#define coap_log_err(...)
Definition coap_debug.h:96
coap_package_name
const char * coap_package_name(void)
Get the library package name.
Definition coap_debug.c:67
coap_log_handler_t
void(* coap_log_handler_t)(coap_log_t level, const char *message)
Logging callback handler definition.
Definition coap_debug.h:202
coap_log
#define coap_log(level,...)
Logging function.
Definition coap_debug.h:277
COAP_LOG_INFO
@ COAP_LOG_INFO
Definition coap_debug.h:57
COAP_LOG_EMERG
@ COAP_LOG_EMERG
Definition coap_debug.h:51
COAP_LOG_DEBUG
@ COAP_LOG_DEBUG
Definition coap_debug.h:58
COAP_LOG_CRIT
@ COAP_LOG_CRIT
Definition coap_debug.h:53
COAP_LOG_ERR
@ COAP_LOG_ERR
Definition coap_debug.h:54
COAP_LOG_WARN
@ COAP_LOG_WARN
Definition coap_debug.h:55
coap_option_next
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
coap_opt_length
uint32_t coap_opt_length(const coap_opt_t *opt)
Returns the length of the given option.
Definition coap_option.c:212
coap_option_iterator_init
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
COAP_OPT_ALL
#define COAP_OPT_ALL
Pre-defined filter that includes all options.
Definition coap_option.h:108
coap_opt_value
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
coap_oscore_is_supported
int coap_oscore_is_supported(void)
Check whether OSCORE is available.
Definition coap_oscore.c:2104
COAP_DEFAULT_VERSION
#define COAP_DEFAULT_VERSION
Definition coap_pdu_internal.h:35
COAP_OPTION_HOP_LIMIT
#define COAP_OPTION_HOP_LIMIT
Definition coap_pdu.h:129
COAP_OPTION_NORESPONSE
#define COAP_OPTION_NORESPONSE
Definition coap_pdu.h:141
COAP_OPTION_URI_HOST
#define COAP_OPTION_URI_HOST
Definition coap_pdu.h:116
COAP_OPTION_IF_MATCH
#define COAP_OPTION_IF_MATCH
Definition coap_pdu.h:115
COAP_MEDIATYPE_APPLICATION_COSE_MAC
#define COAP_MEDIATYPE_APPLICATION_COSE_MAC
Definition coap_pdu.h:223
COAP_MEDIATYPE_APPLICATION_SENSML_EXI
#define COAP_MEDIATYPE_APPLICATION_SENSML_EXI
Definition coap_pdu.h:235
COAP_MEDIATYPE_APPLICATION_CWT
#define COAP_MEDIATYPE_APPLICATION_CWT
Definition coap_pdu.h:213
COAP_OPTION_BLOCK2
#define COAP_OPTION_BLOCK2
Definition coap_pdu.h:133
COAP_MEDIATYPE_APPLICATION_MB_CBOR_SEQ
#define COAP_MEDIATYPE_APPLICATION_MB_CBOR_SEQ
Definition coap_pdu.h:246
COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT
#define COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT
Definition coap_pdu.h:221
COAP_MEDIATYPE_APPLICATION_RDF_XML
#define COAP_MEDIATYPE_APPLICATION_RDF_XML
Definition coap_pdu.h:209
COAP_OPTION_CONTENT_FORMAT
#define COAP_OPTION_CONTENT_FORMAT
Definition coap_pdu.h:124
COAP_SIGNALING_OPTION_ALTERNATIVE_ADDRESS
#define COAP_SIGNALING_OPTION_ALTERNATIVE_ADDRESS
Definition coap_pdu.h:197
COAP_OPTION_SIZE2
#define COAP_OPTION_SIZE2
Definition coap_pdu.h:135
COAP_MEDIATYPE_APPLICATION_SENSML_XML
#define COAP_MEDIATYPE_APPLICATION_SENSML_XML
Definition coap_pdu.h:237
COAP_MEDIATYPE_APPLICATION_COSE_SIGN
#define COAP_MEDIATYPE_APPLICATION_COSE_SIGN
Definition coap_pdu.h:219
COAP_OPTION_BLOCK1
#define COAP_OPTION_BLOCK1
Definition coap_pdu.h:134
COAP_OPTION_Q_BLOCK1
#define COAP_OPTION_Q_BLOCK1
Definition coap_pdu.h:131
COAP_OPTION_PROXY_SCHEME
#define COAP_OPTION_PROXY_SCHEME
Definition coap_pdu.h:138
COAP_MEDIATYPE_APPLICATION_COSE_KEY_SET
#define COAP_MEDIATYPE_APPLICATION_COSE_KEY_SET
Definition coap_pdu.h:227
COAP_MEDIATYPE_APPLICATION_OSCORE
#define COAP_MEDIATYPE_APPLICATION_OSCORE
Definition coap_pdu.h:249
COAP_MEDIATYPE_APPLICATION_SENML_CBOR
#define COAP_MEDIATYPE_APPLICATION_SENML_CBOR
Definition coap_pdu.h:232
COAP_OPTION_URI_QUERY
#define COAP_OPTION_URI_QUERY
Definition coap_pdu.h:128
COAP_MEDIATYPE_APPLICATION_COSE_KEY
#define COAP_MEDIATYPE_APPLICATION_COSE_KEY
Definition coap_pdu.h:226
COAP_MEDIATYPE_APPLICATION_COSE_SIGN1
#define COAP_MEDIATYPE_APPLICATION_COSE_SIGN1
Definition coap_pdu.h:220
COAP_OPTION_IF_NONE_MATCH
#define COAP_OPTION_IF_NONE_MATCH
Definition coap_pdu.h:118
COAP_MEDIATYPE_APPLICATION_OCTET_STREAM
#define COAP_MEDIATYPE_APPLICATION_OCTET_STREAM
Definition coap_pdu.h:208
COAP_OPTION_LOCATION_PATH
#define COAP_OPTION_LOCATION_PATH
Definition coap_pdu.h:121
COAP_OPTION_URI_PATH
#define COAP_OPTION_URI_PATH
Definition coap_pdu.h:123
COAP_SIGNALING_OPTION_EXTENDED_TOKEN_LENGTH
#define COAP_SIGNALING_OPTION_EXTENDED_TOKEN_LENGTH
Definition coap_pdu.h:191
COAP_MEDIATYPE_APPLICATION_SENML_EXI
#define COAP_MEDIATYPE_APPLICATION_SENML_EXI
Definition coap_pdu.h:234
COAP_OPTION_OSCORE
#define COAP_OPTION_OSCORE
Definition coap_pdu.h:122
COAP_MEDIATYPE_APPLICATION_CBOR
#define COAP_MEDIATYPE_APPLICATION_CBOR
Definition coap_pdu.h:212
COAP_OPTION_SIZE1
#define COAP_OPTION_SIZE1
Definition coap_pdu.h:139
COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT0
#define COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT0
Definition coap_pdu.h:222
COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER
#define COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER
Definition coap_pdu.h:190
COAP_MEDIATYPE_TEXT_PLAIN
#define COAP_MEDIATYPE_TEXT_PLAIN
Definition coap_pdu.h:205
COAP_MEDIATYPE_APPLICATION_JSON
#define COAP_MEDIATYPE_APPLICATION_JSON
Definition coap_pdu.h:211
COAP_OPTION_LOCATION_QUERY
#define COAP_OPTION_LOCATION_QUERY
Definition coap_pdu.h:132
COAP_MEDIATYPE_APPLICATION_COSE_MAC0
#define COAP_MEDIATYPE_APPLICATION_COSE_MAC0
Definition coap_pdu.h:224
COAP_MEDIATYPE_APPLICATION_ACE_CBOR
#define COAP_MEDIATYPE_APPLICATION_ACE_CBOR
Definition coap_pdu.h:243
COAP_OPTION_Q_BLOCK2
#define COAP_OPTION_Q_BLOCK2
Definition coap_pdu.h:136
COAP_MEDIATYPE_APPLICATION_SENML_JSON
#define COAP_MEDIATYPE_APPLICATION_SENML_JSON
Definition coap_pdu.h:230
COAP_MEDIATYPE_APPLICATION_EXI
#define COAP_MEDIATYPE_APPLICATION_EXI
Definition coap_pdu.h:210
COAP_SIGNALING_OPTION_CUSTODY
#define COAP_SIGNALING_OPTION_CUSTODY
Definition coap_pdu.h:194
coap_get_data
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
COAP_OPTION_RTAG
#define COAP_OPTION_RTAG
Definition coap_pdu.h:142
COAP_MEDIATYPE_APPLICATION_COAP_GROUP_JSON
#define COAP_MEDIATYPE_APPLICATION_COAP_GROUP_JSON
Definition coap_pdu.h:216
COAP_OPTION_URI_PORT
#define COAP_OPTION_URI_PORT
Definition coap_pdu.h:120
COAP_MEDIATYPE_APPLICATION_SENML_XML
#define COAP_MEDIATYPE_APPLICATION_SENML_XML
Definition coap_pdu.h:236
COAP_OPTION_ACCEPT
#define COAP_OPTION_ACCEPT
Definition coap_pdu.h:130
COAP_MEDIATYPE_APPLICATION_DOTS_CBOR
#define COAP_MEDIATYPE_APPLICATION_DOTS_CBOR
Definition coap_pdu.h:240
COAP_OPTION_MAXAGE
#define COAP_OPTION_MAXAGE
Definition coap_pdu.h:127
COAP_OPTION_ETAG
#define COAP_OPTION_ETAG
Definition coap_pdu.h:117
COAP_MEDIATYPE_APPLICATION_SENSML_JSON
#define COAP_MEDIATYPE_APPLICATION_SENSML_JSON
Definition coap_pdu.h:231
COAP_OPTION_PROXY_URI
#define COAP_OPTION_PROXY_URI
Definition coap_pdu.h:137
COAP_OPTION_OBSERVE
#define COAP_OPTION_OBSERVE
Definition coap_pdu.h:119
COAP_SIGNALING_OPTION_HOLD_OFF
#define COAP_SIGNALING_OPTION_HOLD_OFF
Definition coap_pdu.h:198
COAP_OPTION_ECHO
#define COAP_OPTION_ECHO
Definition coap_pdu.h:140
COAP_MEDIATYPE_APPLICATION_LINK_FORMAT
#define COAP_MEDIATYPE_APPLICATION_LINK_FORMAT
Definition coap_pdu.h:206
COAP_SIGNALING_OPTION_BAD_CSM_OPTION
#define COAP_SIGNALING_OPTION_BAD_CSM_OPTION
Definition coap_pdu.h:201
COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE
#define COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE
Definition coap_pdu.h:189
COAP_MEDIATYPE_APPLICATION_XML
#define COAP_MEDIATYPE_APPLICATION_XML
Definition coap_pdu.h:207
COAP_MEDIATYPE_APPLICATION_SENSML_CBOR
#define COAP_MEDIATYPE_APPLICATION_SENSML_CBOR
Definition coap_pdu.h:233
COAP_PROTO_WS
@ COAP_PROTO_WS
Definition coap_pdu.h:310
COAP_PROTO_WSS
@ COAP_PROTO_WSS
Definition coap_pdu.h:311
COAP_SIGNALING_CODE_ABORT
@ COAP_SIGNALING_CODE_ABORT
Definition coap_pdu.h:361
COAP_SIGNALING_CODE_CSM
@ COAP_SIGNALING_CODE_CSM
Definition coap_pdu.h:357
COAP_SIGNALING_CODE_PING
@ COAP_SIGNALING_CODE_PING
Definition coap_pdu.h:358
COAP_SIGNALING_CODE_PONG
@ COAP_SIGNALING_CODE_PONG
Definition coap_pdu.h:359
COAP_SIGNALING_CODE_RELEASE
@ COAP_SIGNALING_CODE_RELEASE
Definition coap_pdu.h:360
COAP_MESSAGE_CON
@ COAP_MESSAGE_CON
Definition coap_pdu.h:65
COAP_SIGNALING_RELEASE
@ COAP_SIGNALING_RELEASE
Definition coap_pdu.h:184
COAP_SIGNALING_CSM
@ COAP_SIGNALING_CSM
Definition coap_pdu.h:181
COAP_SIGNALING_PONG
@ COAP_SIGNALING_PONG
Definition coap_pdu.h:183
COAP_SIGNALING_PING
@ COAP_SIGNALING_PING
Definition coap_pdu.h:182
COAP_SIGNALING_ABORT
@ COAP_SIGNALING_ABORT
Definition coap_pdu.h:185
COAP_PROTO_NOT_RELIABLE
#define COAP_PROTO_NOT_RELIABLE(p)
Definition coap_session.h:36
coap_ws_is_supported
int coap_ws_is_supported(void)
Check whether WebSockets is available.
Definition coap_ws.c:935
COAP_STATIC_INLINE
#define COAP_STATIC_INLINE
Definition libcoap.h:53
coap_address_t
Multi-purpose address abstraction.
Definition coap_address.h:109
coap_address_t::sin
struct sockaddr_in sin
Definition coap_address.h:113
coap_address_t::cun
struct coap_sockaddr_un cun
Definition coap_address.h:115
coap_address_t::sin6
struct sockaddr_in6 sin6
Definition coap_address.h:114
coap_address_t::sa
struct sockaddr sa
Definition coap_address.h:112
coap_address_t::addr
union coap_address_t::@0 addr
coap_bin_const_t::length
size_t length
length of binary data
Definition coap_str.h:65
coap_bin_const_t::s
const uint8_t * s
read-only binary data
Definition coap_str.h:66
coap_opt_iterator_t
Iterator to run through PDU options.
Definition coap_option.h:168
coap_opt_iterator_t::number
coap_option_num_t number
decoded option number
Definition coap_option.h:170
coap_pdu_t
structure for CoAP PDUs
Definition coap_pdu_internal.h:119
coap_pdu_t::code
coap_pdu_code_t code
request method (value 1–31) or response code (value 64-255)
Definition coap_pdu_internal.h:121
coap_pdu_t::actual_token
coap_bin_const_t actual_token
Actual token in pdu.
Definition coap_pdu_internal.h:132
coap_pdu_t::mid
coap_mid_t mid
message id, if any, in regular host byte order
Definition coap_pdu_internal.h:123
coap_pdu_t::session
coap_session_t * session
Session responsible for PDU or NULL.
Definition coap_pdu_internal.h:158
coap_pdu_t::type
coap_pdu_type_t type
message type
Definition coap_pdu_internal.h:120
coap_session_t::proto
coap_proto_t proto
protocol used
Definition coap_session_internal.h:69
coap_sockaddr_un::sun_path
char sun_path[COAP_UNIX_PATH_MAX]
Definition coap_address.h:105
coap_tls_version_t
The structure used for returning the underlying (D)TLS library information.
Definition coap_dtls.h:104
coap_tls_version_t::built_version
uint64_t built_version
(D)TLS Built against Library Version
Definition coap_dtls.h:107
coap_tls_version_t::type
coap_tls_library_t type
Library type.
Definition coap_dtls.h:106
coap_tls_version_t::version
uint64_t version
(D)TLS runtime Library Version
Definition coap_dtls.h:105
packet_num_interval
Definition coap_debug.c:1235
packet_num_interval::start
int start
Definition coap_debug.c:1236
packet_num_interval::end
int end
Definition coap_debug.c:1237