Utils/Console: Parser based character classifiers
[senf.git] / Utils / Logger / SyslogUDPTarget.cc
index 331485b..e420ec5 100644 (file)
 
 // Custom includes
 #include <sstream>
-#include "../../Socket/Protocols/INet/ConnectedUDPSocketHandle.hh"
 #include <boost/algorithm/string/trim.hpp>
 #include <boost/tokenizer.hpp>
+#include "../Console/Console.hh"
 
 //#include "SyslogUDPTarget.mpp"
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
 
-prefix_ senf::log::SyslogUDPTarget::SyslogUDPTarget(senf::INet4Address const & target,
-                                                    int facility)
-    : facility_ (facility),
-      handle_ ( senf::ConnectedUDPv4ClientSocketHandle(senf::INet4SocketAddress(target, 514u)) )
-{}
-
-prefix_ senf::log::SyslogUDPTarget::SyslogUDPTarget(senf::INet4SocketAddress const & target,
-                                                    int facility)
-    : facility_ (facility),
-      handle_ ( senf::ConnectedUDPv4ClientSocketHandle(target) )
-{}
-
-prefix_ senf::log::SyslogUDPTarget::SyslogUDPTarget(senf::INet6Address const & target,
-                                                    int facility)
-    : facility_ (facility),
-      handle_ ( senf::ConnectedUDPv6ClientSocketHandle(senf::INet6SocketAddress(target, 514u)) )
-{}
-
-prefix_ senf::log::SyslogUDPTarget::SyslogUDPTarget(senf::INet6SocketAddress const & target,
-                                                    int facility)
-    : facility_ (facility),
-      handle_ ( senf::ConnectedUDPv6ClientSocketHandle(target) )
-{}
-
 prefix_ void senf::log::SyslogUDPTarget::v_write(time_type timestamp, std::string const & stream,
                                                  std::string const & area, unsigned level,
                                                  std::string const & message)
 {
-    std::stringstream prefix;
-    prefix << '<' << (facility_ | senf::log::SyslogTarget::LEVELMAP[level]) << "> ";
-    if (area != "senf::log::DefaultArea")
-        prefix << '[' << area << "] ";
-    std::string m (boost::trim_right_copy(message));
+    std::string m (message);
+    boost::trim_right(m);
+    detail::quoteNonPrintable(m);
+
+    std::stringstream prfstream;
+    // The space after the '>' is there on purpose: It ensures, that the prefix (which may be empty)
+    // or message will not inadvertently be interpreted as date or hostname by a receiving syslog
+    // daemon or proxy
+    prfstream << '<' << (facility_ | senf::log::SyslogTarget::LEVELMAP[level]) << "> "
+              << prefix(timestamp, stream, area, level);
+    std::string const & prf (prfstream.str());
 
     typedef boost::char_separator<char> Separator;
     typedef boost::tokenizer<Separator> Tokenizer;
@@ -77,15 +59,101 @@ prefix_ void senf::log::SyslogUDPTarget::v_write(time_type timestamp, std::strin
     Tokenizer::iterator i (tokenizer.begin());
     Tokenizer::iterator const i_end (tokenizer.end());
 
-    std::stringstream line;
+    std::string line;
+    unsigned sz (896-prf.size());
     for (; i != i_end; ++i) 
-        for (unsigned j (0); j < i->size(); j += 896) {
-            line << prefix.str() << std::string(*i, j, 896);
-            handle_.write(line.str());
-            line.str("");
+        for (unsigned j (0); j < i->size(); j += sz) {
+            line = prf;
+            line += std::string(*i, j, sz);
+            handle_.write(line);
         }
 }
 
+namespace senf {
+namespace log {
+
+    SENF_CONSOLE_REGISTER_ENUM_MEMBER(SyslogUDPTarget, LogFacility,
+                                      (AUTHPRIV)(CRON)(DAEMON)(FTP)(KERN)(LPR)(MAIL)(NEWS)(SYSLOG)
+                                      (USER)(UUCP)(LOCAL0)(LOCAL1)(LOCAL2)(LOCAL3)(LOCAL4)(LOCAL5)
+                                      (LOCAL6)(LOCAL7));
+
+}}
+
+prefix_ senf::log::SyslogUDPTarget::RegisterConsole::RegisterConsole()
+{
+    namespace kw = senf::console::kw;
+
+    detail::TargetRegistry::instance().consoleDir().add(
+        "udp-target", 
+        static_cast<senf::console::DirectoryNode::ptr (*)(INet4SocketAddress const &, LogFacility)>(
+            &RegisterConsole::create))
+        .arg("address", "target address to send log messages to")
+        .arg("facility", "syslog facility to send messages to. One of\n"
+             "                  AUTHPRIV CRON DAEMON FTP KERN LPR MAIL NEWS SYSLOG USER\n"
+             "                  UUCP LOCAL0 LOCAL1 LOCAL2 LOCAL3 LOCAL4 LOCAL5 LOCAL6 LOCAL7",
+             kw::default_value = USER)
+        .doc("Create new udp target. The {address} can be an IPv4 or IPv6 address. If the port\n"
+             "number is omitted, it defaults to the default syslog port 514.");
+    detail::TargetRegistry::instance().consoleDir().add(
+        "udp-target", 
+        static_cast<senf::console::DirectoryNode::ptr (*)(INet4Address const &, LogFacility)>(
+            &RegisterConsole::create))
+        .arg("address")
+        .arg("facility", kw::default_value = USER);
+    detail::TargetRegistry::instance().consoleDir().add(
+        "udp-target", 
+        static_cast<senf::console::DirectoryNode::ptr (*)(INet6SocketAddress const &, LogFacility)>(
+            &RegisterConsole::create))
+        .arg("address")
+        .arg("facility", kw::default_value = USER);
+    detail::TargetRegistry::instance().consoleDir().add(
+        "udp-target", 
+        static_cast<senf::console::DirectoryNode::ptr (*)(INet6Address const &, LogFacility)>(
+            &RegisterConsole::create))
+        .arg("address")
+        .arg("facility", kw::default_value = USER);
+}
+
+prefix_ boost::shared_ptr<senf::console::DirectoryNode>
+senf::log::SyslogUDPTarget::RegisterConsole::create(senf::INet4SocketAddress const & target,
+                                                    LogFacility facility)
+{
+    std::auto_ptr<Target> tp (new SyslogUDPTarget(target, facility));
+    Target & tg (*tp.get());
+    detail::TargetRegistry::instance().dynamicTarget(tp);
+    return tg.consoleDir().node().thisptr();
+}
+
+prefix_ boost::shared_ptr<senf::console::DirectoryNode>
+senf::log::SyslogUDPTarget::RegisterConsole::create(senf::INet4Address const & target,
+                                                    LogFacility facility)
+{
+    std::auto_ptr<Target> tp (new SyslogUDPTarget(target, facility));
+    Target & tg (*tp.get());
+    detail::TargetRegistry::instance().dynamicTarget(tp);
+    return tg.consoleDir().node().thisptr();
+}
+
+prefix_ boost::shared_ptr<senf::console::DirectoryNode>
+senf::log::SyslogUDPTarget::RegisterConsole::create(senf::INet6SocketAddress const & target,
+                                                    LogFacility facility)
+{
+    std::auto_ptr<Target> tp (new SyslogUDPTarget(target, facility));
+    Target & tg (*tp.get());
+    detail::TargetRegistry::instance().dynamicTarget(tp);
+    return tg.consoleDir().node().thisptr();
+}
+
+prefix_ boost::shared_ptr<senf::console::DirectoryNode>
+senf::log::SyslogUDPTarget::RegisterConsole::create(senf::INet6Address const & target,
+                                                    LogFacility facility)
+{
+    std::auto_ptr<Target> tp (new SyslogUDPTarget(target, facility));
+    Target & tg (*tp.get());
+    detail::TargetRegistry::instance().dynamicTarget(tp);
+    return tg.consoleDir().node().thisptr();
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 //#include "SyslogUDPTarget.mpp"