Console: Refactor argument parsing into iterator
[senf.git] / Console / Server.hh
index 59111e6..be3dd6c 100644 (file)
@@ -54,7 +54,6 @@ namespace console {
 
         This class provides an interactive console TCP server.
 
-        \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
@@ -76,10 +75,8 @@ namespace console {
     public:
         ///////////////////////////////////////////////////////////////////////////
         // Types
-
-        typedef senf::ServerSocketHandle<
-            senf::MakeSocketPolicy< senf::TCPv4SocketProtocol::Policy, 
-                                    senf::UnspecifiedAddressingPolicy>::policy > ServerHandle;
+        
+        typedef detail::ServerHandle ServerHandle;
 
         ~Server();
 
@@ -87,9 +84,12 @@ 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
+        Server & name(std::string const & name); ///< Set server name
                                         /**< This information is used in the prompt string. */
-
+        
+        void stop();                    ///< Stop the server
+                                        /**< All clients will be closed */
+        
     protected:
 
     private:
@@ -115,9 +115,6 @@ namespace console {
         Whenever a new client connects, a new instance of this class is created. This class shows a
         command prompt, receives the commands, parses them and then passes (using a CommandParser)
         and passes the commands to an Executor instance.
-
-        \fixme Fix Client::clientData implementation
-        \fixme Don't register a new ReadHelper every round
      */
     class Client
         : public senf::intrusive_refcount, 
@@ -128,37 +125,51 @@ namespace console {
 
         SENF_LOG_CLASS_AREA();
         SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
+
     public:
         typedef Server::ServerHandle::ClientSocketHandle ClientHandle;
 
         ~Client();
 
-        void stopClient();              ///< Stop the client
+        void stop();                    ///< Stop the client
                                         /**< This will close the client socket. */
 
+        std::string const & name() const;
+        ClientHandle handle() const;
+        std::ostream & stream();
+        std::string promptString() const;
+
+        static Client & get(std::ostream & os);
+
     protected:
         
     private:
         Client(Server & server, ClientHandle handle, std::string const & name);
 
-        void clientData(ReadHelper<ClientHandle>::ptr helper);
-        void showPrompt();
-
+        void translate(std::string & data);
+        void handleInput(std::string input);
         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_;
-        unsigned promptLen_;
         std::string lastCommand_;
+        boost::scoped_ptr<detail::ClientReader> reader_;
 
         friend class Server;
+        friend class detail::ClientReader;
+        friend class detail::NonblockingSocketSink;
     };
+        
+    /** \brief Output INet4Address instance as it's string representation
+            \related INet4Address
+         */
+    std::ostream & operator<<(std::ostream & os, Client const & client);
+    std::ostream & operator<<(std::ostream & os, Client * client);
 
 }}