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