From 57e15e67007c8e416cfdc1e0437f5aea42348b29 Mon Sep 17 00:00:00 2001
From: "Matthias P. Braendli" <matthias.braendli@mpb.li>
Date: Sun, 12 Jan 2014 20:50:56 +0100
Subject: remove tcplog, add log

---
 src/Log.cpp    |  51 +++++++++
 src/Log.h      | 174 ++++++++++++++++++++++++++++++
 src/TcpLog.cpp | 330 ---------------------------------------------------------
 src/TcpLog.h   |  69 ------------
 4 files changed, 225 insertions(+), 399 deletions(-)
 create mode 100644 src/Log.cpp
 create mode 100644 src/Log.h
 delete mode 100644 src/TcpLog.cpp
 delete mode 100644 src/TcpLog.h

(limited to 'src')

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
-- 
cgit v1.2.3