aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Log.cpp51
-rw-r--r--src/Log.h174
-rw-r--r--src/TcpLog.cpp330
-rw-r--r--src/TcpLog.h69
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