Imported Upstream version 1.0.0
[platform/upstream/iotivity.git] / extlibs / tinydtls / debug.c
1 /* debug.c -- debug utilities
2  *
3  * Copyright (C) 2011--2012 Olaf Bergmann <bergmann@tzi.org>
4  *
5  * Permission is hereby granted, free of charge, to any person
6  * obtaining a copy of this software and associated documentation
7  * files (the "Software"), to deal in the Software without
8  * restriction, including without limitation the rights to use, copy,
9  * modify, merge, publish, distribute, sublicense, and/or sell copies
10  * of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  */
25
26 #include "tinydtls.h"
27 #include "dtls_config.h"
28
29 #if defined(HAVE_ASSERT_H) && !defined(assert)
30 #include <assert.h>
31 #endif
32
33 #include <stdarg.h>
34 #include <stdio.h>
35
36 #ifdef HAVE_ARPA_INET_H
37 #include <arpa/inet.h>
38 #endif
39
40 #ifdef HAVE_TIME_H
41 #include <time.h>
42 #endif
43
44 #ifdef __ANDROID__
45 #include <android/log.h>
46 #endif
47
48 #include "global.h"
49 #include "debug.h"
50
51 static int maxlog = DTLS_LOG_WARN;      /* default maximum log level */
52
53 const char *dtls_package_name() {
54   return PACKAGE_NAME;
55 }
56
57 const char *dtls_package_version() {
58   return PACKAGE_VERSION;
59 }
60
61 log_t 
62 dtls_get_log_level() {
63   return maxlog;
64 }
65
66 void
67 dtls_set_log_level(log_t level) {
68   maxlog = level;
69 }
70
71 /* this array has the same order as the type log_t */
72 #ifdef __ANDROID__
73 static android_LogPriority loglevels_android[] = {
74   ANDROID_LOG_FATAL,
75   ANDROID_LOG_ERROR,
76   ANDROID_LOG_ERROR,
77   ANDROID_LOG_WARN,
78   ANDROID_LOG_INFO,
79   ANDROID_LOG_INFO,
80   ANDROID_LOG_DEBUG
81 };
82 #else
83 static char *loglevels[] = {
84   "EMRG", "ALRT", "CRIT", "WARN", "NOTE", "INFO", "DEBG" 
85 };
86 #endif
87
88 #ifdef HAVE_TIME_H
89
90 static inline size_t
91 print_timestamp(char *s, size_t len, time_t t) {
92   struct tm *tmp;
93   tmp = localtime(&t);
94   return strftime(s, len, "%b %d %H:%M:%S", tmp);
95 }
96
97 #else /* alternative implementation: just print the timestamp */
98
99 static inline size_t
100 print_timestamp(char *s, size_t len, clock_time_t t) {
101 #ifdef HAVE_SNPRINTF
102   return snprintf(s, len, "%u.%03u", 
103                   (unsigned int)(t / CLOCK_SECOND), 
104                   (unsigned int)(t % CLOCK_SECOND));
105 #else /* HAVE_SNPRINTF */
106   /* @todo do manual conversion of timestamp */
107   return 0;
108 #endif /* HAVE_SNPRINTF */
109 }
110
111 #endif /* HAVE_TIME_H */
112
113 /** 
114  * A length-safe strlen() fake. 
115  * 
116  * @param s      The string to count characters != 0.
117  * @param maxlen The maximum length of @p s.
118  * 
119  * @return The length of @p s.
120  */
121 static inline size_t
122 dtls_strnlen(const char *s, size_t maxlen) {
123   size_t n = 0;
124   while(*s++ && n < maxlen)
125     ++n;
126   return n;
127 }
128
129 #ifndef min
130 #define min(a,b) ((a) < (b) ? (a) : (b))
131 #endif
132
133 static size_t
134 dsrv_print_addr(const session_t *addr, char *buf, size_t len) {
135 #ifdef HAVE_ARPA_INET_H
136   const void *addrptr = NULL;
137 #ifdef __ANDROID__
138   unsigned short int port;
139 #else
140   in_port_t port;
141 #endif
142   char *p = buf;
143
144   switch (addr->addr.sa.sa_family) {
145   case AF_INET: 
146     if (len < INET_ADDRSTRLEN)
147       return 0;
148   
149     addrptr = &addr->addr.sin.sin_addr;
150     port = ntohs(addr->addr.sin.sin_port);
151     break;
152   case AF_INET6:
153     if (len < INET6_ADDRSTRLEN + 2)
154       return 0;
155
156     *p++ = '[';
157
158     addrptr = &addr->addr.sin6.sin6_addr;
159     port = ntohs(addr->addr.sin6.sin6_port);
160
161     break;
162   default:
163     memcpy(buf, "(unknown address type)", min(22, len));
164     return min(22, len);
165   }
166
167   if (inet_ntop(addr->addr.sa.sa_family, addrptr, p, len) == 0) {
168     perror("dsrv_print_addr");
169     return 0;
170   }
171
172   p += dtls_strnlen(p, len);
173
174   if (addr->addr.sa.sa_family == AF_INET6) {
175     if (p < buf + len) {
176       *p++ = ']';
177     } else 
178       return 0;
179   }
180
181   p += snprintf(p, buf + len - p + 1, ":%d", port);
182
183   return p - buf;
184 #else /* HAVE_ARPA_INET_H */
185 # if WITH_CONTIKI
186   char *p = buf;
187 #  ifdef UIP_CONF_IPV6
188   uint8_t i;
189   const char hex[] = "0123456789ABCDEF";
190
191   if (len < 41)
192     return 0;
193
194   *p++ = '[';
195
196   for (i=0; i < 16; i += 2) {
197     if (i) {
198       *p++ = ':';
199     }
200     *p++ = hex[(addr->addr.u8[i] & 0xf0) >> 4];
201     *p++ = hex[(addr->addr.u8[i] & 0x0f)];
202     *p++ = hex[(addr->addr.u8[i+1] & 0xf0) >> 4];
203     *p++ = hex[(addr->addr.u8[i+1] & 0x0f)];
204   }
205   *p++ = ']';
206 #  else /* UIP_CONF_IPV6 */
207 #   warning "IPv4 network addresses will not be included in debug output"
208
209   if (len < 21)
210     return 0;
211 #  endif /* UIP_CONF_IPV6 */
212   if (buf + len - p < 6)
213     return 0;
214
215   p += sprintf(p, ":%d", uip_htons(addr->port));
216
217   return p - buf;
218 # else /* WITH_CONTIKI */
219   /* TODO: output addresses manually */
220 #   warning "inet_ntop() not available, network addresses will not be included in debug output"
221 # endif /* WITH_CONTIKI */
222   return 0;
223 #endif
224 }
225
226 #ifdef __ANDROID__
227 void
228 dsrv_log(log_t level, char *format, ...) {
229   va_list ap;
230
231   if (maxlog < level)
232     return;
233
234   va_start(ap, format);
235   __android_log_vprint(loglevels_android[level], PACKAGE_NAME, format, ap);
236   va_end(ap);
237 }
238 #elif !defined (WITH_CONTIKI)
239 void 
240 dsrv_log(log_t level, char *format, ...) {
241   static char timebuf[32];
242   va_list ap;
243   FILE *log_fd;
244
245   if (maxlog < level)
246     return;
247
248   log_fd = level <= DTLS_LOG_CRIT ? stderr : stdout;
249
250   if (print_timestamp(timebuf,sizeof(timebuf), time(NULL)))
251     fprintf(log_fd, "%s ", timebuf);
252
253   if (level <= DTLS_LOG_DEBUG) 
254     fprintf(log_fd, "%s ", loglevels[level]);
255
256   va_start(ap, format);
257   vfprintf(log_fd, format, ap);
258   va_end(ap);
259   fflush(log_fd);
260 }
261 #elif defined (HAVE_VPRINTF) /* WITH_CONTIKI */
262 void 
263 dsrv_log(log_t level, char *format, ...) {
264   static char timebuf[32];
265   va_list ap;
266
267   if (maxlog < level)
268     return;
269
270   if (print_timestamp(timebuf,sizeof(timebuf), clock_time()))
271     PRINTF("%s ", timebuf);
272
273   if (level <= DTLS_LOG_DEBUG) 
274     PRINTF("%s ", loglevels[level]);
275
276   va_start(ap, format);
277   vprintf(format, ap);
278   va_end(ap);
279 }
280 #endif /* WITH_CONTIKI */
281
282 #ifndef NDEBUG
283 /** dumps packets in usual hexdump format */
284 void hexdump(const unsigned char *packet, int length) {
285   int n = 0;
286
287   while (length--) { 
288     if (n % 16 == 0)
289       printf("%08X ",n);
290
291     printf("%02X ", *packet++);
292     
293     n++;
294     if (n % 8 == 0) {
295       if (n % 16 == 0)
296         printf("\n");
297       else
298         printf(" ");
299     }
300   }
301 }
302
303 /** dump as narrow string of hex digits */
304 void dump(unsigned char *buf, size_t len) {
305   while (len--) 
306     printf("%02x", *buf++);
307 }
308
309 void dtls_dsrv_log_addr(log_t level, const char *name, const session_t *addr)
310 {
311   char addrbuf[73];
312   int len;
313
314   len = dsrv_print_addr(addr, addrbuf, sizeof(addrbuf));
315   if (!len)
316     return;
317   dsrv_log(level, "%s: %s\n", name, addrbuf);
318 }
319
320 #ifdef __ANDROID__
321 void
322 dtls_dsrv_hexdump_log(log_t level, const char *name, const unsigned char *buf, size_t length, int extend) {
323   char *hex_dump_text;
324   char *p;
325   int ret;
326   int size;
327
328   if (maxlog < level)
329     return;
330
331   size = length * 3 + strlen(name) + 22;
332   hex_dump_text = malloc(size);
333   if (!hex_dump_text)
334     return;
335
336   p = hex_dump_text;
337
338   ret = snprintf(p, size, "%s: (%zu bytes): ", name, length);
339   if (ret >= size)
340     goto print;
341   p += ret;
342   size -= ret;
343   while (length--) {
344     ret = snprintf(p, size, "%02X ", *buf++);
345     if (ret >= size)
346       goto print;
347     p += ret;
348     size -= ret;
349   }
350 print:
351   __android_log_print(loglevels_android[level], PACKAGE_NAME, "%s\n", hex_dump_text);
352   free(hex_dump_text);
353 }
354 #elif !defined (WITH_CONTIKI)
355 void 
356 dtls_dsrv_hexdump_log(log_t level, const char *name, const unsigned char *buf, size_t length, int extend) {
357   static char timebuf[32];
358   FILE *log_fd;
359   int n = 0;
360
361   if (maxlog < level)
362     return;
363
364   log_fd = level <= DTLS_LOG_CRIT ? stderr : stdout;
365
366   if (print_timestamp(timebuf, sizeof(timebuf), time(NULL)))
367     fprintf(log_fd, "%s ", timebuf);
368
369   if (level <= DTLS_LOG_DEBUG) 
370     fprintf(log_fd, "%s ", loglevels[level]);
371
372   if (extend) {
373     fprintf(log_fd, "%s: (%zu bytes):\n", name, length);
374
375     while (length--) {
376       if (n % 16 == 0)
377         fprintf(log_fd, "%08X ", n);
378
379       fprintf(log_fd, "%02X ", *buf++);
380
381       n++;
382       if (n % 8 == 0) {
383         if (n % 16 == 0)
384           fprintf(log_fd, "\n");
385         else
386           fprintf(log_fd, " ");
387       }
388     }
389   } else {
390     fprintf(log_fd, "%s: (%zu bytes): ", name, length);
391     while (length--) 
392       fprintf(log_fd, "%02X", *buf++);
393   }
394   fprintf(log_fd, "\n");
395
396   fflush(log_fd);
397 }
398 #else /* WITH_CONTIKI */
399 void 
400 dtls_dsrv_hexdump_log(log_t level, const char *name, const unsigned char *buf, size_t length, int extend) {
401   static char timebuf[32];
402   int n = 0;
403
404   if (maxlog < level)
405     return;
406
407   if (print_timestamp(timebuf,sizeof(timebuf), clock_time()))
408     PRINTF("%s ", timebuf);
409
410   if (level >= 0 && level <= DTLS_LOG_DEBUG) 
411     PRINTF("%s ", loglevels[level]);
412
413   if (extend) {
414     PRINTF("%s: (%zu bytes):\n", name, length);
415
416     while (length--) {
417       if (n % 16 == 0)
418         PRINTF("%08X ", n);
419
420       PRINTF("%02X ", *buf++);
421
422       n++;
423       if (n % 8 == 0) {
424         if (n % 16 == 0)
425           PRINTF("\n");
426         else
427           PRINTF(" ");
428       }
429     }
430   } else {
431     PRINTF("%s: (%zu bytes): ", name, length);
432     while (length--) 
433       PRINTF("%02X", *buf++);
434   }
435   PRINTF("\n");
436 }
437 #endif /* WITH_CONTIKI */
438
439 #endif /* NDEBUG */