BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file BLog.h
3 * @author Ambroz Bizjak <ambrop7@gmail.com>
4 *
5 * @section LICENSE
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * @section DESCRIPTION
30 *
31 * A global object for logging.
32 */
33  
34 #ifndef BADVPN_BLOG_H
35 #define BADVPN_BLOG_H
36  
37 #include <stdarg.h>
38 #include <string.h>
39  
40 #include <misc/debug.h>
41 #include <misc/memref.h>
42 #include <base/BMutex.h>
43  
44 // auto-generated channel numbers and number of channels
45 #include <generated/blog_channels_defines.h>
46  
47 // keep in sync with level names in BLog.c!
48 #define BLOG_ERROR 1
49 #define BLOG_WARNING 2
50 #define BLOG_NOTICE 3
51 #define BLOG_INFO 4
52 #define BLOG_DEBUG 5
53  
54 #define BLog(...) BLog_LogToChannel(BLOG_CURRENT_CHANNEL, __VA_ARGS__)
55 #define BContextLog(context, ...) BLog_ContextLog((context), BLOG_CURRENT_CHANNEL, __VA_ARGS__)
56 #define BLOG_CCCC(context) BLog_MakeChannelContext((context), BLOG_CURRENT_CHANNEL)
57  
58 typedef void (*_BLog_log_func) (int channel, int level, const char *msg);
59 typedef void (*_BLog_free_func) (void);
60  
61 struct _BLog_channel {
62 const char *name;
63 int loglevel;
64 };
65  
66 struct _BLog_global {
67 #ifndef NDEBUG
68 int initialized; // initialized statically
69 #endif
70 struct _BLog_channel channels[BLOG_NUM_CHANNELS];
71 _BLog_log_func log_func;
72 _BLog_free_func free_func;
73 BMutex mutex;
74 #ifndef NDEBUG
75 int logging;
76 #endif
77 char logbuf[2048];
78 int logbuf_pos;
79 };
80  
81 extern struct _BLog_channel blog_channel_list[];
82 extern struct _BLog_global blog_global;
83  
84 typedef void (*BLog_logfunc) (void *);
85  
86 typedef struct {
87 BLog_logfunc logfunc;
88 void *logfunc_user;
89 } BLogContext;
90  
91 typedef struct {
92 BLogContext context;
93 int channel;
94 } BLogChannelContext;
95  
96 static int BLogGlobal_GetChannelByName (const char *channel_name);
97  
98 static void BLog_Init (_BLog_log_func log_func, _BLog_free_func free_func);
99 static void BLog_Free (void);
100 static void BLog_SetChannelLoglevel (int channel, int loglevel);
101 static int BLog_WouldLog (int channel, int level);
102 static void BLog_Begin (void);
103 static void BLog_AppendVarArg (const char *fmt, va_list vl);
104 static void BLog_Append (const char *fmt, ...);
105 static void BLog_AppendBytes (MemRef data);
106 static void BLog_Finish (int channel, int level);
107 static void BLog_LogToChannelVarArg (int channel, int level, const char *fmt, va_list vl);
108 static void BLog_LogToChannel (int channel, int level, const char *fmt, ...);
109 static void BLog_LogViaFuncVarArg (BLog_logfunc func, void *arg, int channel, int level, const char *fmt, va_list vl);
110 static void BLog_LogViaFunc (BLog_logfunc func, void *arg, int channel, int level, const char *fmt, ...);
111 static BLogContext BLog_RootContext (void);
112 static BLogContext BLog_MakeContext (BLog_logfunc logfunc, void *logfunc_user);
113 static void BLog_ContextLogVarArg (BLogContext context, int channel, int level, const char *fmt, va_list vl);
114 static void BLog_ContextLog (BLogContext context, int channel, int level, const char *fmt, ...);
115 static BLogChannelContext BLog_MakeChannelContext (BLogContext context, int channel);
116 static void BLog_ChannelContextLogVarArg (BLogChannelContext ccontext, int level, const char *fmt, va_list vl);
117 static void BLog_ChannelContextLog (BLogChannelContext ccontext, int level, const char *fmt, ...);
118  
119 void BLog_InitStdout (void);
120 void BLog_InitStderr (void);
121  
122 int BLogGlobal_GetChannelByName (const char *channel_name)
123 {
124 int i;
125 for (i = 0; i < BLOG_NUM_CHANNELS; i++) {
126 if (!strcmp(blog_channel_list[i].name, channel_name)) {
127 return i;
128 }
129 }
130  
131 return -1;
132 }
133  
134 void BLog_Init (_BLog_log_func log_func, _BLog_free_func free_func)
135 {
136 ASSERT(!blog_global.initialized)
137  
138 #ifndef NDEBUG
139 blog_global.initialized = 1;
140 #endif
141  
142 // initialize channels
143 memcpy(blog_global.channels, blog_channel_list, BLOG_NUM_CHANNELS * sizeof(struct _BLog_channel));
144  
145 blog_global.log_func = log_func;
146 blog_global.free_func = free_func;
147 #ifndef NDEBUG
148 blog_global.logging = 0;
149 #endif
150 blog_global.logbuf_pos = 0;
151 blog_global.logbuf[0] = '\0';
152  
153 ASSERT_FORCE(BMutex_Init(&blog_global.mutex))
154 }
155  
156 void BLog_Free (void)
157 {
158 ASSERT(blog_global.initialized)
159 #ifndef NDEBUG
160 ASSERT(!blog_global.logging)
161 #endif
162  
163 BMutex_Free(&blog_global.mutex);
164  
165 #ifndef NDEBUG
166 blog_global.initialized = 0;
167 #endif
168  
169 blog_global.free_func();
170 }
171  
172 void BLog_SetChannelLoglevel (int channel, int loglevel)
173 {
174 ASSERT(blog_global.initialized)
175 ASSERT(channel >= 0 && channel < BLOG_NUM_CHANNELS)
176 ASSERT(loglevel >= 0 && loglevel <= BLOG_DEBUG)
177  
178 blog_global.channels[channel].loglevel = loglevel;
179 }
180  
181 int BLog_WouldLog (int channel, int level)
182 {
183 ASSERT(blog_global.initialized)
184 ASSERT(channel >= 0 && channel < BLOG_NUM_CHANNELS)
185 ASSERT(level >= BLOG_ERROR && level <= BLOG_DEBUG)
186  
187 return (level <= blog_global.channels[channel].loglevel);
188 }
189  
190 void BLog_Begin (void)
191 {
192 ASSERT(blog_global.initialized)
193  
194 BMutex_Lock(&blog_global.mutex);
195  
196 #ifndef NDEBUG
197 ASSERT(!blog_global.logging)
198 blog_global.logging = 1;
199 #endif
200 }
201  
202 void BLog_AppendVarArg (const char *fmt, va_list vl)
203 {
204 ASSERT(blog_global.initialized)
205 #ifndef NDEBUG
206 ASSERT(blog_global.logging)
207 #endif
208 ASSERT(blog_global.logbuf_pos >= 0)
209 ASSERT(blog_global.logbuf_pos < sizeof(blog_global.logbuf))
210  
211 int w = vsnprintf(blog_global.logbuf + blog_global.logbuf_pos, sizeof(blog_global.logbuf) - blog_global.logbuf_pos, fmt, vl);
212  
213 if (w >= sizeof(blog_global.logbuf) - blog_global.logbuf_pos) {
214 blog_global.logbuf_pos = sizeof(blog_global.logbuf) - 1;
215 } else {
216 blog_global.logbuf_pos += w;
217 }
218 }
219  
220 void BLog_Append (const char *fmt, ...)
221 {
222 ASSERT(blog_global.initialized)
223 #ifndef NDEBUG
224 ASSERT(blog_global.logging)
225 #endif
226  
227 va_list vl;
228 va_start(vl, fmt);
229 BLog_AppendVarArg(fmt, vl);
230 va_end(vl);
231 }
232  
233 void BLog_AppendBytes (MemRef data)
234 {
235 ASSERT(blog_global.initialized)
236 #ifndef NDEBUG
237 ASSERT(blog_global.logging)
238 #endif
239 ASSERT(blog_global.logbuf_pos >= 0)
240 ASSERT(blog_global.logbuf_pos < sizeof(blog_global.logbuf))
241  
242 size_t avail = (sizeof(blog_global.logbuf) - 1) - blog_global.logbuf_pos;
243 data.len = (data.len > avail ? avail : data.len);
244  
245 memcpy(blog_global.logbuf + blog_global.logbuf_pos, data.ptr, data.len);
246 blog_global.logbuf_pos += data.len;
247 blog_global.logbuf[blog_global.logbuf_pos] = '\0';
248 }
249  
250 void BLog_Finish (int channel, int level)
251 {
252 ASSERT(blog_global.initialized)
253 #ifndef NDEBUG
254 ASSERT(blog_global.logging)
255 #endif
256 ASSERT(channel >= 0 && channel < BLOG_NUM_CHANNELS)
257 ASSERT(level >= BLOG_ERROR && level <= BLOG_DEBUG)
258 ASSERT(BLog_WouldLog(channel, level))
259  
260 ASSERT(blog_global.logbuf_pos >= 0)
261 ASSERT(blog_global.logbuf_pos < sizeof(blog_global.logbuf))
262 ASSERT(blog_global.logbuf[blog_global.logbuf_pos] == '\0')
263  
264 blog_global.log_func(channel, level, blog_global.logbuf);
265  
266 #ifndef NDEBUG
267 blog_global.logging = 0;
268 #endif
269 blog_global.logbuf_pos = 0;
270 blog_global.logbuf[0] = '\0';
271  
272 BMutex_Unlock(&blog_global.mutex);
273 }
274  
275 void BLog_LogToChannelVarArg (int channel, int level, const char *fmt, va_list vl)
276 {
277 ASSERT(blog_global.initialized)
278 ASSERT(channel >= 0 && channel < BLOG_NUM_CHANNELS)
279 ASSERT(level >= BLOG_ERROR && level <= BLOG_DEBUG)
280  
281 if (!BLog_WouldLog(channel, level)) {
282 return;
283 }
284  
285 BLog_Begin();
286 BLog_AppendVarArg(fmt, vl);
287 BLog_Finish(channel, level);
288 }
289  
290 void BLog_LogToChannel (int channel, int level, const char *fmt, ...)
291 {
292 ASSERT(blog_global.initialized)
293 ASSERT(channel >= 0 && channel < BLOG_NUM_CHANNELS)
294 ASSERT(level >= BLOG_ERROR && level <= BLOG_DEBUG)
295  
296 if (!BLog_WouldLog(channel, level)) {
297 return;
298 }
299  
300 va_list vl;
301 va_start(vl, fmt);
302  
303 BLog_Begin();
304 BLog_AppendVarArg(fmt, vl);
305 BLog_Finish(channel, level);
306  
307 va_end(vl);
308 }
309  
310 void BLog_LogViaFuncVarArg (BLog_logfunc func, void *arg, int channel, int level, const char *fmt, va_list vl)
311 {
312 ASSERT(blog_global.initialized)
313 ASSERT(channel >= 0 && channel < BLOG_NUM_CHANNELS)
314 ASSERT(level >= BLOG_ERROR && level <= BLOG_DEBUG)
315  
316 if (!BLog_WouldLog(channel, level)) {
317 return;
318 }
319  
320 BLog_Begin();
321 func(arg);
322 BLog_AppendVarArg(fmt, vl);
323 BLog_Finish(channel, level);
324 }
325  
326 void BLog_LogViaFunc (BLog_logfunc func, void *arg, int channel, int level, const char *fmt, ...)
327 {
328 ASSERT(blog_global.initialized)
329 ASSERT(channel >= 0 && channel < BLOG_NUM_CHANNELS)
330 ASSERT(level >= BLOG_ERROR && level <= BLOG_DEBUG)
331  
332 if (!BLog_WouldLog(channel, level)) {
333 return;
334 }
335  
336 va_list vl;
337 va_start(vl, fmt);
338  
339 BLog_Begin();
340 func(arg);
341 BLog_AppendVarArg(fmt, vl);
342 BLog_Finish(channel, level);
343  
344 va_end(vl);
345 }
346  
347 static void BLog__root_logfunc (void *unused)
348 {
349 }
350  
351 static BLogContext BLog_RootContext (void)
352 {
353 return BLog_MakeContext(BLog__root_logfunc, NULL);
354 }
355  
356 static BLogContext BLog_MakeContext (BLog_logfunc logfunc, void *logfunc_user)
357 {
358 ASSERT(logfunc)
359  
360 BLogContext context;
361 context.logfunc = logfunc;
362 context.logfunc_user = logfunc_user;
363 return context;
364 }
365  
366 static void BLog_ContextLogVarArg (BLogContext context, int channel, int level, const char *fmt, va_list vl)
367 {
368 BLog_LogViaFuncVarArg(context.logfunc, context.logfunc_user, channel, level, fmt, vl);
369 }
370  
371 static void BLog_ContextLog (BLogContext context, int channel, int level, const char *fmt, ...)
372 {
373 va_list vl;
374 va_start(vl, fmt);
375 BLog_ContextLogVarArg(context, channel, level, fmt, vl);
376 va_end(vl);
377 }
378  
379 static BLogChannelContext BLog_MakeChannelContext (BLogContext context, int channel)
380 {
381 BLogChannelContext ccontext;
382 ccontext.context = context;
383 ccontext.channel = channel;
384 return ccontext;
385 }
386  
387 static void BLog_ChannelContextLogVarArg (BLogChannelContext ccontext, int level, const char *fmt, va_list vl)
388 {
389 BLog_ContextLogVarArg(ccontext.context, ccontext.channel, level, fmt, vl);
390 }
391  
392 static void BLog_ChannelContextLog (BLogChannelContext ccontext, int level, const char *fmt, ...)
393 {
394 va_list vl;
395 va_start(vl, fmt);
396 BLog_ChannelContextLogVarArg(ccontext, level, fmt, vl);
397 va_end(vl);
398 }
399  
400 #endif