prefix_ typename senf::ServerSocketHandle<SPolicy>::ClientHandle
senf::ServerSocketHandle<SPolicy>::acceptfrom(Address & addr)
{
- return ClienttHandle(this->protocol().clone(),
- SPolicy::CommunicationPolicy::accept(*this,addr));
+ return ClientHandle(this->body().clone(
+ SPolicy::CommunicationPolicy::accept(*this,addr), false));
}
///////////////////////////////////////////////////////////////////////////
++ args;
BOOST_REQUIRE( args != info.arguments().end() );
- BOOST_REQUIRE_EQUAL( args->size(), 1 );
+ BOOST_REQUIRE_EQUAL( args->size(), 1u );
BOOST_CHECK_EQUAL( args->begin()->value(), tokens[1] );
++ args;
BOOST_REQUIRE( args != info.arguments().end() );
- BOOST_REQUIRE_EQUAL( args->size(), 1 );
+ BOOST_REQUIRE_EQUAL( args->size(), 1u );
BOOST_CHECK_EQUAL( args->begin()->value(), tokens[2] );
++ args;
BOOST_REQUIRE( args != info.arguments().end() );
- BOOST_REQUIRE_EQUAL( args->size(), 8 );
+ BOOST_REQUIRE_EQUAL( args->size(), 8u );
for (unsigned i (0); i<8; ++i)
BOOST_CHECK_EQUAL( args->begin()[i].value(), tokens[4+i] );
++ args;
BOOST_REQUIRE( args != info.arguments().end() );
- BOOST_REQUIRE_EQUAL( args->size(), 1 );
+ BOOST_REQUIRE_EQUAL( args->size(), 1u );
BOOST_CHECK_EQUAL( args->begin()->value(), tokens[13] );
++ args;
BOOST_REQUIRE( args != info.arguments().end() );
- BOOST_REQUIRE_EQUAL( args->size(), 1 );
+ BOOST_REQUIRE_EQUAL( args->size(), 1u );
BOOST_CHECK_EQUAL( args->begin()->value(), tokens[14] );
++ args;
ServerHandle::ClientHandle client (handle_.accept());
boost::intrusive_ptr<Client> p (new Client(*this, client));
clients_.insert( p );
- SENF_LOG(( "Registered new client " << p.get() ));
+ SENF_LOG(( "Registered new client " << client.peer() ));
}
prefix_ void senf::console::Server::removeClient(Client & client)
{
- SENF_LOG(( "Disposing client " << & client ));
+ SENF_LOG(( "Disposing client " << client.handle().peer() ));
// THIS DELETES THE CLIENT INSTANCE !!
clients_.erase(boost::intrusive_ptr<Client>(&client));
}
// senf::console::Client
prefix_ senf::console::Client::Client(Server & server, ClientHandle handle)
- : out_t(boost::ref(*this)), senf::log::IOStreamTarget(out_t::member), server_ (server),
- handle_ (handle),
+ : out_t(boost::ref(*this)),
+ senf::log::IOStreamTarget("client-" + senf::str(handle.peer()), out_t::member),
+ server_ (server), handle_ (handle),
readevent_ ("senf::console::Client::interactive_check",
boost::bind(&Client::setNoninteractive,this),
handle, scheduler::FdEvent::EV_READ, false),
reader_->enablePrompt();
}
-prefix_ std::ostream & senf::console::operator<<(std::ostream & os, Client const & client)
-{
- typedef ClientSocketHandle< MakeSocketPolicy<
- INet4AddressingPolicy,ConnectedCommunicationPolicy>::policy > V4Socket;
- typedef ClientSocketHandle< MakeSocketPolicy<
- INet6AddressingPolicy,ConnectedCommunicationPolicy>::policy > V6Socket;
-
- try {
- if (check_socket_cast<V4Socket>(client.handle()))
- os << dynamic_socket_cast<V4Socket>(client.handle()).peer();
- else if (check_socket_cast<V6Socket>(client.handle()))
- os << dynamic_socket_cast<V6Socket>(client.handle()).peer();
- else
- os << static_cast<void const *>(&client);
- }
- catch (SystemException &) {
- os << "0.0.0.0:0";
- }
-
- return os;
-}
-
-prefix_ std::ostream & senf::console::operator<<(std::ostream & os, Client * client)
-{
- return os << *client;
-}
-
///////////////////////////////////////////////////////////////////////////
// senf::console::Client::SysBacktrace
typedef senf::ServerSocketHandle<
senf::MakeSocketPolicy< senf::TCPv4SocketProtocol::Policy,
- senf::UnspecifiedAddressingPolicy>::policy > ServerHandle;
+ senf::BSDAddressingPolicy>::policy > ServerHandle;
/** \brief Internal: Generic client interface
}
prefix_ senf::log::ConsoleTarget::ConsoleTarget()
- : IOStreamTarget(std::cout)
+ : IOStreamTarget("console", std::cout)
{}
///////////////////////////////cci.e///////////////////////////////////////
///////////////////////////////cc.p////////////////////////////////////////
prefix_ senf::log::FileTarget::FileTarget(std::string file)
- : ofstream_t(file.c_str(), std::ofstream::app), IOStreamTarget(ofstream_t::member), file_(file)
+ : ofstream_t(file.c_str(), std::ofstream::app), IOStreamTarget(file, ofstream_t::member),
+ file_(file)
{}
prefix_ void senf::log::FileTarget::reopen()
#define prefix_ inline
///////////////////////////////cci.p///////////////////////////////////////
-prefix_ senf::log::IOStreamTarget::IOStreamTarget(std::ostream & os)
- : stream_ (os)
+prefix_ senf::log::IOStreamTarget::IOStreamTarget(std::string const & name, std::ostream & os)
+ : Target(name), stream_ (os)
{}
///////////////////////////////cci.e///////////////////////////////////////
///\name Structors and default members
///@{
- explicit IOStreamTarget(std::ostream & os);
+ IOStreamTarget(std::string const & name, std::ostream & os);
///@}
///////////////////////////////////////////////////////////////////////////
// senf::log::StringTarget
prefix_ senf::log::StringTarget::StringTarget()
- : IOStreamTarget(stream_base::member)
+ : IOStreamTarget("membuffer", stream_base::member)
{}
prefix_ std::string senf::log::StringTarget::str()
///////////////////////////////cci.p///////////////////////////////////////
prefix_ senf::log::SyslogTarget::SyslogTarget(int facility)
- : facility_ (facility)
+ : Target("syslog"), facility_ (facility)
{}
///////////////////////////////cci.e///////////////////////////////////////
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());
// Custom includes
#include "../../Socket/Protocols/INet/ConnectedUDPSocketHandle.hh"
+#include "../String.hh"
#define prefix_ inline
///////////////////////////////cci.p///////////////////////////////////////
prefix_ senf::log::SyslogUDPTarget::SyslogUDPTarget(senf::INet4Address const & target,
int facility)
- : facility_ (facility),
+ : Target("udp-" + senf::str(target)), facility_ (facility),
handle_ ( senf::ConnectedUDPv4ClientSocketHandle(senf::INet4SocketAddress(target, 514u)) )
{}
prefix_ senf::log::SyslogUDPTarget::SyslogUDPTarget(senf::INet4SocketAddress const & target,
int facility)
- : facility_ (facility),
+ : Target("udp-" + senf::str(target)), facility_ (facility),
handle_ ( senf::ConnectedUDPv4ClientSocketHandle(target) )
{}
prefix_ senf::log::SyslogUDPTarget::SyslogUDPTarget(senf::INet6Address const & target,
int facility)
- : facility_ (facility),
+ : Target("udp-" + senf::str(target)), facility_ (facility),
handle_ ( senf::ConnectedUDPv6ClientSocketHandle(senf::INet6SocketAddress(target, 514u)) )
{}
prefix_ senf::log::SyslogUDPTarget::SyslogUDPTarget(senf::INet6SocketAddress const & target,
int facility)
- : facility_ (facility),
+ : Target("udp-" + senf::str(target)), facility_ (facility),
handle_ ( senf::ConnectedUDPv6ClientSocketHandle(target) )
{}
// Custom includes
#include <algorithm>
+#include <boost/format.hpp>
#include "ConsoleTarget.hh"
+#include "../Console/Console.hh"
+#include "../Console/Sysdir.hh"
+#include "../membind.hh"
//#include "Target.mpp"
#define prefix_
///////////////////////////////////////////////////////////////////////////
// senf::log::Target
-prefix_ senf::log::Target::Target()
+namespace senf {
+namespace log {
+
+ SENF_CONSOLE_REGISTER_ENUM_MEMBER( Target, action_t, (ACCEPT)(REJECT) );
+
+}}
+
+namespace {
+namespace local {
+
+ enum Level {
+ VERBOSE = senf::log::VERBOSE::value,
+ NOTICE = senf::log::NOTICE::value,
+ MESSAGE = senf::log::MESSAGE::value,
+ IMPORTANT = senf::log::IMPORTANT::value,
+ CRITICAL = senf::log::CRITICAL::value,
+ FATAL = senf::log::FATAL::value
+ };
+ SENF_CONSOLE_REGISTER_ENUM( Level,
+ (VERBOSE)(NOTICE)(MESSAGE)(IMPORTANT)(CRITICAL)(FATAL) );
+
+}}
+
+prefix_ senf::log::Target::Target(std::string const & name)
{
- detail::TargetRegistry::instance().registerTarget(this);
+ namespace kw = senf::console::kw;
+
+ detail::TargetRegistry::instance().registerTarget(this, name);
+ consoleDir_().add("list", senf::membind(&Target::consoleList, this))
+ .doc("Show routing table\n"
+ "\n"
+ "Columns:\n"
+ " # rule index\n"
+ " STREAM stream to match, empty to match all streams\n"
+ " AREA area to match, empty to match all targets\n"
+ " LEVEL match messages with level above this. Log levels in increasing order\n"
+ " are:\n"
+ " verbose, notice, message, important, critical, fatal\n"
+ " ACTION action to take: accept or reject");
+ consoleDir_().add("route",
+ boost::function<void (std::string const &, std::string const &,
+ local::Level, action_t, int)>(
+ senf::membind(
+ static_cast<void (Target::*)(
+ std::string const &, std::string const &,
+ unsigned, action_t, int)>(&Target::route),
+ this)))
+ .arg("stream", "stream to match or empty to match any stream",
+ kw::default_value="")
+ .arg("area", "area to match or empty to match any area",
+ kw::default_value="")
+ .arg("level", "log level, one of: VERBOSE, NOTICE, MESSAGE, IMPORTANT, CRITICAL, FATAL",
+ kw::default_value=local::VERBOSE)
+ .arg("action", "routing action, one of: ACCEPT, REJECT",
+ kw::default_value=ACCEPT)
+ .arg("index", "index at which to insert new rule",
+ kw::default_value=-1)
+ .doc("Add routing entry. Log messages are matched against the routing table beginning\n"
+ "with the first entry. The action of the first matching entry determines the\n"
+ "handling of the message.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ " route\n"
+ " route all messages to this target.\n"
+ "\n"
+ " route \"\" my::Class\n"
+ " route all messages which are in the my::Class area.\n"
+ "\n"
+ " route senf::log::Debug \"\" VERBOSE REJECT\n"
+ " route \"\" \"\" VERBOSE\n"
+ " route all messages not in the senf::log::Debug stream to the current area.\n"
+ "\n"
+ "The additional optional index argument identifies the position in the routing table\n"
+ "where the new routing entry will be added. Positive numbers count from the\n"
+ "beginning, 0 being the first routing entry. Negative values count from the end.\n");
+ consoleDir_().add("unroute",
+ senf::membind(static_cast<void (Target::*)(int)>(&Target::unroute), this))
+ .arg("index", "index of routing entry to remove")
+ .overloadDoc("Remove routing entry with the given index");
+ consoleDir_().add("unroute",
+ boost::function<void (std::string const &, std::string const &,
+ local::Level, action_t)>(
+ senf::membind(
+ static_cast<void (Target::*)(
+ std::string const &, std::string const &,
+ unsigned, action_t)>(&Target::unroute),
+ this)))
+ .arg("stream", "stream to match or empty to match any stream",
+ kw::default_value="")
+ .arg("area", "area to match or empty to match any area",
+ kw::default_value="")
+ .arg("level", "log level, one of: VERBOSE, NOTICE, MESSAGE, IMPORTANT, CRITICAL, FATAL",
+ kw::default_value=local::VERBOSE)
+ .arg("action", "routing action, one of: ACCEPT, REJECT",
+ kw::default_value=ACCEPT)
+ .overloadDoc("Remove the routing entry matching the specified arguments.");
+ consoleDir_().add("flush", senf::membind(&Target::flush, this))
+ .doc("Remove all routing entries clearing the routing table. This will disable all\n"
+ "logging output on this target.");
}
prefix_ senf::log::Target::~Target()
prefix_ void senf::log::Target::route(std::string const & stream, std::string const & area,
unsigned level, action_t action, int index)
{
- detail::StreamBase const * s (StreamRegistry::instance().lookup(stream));
- if (!s)
- throw InvalidStreamException();
+ detail::StreamBase const * s (0);
+ if (! stream.empty()) {
+ s = StreamRegistry::instance().lookup(stream);
+ if (!s)
+ throw InvalidStreamException();
+ }
detail::AreaBase const * a (0);
if (! area.empty()) {
a = AreaRegistry::instance().lookup(area);
prefix_ void senf::log::Target::unroute(std::string const & stream, std::string const & area,
unsigned level, action_t action)
{
- detail::StreamBase const * s (StreamRegistry::instance().lookup(stream));
- if (!s)
- throw InvalidStreamException();
+ detail::StreamBase const * s (0);
+ if (! stream.empty()) {
+ s = StreamRegistry::instance().lookup(stream);
+ if (!s)
+ throw InvalidStreamException();
+ }
detail::AreaBase const * a (0);
if (! area.empty()) {
a = AreaRegistry::instance().lookup(area);
}
////////////////////////////////////////
+// protected members
+
+prefix_ senf::log::detail::TargetRegistry::TargetRegistry()
+ : fallbackRouting_(true)
+{
+ console::sysdir().add("log", consoleDir_());
+}
+
+////////////////////////////////////////
// private members
prefix_ void senf::log::Target::route(detail::StreamBase const * stream,
}
}
+namespace {
+ std::string formatLabel(std::string const & l)
+ {
+ if (l.empty())
+ return "-";
+ if (l.size() > 29)
+ return l.substr(l.size()-29);
+ return l;
+ }
+}
+
+prefix_ void senf::log::Target::consoleList(std::ostream & os)
+{
+ static char const * levels[] = {
+ "none", "verbose", "notice", "message", "important", "critical", "fatal", "disabled" };
+
+ boost::format fmt ("%2d %-29s %-29s %-9s %-6s\n");
+ os << fmt % "#" % "STREAM" % "AREA" % "LEVEL" % "ACTION";
+ unsigned n (0);
+ for (iterator i (begin()); i != end(); ++i, ++n)
+ os << fmt
+ % n
+ % formatLabel(i->stream())
+ % formatLabel(i->area())
+ % levels[i->level()]
+ % (i->action() == ACCEPT ? "accept" : "reject");
+}
+
///////////////////////////////////////////////////////////////////////////
// senf::log::detail::TargetRegistry
+prefix_ void senf::log::detail::TargetRegistry::registerTarget(Target * target,
+ std::string const & name)
+{
+ targets_.insert(target);
+ consoleDir_().add(name, target->consoleDir_());
+}
+
prefix_ void senf::log::detail::TargetRegistry::write(StreamBase const & stream,
AreaBase const & area, unsigned level,
std::string const & msg)
////////////////////////////////////////
// private members
-prefix_ senf::log::detail::TargetRegistry::TargetRegistry()
- : fallbackRouting_(true)
-{}
-
-prefix_ void senf::log::detail::TargetRegistry::registerTarget(Target * target)
-{
- targets_.insert(target);
-}
-
prefix_ void senf::log::detail::TargetRegistry::unregisterTarget(Target * target)
{
targets_.erase(target);
#include "StreamRegistry.hh"
#include "../Exception.hh"
#include "TimeSource.hh"
+#include "../Console/LazyDirectory.hh"
//#include "Target.mpp"
///////////////////////////////hh.p////////////////////////////////////////
///\name Structors and default members
///@{
- Target();
+ explicit Target(std::string const & name);
virtual ~Target();
///@}
void write(time_type timestamp, detail::StreamBase const & stream,
detail::AreaBase const & area, unsigned level, std::string const & message);
+ void consoleList(std::ostream & os);
+
# ifdef DOXYGEN
protected:
# endif
RIB rib_;
+ console::LazyDirectory consoleDir_;
+
friend class detail::AreaBase;
friend class detail::TargetRegistry;
};
#include <memory>
#include <boost/type_traits/is_same.hpp>
#include <boost/static_assert.hpp>
+#include "../Console/LazyDirectory.hh"
///////////////////////////////ih.p////////////////////////////////////////
private:
TargetRegistry();
- void registerTarget(Target * target);
+ void registerTarget(Target * target, std::string const & name);
void unregisterTarget(Target * target);
typedef std::set<Target *> Targets;
Targets targets_;
bool fallbackRouting_;
+
+ console::LazyDirectory consoleDir_;
friend class senf::log::Target;
friend class senf::singleton<TargetRegistry>;
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2009
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program 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 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief String inline template implementation */
+
+//#include "String.ih"
+
+// Custom includes
+#include <boost/lexical_cast.hpp>
+
+#define prefix_ inline
+///////////////////////////////cti.p///////////////////////////////////////
+
+template <class T>
+prefix_ std::string senf::str(T const & t)
+{
+ return boost::lexical_cast<std::string>(t);
+}
+
+///////////////////////////////cti.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
template <class ForwardReadableRange>
std::string stringJoin(ForwardReadableRange const & range, std::string sep);
+ template <class T>
+ std::string str(T const & t);
+
}
///////////////////////////////hh.e////////////////////////////////////////
//#include "String.cci"
#include "String.ct"
-//#include "String.cti"
+#include "String.cti"
#endif
\f