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