~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* 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