#include "../Socket/Protocols/INet/TCPSocketHandle.hh"
#include "../Socket/ServerSocketHandle.hh"
#include "../Scheduler/Scheduler.hh"
+#include "../Scheduler/Binding.hh"
+#include "../Scheduler/Timer.hh"
#include "../Scheduler/ReadHelper.hh"
#include "Parse.hh"
#include "Executor.hh"
\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.
+
+ \ingroup console_access
*/
class Server
: boost::noncopyable
typedef detail::ServerHandle ServerHandle;
+ enum Mode { Automatic, Interactive, Noninteractive };
+
+ ///////////////////////////////////////////////////////////////////////////
+
~Server();
static Server & start(senf::INet4SocketAddress const & address);
///< Start server on given IPv4 address/port
static Server & start(senf::INet6SocketAddress const & address);
///< Start server on given IPv6 address/port
+
+ std::string const & name() const; ///< Get server name
+ /**< This information is used in the prompt string. */
+
Server & name(std::string const & name); ///< Set server name
/**< This information is used in the prompt string. */
+
+ DirectoryNode & root() const; ///< Get root node
+
+ Server & root(DirectoryNode & root); ///< Set root node
+ /**< \a node will be the root node for all clients launched
+ from this server. */
+
+ Mode mode() const; ///< Get mode
+ /**< \see \ref mode(Mode) */
+ Server & mode(Mode mode); ///< Set mode
+ /**< There are two Server types:
+ \li An interactive server displays a command prompt and
+ optionally supports command-line editing.
+ \li A non-interactive server does not display any
+ prompt and does not allow any interactive
+ editing. This type of server is used for (remote)
+ scripting.
+
+ The \a mode parameter selects between these modes. In
+ \c Automatic (the default), a client connection is
+ considered to be interactive if there is no data
+ traffic in the first 500ms after the connection is
+ opened. */
+
void stop(); ///< Stop the server
/**< All clients will be closed */
+
protected:
void removeClient(Client & client);
ServerHandle handle_;
+ DirectoryNode::ptr root_;
+ Mode mode_;
typedef std::set< boost::intrusive_ptr<Client> > Clients;
Clients clients_;
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.
+
+ \ingroup console_access
*/
class Client
: public senf::intrusive_refcount,
SENF_LOG_CLASS_AREA();
SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
+ static const unsigned INTERACTIVE_TIMEOUT = 500; // milliseconds;
+
public:
typedef Server::ServerHandle::ClientSocketHandle ClientHandle;
ClientHandle handle() const;
std::ostream & stream();
std::string promptString() const;
+ DirectoryNode & root() const;
+ Server::Mode mode() const;
static Client & get(std::ostream & os);
protected:
private:
- Client(Server & server, ClientHandle handle, std::string const & name);
+ Client(Server & server, ClientHandle handle);
+ void setInteractive();
+ void setNoninteractive();
+
void translate(std::string & data);
- void handleInput(std::string input);
- virtual void v_write(boost::posix_time::ptime timestamp, std::string const & stream,
+ unsigned handleInput(std::string input, bool incremental = false);
+ virtual void v_write(senf::log::time_type timestamp, std::string const & stream,
std::string const & area, unsigned level,
std::string const & message);
Server & server_;
ClientHandle handle_;
+ SchedulerBinding binding_;
+ SchedulerTimer timer_;
CommandParser parser_;
Executor executor_;
std::string name_;
std::string lastCommand_;
boost::scoped_ptr<detail::ClientReader> reader_;
+ Server::Mode mode_;
friend class Server;
friend class detail::ClientReader;
friend class detail::NonblockingSocketSink;
};
- /** \brief Output INet4Address instance as it's string representation
- \related INet4Address
- */
+ /** \brief Output Console Client instance as it's string representation
+ \related Client
+ */
std::ostream & operator<<(std::ostream & os, Client const & client);
+
+ /** \brief Output Console Client instance as it's string representation
+ \related Client
+ */
std::ostream & operator<<(std::ostream & os, Client * client);
}}