blob: 5e1c2e83809d52c0504ac22bb4c5f7503471bf77 [file] [log] [blame]
/*
* Copyright (C) 2008-2009 Andrej Stepanchuk
* Copyright (C) 2009-2010 Howard Chu
*
* This file is part of librtmp.
*
* librtmp is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1,
* or (at your option) any later version.
*
* librtmp is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with librtmp see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/lgpl.html
*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include "rtmp_sys.h"
#include "log.h"
#define MAX_PRINT_LEN 2048
RTMP_LogLevel RTMP_debuglevel = RTMP_LOGERROR;
static int neednl;
static FILE *fmsg;
static RTMP_LogCallback rtmp_log_default, *cb = rtmp_log_default;
static const char *levels[] = {
"CRIT", "ERROR", "WARNING", "INFO",
"DEBUG", "DEBUG2"
};
static void
rtmp_log_default (int level, const char *format, va_list vl)
{
char str[MAX_PRINT_LEN] = "";
vsnprintf (str, MAX_PRINT_LEN - 1, format, vl);
/* Filter out 'no-name' */
if (RTMP_debuglevel < RTMP_LOGALL && strstr (str, "no-name") != NULL)
return;
if (!fmsg)
fmsg = stderr;
if (level <= RTMP_debuglevel) {
if (neednl) {
putc ('\n', fmsg);
neednl = 0;
}
fprintf (fmsg, "%s: %s\n", levels[level], str);
#ifdef _DEBUG
fflush (fmsg);
#endif
}
}
void
RTMP_LogSetOutput (FILE * file)
{
fmsg = file;
}
void
RTMP_LogSetLevel (RTMP_LogLevel level)
{
RTMP_debuglevel = level;
}
void
RTMP_LogSetCallback (RTMP_LogCallback * cbp)
{
cb = cbp;
}
RTMP_LogLevel
RTMP_LogGetLevel (void)
{
return RTMP_debuglevel;
}
void
RTMP_Log (int level, const char *format, ...)
{
va_list args;
va_start (args, format);
cb (level, format, args);
va_end (args);
}
static const char hexdig[] = "0123456789abcdef";
void
RTMP_LogHex (int level, const uint8_t * data, unsigned long len)
{
unsigned long i;
char line[50], *ptr;
if (level > RTMP_debuglevel)
return;
ptr = line;
for (i = 0; i < len; i++) {
*ptr++ = hexdig[0x0f & (data[i] >> 4)];
*ptr++ = hexdig[0x0f & data[i]];
if ((i & 0x0f) == 0x0f) {
*ptr = '\0';
ptr = line;
RTMP_Log (level, "%s", line);
} else {
*ptr++ = ' ';
}
}
if (i & 0x0f) {
*ptr = '\0';
RTMP_Log (level, "%s", line);
}
}
void
RTMP_LogHexString (int level, const uint8_t * data, unsigned long len)
{
#define BP_OFFSET 9
#define BP_GRAPH 60
#define BP_LEN 80
char line[BP_LEN];
unsigned long i;
if (!data || level > RTMP_debuglevel)
return;
/* in case len is zero */
line[0] = '\0';
for (i = 0; i < len; i++) {
int n = i % 16;
unsigned off;
if (!n) {
if (i)
RTMP_Log (level, "%s", line);
memset (line, ' ', sizeof (line) - 2);
line[sizeof (line) - 2] = '\0';
off = i % 0x0ffffU;
line[2] = hexdig[0x0f & (off >> 12)];
line[3] = hexdig[0x0f & (off >> 8)];
line[4] = hexdig[0x0f & (off >> 4)];
line[5] = hexdig[0x0f & off];
line[6] = ':';
}
off = BP_OFFSET + n * 3 + ((n >= 8) ? 1 : 0);
line[off] = hexdig[0x0f & (data[i] >> 4)];
line[off + 1] = hexdig[0x0f & data[i]];
off = BP_GRAPH + n + ((n >= 8) ? 1 : 0);
if (isprint (data[i])) {
line[BP_GRAPH + n] = data[i];
} else {
line[BP_GRAPH + n] = '.';
}
}
RTMP_Log (level, "%s", line);
}
/* These should only be used by apps, never by the library itself */
void
RTMP_LogPrintf (const char *format, ...)
{
char str[MAX_PRINT_LEN] = "";
int len;
va_list args;
va_start (args, format);
len = vsnprintf (str, MAX_PRINT_LEN - 1, format, args);
va_end (args);
if (RTMP_debuglevel == RTMP_LOGCRIT)
return;
if (!fmsg)
fmsg = stderr;
if (neednl) {
putc ('\n', fmsg);
neednl = 0;
}
if (len > MAX_PRINT_LEN - 1)
len = MAX_PRINT_LEN - 1;
fprintf (fmsg, "%s", str);
if (str[len - 1] == '\n')
fflush (fmsg);
}
void
RTMP_LogStatus (const char *format, ...)
{
char str[MAX_PRINT_LEN] = "";
va_list args;
va_start (args, format);
vsnprintf (str, MAX_PRINT_LEN - 1, format, args);
va_end (args);
if (RTMP_debuglevel == RTMP_LOGCRIT)
return;
if (!fmsg)
fmsg = stderr;
fprintf (fmsg, "%s", str);
fflush (fmsg);
neednl = 1;
}