// Custom includes
#include <boost/iostreams/concepts.hpp>
#include <boost/iostreams/stream.hpp>
+#include <set>
///////////////////////////////ih.p////////////////////////////////////////
namespace senf {
namespace console {
+
+ class Server;
+ class Client;
+
namespace detail {
+ class ServerManager
+ : public senf::singleton<ServerManager>
+ {
+ public:
+ typedef boost::intrusive_ptr<Server> ptr;
+
+ protected:
+
+ private:
+ static void add(ptr server);
+ static void remove(ptr server);
+
+ typedef std::set<ptr> Servers;
+ Servers servers_;
+
+ friend class senf::console::Server;
+ };
+
+ /** \brief Internal: Nonblocking boost::iostreams::sink
+
+ The sink discards data if the output socket would.
+
+ \fixme Don't throw exceptions ... set stream error indicator (if at all)
+ */
class NonblockingSocketSink
: public boost::iostreams::sink
{
WriteablePolicy,
ConnectedCommunicationPolicy>::policy > Handle;
- NonblockingSocketSink(Handle handle);
+ NonblockingSocketSink(Client & client);
std::streamsize write(const char * s, std::streamsize n);
+
+ Client & client() const;
private:
- Handle handle_;
+ Client & client_;
};
typedef boost::iostreams::stream<NonblockingSocketSink> NonblockingSocketOStream;
+ typedef senf::ServerSocketHandle<
+ senf::MakeSocketPolicy< senf::TCPv4SocketProtocol::Policy,
+ senf::UnspecifiedAddressingPolicy>::policy > ServerHandle;
+
+ /** \brief Internal: Generic client interface
+
+ The ClientReader encapsulates the interaction of a single network client with the user: It
+ manages prompt display and reading an interactive command.
+ */
+ class ClientReader
+ {
+ public:
+ typedef ServerHandle::ClientSocketHandle ClientHandle;
+
+ virtual ~ClientReader() = 0;
+
+ // 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();
+ std::string::size_type handleInput(std::string const & input, bool incremental=false) const;
+
+ // Called by the Client
+
+ void disablePrompt();
+ void enablePrompt();
+ void translate(std::string & data);
+
+ protected:
+ ClientReader(Client & client);
+
+ private:
+ virtual void v_disablePrompt() = 0;
+ virtual void v_enablePrompt() = 0;
+ virtual void v_translate(std::string & data) = 0;
+
+ Client & client_;
+ };
+
+ /** \brief Internal: Primitive ClientReader implementation
+
+ 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);
+
+ void clientData(senf::ReadHelper<ClientHandle>::ptr helper);
+ void showPrompt();
+
+ std::string tail_;
+ unsigned promptLen_;
+ bool promptActive_;
+ };
+
+ /** \brief Internal: Primitive ClientReader implementation
+
+ 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 NoninteractiveClientReader
+ : public ClientReader
+ {
+ public:
+ NoninteractiveClientReader(Client & client);
+
+ private:
+ virtual void v_disablePrompt();
+ virtual void v_enablePrompt();
+ virtual void v_translate(std::string & data);
+
+ void newData(senf::Scheduler::EventId event);
+
+ SchedulerBinding binding_;
+ std::string buffer_;
+ };
+
}}}
///////////////////////////////ih.e////////////////////////////////////////