Console: Add log support to network client (every client is a log target)
[senf.git] / Console / Server.cc
index 569a7cf..eb1fac1 100644 (file)
@@ -102,11 +102,13 @@ prefix_ void senf::console::Server::removeClient(Client & client)
 // senf::console::Client
 
 prefix_ senf::console::Client::Client(ClientHandle handle, std::string const & name)
-    : handle_ (handle), name_ (name), out_(::dup(handle.fd()))
+    : out_t(::dup(handle.fd())), senf::log::IOStreamTarget(out_t::member),
+      handle_ (handle), name_ (name), promptLen_(0)
 {
     showPrompt();
     ReadHelper<ClientHandle>::dispatch( handle_, 16384u, ReadUntil("\n"),
                                         senf::membind(&Client::clientData, this) );
+    route< senf::SenfLog, senf::log::NOTICE >();
 }
 
 prefix_ senf::console::Client::~Client()
@@ -120,30 +122,33 @@ prefix_ void senf::console::Client::stopClient()
 
 prefix_ void senf::console::Client::clientData(ReadHelper<ClientHandle>::ptr helper)
 {
+    promptLen_ = 0;
     if (helper->error() || handle_.eof()) {
         // THIS COMMITS SUICIDE. THE INSTANCE IS GONE AFTER stopClient RETURNS
         stopClient();
         return;
     }
 
-#   warning fix Client::clientData implementation
-    // Remove the 'dup' needed here so we don't close the same fd twice (see Client constructor)
-    // Make output non-blocking
-    // Don't register a new ReadHelper every round
-
     std::string data (tail_ + helper->data());
     tail_ = helper->tail();
     boost::trim(data); // Gets rid of superfluous  \r or \n characters
 
     try {
-        if (! parser_.parse(data, boost::bind<void>(boost::ref(executor_), _1, boost::ref(out_))))
-            out_ << "syntax error" << std::endl;
+        if (! parser_.parse(data, boost::bind<void>(boost::ref(executor_), _1, 
+                                                    boost::ref(out_t::member))))
+            out_t::member << "syntax error" << std::endl;
     }
     catch (Executor::ExitException &) {
         // THIS COMMITS SUICIDE. THE INSTANCE IS GONE AFTER stopClient RETURNS
         stopClient();
         return;
-    }        
+    }
+    catch (std::exception & ex) {
+        out_t::member << ex.what() << std::endl;
+    }
+    catch (...) {
+        out_t::member << "unidentified error (unknown exception thrown)" << std::endl;
+    }
 
     showPrompt();
     ReadHelper<ClientHandle>::dispatch( handle_, 16384u, ReadUntil("\n"),
@@ -152,7 +157,21 @@ prefix_ void senf::console::Client::clientData(ReadHelper<ClientHandle>::ptr hel
 
 prefix_ void senf::console::Client::showPrompt()
 {
-    out_ << name_ << ":" << executor_.cwd().path() << "# " << std::flush;
+    std::string path (executor_.cwd().path());
+    out_t::member << name_ << ":" << path << "# " << std::flush;
+    promptLen_ = name_.size() + 1 + path.size() + 1;
+}
+
+prefix_ void senf::console::Client::v_write(boost::posix_time::ptime timestamp,
+                                            std::string const & stream,
+                                            std::string const & area, unsigned level,
+                                            std::string const & message)
+{
+    if (promptLen_)
+        out_t::member << '\r' << std::string(' ', promptLen_) << '\r';
+    IOStreamTarget::v_write(timestamp, stream, area, level, message);
+    if (promptLen_)
+        showPrompt();
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////