X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Console%2FServer.hh;h=59111e63970543f0a124a1b81393421ade5a24bc;hb=9cda1b12a3e68538ea8157ca96810f0423123a70;hp=685eae2a4a8ef9ea2648ec98bc47ba1a277d9e6e;hpb=c70f7413515b513656f850f51a3cc2ea9d776a37;p=senf.git diff --git a/Console/Server.hh b/Console/Server.hh index 685eae2..59111e6 100644 --- a/Console/Server.hh +++ b/Console/Server.hh @@ -31,8 +31,6 @@ #include #include #include -#include -#include #include "../Utils/intrusive_refcount.hh" #include "../Socket/Protocols/INet/TCPSocketHandle.hh" #include "../Socket/ServerSocketHandle.hh" @@ -41,8 +39,10 @@ #include "Parse.hh" #include "Executor.hh" #include "../Socket/Protocols/INet/INetAddressing.hh" +#include "../Utils/Logger.hh" //#include "Server.mpp" +#include "Server.ih" ///////////////////////////////hh.p//////////////////////////////////////// namespace senf { @@ -56,6 +56,17 @@ namespace console { \todo Add readline support \todo Add interactivity detection using timeout + \idea To support blocking commands, we could give the Client 'suspend()' and 'resume()' + members. suspend() would probably throw some kind of exception to transfer control back + to the Client instance. on resume(), the command would be called again, maybe setting + some flag or something. Example for use: Host name resolution: Here we can just built + our own little host-name cache. When the name is not found, we ask the resolver to + resolve it and call 'resume' when the name is found. Since it is in the cache now, the + command will now complete. + + \implementation We do \e not provide an \c instance() member so we can easily later extend + the server to allow registering more than one instance, e.g. with each instance on a + differently firewalled port and with different security restrictions. */ class Server : boost::noncopyable @@ -76,7 +87,6 @@ namespace console { ///< Start server on given IPv4 address/port static Server & start(senf::INet6SocketAddress const & address); ///< Start server on given IPv6 address/port - void name(std::string const & name); ///< Set server name /**< This information is used in the prompt string. */ @@ -85,7 +95,8 @@ namespace console { private: Server(ServerHandle handle); - static void start(ServerHandle handle); + static Server & start(ServerHandle handle); + static boost::scoped_ptr & instancePtr(); void newClient(Scheduler::EventId event); void removeClient(Client & client); @@ -96,8 +107,6 @@ namespace console { Clients clients_; std::string name_; - static boost::scoped_ptr instance_; - friend class Client; }; @@ -108,15 +117,15 @@ namespace console { and passes the commands to an Executor instance. \fixme Fix Client::clientData implementation - \fixme Remove the 'dup' needed here so we don't close the same fd twice (see Client - constructor) - \fixme Make output non-blocking (use a non-blocking/discarding streambuf) and possibly set - socket send buffer size \fixme Don't register a new ReadHelper every round */ class Client - : public senf::intrusive_refcount + : public senf::intrusive_refcount, + private boost::base_from_member< detail::NonblockingSocketOStream >, + public senf::log::IOStreamTarget { + typedef boost::base_from_member< detail::NonblockingSocketOStream > out_t; + SENF_LOG_CLASS_AREA(); SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE ); public: @@ -130,19 +139,23 @@ namespace console { protected: private: - Client(ClientHandle handle, std::string const & name); + Client(Server & server, ClientHandle handle, std::string const & name); void clientData(ReadHelper::ptr helper); void showPrompt(); + + virtual void v_write(boost::posix_time::ptime timestamp, std::string const & stream, + std::string const & area, unsigned level, + std::string const & message); + Server & server_; ClientHandle handle_; std::string tail_; CommandParser parser_; Executor executor_; std::string name_; - - typedef boost::iostreams::stream fdostream; - fdostream out_; + unsigned promptLen_; + std::string lastCommand_; friend class Server; };