Initial merge-commit of the OIC code. Should successfully do discovery for single...
[platform/upstream/iotivity.git] / csdk / libcoap-4.1.1 / debug.c
1 /* debug.c -- debug utilities
2  *
3  * Copyright (C) 2010--2012 Olaf Bergmann <bergmann@tzi.org>
4  *
5  * This file is part of the CoAP library libcoap. Please see
6  * README for terms of use.
7  */
8
9 #include "config.h"
10
11 #if defined(HAVE_ASSERT_H) && !defined(assert)
12 # include <assert.h>
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
24 #ifdef HAVE_TIME_H
25 #include <time.h>
26 #endif
27
28 #include "debug.h"
29 #include "net.h"
30
31 #ifdef WITH_CONTIKI
32 # ifndef DEBUG
33 #  define DEBUG DEBUG_PRINT
34 # endif /* DEBUG */
35 #include "net/uip-debug.h"
36 #endif
37
38 static coap_log_t maxlog = LOG_WARNING; /* default maximum log level */
39
40 coap_log_t
41 coap_get_log_level() {
42   return maxlog;
43 }
44
45 void
46 coap_set_log_level(coap_log_t level) {
47   maxlog = level;
48 }
49
50 /* this array has the same order as the type log_t */
51 static char *loglevels[] = {
52   "EMRG", "ALRT", "CRIT", "ERR", "WARN", "NOTE", "INFO", "DEBG"
53 };
54
55 #ifdef HAVE_TIME_H
56
57 static inline size_t
58 print_timestamp(char *s, size_t len, coap_tick_t t) {
59   struct tm *tmp;
60   time_t now = clock_offset + (t / COAP_TICKS_PER_SECOND);
61   tmp = localtime(&now);
62   return strftime(s, len, "%b %d %H:%M:%S", tmp);
63 }
64
65 #else /* alternative implementation: just print the timestamp */
66
67 static inline size_t
68 print_timestamp(char *s, size_t len, coap_tick_t t) {
69 #ifdef HAVE_SNPRINTF
70   return snprintf(s, len, "%u.%03u",
71                   (unsigned int)(clock_offset + (t / COAP_TICKS_PER_SECOND)),
72                   (unsigned int)(t % COAP_TICKS_PER_SECOND));
73 #else /* HAVE_SNPRINTF */
74   /* @todo do manual conversion of timestamp */
75   return 0;
76 #endif /* HAVE_SNPRINTF */
77 }
78
79 #endif /* HAVE_TIME_H */
80
81 #ifndef NDEBUG
82
83 #ifndef HAVE_STRNLEN
84 /**
85  * A length-safe strlen() fake.
86  *
87  * @param s      The string to count characters != 0.
88  * @param maxlen The maximum length of @p s.
89  *
90  * @return The length of @p s.
91  */
92 static inline size_t
93 strnlen(const char *s, size_t maxlen) {
94   size_t n = 0;
95   while(*s++ && n < maxlen)
96     ++n;
97   return n;
98 }
99 #endif /* HAVE_STRNLEN */
100
101 unsigned int
102 print_readable( const unsigned char *data, unsigned int len,
103                 unsigned char *result, unsigned int buflen, int encode_always ) {
104   const unsigned char hex[] = "0123456789ABCDEF";
105   unsigned int cnt = 0;
106   assert(data || len == 0);
107
108   if (buflen == 0 || len == 0)
109     return 0;
110
111   while (len) {
112     if (!encode_always && isprint(*data)) {
113       if (cnt == buflen)
114         break;
115       *result++ = *data;
116       ++cnt;
117     } else {
118       if (cnt+4 < buflen) {
119         *result++ = '\\';
120         *result++ = 'x';
121         *result++ = hex[(*data & 0xf0) >> 4];
122         *result++ = hex[*data & 0x0f];
123         cnt += 4;
124       } else
125         break;
126     }
127
128     ++data; --len;
129   }
130
131   *result = '\0';
132   return cnt;
133 }
134
135 #ifndef min
136 #define min(a,b) ((a) < (b) ? (a) : (b))
137 #endif
138
139 size_t
140 coap_print_addr(const struct coap_address_t *addr, unsigned char *buf, size_t len) {
141 TODO(FIX: Fix this)
142     (void)addr;
143     (void)buf;
144     (void)len;
145 #if 0
146 #ifdef HAVE_ARPA_INET_H
147   const void *addrptr = NULL;
148   in_port_t port;
149   unsigned char *p = buf;
150
151   switch (addr->addr.sa.sa_family) {
152   case AF_INET:
153     addrptr = &addr->addr.sin.sin_addr;
154     port = ntohs(addr->addr.sin.sin_port);
155     break;
156   case AF_INET6:
157     if (len < 7) /* do not proceed if buffer is even too short for [::]:0 */
158       return 0;
159
160     *p++ = '[';
161
162     addrptr = &addr->addr.sin6.sin6_addr;
163     port = ntohs(addr->addr.sin6.sin6_port);
164
165     break;
166   default:
167     memcpy(buf, "(unknown address type)", min(22, len));
168     return min(22, len);
169   }
170
171   if (inet_ntop(addr->addr.sa.sa_family, addrptr, (char *)p, len) == 0) {
172     perror("coap_print_addr");
173     return 0;
174   }
175
176   p += strnlen((char *)p, len);
177
178   if (addr->addr.sa.sa_family == AF_INET6) {
179     if (p < buf + len) {
180       *p++ = ']';
181     } else
182       return 0;
183   }
184
185   p += snprintf((char *)p, buf + len - p + 1, ":%d", port);
186
187   return buf + len - p;
188 #else /* HAVE_ARPA_INET_H */
189 # if WITH_CONTIKI
190   unsigned char *p = buf;
191   uint8_t i;
192 #  if WITH_UIP6
193   const unsigned char hex[] = "0123456789ABCDEF";
194
195   if (len < 41)
196     return 0;
197
198   *p++ = '[';
199
200   for (i=0; i < 16; i += 2) {
201     if (i) {
202       *p++ = ':';
203     }
204     *p++ = hex[(addr->addr.u8[i] & 0xf0) >> 4];
205     *p++ = hex[(addr->addr.u8[i] & 0x0f)];
206     *p++ = hex[(addr->addr.u8[i+1] & 0xf0) >> 4];
207     *p++ = hex[(addr->addr.u8[i+1] & 0x0f)];
208   }
209   *p++ = ']';
210 #  else /* WITH_UIP6 */
211 #   warning "IPv4 network addresses will not be included in debug output"
212
213   if (len < 21)
214     return 0;
215 #  endif /* WITH_UIP6 */
216   if (buf + len - p < 6)
217     return 0;
218
219 #ifdef HAVE_SNPRINTF
220   p += snprintf((char *)p, buf + len - p + 1, ":%d", uip_htons(addr->port));
221 #else /* HAVE_SNPRINTF */
222   /* @todo manual conversion of port number */
223 #endif /* HAVE_SNPRINTF */
224
225   return p - buf;
226 # else /* WITH_CONTIKI */
227   /* TODO: output addresses manually */
228 #   warning "inet_ntop() not available, network addresses will not be included in debug output"
229 # endif /* WITH_CONTIKI */
230   return 0;
231 #endif
232 #endif //if 0
233 }
234
235 #ifndef WITH_CONTIKI
236 void
237 coap_show_pdu(const coap_pdu_t *pdu) {
238   unsigned char buf[COAP_MAX_PDU_SIZE]; /* need some space for output creation */
239   int encode = 0, have_options = 0;
240   coap_opt_iterator_t opt_iter;
241   coap_opt_t *option;
242
243   fprintf(COAP_DEBUG_FD, "v:%d t:%d tkl:%d c:%d id:%u",
244           pdu->hdr->version, pdu->hdr->type,
245           pdu->hdr->token_length,
246           pdu->hdr->code, ntohs(pdu->hdr->id));
247
248   /* show options, if any */
249   coap_option_iterator_init((coap_pdu_t *)pdu, &opt_iter, COAP_OPT_ALL);
250
251   while ((option = coap_option_next(&opt_iter))) {
252     if (!have_options) {
253       have_options = 1;
254       fprintf(COAP_DEBUG_FD, " o: [");
255     } else {
256       fprintf(COAP_DEBUG_FD, ",");
257     }
258
259     if (opt_iter.type == COAP_OPTION_URI_PATH ||
260         opt_iter.type == COAP_OPTION_PROXY_URI ||
261         opt_iter.type == COAP_OPTION_URI_HOST ||
262         opt_iter.type == COAP_OPTION_LOCATION_PATH ||
263         opt_iter.type == COAP_OPTION_LOCATION_QUERY ||
264           opt_iter.type == COAP_OPTION_URI_PATH ||
265         opt_iter.type == COAP_OPTION_URI_QUERY) {
266       encode = 0;
267     } else {
268       encode = 1;
269     }
270
271     if (print_readable(COAP_OPT_VALUE(option),
272                        COAP_OPT_LENGTH(option),
273                        buf, sizeof(buf), encode ))
274       fprintf(COAP_DEBUG_FD, " %d:'%s'", opt_iter.type, buf);
275   }
276
277   if (have_options)
278     fprintf(COAP_DEBUG_FD, " ]");
279
280   if (pdu->data) {
281     assert(pdu->data < (unsigned char *)pdu->hdr + pdu->length);
282     print_readable(pdu->data,
283                    (unsigned char *)pdu->hdr + pdu->length - pdu->data,
284                    buf, sizeof(buf), 0 );
285     fprintf(COAP_DEBUG_FD, " d:%s", buf);
286   }
287   fprintf(COAP_DEBUG_FD, "\n");
288   fflush(COAP_DEBUG_FD);
289 }
290
291 #else /* WITH_CONTIKI */
292
293 void
294 coap_show_pdu(const coap_pdu_t *pdu) {
295   unsigned char buf[80]; /* need some space for output creation */
296
297   PRINTF("v:%d t:%d oc:%d c:%d id:%u",
298           pdu->hdr->version, pdu->hdr->type,
299           pdu->hdr->optcnt, pdu->hdr->code, uip_ntohs(pdu->hdr->id));
300
301   /* show options, if any */
302   if (pdu->hdr->optcnt) {
303     coap_opt_iterator_t opt_iter;
304     coap_opt_t *option;
305     coap_option_iterator_init((coap_pdu_t *)pdu, &opt_iter, COAP_OPT_ALL);
306
307     PRINTF(" o:");
308     while ((option = coap_option_next(&opt_iter))) {
309
310       if (print_readable(COAP_OPT_VALUE(option),
311                          COAP_OPT_LENGTH(option),
312                          buf, sizeof(buf), 0))
313         PRINTF(" %d:%s", opt_iter.type, buf);
314     }
315   }
316
317   if (pdu->data < (unsigned char *)pdu->hdr + pdu->length) {
318     print_readable(pdu->data,
319                    (unsigned char *)pdu->hdr + pdu->length - pdu->data,
320                    buf, sizeof(buf), 0 );
321     PRINTF(" d:%s", buf);
322   }
323   PRINTF("\r\n");
324 }
325 #endif /* WITH_CONTIKI */
326
327 #endif /* NDEBUG */
328
329 #ifndef WITH_CONTIKI
330 void
331 coap_log_impl(coap_log_t level, const char *format, ...) {
332   char timebuf[32];
333   coap_tick_t now;
334   va_list ap;
335   FILE *log_fd;
336
337   if (maxlog < level)
338     return;
339
340   log_fd = level <= LOG_CRIT ? COAP_ERR_FD : COAP_DEBUG_FD;
341
342   coap_ticks(&now);
343   if (print_timestamp(timebuf,sizeof(timebuf), now))
344     fprintf(log_fd, "%s ", timebuf);
345
346   if (level <= LOG_DEBUG)
347     fprintf(log_fd, "%s ", loglevels[level]);
348
349   va_start(ap, format);
350   vfprintf(log_fd, format, ap);
351   va_end(ap);
352   fflush(log_fd);
353 }
354 #else /* WITH_CONTIKI */
355 void
356 coap_log_impl(coap_log_t level, const char *format, ...) {
357   char timebuf[32];
358   coap_tick_t now;
359   va_list ap;
360
361   if (maxlog < level)
362     return;
363
364   coap_ticks(&now);
365   if (print_timestamp(timebuf,sizeof(timebuf), now))
366     PRINTF("%s ", timebuf);
367
368   if (level <= LOG_DEBUG)
369     PRINTF("%s ", loglevels[level]);
370
371   va_start(ap, format);
372   PRINTF(format, ap);
373   va_end(ap);
374 }
375 #endif /* WITH_CONTIKI */