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