~ubuntu-branches/ubuntu/trusty/sflphone/trusty

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/pjlib/src/pj/log.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (4.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20140128182336-jrsv0k9u6cawc068
Tags: 1.3.0-1
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: log.c 3752 2011-09-18 14:38:46Z bennylp $ */
 
2
/* 
 
3
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 
4
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 
19
 */
 
20
#include <pj/types.h>
 
21
#include <pj/log.h>
 
22
#include <pj/string.h>
 
23
#include <pj/os.h>
 
24
#include <pj/compat/stdarg.h>
 
25
 
 
26
#if PJ_LOG_MAX_LEVEL >= 1
 
27
 
 
28
#if 0
 
29
PJ_DEF_DATA(int) pj_log_max_level = PJ_LOG_MAX_LEVEL;
 
30
#else
 
31
static int pj_log_max_level = PJ_LOG_MAX_LEVEL;
 
32
#endif
 
33
 
 
34
static void *g_last_thread;
 
35
 
 
36
#if PJ_HAS_THREADS
 
37
static long thread_suspended_tls_id = -1;
 
38
#  if PJ_LOG_ENABLE_INDENT
 
39
static long thread_indent_tls_id = -1;
 
40
#  endif
 
41
#endif
 
42
 
 
43
#if !PJ_LOG_ENABLE_INDENT || !PJ_HAS_THREADS
 
44
static int log_indent;
 
45
#endif
 
46
 
 
47
static pj_log_func *log_writer = &pj_log_write;
 
48
static unsigned log_decor = PJ_LOG_HAS_TIME | PJ_LOG_HAS_MICRO_SEC |
 
49
                            PJ_LOG_HAS_SENDER | PJ_LOG_HAS_NEWLINE |
 
50
                            PJ_LOG_HAS_SPACE | PJ_LOG_HAS_THREAD_SWC |
 
51
                            PJ_LOG_HAS_INDENT
 
52
#if defined(PJ_WIN32) && PJ_WIN32!=0
 
53
                            | PJ_LOG_HAS_COLOR
 
54
#endif
 
55
                            ;
 
56
 
 
57
static pj_color_t PJ_LOG_COLOR_0 = PJ_TERM_COLOR_BRIGHT | PJ_TERM_COLOR_R;
 
58
static pj_color_t PJ_LOG_COLOR_1 = PJ_TERM_COLOR_BRIGHT | PJ_TERM_COLOR_R;
 
59
static pj_color_t PJ_LOG_COLOR_2 = PJ_TERM_COLOR_BRIGHT | 
 
60
                                   PJ_TERM_COLOR_R | 
 
61
                                   PJ_TERM_COLOR_G;
 
62
static pj_color_t PJ_LOG_COLOR_3 = PJ_TERM_COLOR_BRIGHT | 
 
63
                                   PJ_TERM_COLOR_R | 
 
64
                                   PJ_TERM_COLOR_G | 
 
65
                                   PJ_TERM_COLOR_B;
 
66
static pj_color_t PJ_LOG_COLOR_4 = PJ_TERM_COLOR_R | 
 
67
                                   PJ_TERM_COLOR_G | 
 
68
                                   PJ_TERM_COLOR_B;
 
69
static pj_color_t PJ_LOG_COLOR_5 = PJ_TERM_COLOR_R | 
 
70
                                   PJ_TERM_COLOR_G | 
 
71
                                   PJ_TERM_COLOR_B;
 
72
static pj_color_t PJ_LOG_COLOR_6 = PJ_TERM_COLOR_R | 
 
73
                                   PJ_TERM_COLOR_G | 
 
74
                                   PJ_TERM_COLOR_B;
 
75
/* Default terminal color */
 
76
static pj_color_t PJ_LOG_COLOR_77 = PJ_TERM_COLOR_R | 
 
77
                                    PJ_TERM_COLOR_G | 
 
78
                                    PJ_TERM_COLOR_B;
 
79
 
 
80
#if PJ_LOG_USE_STACK_BUFFER==0
 
81
static char log_buffer[PJ_LOG_MAX_SIZE];
 
82
#endif
 
83
 
 
84
#define LOG_MAX_INDENT          80
 
85
 
 
86
#if PJ_HAS_THREADS
 
87
static void logging_shutdown(void)
 
88
{
 
89
    if (thread_suspended_tls_id != -1) {
 
90
        pj_thread_local_free(thread_suspended_tls_id);
 
91
        thread_suspended_tls_id = -1;
 
92
    }
 
93
#  if PJ_LOG_ENABLE_INDENT
 
94
    if (thread_indent_tls_id != -1) {
 
95
        pj_thread_local_free(thread_indent_tls_id);
 
96
        thread_indent_tls_id = -1;
 
97
    }
 
98
#  endif
 
99
}
 
100
#endif  /* PJ_HAS_THREADS */
 
101
 
 
102
#if PJ_LOG_ENABLE_INDENT && PJ_HAS_THREADS
 
103
static void log_set_indent(int indent)
 
104
{
 
105
    if (indent < 0) indent = 0;
 
106
    pj_thread_local_set(thread_indent_tls_id, (void*)(long)indent);
 
107
}
 
108
 
 
109
static int log_get_raw_indent()
 
110
{
 
111
    return (long)pj_thread_local_get(thread_indent_tls_id);
 
112
}
 
113
 
 
114
#else
 
115
static void log_set_indent(int indent)
 
116
{
 
117
    log_indent = indent;
 
118
    if (log_indent < 0) log_indent = 0;
 
119
}
 
120
 
 
121
static int log_get_raw_indent()
 
122
{
 
123
    return log_indent;
 
124
}
 
125
#endif  /* PJ_LOG_ENABLE_INDENT && PJ_HAS_THREADS */
 
126
 
 
127
static int log_get_indent()
 
128
{
 
129
    int indent = log_get_raw_indent();
 
130
    return indent > LOG_MAX_INDENT ? LOG_MAX_INDENT : indent;
 
131
}
 
132
 
 
133
PJ_DEF(void) pj_log_add_indent(int indent)
 
134
{
 
135
    log_set_indent(log_get_raw_indent() + indent);
 
136
}
 
137
 
 
138
PJ_DEF(void) pj_log_push_indent(void)
 
139
{
 
140
    pj_log_add_indent(PJ_LOG_INDENT_SIZE);
 
141
}
 
142
 
 
143
PJ_DEF(void) pj_log_pop_indent(void)
 
144
{
 
145
    pj_log_add_indent(-PJ_LOG_INDENT_SIZE);
 
146
}
 
147
 
 
148
pj_status_t pj_log_init(void)
 
149
{
 
150
#if PJ_HAS_THREADS
 
151
    if (thread_suspended_tls_id == -1) {
 
152
        pj_status_t status;
 
153
        status = pj_thread_local_alloc(&thread_suspended_tls_id);
 
154
        if (status != PJ_SUCCESS)
 
155
            return status;
 
156
 
 
157
#  if PJ_LOG_ENABLE_INDENT
 
158
        status = pj_thread_local_alloc(&thread_indent_tls_id);
 
159
        if (status != PJ_SUCCESS) {
 
160
            pj_thread_local_free(thread_suspended_tls_id);
 
161
            thread_suspended_tls_id = -1;
 
162
            return status;
 
163
        }
 
164
#  endif
 
165
        pj_atexit(&logging_shutdown);
 
166
    }
 
167
#endif
 
168
    g_last_thread = NULL;
 
169
    return PJ_SUCCESS;
 
170
}
 
171
 
 
172
PJ_DEF(void) pj_log_set_decor(unsigned decor)
 
173
{
 
174
    log_decor = decor;
 
175
}
 
176
 
 
177
PJ_DEF(unsigned) pj_log_get_decor(void)
 
178
{
 
179
    return log_decor;
 
180
}
 
181
 
 
182
PJ_DEF(void) pj_log_set_color(int level, pj_color_t color)
 
183
{
 
184
    switch (level) 
 
185
    {
 
186
        case 0: PJ_LOG_COLOR_0 = color; 
 
187
            break;
 
188
        case 1: PJ_LOG_COLOR_1 = color; 
 
189
            break;
 
190
        case 2: PJ_LOG_COLOR_2 = color; 
 
191
            break;
 
192
        case 3: PJ_LOG_COLOR_3 = color; 
 
193
            break;
 
194
        case 4: PJ_LOG_COLOR_4 = color; 
 
195
            break;
 
196
        case 5: PJ_LOG_COLOR_5 = color; 
 
197
            break;
 
198
        case 6: PJ_LOG_COLOR_6 = color; 
 
199
            break;
 
200
        /* Default terminal color */
 
201
        case 77: PJ_LOG_COLOR_77 = color; 
 
202
            break;
 
203
        default:
 
204
            /* Do nothing */
 
205
            break;
 
206
    }
 
207
}
 
208
 
 
209
PJ_DEF(pj_color_t) pj_log_get_color(int level)
 
210
{
 
211
    switch (level) {
 
212
        case 0:
 
213
            return PJ_LOG_COLOR_0;
 
214
        case 1:
 
215
            return PJ_LOG_COLOR_1;
 
216
        case 2:
 
217
            return PJ_LOG_COLOR_2;
 
218
        case 3:
 
219
            return PJ_LOG_COLOR_3;
 
220
        case 4:
 
221
            return PJ_LOG_COLOR_4;
 
222
        case 5:
 
223
            return PJ_LOG_COLOR_5;
 
224
        case 6:
 
225
            return PJ_LOG_COLOR_6;
 
226
        default:
 
227
            /* Return default terminal color */
 
228
            return PJ_LOG_COLOR_77;
 
229
    }
 
230
}
 
231
 
 
232
PJ_DEF(void) pj_log_set_level(int level)
 
233
{
 
234
    pj_log_max_level = level;
 
235
}
 
236
 
 
237
#if 1
 
238
PJ_DEF(int) pj_log_get_level(void)
 
239
{
 
240
    return pj_log_max_level;
 
241
}
 
242
#endif
 
243
 
 
244
PJ_DEF(void) pj_log_set_log_func( pj_log_func *func )
 
245
{
 
246
    log_writer = func;
 
247
}
 
248
 
 
249
PJ_DEF(pj_log_func*) pj_log_get_log_func(void)
 
250
{
 
251
    return log_writer;
 
252
}
 
253
 
 
254
/* Temporarily suspend logging facility for this thread.
 
255
 * If thread local storage/variable is not used or not initialized, then
 
256
 * we can only suspend the logging globally across all threads. This may
 
257
 * happen e.g. when log function is called before PJLIB is fully initialized
 
258
 * or after PJLIB is shutdown.
 
259
 */
 
260
static void suspend_logging(int *saved_level)
 
261
{
 
262
        /* Save the level regardless, just in case PJLIB is shutdown
 
263
         * between suspend and resume.
 
264
         */
 
265
        *saved_level = pj_log_max_level;
 
266
 
 
267
#if PJ_HAS_THREADS
 
268
    if (thread_suspended_tls_id != -1) 
 
269
    {
 
270
        pj_thread_local_set(thread_suspended_tls_id, (void*)PJ_TRUE);
 
271
    } 
 
272
    else
 
273
#endif
 
274
    {
 
275
        pj_log_max_level = 0;
 
276
    }
 
277
}
 
278
 
 
279
/* Resume logging facility for this thread */
 
280
static void resume_logging(int *saved_level)
 
281
{
 
282
#if PJ_HAS_THREADS
 
283
    if (thread_suspended_tls_id != -1) 
 
284
    {
 
285
        pj_thread_local_set(thread_suspended_tls_id, (void*)PJ_FALSE);
 
286
    }
 
287
    else
 
288
#endif
 
289
    {
 
290
        /* Only revert the level if application doesn't change the
 
291
         * logging level between suspend and resume.
 
292
         */
 
293
        if (pj_log_max_level==0 && *saved_level)
 
294
            pj_log_max_level = *saved_level;
 
295
    }
 
296
}
 
297
 
 
298
/* Is logging facility suspended for this thread? */
 
299
static pj_bool_t is_logging_suspended(void)
 
300
{
 
301
#if PJ_HAS_THREADS
 
302
    if (thread_suspended_tls_id != -1) 
 
303
    {
 
304
        return pj_thread_local_get(thread_suspended_tls_id) != NULL;
 
305
    }
 
306
    else
 
307
#endif
 
308
    {
 
309
        return pj_log_max_level == 0;
 
310
    }
 
311
}
 
312
 
 
313
PJ_DEF(void) pj_log( const char *sender, int level, 
 
314
                     const char *format, va_list marker)
 
315
{
 
316
    pj_time_val now;
 
317
    pj_parsed_time ptime;
 
318
    char *pre;
 
319
#if PJ_LOG_USE_STACK_BUFFER
 
320
    char log_buffer[PJ_LOG_MAX_SIZE];
 
321
#endif
 
322
    int saved_level, len, print_len, indent;
 
323
 
 
324
    PJ_CHECK_STACK();
 
325
 
 
326
    if (level > pj_log_max_level)
 
327
        return;
 
328
 
 
329
    if (is_logging_suspended())
 
330
        return;
 
331
 
 
332
    /* Temporarily disable logging for this thread. Some of PJLIB APIs that
 
333
     * this function calls below will recursively call the logging function 
 
334
     * back, hence it will cause infinite recursive calls if we allow that.
 
335
     */
 
336
    suspend_logging(&saved_level);
 
337
 
 
338
    /* Get current date/time. */
 
339
    pj_gettimeofday(&now);
 
340
    pj_time_decode(&now, &ptime);
 
341
 
 
342
    pre = log_buffer;
 
343
    if (log_decor & PJ_LOG_HAS_LEVEL_TEXT) {
 
344
        static const char *ltexts[] = { "FATAL:", "ERROR:", " WARN:", 
 
345
                              " INFO:", "DEBUG:", "TRACE:", "DETRC:"};
 
346
        pj_ansi_strcpy(pre, ltexts[level]);
 
347
        pre += 6;
 
348
    }
 
349
    if (log_decor & PJ_LOG_HAS_DAY_NAME) {
 
350
        static const char *wdays[] = { "Sun", "Mon", "Tue", "Wed",
 
351
                                       "Thu", "Fri", "Sat"};
 
352
        pj_ansi_strcpy(pre, wdays[ptime.wday]);
 
353
        pre += 3;
 
354
    }
 
355
    if (log_decor & PJ_LOG_HAS_YEAR) {
 
356
        if (pre!=log_buffer) *pre++ = ' ';
 
357
        pre += pj_utoa(ptime.year, pre);
 
358
    }
 
359
    if (log_decor & PJ_LOG_HAS_MONTH) {
 
360
        *pre++ = '-';
 
361
        pre += pj_utoa_pad(ptime.mon+1, pre, 2, '0');
 
362
    }
 
363
    if (log_decor & PJ_LOG_HAS_DAY_OF_MON) {
 
364
        *pre++ = '-';
 
365
        pre += pj_utoa_pad(ptime.day, pre, 2, '0');
 
366
    }
 
367
    if (log_decor & PJ_LOG_HAS_TIME) {
 
368
        if (pre!=log_buffer) *pre++ = ' ';
 
369
        pre += pj_utoa_pad(ptime.hour, pre, 2, '0');
 
370
        *pre++ = ':';
 
371
        pre += pj_utoa_pad(ptime.min, pre, 2, '0');
 
372
        *pre++ = ':';
 
373
        pre += pj_utoa_pad(ptime.sec, pre, 2, '0');
 
374
    }
 
375
    if (log_decor & PJ_LOG_HAS_MICRO_SEC) {
 
376
        *pre++ = '.';
 
377
        pre += pj_utoa_pad(ptime.msec, pre, 3, '0');
 
378
    }
 
379
    if (log_decor & PJ_LOG_HAS_SENDER) {
 
380
        enum { SENDER_WIDTH = 14 };
 
381
        int sender_len = strlen(sender);
 
382
        if (pre!=log_buffer) *pre++ = ' ';
 
383
        if (sender_len <= SENDER_WIDTH) {
 
384
            while (sender_len < SENDER_WIDTH)
 
385
                *pre++ = ' ', ++sender_len;
 
386
            while (*sender)
 
387
                *pre++ = *sender++;
 
388
        } else {
 
389
            int i;
 
390
            for (i=0; i<SENDER_WIDTH; ++i)
 
391
                *pre++ = *sender++;
 
392
        }
 
393
    }
 
394
    if (log_decor & PJ_LOG_HAS_THREAD_ID) {
 
395
        enum { THREAD_WIDTH = 12 };
 
396
        const char *thread_name = pj_thread_get_name(pj_thread_this());
 
397
        int thread_len = strlen(thread_name);
 
398
        *pre++ = ' ';
 
399
        if (thread_len <= THREAD_WIDTH) {
 
400
            while (thread_len < THREAD_WIDTH)
 
401
                *pre++ = ' ', ++thread_len;
 
402
            while (*thread_name)
 
403
                *pre++ = *thread_name++;
 
404
        } else {
 
405
            int i;
 
406
            for (i=0; i<THREAD_WIDTH; ++i)
 
407
                *pre++ = *thread_name++;
 
408
        }
 
409
    }
 
410
 
 
411
    if (log_decor != 0 && log_decor != PJ_LOG_HAS_NEWLINE)
 
412
        *pre++ = ' ';
 
413
 
 
414
    if (log_decor & PJ_LOG_HAS_THREAD_SWC) {
 
415
        void *current_thread = (void*)pj_thread_this();
 
416
        if (current_thread != g_last_thread) {
 
417
            *pre++ = '!';
 
418
            g_last_thread = current_thread;
 
419
        } else {
 
420
            *pre++ = ' ';
 
421
        }
 
422
    } else if (log_decor & PJ_LOG_HAS_SPACE) {
 
423
        *pre++ = ' ';
 
424
    }
 
425
 
 
426
#if PJ_LOG_ENABLE_INDENT
 
427
    if (log_decor & PJ_LOG_HAS_INDENT) {
 
428
        indent = log_get_indent();
 
429
        if (indent > 0) {
 
430
            pj_memset(pre, PJ_LOG_INDENT_CHAR, indent);
 
431
            pre += indent;
 
432
        }
 
433
    }
 
434
#endif
 
435
 
 
436
    len = pre - log_buffer;
 
437
 
 
438
    /* Print the whole message to the string log_buffer. */
 
439
    print_len = pj_ansi_vsnprintf(pre, sizeof(log_buffer)-len, format, 
 
440
                                  marker);
 
441
    if (print_len < 0) {
 
442
        level = 1;
 
443
        print_len = pj_ansi_snprintf(pre, sizeof(log_buffer)-len, 
 
444
                                     "<logging error: msg too long>");
 
445
    }
 
446
    len = len + print_len;
 
447
    if (len > 0 && len < (int)sizeof(log_buffer)-2) {
 
448
        if (log_decor & PJ_LOG_HAS_CR) {
 
449
            log_buffer[len++] = '\r';
 
450
        }
 
451
        if (log_decor & PJ_LOG_HAS_NEWLINE) {
 
452
            log_buffer[len++] = '\n';
 
453
        }
 
454
        log_buffer[len] = '\0';
 
455
    } else {
 
456
        len = sizeof(log_buffer)-1;
 
457
        if (log_decor & PJ_LOG_HAS_CR) {
 
458
            log_buffer[sizeof(log_buffer)-3] = '\r';
 
459
        }
 
460
        if (log_decor & PJ_LOG_HAS_NEWLINE) {
 
461
            log_buffer[sizeof(log_buffer)-2] = '\n';
 
462
        }
 
463
        log_buffer[sizeof(log_buffer)-1] = '\0';
 
464
    }
 
465
 
 
466
    /* It should be safe to resume logging at this point. Application can
 
467
     * recursively call the logging function inside the callback.
 
468
     */
 
469
    resume_logging(&saved_level);
 
470
 
 
471
    if (log_writer)
 
472
        (*log_writer)(level, log_buffer, len);
 
473
}
 
474
 
 
475
/*
 
476
PJ_DEF(void) pj_log_0(const char *obj, const char *format, ...)
 
477
{
 
478
    va_list arg;
 
479
    va_start(arg, format);
 
480
    pj_log(obj, 0, format, arg);
 
481
    va_end(arg);
 
482
}
 
483
*/
 
484
 
 
485
PJ_DEF(void) pj_log_1(const char *obj, const char *format, ...)
 
486
{
 
487
    va_list arg;
 
488
    va_start(arg, format);
 
489
    pj_log(obj, 1, format, arg);
 
490
    va_end(arg);
 
491
}
 
492
#endif  /* PJ_LOG_MAX_LEVEL >= 1 */
 
493
 
 
494
#if PJ_LOG_MAX_LEVEL >= 2
 
495
PJ_DEF(void) pj_log_2(const char *obj, const char *format, ...)
 
496
{
 
497
    va_list arg;
 
498
    va_start(arg, format);
 
499
    pj_log(obj, 2, format, arg);
 
500
    va_end(arg);
 
501
}
 
502
#endif
 
503
 
 
504
#if PJ_LOG_MAX_LEVEL >= 3
 
505
PJ_DEF(void) pj_log_3(const char *obj, const char *format, ...)
 
506
{
 
507
    va_list arg;
 
508
    va_start(arg, format);
 
509
    pj_log(obj, 3, format, arg);
 
510
    va_end(arg);
 
511
}
 
512
#endif
 
513
 
 
514
#if PJ_LOG_MAX_LEVEL >= 4
 
515
PJ_DEF(void) pj_log_4(const char *obj, const char *format, ...)
 
516
{
 
517
    va_list arg;
 
518
    va_start(arg, format);
 
519
    pj_log(obj, 4, format, arg);
 
520
    va_end(arg);
 
521
}
 
522
#endif
 
523
 
 
524
#if PJ_LOG_MAX_LEVEL >= 5
 
525
PJ_DEF(void) pj_log_5(const char *obj, const char *format, ...)
 
526
{
 
527
    va_list arg;
 
528
    va_start(arg, format);
 
529
    pj_log(obj, 5, format, arg);
 
530
    va_end(arg);
 
531
}
 
532
#endif
 
533
 
 
534
#if PJ_LOG_MAX_LEVEL >= 6
 
535
PJ_DEF(void) pj_log_6(const char *obj, const char *format, ...)
 
536
{
 
537
    va_list arg;
 
538
    va_start(arg, format);
 
539
    pj_log(obj, 6, format, arg);
 
540
    va_end(arg);
 
541
}
 
542
#endif
 
543