1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
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
25 /** \defgroup log Logging
26 *
27 * ##Logging
28 *
29 * Lws provides flexible and filterable logging facilities, which can be
30 * used inside lws and in user code.
31 *
32 * Log categories may be individually filtered bitwise, and directed to built-in
33 * sinks for syslog-compatible logging, or a user-defined function.
34 */
35 ///@{
36
37 #define LLL_ERR (1 << 0)
38 #define LLL_WARN (1 << 1)
39 #define LLL_NOTICE (1 << 2)
40 #define LLL_INFO (1 << 3)
41 #define LLL_DEBUG (1 << 4)
42 #define LLL_PARSER (1 << 5)
43 #define LLL_HEADER (1 << 6)
44 #define LLL_EXT (1 << 7)
45 #define LLL_CLIENT (1 << 8)
46 #define LLL_LATENCY (1 << 9)
47 #define LLL_USER (1 << 10)
48 #define LLL_THREAD (1 << 11)
49
50 #define LLL_COUNT (12) /* set to count of valid flags */
51
52 /**
53 * lwsl_timestamp: generate logging timestamp string
54 *
55 * \param level: logging level
56 * \param p: char * buffer to take timestamp
57 * \param len: length of p
58 *
59 * returns length written in p
60 */
61 LWS_VISIBLE LWS_EXTERN int
62 lwsl_timestamp(int level, char *p, int len);
63
64 #if defined(LWS_PLAT_OPTEE) && !defined(LWS_WITH_NETWORK)
65 #define _lws_log(aaa, ...) SMSG(__VA_ARGS__)
66 #else
67 LWS_VISIBLE LWS_EXTERN void _lws_log(int filter, const char *format, ...) LWS_FORMAT(2);
68 LWS_VISIBLE LWS_EXTERN void _lws_logv(int filter, const char *format, va_list vl);
69 #endif
70
71 /*
72 * Figure out which logs to build in or not
73 */
74
75 #if defined(_DEBUG)
76 /*
77 * In DEBUG build, select all logs unless NO_LOGS
78 */
79 #if defined(LWS_WITH_NO_LOGS)
80 #define _LWS_LINIT (LLL_ERR | LLL_USER)
81 #else
82 #define _LWS_LINIT ((1 << LLL_COUNT) - 1)
83 #endif
84 #else /* not _DEBUG */
85 #define _LWS_LINIT (LLL_ERR | LLL_USER | LLL_WARN | LLL_NOTICE)
86 #endif /* _DEBUG */
87
88 /*
89 * Create either empty overrides or the ones forced at build-time.
90 * These overrides have the final say... any bits set in
91 * LWS_LOGGING_BITFIELD_SET force the build of those logs, any bits
92 * set in LWS_LOGGING_BITFIELD_CLEAR disable the build of those logs.
93 *
94 * If not defined lws decides based on CMAKE_BUILD_TYPE=DEBUG or not
95 */
96
97 #if defined(LWS_LOGGING_BITFIELD_SET)
98 #define _LWS_LBS (LWS_LOGGING_BITFIELD_SET)
99 #else
100 #define _LWS_LBS 0
101 #endif
102
103 #if defined(LWS_LOGGING_BITFIELD_CLEAR)
104 #define _LWS_LBC (LWS_LOGGING_BITFIELD_CLEAR)
105 #else
106 #define _LWS_LBC 0
107 #endif
108
109 /*
110 * Compute the final active logging bitfield for build
111 */
112 #define _LWS_ENABLED_LOGS (((_LWS_LINIT) | (_LWS_LBS)) & ~(_LWS_LBC))
113
114 /*
115 * Individually enable or disable log levels for build
116 * depending on what was computed
117 */
118
119 #if (_LWS_ENABLED_LOGS & LLL_ERR)
120 #define lwsl_err(...) _lws_log(LLL_ERR, __VA_ARGS__)
121 #else
122 #define lwsl_err(...) do {} while(0)
123 #endif
124
125 #if (_LWS_ENABLED_LOGS & LLL_WARN)
126 #define lwsl_warn(...) _lws_log(LLL_WARN, __VA_ARGS__)
127 #else
128 #define lwsl_warn(...) do {} while(0)
129 #endif
130
131 #if (_LWS_ENABLED_LOGS & LLL_NOTICE)
132 #define lwsl_notice(...) _lws_log(LLL_NOTICE, __VA_ARGS__)
133 #else
134 #define lwsl_notice(...) do {} while(0)
135 #endif
136
137 #if (_LWS_ENABLED_LOGS & LLL_INFO)
138 #define lwsl_info(...) _lws_log(LLL_INFO, __VA_ARGS__)
139 #else
140 #define lwsl_info(...) do {} while(0)
141 #endif
142
143 #if (_LWS_ENABLED_LOGS & LLL_DEBUG)
144 #define lwsl_debug(...) _lws_log(LLL_DEBUG, __VA_ARGS__)
145 #else
146 #define lwsl_debug(...) do {} while(0)
147 #endif
148
149 #if (_LWS_ENABLED_LOGS & LLL_PARSER)
150 #define lwsl_parser(...) _lws_log(LLL_PARSER, __VA_ARGS__)
151 #else
152 #define lwsl_parser(...) do {} while(0)
153 #endif
154
155 #if (_LWS_ENABLED_LOGS & LLL_HEADER)
156 #define lwsl_header(...) _lws_log(LLL_HEADER, __VA_ARGS__)
157 #else
158 #define lwsl_header(...) do {} while(0)
159 #endif
160
161 #if (_LWS_ENABLED_LOGS & LLL_EXT)
162 #define lwsl_ext(...) _lws_log(LLL_EXT, __VA_ARGS__)
163 #else
164 #define lwsl_ext(...) do {} while(0)
165 #endif
166
167 #if (_LWS_ENABLED_LOGS & LLL_CLIENT)
168 #define lwsl_client(...) _lws_log(LLL_CLIENT, __VA_ARGS__)
169 #else
170 #define lwsl_client(...) do {} while(0)
171 #endif
172
173 #if (_LWS_ENABLED_LOGS & LLL_LATENCY)
174 #define lwsl_latency(...) _lws_log(LLL_LATENCY, __VA_ARGS__)
175 #else
176 #define lwsl_latency(...) do {} while(0)
177 #endif
178
179 #if (_LWS_ENABLED_LOGS & LLL_THREAD)
180 #define lwsl_thread(...) _lws_log(LLL_THREAD, __VA_ARGS__)
181 #else
182 #define lwsl_thread(...) do {} while(0)
183 #endif
184
185 #if (_LWS_ENABLED_LOGS & LLL_USER)
186 #define lwsl_user(...) _lws_log(LLL_USER, __VA_ARGS__)
187 #else
188 #define lwsl_user(...) do {} while(0)
189 #endif
190
191
192 #define lwsl_hexdump_err(...) lwsl_hexdump_level(LLL_ERR, __VA_ARGS__)
193 #define lwsl_hexdump_warn(...) lwsl_hexdump_level(LLL_WARN, __VA_ARGS__)
194 #define lwsl_hexdump_notice(...) lwsl_hexdump_level(LLL_NOTICE, __VA_ARGS__)
195 #define lwsl_hexdump_info(...) lwsl_hexdump_level(LLL_INFO, __VA_ARGS__)
196 #define lwsl_hexdump_debug(...) lwsl_hexdump_level(LLL_DEBUG, __VA_ARGS__)
197
198 /**
199 * lwsl_hexdump_level() - helper to hexdump a buffer at a selected debug level
200 *
201 * \param level: one of LLL_ constants
202 * \param vbuf: buffer start to dump
203 * \param len: length of buffer to dump
204 *
205 * If \p level is visible, does a nice hexdump -C style dump of \p vbuf for
206 * \p len bytes. This can be extremely convenient while debugging.
207 */
208 LWS_VISIBLE LWS_EXTERN void
209 lwsl_hexdump_level(int level, const void *vbuf, size_t len);
210
211 /**
212 * lwsl_hexdump() - helper to hexdump a buffer (DEBUG builds only)
213 *
214 * \param buf: buffer start to dump
215 * \param len: length of buffer to dump
216 *
217 * Calls through to lwsl_hexdump_level(LLL_DEBUG, ... for compatability.
218 * It's better to use lwsl_hexdump_level(level, ... directly so you can control
219 * the visibility.
220 */
221 LWS_VISIBLE LWS_EXTERN void
222 lwsl_hexdump(const void *buf, size_t len);
223
224 /**
225 * lws_is_be() - returns nonzero if the platform is Big Endian
226 */
lws_is_be(void)227 static LWS_INLINE int lws_is_be(void) {
228 const int probe = ~0xff;
229
230 return *(const char *)&probe;
231 }
232
233 /**
234 * lws_set_log_level() - Set the logging bitfield
235 * \param level: OR together the LLL_ debug contexts you want output from
236 * \param log_emit_function: NULL to leave it as it is, or a user-supplied
237 * function to perform log string emission instead of
238 * the default stderr one.
239 *
240 * log level defaults to "err", "warn" and "notice" contexts enabled and
241 * emission on stderr. If stderr is a tty (according to isatty()) then
242 * the output is coloured according to the log level using ANSI escapes.
243 */
244 LWS_VISIBLE LWS_EXTERN void
245 lws_set_log_level(int level,
246 void (*log_emit_function)(int level, const char *line));
247
248 /**
249 * lwsl_emit_syslog() - helper log emit function writes to system log
250 *
251 * \param level: one of LLL_ log level indexes
252 * \param line: log string
253 *
254 * You use this by passing the function pointer to lws_set_log_level(), to set
255 * it as the log emit function, it is not called directly.
256 */
257 LWS_VISIBLE LWS_EXTERN void
258 lwsl_emit_syslog(int level, const char *line);
259
260 /**
261 * lwsl_emit_stderr() - helper log emit function writes to stderr
262 *
263 * \param level: one of LLL_ log level indexes
264 * \param line: log string
265 *
266 * You use this by passing the function pointer to lws_set_log_level(), to set
267 * it as the log emit function, it is not called directly.
268 *
269 * It prepends a system timestamp like [2018/11/13 07:41:57:3989]
270 *
271 * If stderr is a tty, then ansi colour codes are added.
272 */
273 LWS_VISIBLE LWS_EXTERN void
274 lwsl_emit_stderr(int level, const char *line);
275
276 /**
277 * lwsl_emit_stderr_notimestamp() - helper log emit function writes to stderr
278 *
279 * \param level: one of LLL_ log level indexes
280 * \param line: log string
281 *
282 * You use this by passing the function pointer to lws_set_log_level(), to set
283 * it as the log emit function, it is not called directly.
284 *
285 * If stderr is a tty, then ansi colour codes are added.
286 */
287 LWS_VISIBLE LWS_EXTERN void
288 lwsl_emit_stderr_notimestamp(int level, const char *line);
289
290 /**
291 * lwsl_visible() - returns true if the log level should be printed
292 *
293 * \param level: one of LLL_ log level indexes
294 *
295 * This is useful if you have to do work to generate the log content, you
296 * can skip the work if the log level used to print it is not actually
297 * enabled at runtime.
298 */
299 LWS_VISIBLE LWS_EXTERN int
300 lwsl_visible(int level);
301
302 ///@}
303