Console: Implement ObjectDirectory proxy
[senf.git] / Console / Server.cc
index 0fd831d..4e37e68 100644 (file)
@@ -24,7 +24,7 @@
     \brief Server non-inline non-template implementation */
 
 #include "Server.hh"
-#include "Server.ih"
+//#include "Server.ih"
 
 // Custom includes
 #include <unistd.h>
@@ -32,6 +32,7 @@
 #include <boost/algorithm/string/trim.hpp>
 #include <boost/iostreams/device/file_descriptor.hpp>
 #include <boost/iostreams/stream.hpp>
+#include <boost/bind.hpp>
 #include "../Utils/senfassert.hh"
 #include "../Utils/membind.hh"
 #include "../Utils/Logger/SenfLog.hh"
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
 
-prefix_ void senf::console::start(senf::INet4SocketAddress const & address)
+prefix_ senf::console::Server &
+senf::console::Server::start(senf::INet4SocketAddress const & address)
 {
     senf::TCPv4ServerSocketHandle handle (address);
-    handle.protocol().reuseaddr();
-    senf::console::detail::Server::start(handle);
-    SENF_LOG((detail::Server::SENFLogArea)(log::NOTICE)( 
+    senf::console::Server::start(handle);
+    SENF_LOG((Server::SENFLogArea)(log::NOTICE)( 
                  "Console server started at " << address ));
+    return *instance_;
 }
 
-prefix_ void senf::console::start(senf::INet6SocketAddress const & address)
+prefix_ senf::console::Server &
+senf::console::Server::start(senf::INet6SocketAddress const & address)
 {
     senf::TCPv6ServerSocketHandle handle (address);
-    handle.protocol().reuseaddr();
-    senf::console::detail::Server::start(handle);
-    SENF_LOG((detail::Server::SENFLogArea)(log::NOTICE)( 
+    senf::console::Server::start(handle);
+    SENF_LOG((Server::SENFLogArea)(log::NOTICE)( 
                  "Console server started at " << address ));
+    return *instance_;
 }
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::console::detail::Server
+// senf::console::Server
 
-boost::scoped_ptr<senf::console::detail::Server> senf::console::detail::Server::instance_;
+boost::scoped_ptr<senf::console::Server> senf::console::Server::instance_;
 
-prefix_ void senf::console::detail::Server::start(ServerHandle handle)
+prefix_ void senf::console::Server::start(ServerHandle handle)
 {
     SENF_ASSERT( ! instance_ );
     instance_.reset(new Server(handle));
 }
 
-prefix_ senf::console::detail::Server::Server(ServerHandle handle)
+prefix_ senf::console::Server::Server(ServerHandle handle)
     : handle_ (handle)
 {
     Scheduler::instance().add( handle_, senf::membind(&Server::newClient, this) );
 }
 
-prefix_ senf::console::detail::Server::~Server()
+prefix_ senf::console::Server::~Server()
 {
     Scheduler::instance().remove(handle_);
 }
 
-prefix_ void senf::console::detail::Server::newClient(Scheduler::EventId event)
+prefix_ void senf::console::Server::newClient(Scheduler::EventId event)
 {
     ServerHandle::ClientSocketHandle client (handle_.accept());
-    boost::intrusive_ptr<Client> p (new Client(client));
+    boost::intrusive_ptr<Client> p (new Client(client, name_));
     clients_.insert( p );
     SENF_LOG(( "Registered new client " << p.get() ));
 }
 
-prefix_ void senf::console::detail::Server::removeClient(Client & client)
+prefix_ void senf::console::Server::removeClient(Client & client)
 {
     SENF_LOG(( "Disposing client " << & client ));
     // THIS DELETES THE CLIENT INSTANCE !!
@@ -96,26 +99,26 @@ prefix_ void senf::console::detail::Server::removeClient(Client & client)
 }
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::console::detail::Client
+// senf::console::Client
 
-prefix_ senf::console::detail::Client::Client(ClientHandle handle)
-    : handle_ (handle), out_(::dup(handle.fd()))
+prefix_ senf::console::Client::Client(ClientHandle handle, std::string const & name)
+    : handle_ (handle), name_ (name), out_(::dup(handle.fd()))
 {
-    out_ << "# " << std::flush;
+    showPrompt();
     ReadHelper<ClientHandle>::dispatch( handle_, 16384u, ReadUntil("\n"),
                                         senf::membind(&Client::clientData, this) );
 }
 
-prefix_ senf::console::detail::Client::~Client()
+prefix_ senf::console::Client::~Client()
 {}
 
-prefix_ void senf::console::detail::Client::stopClient()
+prefix_ void senf::console::Client::stopClient()
 {
     // THIS COMMITS SUICIDE. THE INSTANCE IS GONE AFTER removeClient RETURNS
     Server::instance_->removeClient(*this);
 }
 
-prefix_ void senf::console::detail::Client::clientData(ReadHelper<ClientHandle>::ptr helper)
+prefix_ void senf::console::Client::clientData(ReadHelper<ClientHandle>::ptr helper)
 {
     if (helper->error() || handle_.eof()) {
         // THIS COMMITS SUICIDE. THE INSTANCE IS GONE AFTER stopClient RETURNS
@@ -123,26 +126,36 @@ prefix_ void senf::console::detail::Client::clientData(ReadHelper<ClientHandle>:
         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
 
-    ParseCommandInfo command;
-    if (parser_.parseCommand(data, command))
-        executor_(command, out_);
-    else 
-        out_ << "syntax error" << std::endl;
+    try {
+        if (! parser_.parse(data, boost::bind<void>(boost::ref(executor_), _1, boost::ref(out_))))
+            out_ << "syntax error" << std::endl;
+    }
+    catch (Executor::ExitException &) {
+        // THIS COMMITS SUICIDE. THE INSTANCE IS GONE AFTER stopClient RETURNS
+        stopClient();
+        return;
+    }
+    catch (std::exception & ex) {
+        out_ << ex.what() << std::endl;
+    }
+    catch (...) {
+        out_ << "unidentified error (unknown exception thrown)" << std::endl;
+    }
 
-    out_ << "# " << std::flush;
+    showPrompt();
     ReadHelper<ClientHandle>::dispatch( handle_, 16384u, ReadUntil("\n"),
                                         senf::membind(&Client::clientData, this) );
 }
 
+prefix_ void senf::console::Client::showPrompt()
+{
+    out_ << name_ << ":" << executor_.cwd().path() << "# " << std::flush;
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 //#include "Server.mpp"