logs.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to
  8. * deal in the Software without restriction, including without limitation the
  9. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  10. * sell copies 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 included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  22. * IN THE SOFTWARE.
  23. */
  24. #include "private-lib-core.h"
  25. #ifdef LWS_HAVE_SYS_TYPES_H
  26. #include <sys/types.h>
  27. #endif
  28. #if defined(LWS_PLAT_OPTEE)
  29. void lwsl_emit_optee(int level, const char *line);
  30. #endif
  31. int log_level = LLL_ERR | LLL_WARN | LLL_NOTICE;
  32. static void (*lwsl_emit)(int level, const char *line)
  33. #ifndef LWS_PLAT_OPTEE
  34. = lwsl_emit_stderr
  35. #else
  36. = lwsl_emit_optee;
  37. #endif
  38. ;
  39. #ifndef LWS_PLAT_OPTEE
  40. static const char * log_level_names ="EWNIDPHXCLUT??";
  41. #endif
  42. #if defined(LWS_LOGS_TIMESTAMP)
  43. int
  44. lwsl_timestamp(int level, char *p, int len)
  45. {
  46. #ifndef LWS_PLAT_OPTEE
  47. time_t o_now;
  48. unsigned long long now;
  49. struct timeval tv;
  50. struct tm *ptm = NULL;
  51. #ifndef WIN32
  52. struct tm tm;
  53. #endif
  54. int n;
  55. gettimeofday(&tv, NULL);
  56. o_now = tv.tv_sec;
  57. now = ((unsigned long long)tv.tv_sec * 10000) + (tv.tv_usec / 100);
  58. #ifndef _WIN32_WCE
  59. #ifdef WIN32
  60. ptm = localtime(&o_now);
  61. #else
  62. if (localtime_r(&o_now, &tm))
  63. ptm = &tm;
  64. #endif
  65. #endif
  66. p[0] = '\0';
  67. for (n = 0; n < LLL_COUNT; n++) {
  68. if (level != (1 << n))
  69. continue;
  70. if (ptm)
  71. n = lws_snprintf(p, len,
  72. "[%04d/%02d/%02d %02d:%02d:%02d:%04d] %c: ",
  73. ptm->tm_year + 1900,
  74. ptm->tm_mon + 1,
  75. ptm->tm_mday,
  76. ptm->tm_hour,
  77. ptm->tm_min,
  78. ptm->tm_sec,
  79. (int)(now % 10000), log_level_names[n]);
  80. else
  81. n = lws_snprintf(p, len, "[%llu:%04d] %c: ",
  82. (unsigned long long) now / 10000,
  83. (int)(now % 10000), log_level_names[n]);
  84. return n;
  85. }
  86. #else
  87. p[0] = '\0';
  88. #endif
  89. return 0;
  90. }
  91. #endif
  92. #ifndef LWS_PLAT_OPTEE
  93. static const char * const colours[] = {
  94. "[31;1m", /* LLL_ERR */
  95. "[36;1m", /* LLL_WARN */
  96. "[35;1m", /* LLL_NOTICE */
  97. "[32;1m", /* LLL_INFO */
  98. "[34;1m", /* LLL_DEBUG */
  99. "[33;1m", /* LLL_PARSER */
  100. "[33m", /* LLL_HEADER */
  101. "[33m", /* LLL_EXT */
  102. "[33m", /* LLL_CLIENT */
  103. "[33;1m", /* LLL_LATENCY */
  104. "[0;1m", /* LLL_USER */
  105. "[31m", /* LLL_THREAD */
  106. };
  107. static char tty;
  108. static void
  109. _lwsl_emit_stderr(int level, const char *line, int ts)
  110. {
  111. char buf[50];
  112. int n, m = LWS_ARRAY_SIZE(colours) - 1;
  113. if (!tty)
  114. tty = isatty(2) | 2;
  115. buf[0] = '\0';
  116. #if defined(LWS_LOGS_TIMESTAMP)
  117. if (ts)
  118. lwsl_timestamp(level, buf, sizeof(buf));
  119. #endif
  120. if (tty == 3) {
  121. n = 1 << (LWS_ARRAY_SIZE(colours) - 1);
  122. while (n) {
  123. if (level & n)
  124. break;
  125. m--;
  126. n >>= 1;
  127. }
  128. fprintf(stderr, "%c%s%s%s%c[0m", 27, colours[m], buf, line, 27);
  129. } else
  130. fprintf(stderr, "%s%s", buf, line);
  131. }
  132. void
  133. lwsl_emit_stderr(int level, const char *line)
  134. {
  135. _lwsl_emit_stderr(level, line, 1);
  136. }
  137. void
  138. lwsl_emit_stderr_notimestamp(int level, const char *line)
  139. {
  140. _lwsl_emit_stderr(level, line, 0);
  141. }
  142. #endif
  143. #if !(defined(LWS_PLAT_OPTEE) && !defined(LWS_WITH_NETWORK))
  144. void _lws_logv(int filter, const char *format, va_list vl)
  145. {
  146. #if LWS_MAX_SMP == 1 && !defined(LWS_WITH_THREADPOOL)
  147. /* this is incompatible with multithreaded logging */
  148. static char buf[256];
  149. #else
  150. char buf[1024];
  151. #endif
  152. int n;
  153. if (!(log_level & filter))
  154. return;
  155. n = vsnprintf(buf, sizeof(buf) - 1, format, vl);
  156. (void)n;
  157. /* vnsprintf returns what it would have written, even if truncated */
  158. if (n > (int)sizeof(buf) - 1) {
  159. n = sizeof(buf) - 5;
  160. buf[n++] = '.';
  161. buf[n++] = '.';
  162. buf[n++] = '.';
  163. buf[n++] = '\n';
  164. buf[n] = '\0';
  165. }
  166. if (n > 0)
  167. buf[n] = '\0';
  168. lwsl_emit(filter, buf);
  169. }
  170. void _lws_log(int filter, const char *format, ...)
  171. {
  172. va_list ap;
  173. va_start(ap, format);
  174. _lws_logv(filter, format, ap);
  175. va_end(ap);
  176. }
  177. #endif
  178. void lws_set_log_level(int level, void (*func)(int level, const char *line))
  179. {
  180. log_level = level;
  181. if (func)
  182. lwsl_emit = func;
  183. }
  184. int lwsl_visible(int level)
  185. {
  186. return log_level & level;
  187. }
  188. void
  189. lwsl_hexdump_level(int hexdump_level, const void *vbuf, size_t len)
  190. {
  191. unsigned char *buf = (unsigned char *)vbuf;
  192. unsigned int n;
  193. if (!lwsl_visible(hexdump_level))
  194. return;
  195. if (!len) {
  196. _lws_log(hexdump_level, "(hexdump: zero length)\n");
  197. return;
  198. }
  199. if (!vbuf) {
  200. _lws_log(hexdump_level, "(hexdump: NULL ptr)\n");
  201. return;
  202. }
  203. _lws_log(hexdump_level, "\n");
  204. for (n = 0; n < len;) {
  205. unsigned int start = n, m;
  206. char line[80], *p = line;
  207. p += lws_snprintf(p, 10, "%04X: ", start);
  208. for (m = 0; m < 16 && n < len; m++)
  209. p += lws_snprintf(p, 5, "%02X ", buf[n++]);
  210. while (m++ < 16)
  211. p += lws_snprintf(p, 5, " ");
  212. p += lws_snprintf(p, 6, " ");
  213. for (m = 0; m < 16 && (start + m) < len; m++) {
  214. if (buf[start + m] >= ' ' && buf[start + m] < 127)
  215. *p++ = buf[start + m];
  216. else
  217. *p++ = '.';
  218. }
  219. while (m++ < 16)
  220. *p++ = ' ';
  221. *p++ = '\n';
  222. *p = '\0';
  223. _lws_log(hexdump_level, "%s", line);
  224. (void)line;
  225. }
  226. _lws_log(hexdump_level, "\n");
  227. }
  228. void
  229. lwsl_hexdump(const void *vbuf, size_t len)
  230. {
  231. #if defined(_DEBUG)
  232. lwsl_hexdump_level(LLL_DEBUG, vbuf, len);
  233. #endif
  234. }