Utils/Logger: Remove dependency on libboost_datetime
[senf.git] / Console / Server.ih
index d25aed3..6bbaf5a 100644 (file)
 #define IH_Server_ 1
 
 // Custom includes
-#include <set>
-#include <boost/utility.hpp>
-#include <boost/scoped_ptr.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/iostreams/device/file_descriptor.hpp>
+#include <boost/iostreams/concepts.hpp>
 #include <boost/iostreams/stream.hpp>
-#include "../Utils/intrusive_refcount.hh"
-#include "../Socket/Protocols/INet/TCPSocketHandle.hh"
-#include "../Socket/ServerSocketHandle.hh"
-#include "../Scheduler/Scheduler.hh"
-#include "../Scheduler/ReadHelper.hh"
-#include "Parse.hh"
-#include "Executor.hh"
 
 ///////////////////////////////ih.p////////////////////////////////////////
 
 namespace senf {
 namespace console {
-namespace detail {
 
+    class Server;
     class Client;
 
-    /** \brief
-      */
-    class Server
-        : boost::noncopyable
+namespace detail {
+
+    /** \brief Internal: Nonblocking boost::iostreams::sink
+
+        The sink discards data if the output socket would.
+     */
+    class NonblockingSocketSink 
+        : public boost::iostreams::sink
     {
-        SENF_LOG_CLASS_AREA();
-        SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
     public:
-        ///////////////////////////////////////////////////////////////////////////
-        // Types
+        typedef ClientSocketHandle< 
+            MakeSocketPolicy<StreamFramingPolicy,
+                             WriteablePolicy,
+                             ConnectedCommunicationPolicy>::policy > Handle;
 
-        typedef senf::ServerSocketHandle<
-            senf::MakeSocketPolicy< senf::TCPv4SocketProtocol::Policy, 
-                                    senf::UnspecifiedAddressingPolicy>::policy > ServerHandle;
+        NonblockingSocketSink(Client & client);
+        std::streamsize write(const char * s, std::streamsize n);
 
-        ~Server();
+        Client & client() const;
+        
+    private:
+        Client & client_;
+    };
 
-        static void start(ServerHandle handle);
+    typedef boost::iostreams::stream<NonblockingSocketSink> NonblockingSocketOStream;
 
-    protected:
+    typedef senf::ServerSocketHandle<
+        senf::MakeSocketPolicy< senf::TCPv4SocketProtocol::Policy, 
+                                senf::UnspecifiedAddressingPolicy>::policy > ServerHandle;
 
-    private:
-        Server(ServerHandle handle);
+    /** \brief Internal: Generic client interface
 
-        void newClient(Scheduler::EventId event);
-        void removeClient(Client & client);
-        
-        ServerHandle handle_;
-        
-        typedef std::set< boost::intrusive_ptr<Client> > Clients;
-        Clients clients_;
-        
-        static boost::scoped_ptr<Server> instance_;
-        
-        friend class Client;
-    };
-    
-    /** \brief
+        The ClientReader encapsulates the interaction of a single network client with the user: It
+        manages prompt display and reading an interactive command.
      */
-    class Client
-        : public senf::intrusive_refcount
+    class ClientReader
     {
-        SENF_LOG_CLASS_AREA();
-        SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
     public:
-        typedef Server::ServerHandle::ClientSocketHandle ClientHandle;
+        typedef ServerHandle::ClientSocketHandle ClientHandle;
+
+        virtual ~ClientReader() = 0;
 
-        ~Client();
+        // Called by subclasses to get information from the Client
+
+        Client & client() const;
+        std::string promptString() const;
+        ClientHandle handle() const;
+        std::ostream & stream() const;
+
+        // Called by subclasses to perform actions in the Client
 
         void stopClient();
+        void handleInput(std::string const & input) const;
+
+        // Called by the Client
+
+        void disablePrompt();
+        void enablePrompt();
+        void translate(std::string & data);
 
     protected:
-        
+        ClientReader(Client & client);
+
     private:
-        Client(ClientHandle handle);
+        virtual void v_disablePrompt() = 0;
+        virtual void v_enablePrompt() = 0;
+        virtual void v_translate(std::string & data) = 0;
+
+        Client & client_;
+    };
 
-        void clientData(ReadHelper<ClientHandle>::ptr helper);
+    /** \brief Internal: Primitive ClientReader implementation
         
-        ClientHandle handle_;
-        std::string tail_;
-        SingleCommandParser parser_;
-        Executor executor_;
+        This implementation uses the cooked telnet mode to read lines from the console. It does not
+        support explicit line editing or any other advanced features.
+     */
+    class DumbClientReader
+        : public ClientReader
+    {
+    public:
+        DumbClientReader(Client & client);
+
+    private:
+        virtual void v_disablePrompt();
+        virtual void v_enablePrompt();
+        virtual void v_translate(std::string & data);
 
-        typedef boost::iostreams::stream<boost::iostreams::file_descriptor_sink> fdostream;
-        fdostream out_;
+        void clientData(senf::ReadHelper<ClientHandle>::ptr helper);
+        void showPrompt();
 
-        friend class Server;
+        std::string tail_;
+        unsigned promptLen_;
+        bool promptActive_;
     };
-
+    
 }}}
 
 ///////////////////////////////ih.e////////////////////////////////////////