lsquic_logger.c revision 229fce07
1229fce07SDmitri Tikhonov/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc. See LICENSE. */ 250aadb33SDmitri Tikhonov/* 350aadb33SDmitri Tikhonov * LSQUIC Logger implementation. 450aadb33SDmitri Tikhonov */ 550aadb33SDmitri Tikhonov 6560db45bSDmitri Tikhonov#include <assert.h> 750aadb33SDmitri Tikhonov#include <errno.h> 850aadb33SDmitri Tikhonov#include <inttypes.h> 950aadb33SDmitri Tikhonov#include <stdarg.h> 1050aadb33SDmitri Tikhonov#include <stdio.h> 1150aadb33SDmitri Tikhonov#include <stdlib.h> 1250aadb33SDmitri Tikhonov#include <string.h> 13461e84d8SAmol Deshpande#ifndef WIN32 1450aadb33SDmitri Tikhonov#include <sys/time.h> 15461e84d8SAmol Deshpande#endif 1650aadb33SDmitri Tikhonov#include <time.h> 1750aadb33SDmitri Tikhonov 1850aadb33SDmitri Tikhonov#define LSQUIC_LOGGER_MODULE LSQLM_LOGGER /* Quis custodiet ipsos custodes? */ 1950aadb33SDmitri Tikhonov#include "lsquic_logger.h" 203229dd11SDmitri Tikhonov#include "lsquic_byteswap.h" 2150aadb33SDmitri Tikhonov#include "lsquic.h" 2250aadb33SDmitri Tikhonov 233229dd11SDmitri Tikhonov/* The switch to big-endian format in GQUIC also resulted in Chrome swapping 243229dd11SDmitri Tikhonov * the CID in its log. We do the same thing in our log messages so that the 253229dd11SDmitri Tikhonov * CIDs are easy to match. The exception is Q035, which is the last little- 263229dd11SDmitri Tikhonov * endian GQUIC version this library supports. 273229dd11SDmitri Tikhonov */ 283229dd11SDmitri Tikhonov#if __BYTE_ORDER == __LITTLE_ENDIAN 293229dd11SDmitri Tikhonov#define DISP_CID(cid) bswap_64(cid) 303229dd11SDmitri Tikhonov#else 313229dd11SDmitri Tikhonov#define DISP_CID(cid) (cid) 323229dd11SDmitri Tikhonov#endif 333229dd11SDmitri Tikhonov 3450aadb33SDmitri Tikhonovstatic enum lsquic_logger_timestamp_style g_llts = LLTS_NONE; 3550aadb33SDmitri Tikhonov 3650aadb33SDmitri Tikhonovstatic int 3750aadb33SDmitri Tikhonovnull_vprintf (void *ctx, const char *fmt, va_list ap) 3850aadb33SDmitri Tikhonov{ 3950aadb33SDmitri Tikhonov return 0; 4050aadb33SDmitri Tikhonov} 4150aadb33SDmitri Tikhonov 4250aadb33SDmitri Tikhonov 4350aadb33SDmitri Tikhonovstatic int 4450aadb33SDmitri Tikhonovfile_vprintf (void *ctx, const char *fmt, va_list ap) 4550aadb33SDmitri Tikhonov{ 4650aadb33SDmitri Tikhonov return vfprintf((FILE *) ctx, fmt, ap); 4750aadb33SDmitri Tikhonov} 4850aadb33SDmitri Tikhonov 4950aadb33SDmitri Tikhonov 5050aadb33SDmitri Tikhonovstatic const struct lsquic_logger_if file_logger_if = { 5150aadb33SDmitri Tikhonov .vprintf = file_vprintf, 5250aadb33SDmitri Tikhonov}; 5350aadb33SDmitri Tikhonov 5450aadb33SDmitri Tikhonovstatic const struct lsquic_logger_if null_logger_if = { 5550aadb33SDmitri Tikhonov .vprintf = null_vprintf, 5650aadb33SDmitri Tikhonov}; 5750aadb33SDmitri Tikhonov 5850aadb33SDmitri Tikhonovstatic void *logger_ctx = NULL; 5950aadb33SDmitri Tikhonovstatic const struct lsquic_logger_if *logger_if = &null_logger_if; 6050aadb33SDmitri Tikhonov 6150aadb33SDmitri Tikhonovenum lsq_log_level lsq_log_levels[N_LSQUIC_LOGGER_MODULES] = { 6250aadb33SDmitri Tikhonov [LSQLM_NOMODULE] = LSQ_LOG_WARN, 6350aadb33SDmitri Tikhonov [LSQLM_LOGGER] = LSQ_LOG_WARN, 6450aadb33SDmitri Tikhonov [LSQLM_EVENT] = LSQ_LOG_WARN, 6550aadb33SDmitri Tikhonov [LSQLM_ENGINE] = LSQ_LOG_WARN, 6650aadb33SDmitri Tikhonov [LSQLM_CONN] = LSQ_LOG_WARN, 6750aadb33SDmitri Tikhonov [LSQLM_RECHIST] = LSQ_LOG_WARN, 6850aadb33SDmitri Tikhonov [LSQLM_STREAM] = LSQ_LOG_WARN, 6950aadb33SDmitri Tikhonov [LSQLM_PARSE] = LSQ_LOG_WARN, 7050aadb33SDmitri Tikhonov [LSQLM_CFCW] = LSQ_LOG_WARN, 7150aadb33SDmitri Tikhonov [LSQLM_SFCW] = LSQ_LOG_WARN, 7250aadb33SDmitri Tikhonov [LSQLM_SENDCTL] = LSQ_LOG_WARN, 7350aadb33SDmitri Tikhonov [LSQLM_ALARMSET] = LSQ_LOG_WARN, 7450aadb33SDmitri Tikhonov [LSQLM_CRYPTO] = LSQ_LOG_WARN, 7550aadb33SDmitri Tikhonov [LSQLM_HANDSHAKE] = LSQ_LOG_WARN, 7650aadb33SDmitri Tikhonov [LSQLM_HSK_ADAPTER] = LSQ_LOG_WARN, 7750aadb33SDmitri Tikhonov [LSQLM_CUBIC] = LSQ_LOG_WARN, 7850aadb33SDmitri Tikhonov [LSQLM_HEADERS] = LSQ_LOG_WARN, 7950aadb33SDmitri Tikhonov [LSQLM_FRAME_READER]= LSQ_LOG_WARN, 8050aadb33SDmitri Tikhonov [LSQLM_FRAME_WRITER]= LSQ_LOG_WARN, 8150aadb33SDmitri Tikhonov [LSQLM_CONN_HASH] = LSQ_LOG_WARN, 8250aadb33SDmitri Tikhonov [LSQLM_ENG_HIST] = LSQ_LOG_WARN, 8350aadb33SDmitri Tikhonov [LSQLM_SPI] = LSQ_LOG_WARN, 8450aadb33SDmitri Tikhonov [LSQLM_DI] = LSQ_LOG_WARN, 8550aadb33SDmitri Tikhonov [LSQLM_PACER] = LSQ_LOG_WARN, 86e8bd737dSDmitri Tikhonov [LSQLM_MIN_HEAP] = LSQ_LOG_WARN, 873b55e6aeSDmitri Tikhonov [LSQLM_HTTP1X] = LSQ_LOG_WARN, 8850aadb33SDmitri Tikhonov}; 8950aadb33SDmitri Tikhonov 9050aadb33SDmitri Tikhonovconst char *const lsqlm_to_str[N_LSQUIC_LOGGER_MODULES] = { 9150aadb33SDmitri Tikhonov [LSQLM_NOMODULE] = "", 9250aadb33SDmitri Tikhonov [LSQLM_LOGGER] = "logger", 9350aadb33SDmitri Tikhonov [LSQLM_EVENT] = "event", 9450aadb33SDmitri Tikhonov [LSQLM_ENGINE] = "engine", 9550aadb33SDmitri Tikhonov [LSQLM_CONN] = "conn", 9650aadb33SDmitri Tikhonov [LSQLM_RECHIST] = "rechist", 9750aadb33SDmitri Tikhonov [LSQLM_STREAM] = "stream", 9850aadb33SDmitri Tikhonov [LSQLM_PARSE] = "parse", 9950aadb33SDmitri Tikhonov [LSQLM_CFCW] = "cfcw", 10050aadb33SDmitri Tikhonov [LSQLM_SFCW] = "sfcw", 10150aadb33SDmitri Tikhonov [LSQLM_SENDCTL] = "sendctl", 10250aadb33SDmitri Tikhonov [LSQLM_ALARMSET] = "alarmset", 10350aadb33SDmitri Tikhonov [LSQLM_CRYPTO] = "crypto", 10450aadb33SDmitri Tikhonov [LSQLM_HANDSHAKE] = "handshake", 10550aadb33SDmitri Tikhonov [LSQLM_HSK_ADAPTER] = "hsk-adapter", 10650aadb33SDmitri Tikhonov [LSQLM_CUBIC] = "cubic", 10750aadb33SDmitri Tikhonov [LSQLM_HEADERS] = "headers", 10850aadb33SDmitri Tikhonov [LSQLM_FRAME_READER]= "frame-reader", 10950aadb33SDmitri Tikhonov [LSQLM_FRAME_WRITER]= "frame-writer", 11050aadb33SDmitri Tikhonov [LSQLM_CONN_HASH] = "conn-hash", 11150aadb33SDmitri Tikhonov [LSQLM_ENG_HIST] = "eng-hist", 11250aadb33SDmitri Tikhonov [LSQLM_SPI] = "spi", 11350aadb33SDmitri Tikhonov [LSQLM_DI] = "di", 11450aadb33SDmitri Tikhonov [LSQLM_PACER] = "pacer", 115e8bd737dSDmitri Tikhonov [LSQLM_MIN_HEAP] = "min-heap", 1163b55e6aeSDmitri Tikhonov [LSQLM_HTTP1X] = "http1x", 11750aadb33SDmitri Tikhonov}; 11850aadb33SDmitri Tikhonov 11950aadb33SDmitri Tikhonovconst char *const lsq_loglevel2str[N_LSQUIC_LOG_LEVELS] = { 12050aadb33SDmitri Tikhonov [LSQ_LOG_ALERT] = "ALERT", 12150aadb33SDmitri Tikhonov [LSQ_LOG_CRIT] = "CRIT", 12250aadb33SDmitri Tikhonov [LSQ_LOG_DEBUG] = "DEBUG", 12350aadb33SDmitri Tikhonov [LSQ_LOG_EMERG] = "EMERG", 12450aadb33SDmitri Tikhonov [LSQ_LOG_ERROR] = "ERROR", 12550aadb33SDmitri Tikhonov [LSQ_LOG_INFO] = "INFO", 12650aadb33SDmitri Tikhonov [LSQ_LOG_NOTICE] = "NOTICE", 12750aadb33SDmitri Tikhonov [LSQ_LOG_WARN] = "WARN", 12850aadb33SDmitri Tikhonov}; 12950aadb33SDmitri Tikhonov 13050aadb33SDmitri Tikhonov 13150aadb33SDmitri Tikhonovstatic void 13250aadb33SDmitri Tikhonovlsquic_printf (const char *fmt, ...) 13350aadb33SDmitri Tikhonov{ 13450aadb33SDmitri Tikhonov va_list ap; 13550aadb33SDmitri Tikhonov va_start(ap, fmt); 13650aadb33SDmitri Tikhonov logger_if->vprintf(logger_ctx, fmt, ap); 13750aadb33SDmitri Tikhonov va_end(ap); 13850aadb33SDmitri Tikhonov} 13950aadb33SDmitri Tikhonov 14050aadb33SDmitri Tikhonov 141b93f59beSBob Perper#ifdef WIN32 142560db45bSDmitri Tikhonov#define DELTA_EPOCH_IN_TICKS 116444736000000000Ui64 143b93f59beSBob Perperstruct timezone 144b93f59beSBob Perper{ 145ab5c8df2SBob Perper time_t tz_minuteswest; /* minutes W of Greenwich */ 146ab5c8df2SBob Perper time_t tz_dsttime; /* type of dst correction */ 147b93f59beSBob Perper}; 148b93f59beSBob Perper 149b93f59beSBob Perperstatic int 150b93f59beSBob Perpergettimeofday (struct timeval *tv, struct timezone *tz) 151b93f59beSBob Perper{ 152b93f59beSBob Perper FILETIME ft; 153560db45bSDmitri Tikhonov uint64_t tmpres; 154b93f59beSBob Perper static int tzflag; 155b93f59beSBob Perper 156b93f59beSBob Perper if (NULL != tv) 157b93f59beSBob Perper { 158b93f59beSBob Perper GetSystemTimeAsFileTime(&ft); 159b93f59beSBob Perper 160560db45bSDmitri Tikhonov tmpres = ((uint64_t) ft.dwHighDateTime << 32) 161560db45bSDmitri Tikhonov | (ft.dwLowDateTime); 162b93f59beSBob Perper 163560db45bSDmitri Tikhonov tmpres -= DELTA_EPOCH_IN_TICKS; 164560db45bSDmitri Tikhonov tv->tv_sec = tmpres / 10000000; 165560db45bSDmitri Tikhonov tv->tv_usec = tmpres % 1000000; 166b93f59beSBob Perper } 167b93f59beSBob Perper 168b93f59beSBob Perper if (NULL != tz) 169b93f59beSBob Perper { 170b93f59beSBob Perper if (!tzflag) 171b93f59beSBob Perper { 172b93f59beSBob Perper _tzset(); 173b93f59beSBob Perper tzflag++; 174b93f59beSBob Perper } 175b93f59beSBob Perper tz->tz_minuteswest = _timezone / 60; 176b93f59beSBob Perper tz->tz_dsttime = _daylight; 177b93f59beSBob Perper } 178b93f59beSBob Perper 179b93f59beSBob Perper return 0; 180b93f59beSBob Perper} 181b93f59beSBob Perper 182b93f59beSBob Perper 183b93f59beSBob Perper#endif 184b93f59beSBob Perper 185b93f59beSBob Perper 18650aadb33SDmitri Tikhonovstatic void 18750aadb33SDmitri Tikhonovprint_timestamp (void) 18850aadb33SDmitri Tikhonov{ 18950aadb33SDmitri Tikhonov struct tm tm; 19050aadb33SDmitri Tikhonov struct timeval tv; 19150aadb33SDmitri Tikhonov gettimeofday(&tv, NULL); 192ab5c8df2SBob Perper#ifdef WIN32 193ab5c8df2SBob Perper { 1947b1586ddSDmitri Tikhonov time_t t = tv.tv_sec; 195560db45bSDmitri Tikhonov#ifndef NDEBUG 1967b1586ddSDmitri Tikhonov errno_t e = 197560db45bSDmitri Tikhonov#endif 1987b1586ddSDmitri Tikhonov localtime_s(&tm, &t); 199560db45bSDmitri Tikhonov assert(!e); 200ab5c8df2SBob Perper } 201ab5c8df2SBob Perper#else 20250aadb33SDmitri Tikhonov localtime_r(&tv.tv_sec, &tm); 203ab5c8df2SBob Perper#endif 204bfc7bfd8SDmitri Tikhonov if (g_llts == LLTS_YYYYMMDD_HHMMSSUS) 205bfc7bfd8SDmitri Tikhonov lsquic_printf("%04d-%02d-%02d %02d:%02d:%02d.%06d ", 206bfc7bfd8SDmitri Tikhonov tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 207bfc7bfd8SDmitri Tikhonov tm.tm_hour, tm.tm_min, tm.tm_sec, (int) (tv.tv_usec)); 208bfc7bfd8SDmitri Tikhonov else if (g_llts == LLTS_YYYYMMDD_HHMMSSMS) 20950aadb33SDmitri Tikhonov lsquic_printf("%04d-%02d-%02d %02d:%02d:%02d.%03d ", 21050aadb33SDmitri Tikhonov tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 21150aadb33SDmitri Tikhonov tm.tm_hour, tm.tm_min, tm.tm_sec, (int) (tv.tv_usec / 1000)); 21250aadb33SDmitri Tikhonov else if (g_llts == LLTS_HHMMSSMS) 21350aadb33SDmitri Tikhonov lsquic_printf("%02d:%02d:%02d.%03d ", tm.tm_hour, tm.tm_min, 21450aadb33SDmitri Tikhonov tm.tm_sec, (int) (tv.tv_usec / 1000)); 21550aadb33SDmitri Tikhonov else if (g_llts == LLTS_HHMMSSUS) 21650aadb33SDmitri Tikhonov lsquic_printf("%02d:%02d:%02d.%06d ", tm.tm_hour, tm.tm_min, 21750aadb33SDmitri Tikhonov tm.tm_sec, (int) tv.tv_usec); 21850aadb33SDmitri Tikhonov else if (g_llts == LLTS_CHROMELIKE) 21950aadb33SDmitri Tikhonov lsquic_printf("%02d%02d/%02d%02d%02d.%06d ", tm.tm_mon + 1, 22050aadb33SDmitri Tikhonov tm.tm_mday,tm.tm_hour, tm.tm_min, tm.tm_sec, (int) tv.tv_usec); 22150aadb33SDmitri Tikhonov} 22250aadb33SDmitri Tikhonov 22350aadb33SDmitri Tikhonov 22450aadb33SDmitri Tikhonovvoid 22550aadb33SDmitri Tikhonovlsquic_logger_log3 (enum lsq_log_level log_level, 22650aadb33SDmitri Tikhonov enum lsquic_logger_module module, 22750aadb33SDmitri Tikhonov uint64_t conn_id, uint32_t stream_id, const char *fmt, ...) 22850aadb33SDmitri Tikhonov{ 22950aadb33SDmitri Tikhonov const int saved_errno = errno; 23050aadb33SDmitri Tikhonov 23150aadb33SDmitri Tikhonov if (g_llts != LLTS_NONE) 23250aadb33SDmitri Tikhonov print_timestamp(); 23350aadb33SDmitri Tikhonov 23450aadb33SDmitri Tikhonov lsquic_printf("[%s] [QUIC:%"PRIu64"-%"PRIu32"] %s: ", 2353229dd11SDmitri Tikhonov lsq_loglevel2str[log_level], DISP_CID(conn_id), stream_id, 2363229dd11SDmitri Tikhonov lsqlm_to_str[module]); 23750aadb33SDmitri Tikhonov va_list ap; 23850aadb33SDmitri Tikhonov va_start(ap, fmt); 23950aadb33SDmitri Tikhonov logger_if->vprintf(logger_ctx, fmt, ap); 24050aadb33SDmitri Tikhonov va_end(ap); 24150aadb33SDmitri Tikhonov lsquic_printf("\n"); 24250aadb33SDmitri Tikhonov errno = saved_errno; 24350aadb33SDmitri Tikhonov} 24450aadb33SDmitri Tikhonov 24550aadb33SDmitri Tikhonov 24650aadb33SDmitri Tikhonovvoid 24750aadb33SDmitri Tikhonovlsquic_logger_log2 (enum lsq_log_level log_level, 24850aadb33SDmitri Tikhonov enum lsquic_logger_module module, 24950aadb33SDmitri Tikhonov uint64_t conn_id, const char *fmt, ...) 25050aadb33SDmitri Tikhonov{ 25150aadb33SDmitri Tikhonov const int saved_errno = errno; 25250aadb33SDmitri Tikhonov 25350aadb33SDmitri Tikhonov if (g_llts != LLTS_NONE) 25450aadb33SDmitri Tikhonov print_timestamp(); 25550aadb33SDmitri Tikhonov 25650aadb33SDmitri Tikhonov lsquic_printf("[%s] [QUIC:%"PRIu64"] %s: ", 2573229dd11SDmitri Tikhonov lsq_loglevel2str[log_level], DISP_CID(conn_id), lsqlm_to_str[module]); 25850aadb33SDmitri Tikhonov va_list ap; 25950aadb33SDmitri Tikhonov va_start(ap, fmt); 26050aadb33SDmitri Tikhonov logger_if->vprintf(logger_ctx, fmt, ap); 26150aadb33SDmitri Tikhonov va_end(ap); 26250aadb33SDmitri Tikhonov lsquic_printf("\n"); 26350aadb33SDmitri Tikhonov errno = saved_errno; 26450aadb33SDmitri Tikhonov} 26550aadb33SDmitri Tikhonov 26650aadb33SDmitri Tikhonov 26750aadb33SDmitri Tikhonovvoid 26850aadb33SDmitri Tikhonovlsquic_logger_log1 (enum lsq_log_level log_level, 26950aadb33SDmitri Tikhonov enum lsquic_logger_module module, 27050aadb33SDmitri Tikhonov const char *fmt, ...) 27150aadb33SDmitri Tikhonov{ 27250aadb33SDmitri Tikhonov const int saved_errno = errno; 27350aadb33SDmitri Tikhonov 27450aadb33SDmitri Tikhonov if (g_llts != LLTS_NONE) 27550aadb33SDmitri Tikhonov print_timestamp(); 27650aadb33SDmitri Tikhonov 27750aadb33SDmitri Tikhonov lsquic_printf("[%s] %s: ", lsq_loglevel2str[log_level], 27850aadb33SDmitri Tikhonov lsqlm_to_str[module]); 27950aadb33SDmitri Tikhonov va_list ap; 28050aadb33SDmitri Tikhonov va_start(ap, fmt); 28150aadb33SDmitri Tikhonov logger_if->vprintf(logger_ctx, fmt, ap); 28250aadb33SDmitri Tikhonov va_end(ap); 28350aadb33SDmitri Tikhonov lsquic_printf("\n"); 28450aadb33SDmitri Tikhonov errno = saved_errno; 28550aadb33SDmitri Tikhonov} 28650aadb33SDmitri Tikhonov 28750aadb33SDmitri Tikhonov 28850aadb33SDmitri Tikhonovvoid 28950aadb33SDmitri Tikhonovlsquic_logger_log0 (enum lsq_log_level log_level, const char *fmt, ...) 29050aadb33SDmitri Tikhonov{ 29150aadb33SDmitri Tikhonov const int saved_errno = errno; 29250aadb33SDmitri Tikhonov 29350aadb33SDmitri Tikhonov if (g_llts != LLTS_NONE) 29450aadb33SDmitri Tikhonov print_timestamp(); 29550aadb33SDmitri Tikhonov 29650aadb33SDmitri Tikhonov lsquic_printf("[%s] ", lsq_loglevel2str[log_level]); 29750aadb33SDmitri Tikhonov va_list ap; 29850aadb33SDmitri Tikhonov va_start(ap, fmt); 29950aadb33SDmitri Tikhonov logger_if->vprintf(logger_ctx, fmt, ap); 30050aadb33SDmitri Tikhonov va_end(ap); 30150aadb33SDmitri Tikhonov lsquic_printf("\n"); 30250aadb33SDmitri Tikhonov errno = saved_errno; 30350aadb33SDmitri Tikhonov} 30450aadb33SDmitri Tikhonov 30550aadb33SDmitri Tikhonov 30650aadb33SDmitri Tikhonovvoid 30750aadb33SDmitri Tikhonovlsquic_logger_init (const struct lsquic_logger_if *lif, void *lctx, 30850aadb33SDmitri Tikhonov unsigned llts) 30950aadb33SDmitri Tikhonov{ 31050aadb33SDmitri Tikhonov logger_if = lif; 31150aadb33SDmitri Tikhonov logger_ctx = lctx; 31250aadb33SDmitri Tikhonov if (llts < N_LLTS) 31350aadb33SDmitri Tikhonov g_llts = llts; 31450aadb33SDmitri Tikhonov LSQ_DEBUG("%s called", __func__); 31550aadb33SDmitri Tikhonov} 31650aadb33SDmitri Tikhonov 31750aadb33SDmitri Tikhonov 31850aadb33SDmitri Tikhonovenum lsquic_logger_module 31950aadb33SDmitri Tikhonovlsquic_str_to_logger_module (const char *str) 32050aadb33SDmitri Tikhonov{ 32150aadb33SDmitri Tikhonov enum lsquic_logger_module i; 32250aadb33SDmitri Tikhonov for (i = 0; i < sizeof(lsqlm_to_str) / sizeof(lsqlm_to_str[0]); ++i) 32350aadb33SDmitri Tikhonov if (0 == strcasecmp(lsqlm_to_str[i], str)) 32450aadb33SDmitri Tikhonov return i; 32550aadb33SDmitri Tikhonov return -1; 32650aadb33SDmitri Tikhonov} 32750aadb33SDmitri Tikhonov 32850aadb33SDmitri Tikhonov 32950aadb33SDmitri Tikhonovenum lsq_log_level 33050aadb33SDmitri Tikhonovlsquic_str_to_log_level (const char *str) 33150aadb33SDmitri Tikhonov{ 33250aadb33SDmitri Tikhonov if (0 == strcasecmp(str, "emerg")) 33350aadb33SDmitri Tikhonov return LSQ_LOG_EMERG; 33450aadb33SDmitri Tikhonov if (0 == strcasecmp(str, "alert")) 33550aadb33SDmitri Tikhonov return LSQ_LOG_ALERT; 33650aadb33SDmitri Tikhonov if (0 == strcasecmp(str, "crit")) 33750aadb33SDmitri Tikhonov return LSQ_LOG_CRIT; 33850aadb33SDmitri Tikhonov if (0 == strcasecmp(str, "error")) 33950aadb33SDmitri Tikhonov return LSQ_LOG_ERROR; 34050aadb33SDmitri Tikhonov if (0 == strcasecmp(str, "warn")) 34150aadb33SDmitri Tikhonov return LSQ_LOG_WARN; 34250aadb33SDmitri Tikhonov if (0 == strcasecmp(str, "notice")) 34350aadb33SDmitri Tikhonov return LSQ_LOG_NOTICE; 34450aadb33SDmitri Tikhonov if (0 == strcasecmp(str, "info")) 34550aadb33SDmitri Tikhonov return LSQ_LOG_INFO; 34650aadb33SDmitri Tikhonov if (0 == strcasecmp(str, "debug")) 34750aadb33SDmitri Tikhonov return LSQ_LOG_DEBUG; 34850aadb33SDmitri Tikhonov return -1; 34950aadb33SDmitri Tikhonov} 35050aadb33SDmitri Tikhonov 35150aadb33SDmitri Tikhonov 35250aadb33SDmitri Tikhonovvoid 35350aadb33SDmitri Tikhonovlsquic_log_to_fstream (FILE *file, unsigned llts) 35450aadb33SDmitri Tikhonov{ 35550aadb33SDmitri Tikhonov lsquic_logger_init(&file_logger_if, file, llts); 35650aadb33SDmitri Tikhonov} 35750aadb33SDmitri Tikhonov 35850aadb33SDmitri Tikhonov 35950aadb33SDmitri Tikhonovint 36050aadb33SDmitri Tikhonovlsquic_logger_lopt (const char *optarg_orig) 36150aadb33SDmitri Tikhonov{ 36250aadb33SDmitri Tikhonov char *const optarg = strdup(optarg_orig); 36350aadb33SDmitri Tikhonov char *mod_str; 36450aadb33SDmitri Tikhonov int i; 36550aadb33SDmitri Tikhonov for (i = 0; (mod_str = strtok(i ? NULL : optarg, ",")); ++i) { 36650aadb33SDmitri Tikhonov char *level_str = strchr(mod_str, '='); 36750aadb33SDmitri Tikhonov if (!level_str) { 36850aadb33SDmitri Tikhonov fprintf(stderr, "Invalid module specification `%s'\n", mod_str); 36950aadb33SDmitri Tikhonov break; 37050aadb33SDmitri Tikhonov } 37150aadb33SDmitri Tikhonov *level_str = '\0'; 37250aadb33SDmitri Tikhonov ++level_str; 37350aadb33SDmitri Tikhonov enum lsquic_logger_module mod = lsquic_str_to_logger_module(mod_str); 37450aadb33SDmitri Tikhonov if (-1 == (int) mod) { 37550aadb33SDmitri Tikhonov fprintf(stderr, "`%s' is not a valid module name\n", mod_str); 37650aadb33SDmitri Tikhonov break; 37750aadb33SDmitri Tikhonov } 37850aadb33SDmitri Tikhonov enum lsq_log_level level = lsquic_str_to_log_level(level_str); 37950aadb33SDmitri Tikhonov if (-1 == (int) level) { 38050aadb33SDmitri Tikhonov fprintf(stderr, "`%s' is not a valid level\n", level_str); 38150aadb33SDmitri Tikhonov break; 38250aadb33SDmitri Tikhonov } 38350aadb33SDmitri Tikhonov lsq_log_levels[mod] = level; 38450aadb33SDmitri Tikhonov LSQ_INFO("set %s to %s", mod_str, level_str); 38550aadb33SDmitri Tikhonov } 38650aadb33SDmitri Tikhonov free(optarg); 38750aadb33SDmitri Tikhonov return mod_str == NULL ? 0 : -1; 38850aadb33SDmitri Tikhonov} 38950aadb33SDmitri Tikhonov 39050aadb33SDmitri Tikhonov 39150aadb33SDmitri Tikhonovint 39250aadb33SDmitri Tikhonovlsquic_set_log_level (const char *level_str) 39350aadb33SDmitri Tikhonov{ 39450aadb33SDmitri Tikhonov enum lsq_log_level level; 39550aadb33SDmitri Tikhonov unsigned i; 39650aadb33SDmitri Tikhonov 39750aadb33SDmitri Tikhonov level = lsquic_str_to_log_level(level_str); 39850aadb33SDmitri Tikhonov if ((int) level >= 0) 39950aadb33SDmitri Tikhonov { 40050aadb33SDmitri Tikhonov for (i = 0; i < sizeof(lsq_log_levels) / sizeof(lsq_log_levels[0]); ++i) 40150aadb33SDmitri Tikhonov lsq_log_levels[i] = level; 40250aadb33SDmitri Tikhonov return 0; 40350aadb33SDmitri Tikhonov } 40450aadb33SDmitri Tikhonov else 40550aadb33SDmitri Tikhonov return -1; 40650aadb33SDmitri Tikhonov} 407