X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Console%2FServer.cc;h=ac9f034c693a644d01ded11c9141dbc4163cb7aa;hb=e879290346fe5242d7df2d70ee552d264081492f;hp=53db4e7a280c70854bbac8a984dc4413be9b4595;hpb=9cda1b12a3e68538ea8157ca96810f0423123a70;p=senf.git diff --git a/Console/Server.cc b/Console/Server.cc index 53db4e7..ac9f034 100644 --- a/Console/Server.cc +++ b/Console/Server.cc @@ -27,7 +27,6 @@ #include "Server.ih" // Custom includes -#include #include #include #include @@ -36,6 +35,7 @@ #include "../Utils/senfassert.hh" #include "../Utils/membind.hh" #include "../Utils/Logger/SenfLog.hh" +#include "Readline.hh" //#include "Server.mpp" #define prefix_ @@ -48,8 +48,11 @@ prefix_ std::streamsize senf::console::detail::NonblockingSocketSink::write(cons std::streamsize n) { try { - if (handle_.writeable()) - handle_.write(s, s+n); + if (client_.handle().writeable()) { + std::string data (s, n); + client_.translate(data); + client_.handle().write( data ); + } } catch (SystemException & ex) { ; @@ -126,41 +129,86 @@ prefix_ void senf::console::Server::removeClient(Client & client) } /////////////////////////////////////////////////////////////////////////// -// senf::console::Client +// senf::console::detail::DumbClientReader -prefix_ senf::console::Client::Client(Server & server, ClientHandle handle, - std::string const & name) - : out_t(handle), senf::log::IOStreamTarget(out_t::member), server_ (server), - handle_ (handle), name_ (name), promptLen_(0) +prefix_ senf::console::detail::DumbClientReader::DumbClientReader(Client & client) + : ClientReader(client), promptLen_ (0), promptActive_ (false) { showPrompt(); - ReadHelper::dispatch( handle_, 16384u, ReadUntil("\n"), - senf::membind(&Client::clientData, this) ); - route< senf::SenfLog, senf::log::NOTICE >(); -} - -prefix_ senf::console::Client::~Client() -{} - -prefix_ void senf::console::Client::stopClient() -{ - // THIS COMMITS SUICIDE. THE INSTANCE IS GONE AFTER removeClient RETURNS - server_.removeClient(*this); + ReadHelper::dispatch( handle(), 16384u, ReadUntil("\n"), + senf::membind(&DumbClientReader::clientData, this) ); } -prefix_ void senf::console::Client::clientData(ReadHelper::ptr helper) +prefix_ void +senf::console::detail::DumbClientReader::clientData(senf::ReadHelper::ptr helper) { - promptLen_ = 0; - if (helper->error() || handle_.eof()) { + if (helper->error() || handle().eof()) { // THIS COMMITS SUICIDE. THE INSTANCE IS GONE AFTER stopClient RETURNS stopClient(); return; } + + promptLen_ = 0; + promptActive_ = false; std::string data (tail_ + helper->data()); tail_ = helper->tail(); - boost::trim(data); // Gets rid of superfluous \r or \n characters + boost::trim(data); // Gets rid of superfluous \r or \n characters + handleInput(data); + + showPrompt(); + ReadHelper::dispatch( handle(), 16384u, ReadUntil("\n"), + senf::membind(&DumbClientReader::clientData, this) ); + +} + +prefix_ void senf::console::detail::DumbClientReader::showPrompt() +{ + std::string prompt (promptString()); + + stream() << std::flush; + handle().write(prompt); + promptLen_ = prompt.size(); + promptActive_ = true; +} + +prefix_ void senf::console::detail::DumbClientReader::v_disablePrompt() +{ + if (promptActive_ && promptLen_ > 0) { + stream() << '\r' << std::string(' ', promptLen_) << '\r'; + promptLen_ = 0; + } +} + +prefix_ void senf::console::detail::DumbClientReader::v_enablePrompt() +{ + if (promptActive_ && ! promptLen_) + showPrompt(); +} + +prefix_ void senf::console::detail::DumbClientReader::v_translate(std::string & data) +{} +/////////////////////////////////////////////////////////////////////////// +// senf::console::Client + +prefix_ senf::console::Client::Client(Server & server, ClientHandle handle, + std::string const & name) + : out_t(boost::ref(*this)), senf::log::IOStreamTarget(out_t::member), server_ (server), + handle_ (handle), name_ (name), reader_ (new detail::SafeReadlineClientReader (*this)) +{ + executor_.autocd(true).autocomplete(true); + handle_.facet().nodelay(); + // route< senf::SenfLog, senf::log::NOTICE >(); +} + +prefix_ void senf::console::Client::translate(std::string & data) +{ + reader_->translate(data); +} + +prefix_ void senf::console::Client::handleInput(std::string data) +{ if (data.empty()) data = lastCommand_; else @@ -168,32 +216,24 @@ prefix_ void senf::console::Client::clientData(ReadHelper::ptr hel try { if (! parser_.parse(data, boost::bind( boost::ref(executor_), - boost::ref(out_t::member), + boost::ref(stream()), _1 )) ) - out_t::member << "syntax error" << std::endl; + stream() << "syntax error" << std::endl; } catch (Executor::ExitException &) { - // THIS COMMITS SUICIDE. THE INSTANCE IS GONE AFTER stopClient RETURNS - stopClient(); + // This generates an EOF condition on the Handle. This EOF condition is expected + // to be handled gracefully by the ClientReader. We cannot call stop() here, since we + // are called from the client reader callback and that will continue executing even if we + // call stop here ... + handle_.facet().shutdown(senf::TCPSocketProtocol::ShutRD); return; } catch (std::exception & ex) { - out_t::member << ex.what() << std::endl; + stream() << ex.what() << std::endl; } catch (...) { - out_t::member << "unidentified error (unknown exception thrown)" << std::endl; + stream() << "unidentified error (unknown exception thrown)" << std::endl; } - - showPrompt(); - ReadHelper::dispatch( handle_, 16384u, ReadUntil("\n"), - senf::membind(&Client::clientData, this) ); -} - -prefix_ void senf::console::Client::showPrompt() -{ - 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, @@ -201,13 +241,30 @@ prefix_ void senf::console::Client::v_write(boost::posix_time::ptime timestamp, std::string const & area, unsigned level, std::string const & message) { - if (promptLen_) - out_t::member << '\r' << std::string(' ', promptLen_) << '\r'; + reader_->disablePrompt(); IOStreamTarget::v_write(timestamp, stream, area, level, message); - if (promptLen_) - showPrompt(); + out_t::member << std::flush; + reader_->enablePrompt(); } +prefix_ std::ostream & senf::console::operator<<(std::ostream & os, Client const & client) +{ + // typedef senf::ClientSocketHandle::policy > v4Socket; + if( senf::check_socket_cast( client.handle())) { + os<( client.handle()).peer(); + } + else if( senf::check_socket_cast( client.handle())) { + os<( client.handle()).peer(); + } + else{ + os<<((void *)&client); + } + return os; +} +prefix_ std::ostream & senf::console::operator<<(std::ostream & os, Client * client) +{ + return os<<*client; +} ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ //#include "Server.mpp"