diff options
| author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2014-01-12 20:50:56 +0100 | 
|---|---|---|
| committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2014-01-12 20:50:56 +0100 | 
| commit | 57e15e67007c8e416cfdc1e0437f5aea42348b29 (patch) | |
| tree | 2805234804c5002c693ef32e3770cb01aef54081 | |
| parent | cd76cacd6b57f84514a27b94a6df77b99823e840 (diff) | |
| download | dabmux-57e15e67007c8e416cfdc1e0437f5aea42348b29.tar.gz dabmux-57e15e67007c8e416cfdc1e0437f5aea42348b29.tar.bz2 dabmux-57e15e67007c8e416cfdc1e0437f5aea42348b29.zip  | |
remove tcplog, add log
| -rw-r--r-- | src/Log.cpp | 51 | ||||
| -rw-r--r-- | src/Log.h | 174 | ||||
| -rw-r--r-- | src/TcpLog.cpp | 330 | ||||
| -rw-r--r-- | src/TcpLog.h | 69 | 
4 files changed, 225 insertions, 399 deletions
diff --git a/src/Log.cpp b/src/Log.cpp new file mode 100644 index 0000000..7dd9d18 --- /dev/null +++ b/src/Log.cpp @@ -0,0 +1,51 @@ +/* +   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +   Her Majesty the Queen in Right of Canada (Communications Research +   Center Canada) + +   Copyright (C), 2014, Matthias P. Braendli, matthias.braendli@mpb.li + */ +/* +   This file is part of CRC-DADMOD. + +   CRC-DADMOD is free software: you can redistribute it and/or modify +   it under the terms of the GNU General Public License as +   published by the Free Software Foundation, either version 3 of the +   License, or (at your option) any later version. + +   CRC-DADMOD 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 General Public License +   along with CRC-DADMOD.  If not, see <http://www.gnu.org/licenses/>. + */ + +#include <list> + +#include "Log.h" +#include "porting.h" + +Logger etiLog; + + +void Logger::register_backend(LogBackend* backend) { +    backends.push_back(backend); +    //log(info, "Registered new logger " + backend->get_name()); +} + + +void Logger::log(log_level_t level, std::string message) { +    for (std::list<LogBackend*>::iterator it = backends.begin(); +            it != backends.end(); +            it++) { +        (*it)->log(level, message); +    } +} + + +LogLine Logger::level(log_level_t level) +{ +    return LogLine(this, level); +} diff --git a/src/Log.h b/src/Log.h new file mode 100644 index 0000000..607735c --- /dev/null +++ b/src/Log.h @@ -0,0 +1,174 @@ +/* +   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +   Her Majesty the Queen in Right of Canada (Communications Research +   Center Canada) + +   Copyright (C), 2014, Matthias P. Braendli, matthias.braendli@mpb.li + */ +/* +   This file is part of CRC-DADMOD. + +   CRC-DADMOD is free software: you can redistribute it and/or modify +   it under the terms of the GNU General Public License as +   published by the Free Software Foundation, either version 3 of the +   License, or (at your option) any later version. + +   CRC-DADMOD 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 General Public License +   along with CRC-DADMOD.  If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _LOG_H +#define _LOG_H + +#ifdef HAVE_CONFIG_H +#   include "config.h" +#endif + +#include <stdio.h> +#include <syslog.h> +#include <fstream> +#include <sstream> +#include <iostream> +#include <list> +#include <stdexcept> +#include <string> + +#include "porting.h" + +#define SYSLOG_IDENT "CRC-DABMUX" +#define SYSLOG_FACILITY LOG_LOCAL0 + +extern Logger etiLog; + +enum log_level_t {debug = 0, info, warn, error, alert, emerg}; + +/** Abstract class all backends must inherit from */ +class LogBackend { +    public: +        virtual void log(log_level_t level, std::string message) = 0; +        virtual std::string get_name() = 0; +}; + +/** A Logging backend for Syslog */ +class LogToSyslog : public LogBackend { +    public: +        LogToSyslog() { +            name = "SYSLOG"; +            openlog(SYSLOG_IDENT, LOG_PID, SYSLOG_FACILITY); +        } + +        ~LogToSyslog() { +            closelog(); +        } + +        void log(log_level_t level, std::string message) { + +            int syslog_level = LOG_EMERG; +            switch (level) { +                case debug: syslog_level = LOG_DEBUG; break; +                case alert: syslog_level = LOG_ALERT; break; +                case info:  syslog_level = LOG_INFO; break; +                case warn:  syslog_level = LOG_WARNING; break; +                case error: syslog_level = LOG_ERR; break; +                case emerg: syslog_level = LOG_EMERG; break; +            } + +            syslog(syslog_level, SYSLOG_IDENT " %s", message.c_str()); +        } + +        std::string get_name() { return name; }; + +    private: +        std::string name; +}; + +class LogToFile : public LogBackend { +    public: +        LogToFile(std::string filename) { +            name = "FILE"; + +            log_file = fopen(filename.c_str(), "a"); +            if (log_file == NULL) { +                fprintf(stderr, "Cannot open log file !"); +                throw std::runtime_error("Cannot open log file !"); +            } +        } + +        ~LogToFile() { +            if (log_file != NULL) { +                fclose(log_file); +            } +        } + +        void log(log_level_t level, std::string message) { + +            const char* log_level_text[] = +                {"DEBUG", "INFO", "WARN", "ERROR", "ALERT", "EMERG"}; + +            // fprintf is thread-safe +            fprintf(log_file, "CRC-DABMOD: %s: %s\n", +                    log_level_text[(size_t)level], message.c_str()); +            fflush(log_file); +        } + +        std::string get_name() { return name; }; + +    private: +        std::string name; +        FILE* log_file; +}; + +class LogLine; + +class Logger { +    public: +        Logger() {}; + +        void register_backend(LogBackend* backend); + +        /* Log the message to all backends */ +        void log(log_level_t level, std::string message); + +        /* Return a LogLine for the given level */ +        LogLine level(log_level_t level); + +    private: +        std::list<LogBackend*> backends; +}; + +// Accumulate a line of logs, using same syntax as stringstream +// The line is logged when the LogLine gets destroyed +class LogLine { +    public: +        LogLine(const LogLine& logline); +        LogLine(Logger* logger, log_level_t level) : +            logger_(logger) +        { +            level_ = level; +        } + +        // Push the new element into the stringstream +        template <typename T> +        LogLine& operator<<(T s) { +            os << s; +            return *this; +        } + +        ~LogLine() +        { +            logger_->log(level_, os.str()); +        } + +    private: +        std::ostringstream os; +        log_level_t level_; +        Logger* logger_; +}; + + +#endif diff --git a/src/TcpLog.cpp b/src/TcpLog.cpp deleted file mode 100644 index 9fc73b7..0000000 --- a/src/TcpLog.cpp +++ /dev/null @@ -1,330 +0,0 @@ -/* -   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in -   Right of Canada (Communications Research Center Canada) -   */ -/* -   This file is part of CRC-DabMux. - -   CRC-DabMux is free software: you can redistribute it and/or modify -   it under the terms of the GNU General Public License as -   published by the Free Software Foundation, either version 3 of the -   License, or (at your option) any later version. - -   CRC-DabMux 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 General Public License -   along with CRC-DabMux.  If not, see <http://www.gnu.org/licenses/>. -   */ - -#include "TcpLog.h" -#include "InetAddress.h" -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> - -#ifdef _WIN32 -#   include <io.h> -# -#   define vsnprintf _vsnprintf -#   define MSG_NOSIGNAL 0 -#   define socklen_t int -#else -#   include <sys/socket.h> -#   include <netinet/in.h> -#   include <arpa/inet.h> -#   include <unistd.h> -#endif - -#include <sstream> - - -const int TcpLog::EMERG   = 0;      // system is unusable -const int TcpLog::ALERT   = 1;      // action must be taken immediately -const int TcpLog::CRIT    = 2;      // critical conditions -const int TcpLog::ERR     = 3;      // error conditions -const int TcpLog::WARNING = 4;      // warning conditions -const int TcpLog::NOTICE  = 5;      // normal but significant condition -const int TcpLog::INFO    = 6;      // informational -const int TcpLog::DBG     = 7;      // debug-level messages - - -TcpLog::TcpLog() : listenPort(0), client(-1), name(NULL), serverThread(0), running(false) -{ -    buffer = (char*)malloc(512); -    bufferSize = 512; -    headers = (char**)malloc(sizeof(char**)); -    headers[0] = NULL; -} - - -TcpLog::~TcpLog() -{ -    if (running) { -        running = false; -    } -    if (client != -1) { -        ::close(client); -    } -    if (headers != NULL) { -        for (int count = 0; headers[count] != NULL; ++count) { -            free(headers[count]); -        } -        free(headers); -    } -} - - -//TcpLog::TcpLog(int port); - - -void TcpLog::open(const char *ident, const int option, const int port) -{ -    listenPort = port; - -    if (name != NULL) { -        free(name); -    } -    name = strdup(ident); - -    if (running) { -        running = false; -#ifdef WIN32 -        DWORD status; -        for (int i = 0; i < 5; ++i) { -            if (GetExitCodeThread(serverThread, &status)) { -                break; -            } -            Sleep(100); -        } -        TerminateThread(serverThread, 1); -#else -        pthread_join(serverThread, NULL); -#endif -    } -    running = true; -#ifdef _WIN32 -    serverThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)listen, this, 0, NULL); -    if (serverThread == NULL) { -        fprintf(stderr, "Can't create TCP listen thread\n"); -    } -#else -    pthread_create(&serverThread, NULL, (void*(*)(void*))listen, this); -#endif -} - - -void TcpLog::printHeader(const int priority, const char *format, ...) -{ -    static char last = '\n'; -    std::string beginning; -    std::string message; -    int ret; - - -    beginning = "<"; -    beginning += '0' + (priority % 10); -    beginning += "> "; - -    va_list argp; -    va_start(argp, format); -    for (ret = vsnprintf(buffer, bufferSize, format, argp); -            ret >= bufferSize || ret == -1; -            ret = vsprintf(buffer, format, argp)) { -        if (ret == -1) { -            buffer = (char*)realloc(buffer, bufferSize * 2); -            bufferSize *= 2; -        } else { -            buffer = (char*)realloc(buffer, ret + 1); -            bufferSize = ret + 1; -        } -    } -    va_end(argp); - -    if (last == '\n') { -        message += beginning; -    } -    message += buffer; - -    last = buffer[ret - 1]; - -    for (unsigned long pos = message.find('\n'); -            pos != std::string::npos && ++pos != message.size(); -            pos = message.find('\n', pos)) { -        message.insert(pos, beginning); -    } - -    fprintf(stderr, "%s", message.c_str()); -    if (client != -1) { -        if (write(client, message.c_str(), message.size()) -                != (int)message.size()) { -            fprintf(stderr, "<6> Client closed\n"); -            ::close(client); -            client = -1; -        } -    } - -    int count = 0; -    while (headers[count++] != NULL) { -    } -    headers = (char**)realloc(headers, sizeof(char**) * (count + 1)); -    headers[count - 1] = strdup(message.c_str()); -    headers[count] = NULL; -} - - -void TcpLog::print(const int priority, const char *format, ...) -{ -    static char last = '\n'; -    std::string beginning; -    std::string message; -    int ret; - - -    beginning = "<"; -    beginning += '0' + (priority % 10); -    beginning += "> "; - -    va_list argp; -    va_start(argp, format); -    for (ret = vsnprintf(buffer, bufferSize, format, argp); -            ret >= bufferSize || ret == -1; -            ret = vsprintf(buffer, format, argp)) { -        if (ret == -1) { -            buffer = (char*)realloc(buffer, bufferSize * 2); -            bufferSize *= 2; -        } else { -            buffer = (char*)realloc(buffer, ret + 1); -            bufferSize = ret + 1; -        } -    } -    va_end(argp); - -    if (last == '\n') { -        message += beginning; -    } -    message += buffer; - -    last = buffer[ret - 1]; - -    for (unsigned long pos = message.find('\n'); -            pos != std::string::npos && ++pos != message.size(); -            pos = message.find('\n', pos)) { -        message.insert(pos, beginning); -    } - -    fprintf(stderr, "%s", message.c_str()); -    if (client != -1) { -        if (send(client, message.c_str(), message.size(), MSG_NOSIGNAL) -                != (int)message.size()) { -            fprintf(stderr, "<6> Client closed\n"); -            ::close(client); -            client = -1; -        } -    } -} - - -void TcpLog::close(void) -{ -} - - -void* TcpLog::listen(TcpLog* obj) -{ -    int server; -    struct sockaddr_in server_addr; -    struct sockaddr_in client_addr; -    socklen_t addrlen = sizeof(client_addr); - -#ifdef _WIN32 -    WSADATA wsaData; -    WORD wVersionRequested = wVersionRequested = MAKEWORD( 2, 2 ); - -    int res = WSAStartup( wVersionRequested, &wsaData ); -    if (res) { -        fprintf(stderr, "Can't initialize winsock\n"); -        ExitThread(1); -    } -#endif -    server = socket(PF_INET, SOCK_STREAM, 0); -    if (server == INVALID_SOCKET) { -#ifdef _WIN32 -        fprintf(stderr, "Can't create socket\n"); -        ExitThread(1); -#else -        perror("Can't create socket"); -        pthread_exit(NULL); -#endif -    } - -    int reuse = 1; -    if (setsockopt(server, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse)) -            == -1) { -        perror("Can't set socket reusable"); -    } - -    server_addr.sin_family = AF_INET; -    server_addr.sin_port = htons(obj->listenPort); -    server_addr.sin_addr.s_addr = INADDR_ANY; - -    if (bind(server, (struct sockaddr*)&server_addr, sizeof(server_addr)) -            == -1) { -        perror("Can't bind socket"); -        fprintf(stderr, " port: %i\n", obj->listenPort); -#ifdef _WIN32 -        ExitThread(1); -#else -        pthread_exit(NULL); -#endif -    } - -    if (::listen(server, 1) == -1) { -        perror("Can't listen on socket"); -#ifdef _WIN32 -        ExitThread(1); -#else -        pthread_exit(NULL); -#endif -    } - -    while (obj->running) { -        int client = accept(server, (struct sockaddr*)&client_addr, &addrlen); -        if (client == INVALID_SOCKET) { -#ifdef _WIN32 -            if (WSAGetLastError() != WSAEINTR) { -                setInetError("Can't accept client"); -                fprintf(stderr, "%s: %s\n", inetErrDesc, inetErrMsg); -                ExitThread(1); -            } -#else -            perror("Can't accept client"); -            pthread_exit(NULL); -#endif -        } -        obj->print(INFO, "%s:%d connected\n", -                inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); -        if (obj->client != -1) { -            ::close(obj->client); -        } -        obj->client = client; -        for (int i = 0; obj->headers[i] != NULL; ++i) { -            send(client, obj->headers[i], strlen(obj->headers[i]), MSG_NOSIGNAL); -        } -    } -    if (obj->client != -1) { -        ::close(obj->client); -        obj->client = -1; -    } -    ::close(server); - -#ifdef _WIN32 -    ExitThread(1); -#else -    pthread_exit(NULL); -#endif -    return NULL; -} diff --git a/src/TcpLog.h b/src/TcpLog.h deleted file mode 100644 index c9abd70..0000000 --- a/src/TcpLog.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in -   Right of Canada (Communications Research Center Canada) -   */ -/* -   This file is part of CRC-DabMux. - -   CRC-DabMux is free software: you can redistribute it and/or modify -   it under the terms of the GNU General Public License as -   published by the Free Software Foundation, either version 3 of the -   License, or (at your option) any later version. - -   CRC-DabMux 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 General Public License -   along with CRC-DabMux.  If not, see <http://www.gnu.org/licenses/>. -   */ - -#ifndef _TCP_LOG -#define _TCP_LOG - -#ifdef HAVE_CONFIG_H -#   include "config.h" -#endif - -#ifndef _WIN32 -#  include <pthread.h> -#else -#  include <winsock2.h> -#  define pthread_t HANDLE -#endif - -class TcpLog { -public: -    TcpLog(); -    ~TcpLog(); - -    void open(const char *ident, const int option, const int port); -    void printHeader(const int priority, const char *format, ...); -    void print(const int priority, const char *format, ...); -    void close(void); - -    const static int EMERG;     // system is unusable -    const static int ALERT;     // action must be taken immediately -    const static int CRIT;      // critical conditions -    const static int ERR;       // error conditions -    const static int WARNING;   // warning conditions -    const static int NOTICE;    // normal but significant condition -    const static int INFO;      // informational -    const static int DBG;       // debug-level messages - -private: -    static void* listen(TcpLog* obj); - -    int listenPort; -    int client; -    char* name; -    pthread_t serverThread; -    bool running; -    char* buffer; -    int bufferSize; -    char** headers; -}; - - -#endif // _TCP_LOG  | 
