#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"
This class provides an interactive console TCP server.
- \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
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.
-
+
\ingroup console_access
*/
class Server
- : boost::noncopyable
+ : public senf::intrusive_refcount
{
SENF_LOG_CLASS_AREA();
SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
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 */
-
+ /**< All clients will be closed
+ \warning The Server instance itself will be deleted */
+
protected:
private:
Server(ServerHandle handle);
static Server & start(ServerHandle handle);
- static boost::scoped_ptr<Server> & instancePtr();
void newClient(Scheduler::EventId event);
void removeClient(Client & client);
ServerHandle handle_;
+ DirectoryNode::ptr root_;
+ Mode mode_;
typedef std::set< boost::intrusive_ptr<Client> > Clients;
Clients clients_;
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);
+ 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;