RemoteSyslogAppender.cpp
Go to the documentation of this file.
00001 /*
00002  * RemoteSyslogAppender.cpp
00003  *
00004  * Copyright 2001, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
00005  * Copyright 2001, Walter Stroebel. All rights reserved.
00006  *
00007  * See the COPYING file for the terms of usage and distribution.
00008  */
00009 
00010 #include "PortabilityImpl.hh"
00011 
00012 #ifdef LOG4CPP_HAVE_UNISTD_H
00013 #    include <unistd.h>
00014 #endif
00015 #include <cstdlib>
00016 #include <cstdio>
00017 #include <cstring>
00018 #include <sys/types.h>
00019 #include <sys/stat.h>
00020 #include <fcntl.h>
00021 #include <log4cpp/RemoteSyslogAppender.hh>
00022 #include <log4cpp/FactoryParams.hh>
00023 #include <memory>
00024 
00025 #ifdef WIN32
00026 #include <winsock2.h>
00027 #else
00028 #include <netdb.h>
00029 #include <sys/socket.h>
00030 #include <netinet/in.h>
00031 #include <arpa/inet.h>
00032 #endif
00033 
00034 namespace log4cpp {
00035 
00036     int RemoteSyslogAppender::toSyslogPriority(Priority::Value priority) {
00037         static int priorities[8] = { LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR,
00038                                      LOG_WARNING, LOG_NOTICE, LOG_INFO, 
00039                                      LOG_DEBUG };
00040         int result;
00041 
00042         priority++;
00043         priority /= 100;
00044 
00045         if (priority < 0) {
00046             result = LOG_EMERG;
00047         } else if (priority > 7) {
00048             result = LOG_DEBUG;
00049         } else {
00050             result = priorities[priority];
00051         }
00052 
00053         return result;
00054     }
00055         
00056 
00057     RemoteSyslogAppender::RemoteSyslogAppender(const std::string& name, 
00058                                    const std::string& syslogName, 
00059                                    const std::string& relayer,
00060                                    int facility,
00061                                    int portNumber) : 
00062         LayoutAppender(name),
00063         _syslogName(syslogName),
00064         _relayer(relayer),
00065         _facility((facility == -1) ? LOG_USER : facility),
00066         _portNumber((portNumber == -1) ? 514 : portNumber),
00067         _socket (0),
00068         _ipAddr (0),
00069         _cludge (0)
00070     {
00071         open();
00072     }
00073     
00074     RemoteSyslogAppender::~RemoteSyslogAppender() {
00075         close();
00076 #ifdef WIN32
00077         if (_cludge) {
00078             // we started it, we end it.
00079             WSACleanup ();
00080         }
00081 #endif
00082     }
00083 
00084     void RemoteSyslogAppender::open() {
00085         if (!_ipAddr) {
00086             struct hostent *pent = gethostbyname (_relayer.c_str ());
00087 #ifdef WIN32
00088             if (pent == NULL) {
00089                 if (WSAGetLastError () == WSANOTINITIALISED) {
00090                     WSADATA wsaData;
00091                     int err;
00092  
00093                     err = WSAStartup (0x101, &wsaData );
00094                     if (err) {
00095                         // loglog("RemoteSyslogAppender: WSAStartup returned %d", err);
00096                         return; // fail silently
00097                     }
00098                     pent = gethostbyname (_relayer.c_str ());
00099                     _cludge = 1;
00100                 } else {
00101                     // loglog("RemoteSyslogAppender: gethostbyname returned error");
00102                     return; // fail silently
00103                 }
00104             }
00105 #endif
00106             if (pent == NULL) {
00107                 in_addr_t ip = inet_addr (_relayer.c_str ());
00108                 pent = gethostbyaddr ((const char *) &ip, sizeof(in_addr_t), AF_INET);
00109                 if (pent == NULL) {
00110                     // loglog("RemoteSyslogAppender: failed to resolve host %s", _relayer.c_str());
00111                     return; // fail silently                    
00112                 }
00113             }
00114             _ipAddr = *(pent->h_addr);
00115         }
00116         // Get a datagram socket.
00117         
00118         if ((_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
00119             // loglog("RemoteSyslogAppender: failed to open socket");
00120             return; // fail silently                    
00121         }
00122     }
00123 
00124     void RemoteSyslogAppender::close() {
00125         if (_socket) {
00126 #ifdef WIN32
00127             closesocket (_socket);
00128 #else
00129             ::close (_socket);
00130 #endif
00131             _socket = 0;
00132         }
00133     }
00134 
00135     void RemoteSyslogAppender::_append(const LoggingEvent& event) {
00136         const std::string message(_getLayout().format(event));
00137         size_t messageLength = message.length();
00138         char *buf = new char [messageLength + 16];
00139         int priority = _facility + toSyslogPriority(event.priority);
00140         int preambleLength = std::sprintf (buf, "<%d>", priority);
00141         memcpy (buf + preambleLength, message.data(), messageLength);
00142 
00143         sockaddr_in sain;
00144         sain.sin_family = AF_INET;
00145         sain.sin_port   = htons (_portNumber);
00146         // NO, do NOT use htonl on _ipAddr. Is already in network order.
00147         sain.sin_addr.s_addr = _ipAddr;
00148 
00149         while (messageLength > 0) {
00150             /* if packet larger than maximum (900 bytes), split
00151                into two or more syslog packets. */
00152             if (preambleLength + messageLength > 900) {
00153                 sendto (_socket, buf, 900, 0, (struct sockaddr *) &sain, sizeof (sain));
00154                 messageLength -= (900 - preambleLength);
00155                 std::memmove (buf + preambleLength, buf + 900, messageLength);
00156                 // note: we might need to sleep a bit here
00157             } else {
00158                 sendto (_socket, buf, preambleLength + messageLength, 0, (struct sockaddr *) &sain, sizeof (sain));
00159                 break;
00160             }
00161         }
00162 
00163         delete[] buf;
00164     }
00165 
00166     bool RemoteSyslogAppender::reopen() {
00167         close();
00168         open();
00169         return true;
00170     }
00171     
00172     std::auto_ptr<Appender> create_remote_syslog_appender(const FactoryParams& params)
00173     {
00174        std::string name, syslog_name, relayer;
00175        int facility = -1, port_number = -1;
00176        params.get_for("remote syslog appender").required("name", name)("syslog_name", syslog_name)("relayer", relayer)
00177                                                .optional("facility", facility)("port", port_number);
00178        return std::auto_ptr<Appender>(new RemoteSyslogAppender(name, syslog_name, relayer, facility, port_number));
00179     }
00180 }


log4cpp
Author(s): Stephen Roderick
autogenerated on Mon Oct 6 2014 03:13:14