\brief Server non-inline non-template implementation */
#include "Server.hh"
-#include "Server.ih"
+//#include "Server.ih"
// Custom includes
+#include <unistd.h>
+#include <iostream>
#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::console::detail::Server::start(senf::TCPv4ServerSocketHandle(address));
- SENF_LOG((detail::Server::SENFLogArea)(log::NOTICE)(
+ senf::TCPv4ServerSocketHandle handle (address);
+ 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::console::detail::Server::start(senf::TCPv6ServerSocketHandle(address));
- SENF_LOG((detail::Server::SENFLogArea)(log::NOTICE)(
+ senf::TCPv6ServerSocketHandle handle (address);
+ 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 !!
}
///////////////////////////////////////////////////////////////////////////
-// senf::console::detail::Client
+// senf::console::Client
-prefix_ senf::console::detail::Client::Client(ClientHandle handle)
- : handle_ (handle)
+prefix_ senf::console::Client::Client(ClientHandle handle, std::string const & name)
+ : handle_ (handle), name_ (name), out_(::dup(handle.fd()))
{
+ 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
tail_ = helper->tail();
boost::trim(data); // Gets rid of superfluous \r or \n characters
- SENF_LOG(( this << ": " << data ));
+ 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;
+ }
+
+ 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"