Version 0.5.0 of tinydtls

Dependents:   tinydtls_test_cellular tinydtls_test_ethernet tiny-dtls

Revision:
0:ff9ebe0cf0e9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debug.c	Fri Oct 18 13:18:30 2013 +0000
@@ -0,0 +1,392 @@
+/* debug.c -- debug utilities
+ *
+ * Copyright (C) 2011--2012 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "config.h"
+
+#if defined(HAVE_ASSERT_H) && !defined(assert)
+#include <assert.h>
+#endif
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+#include "global.h"
+#include "debug.h"
+
+#ifdef WITH_CONTIKI
+# ifndef DEBUG
+#  define DEBUG DEBUG_PRINT
+# endif /* DEBUG */
+#include "net/uip-debug.h"
+#else
+#define PRINTF(...)
+#endif
+
+static int maxlog = LOG_WARN;	/* default maximum log level */
+
+log_t 
+dtls_get_log_level() {
+  return maxlog;
+}
+
+void
+dtls_set_log_level(log_t level) {
+  maxlog = level;
+}
+
+/* this array has the same order as the type log_t */
+static char *loglevels[] = {
+  "EMRG", "ALRT", "CRIT", "WARN", "NOTE", "INFO", "DEBG" 
+};
+
+#ifdef HAVE_TIME_H
+
+static inline size_t
+print_timestamp(char *s, size_t len, time_t t) {
+  /*
+  struct tm *tmp;
+  tmp = localtime(&t);
+  return strftime(s, len, "%b %d %H:%M:%S", tmp);
+  */
+  return 0;
+}
+
+#else /* alternative implementation: just print the timestamp */
+
+static inline size_t
+print_timestamp(char *s, size_t len, clock_time_t t) {
+#ifdef HAVE_SNPRINTF
+  return snprintf(s, len, "%u.%03u", 
+		  (unsigned int)(t / CLOCK_SECOND), 
+		  (unsigned int)(t % CLOCK_SECOND));
+#else /* HAVE_SNPRINTF */
+  /* @todo do manual conversion of timestamp */
+  return 0;
+#endif /* HAVE_SNPRINTF */
+}
+
+#endif /* HAVE_TIME_H */
+
+#ifndef HAVE_STRNLEN
+/** 
+ * A length-safe strlen() fake. 
+ * 
+ * @param s      The string to count characters != 0.
+ * @param maxlen The maximum length of @p s.
+ * 
+ * @return The length of @p s.
+ */
+static inline size_t
+strnlen(const char *s, size_t maxlen) {
+  size_t n = 0;
+  while(*s++ && n < maxlen)
+    ++n;
+  return n;
+}
+#endif /* HAVE_STRNLEN */
+
+#ifndef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+size_t
+dsrv_print_addr(const session_t *addr, unsigned char *buf, size_t len) {
+   snprintf(buf,len,"%s:%d",inet_ntoa(addr->addr.sin.sin_addr),ntohs(addr->addr.sin.sin_port));
+}
+
+static size_t
+dsrv_print_addr_unused(const session_t *addr, char *buf, size_t len) {
+#ifdef HAVE_ARPA_INET_H
+  const void *addrptr = NULL;
+  in_port_t port;
+  char *p = buf;
+
+  switch (addr->addr.sa.sa_family) {
+  case AF_INET: 
+    if (len < INET_ADDRSTRLEN)
+      return 0;
+  
+    addrptr = &addr->addr.sin.sin_addr;
+    port = ntohs(addr->addr.sin.sin_port);
+    break;
+  case AF_INET6:
+    if (len < INET6_ADDRSTRLEN + 2)
+      return 0;
+
+    *p++ = '[';
+
+    addrptr = &addr->addr.sin6.sin6_addr;
+    port = ntohs(addr->addr.sin6.sin6_port);
+
+    break;
+  default:
+    memcpy(buf, "(unknown address type)", min(22, len));
+    return min(22, len);
+  }
+
+  if (inet_ntop(addr->addr.sa.sa_family, addrptr, p, len) == 0) {
+    perror("dsrv_print_addr");
+    return 0;
+  }
+
+  p += strnlen(p, len);
+
+  if (addr->addr.sa.sa_family == AF_INET6) {
+    if (p < buf + len) {
+      *p++ = ']';
+    } else 
+      return 0;
+  }
+
+  p += snprintf(p, buf + len - p + 1, ":%d", port);
+
+  return p - buf;
+#else /* HAVE_ARPA_INET_H */
+# if WITH_CONTIKI
+  char *p = buf;
+  uint8_t i;
+#  if WITH_UIP6
+  const char hex[] = "0123456789ABCDEF";
+
+  if (len < 41)
+    return 0;
+
+  *p++ = '[';
+
+  for (i=0; i < 8; i += 4) {
+    *p++ = hex[(addr->addr.u16[i] & 0xf000) >> 24];
+    *p++ = hex[(addr->addr.u16[i] & 0x0f00) >> 16];
+    *p++ = hex[(addr->addr.u16[i] & 0x00f0) >> 8];
+    *p++ = hex[(addr->addr.u16[i] & 0x000f)];
+    *p++ = ':';
+  }
+  *(p-1) = ']';
+#  else /* WITH_UIP6 */
+#   warning "IPv4 network addresses will not be included in debug output"
+
+  if (len < 21)
+    return 0;
+#  endif /* WITH_UIP6 */
+  if (buf + len - p < 6)
+    return 0;
+
+#ifdef HAVE_SNPRINTF
+  p += snprintf(p, buf + len - p + 1, ":%d", uip_htons(addr->port));
+#else /* HAVE_SNPRINTF */
+  /* @todo manual conversion of port number */
+#endif /* HAVE_SNPRINTF */
+
+  return p - buf;
+# else /* WITH_CONTIKI */
+  /* TODO: output addresses manually */
+#   warning "inet_ntop() not available, network addresses will not be included in debug output"
+# endif /* WITH_CONTIKI */
+  return 0;
+#endif
+}
+
+#ifndef WITH_CONTIKI
+void 
+dsrv_log(log_t level, char *format, ...) {
+  static char timebuf[32];
+  va_list ap;
+  FILE *log_fd;
+
+  if (maxlog < level)
+    return;
+
+  log_fd = level <= LOG_CRIT ? stderr : stdout;
+
+  if (print_timestamp(timebuf,sizeof(timebuf), time(NULL)))
+    fprintf(log_fd, "%s ", timebuf);
+
+  if (level >= 0 && level <= LOG_DEBUG) 
+    fprintf(log_fd, "%s ", loglevels[level]);
+
+  va_start(ap, format);
+  vfprintf(log_fd, format, ap);
+  va_end(ap);
+  fflush(log_fd);
+}
+#else /* WITH_CONTIKI */
+void 
+dsrv_log(log_t level, char *format, ...) {
+  static char timebuf[32];
+  va_list ap;
+
+  if (maxlog < level)
+    return;
+/*
+  if (print_timestamp(timebuf,sizeof(timebuf), clock_time()))
+    PRINTF("%s ", timebuf);
+*/
+
+  if (level >= 0 && level <= LOG_DEBUG) 
+    PRINTF("%s ", loglevels[level]);
+
+  va_start(ap, format);
+#ifdef HAVE_VPRINTF
+  vprintf(format, ap);
+#else
+  PRINTF(format, ap);
+#endif
+  va_end(ap);
+}
+#endif /* WITH_CONTIKI */
+
+#ifndef NDEBUG
+/** dumps packets in usual hexdump format */
+void hexdump(const unsigned char *packet, int length) {
+  int n = 0;
+
+  while (length--) { 
+    if (n % 16 == 0)
+      printf("%08X ",n);
+
+    printf("%02X ", *packet++);
+    
+    n++;
+    if (n % 8 == 0) {
+      if (n % 16 == 0)
+	printf("\r\n");
+      else
+	printf(" ");
+    }
+  }
+}
+
+/** dump as narrow string of hex digits */
+void dump(unsigned char *buf, size_t len) {
+  while (len--) 
+    printf("%02x", *buf++);
+}
+
+void dtls_dsrv_log_addr(log_t level, const char *name, const session_t *addr)
+{
+  char addrbuf[73];
+  int len;
+
+  len = dsrv_print_addr(addr, addrbuf, sizeof(addrbuf));
+  if (!len)
+    return;
+  printf("%s: %s\r\n", name, addrbuf);
+}
+
+#ifndef WITH_CONTIKI
+void 
+dtls_dsrv_hexdump_log(log_t level, const char *name, const unsigned char *buf, size_t length, int extend) {
+  static char timebuf[32];
+  FILE *log_fd;
+  int n = 0;
+
+  if (maxlog < level)
+    return;
+
+  log_fd = level <= LOG_CRIT ? stderr : stdout;
+/*
+  if (print_timestamp(timebuf, sizeof(timebuf), time(NULL)))
+    fprintf(log_fd, "%s ", timebuf);
+*/
+
+  if (level >= 0 && level <= LOG_DEBUG) 
+    fprintf(log_fd, "%s ", loglevels[level]);
+
+  if (extend) {
+    fprintf(log_fd, "%s: (%zu bytes):\r\n", name, length);
+
+    while (length--) {
+      if (n % 16 == 0)
+	fprintf(log_fd, "%08X ", n);
+
+      fprintf(log_fd, "%02X ", *buf++);
+
+      n++;
+      if (n % 8 == 0) {
+	if (n % 16 == 0)
+	  fprintf(log_fd, "\r\n");
+	else
+	  fprintf(log_fd, " ");
+      }
+    }
+  } else {
+    fprintf(log_fd, "%s: (%zu bytes): ", name, length);
+    while (length--) 
+      fprintf(log_fd, "%02X", *buf++);
+  }
+  fprintf(log_fd, "\r\n");
+
+  fflush(log_fd);
+}
+#else /* WITH_CONTIKI */
+void 
+dtls_dsrv_hexdump_log(log_t level, const char *name, const unsigned char *buf, size_t length, int extend) {
+  static char timebuf[32];
+  int n = 0;
+
+  if (maxlog < level)
+    return;
+/*
+  if (print_timestamp(timebuf,sizeof(timebuf), clock_time()))
+    PRINTF("%s ", timebuf);
+*/
+  if (level >= 0 && level <= LOG_DEBUG) 
+    PRINTF("%s ", loglevels[level]);
+
+  if (extend) {
+    PRINTF("%s: (%zu bytes):\r\n", name, length);
+
+    while (length--) {
+      if (n % 16 == 0)
+	PRINTF("%08X ", n);
+
+      PRINTF("%02X ", *buf++);
+
+      n++;
+      if (n % 8 == 0) {
+	if (n % 16 == 0)
+	  PRINTF("\r\n");
+	else
+	  PRINTF(" ");
+      }
+    }
+  } else {
+    PRINTF("%s: (%zu bytes): ", name, length);
+    while (length--) 
+      PRINTF("%02X", *buf++);
+  }
+  PRINTF("\r\n");
+}
+#endif /* WITH_CONTIKI */
+
+#endif /* NDEBUG */