4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 \brief Server public header */
31 #include <boost/utility.hpp>
32 #include <boost/scoped_ptr.hpp>
33 #include <boost/shared_ptr.hpp>
34 #include "../Utils/intrusive_refcount.hh"
35 #include "../Socket/Protocols/INet/TCPSocketHandle.hh"
36 #include "../Socket/ServerSocketHandle.hh"
37 #include "../Scheduler/Scheduler.hh"
38 #include "../Scheduler/Binding.hh"
39 #include "../Scheduler/Timer.hh"
40 #include "../Scheduler/ReadHelper.hh"
42 #include "Executor.hh"
43 #include "../Socket/Protocols/INet/INetAddressing.hh"
44 #include "../Utils/Logger.hh"
46 //#include "Server.mpp"
48 ///////////////////////////////hh.p////////////////////////////////////////
55 /** \brief Interactive console server
57 This class provides an interactive console TCP server.
59 \todo Add interactivity detection using timeout
60 \idea To support blocking commands, we could give the Client 'suspend()' and 'resume()'
61 members. suspend() would probably throw some kind of exception to transfer control back
62 to the Client instance. on resume(), the command would be called again, maybe setting
63 some flag or something. Example for use: Host name resolution: Here we can just built
64 our own little host-name cache. When the name is not found, we ask the resolver to
65 resolve it and call 'resume' when the name is found. Since it is in the cache now, the
66 command will now complete.
68 \implementation We do \e not provide an \c instance() member so we can easily later extend
69 the server to allow registering more than one instance, e.g. with each instance on a
70 differently firewalled port and with different security restrictions.
72 \ingroup console_access
77 SENF_LOG_CLASS_AREA();
78 SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
80 ///////////////////////////////////////////////////////////////////////////
83 typedef detail::ServerHandle ServerHandle;
85 enum Mode { Automatic, Interactive, Noninteractive };
87 ///////////////////////////////////////////////////////////////////////////
91 static Server & start(senf::INet4SocketAddress const & address);
92 ///< Start server on given IPv4 address/port
93 static Server & start(senf::INet6SocketAddress const & address);
94 ///< Start server on given IPv6 address/port
96 std::string const & name() const; ///< Get server name
97 /**< This information is used in the prompt string. */
99 Server & name(std::string const & name); ///< Set server name
100 /**< This information is used in the prompt string. */
102 DirectoryNode & root() const; ///< Get root node
104 Server & root(DirectoryNode & root); ///< Set root node
105 /**< \a node will be the root node for all clients launched
108 Mode mode() const; ///< Get mode
109 /**< \see \ref mode(Mode) */
111 Server & mode(Mode mode); ///< Set mode
112 /**< There are two Server types:
113 \li An interactive server displays a command prompt and
114 optionally supports command-line editing.
115 \li A non-interactive server does not display any
116 prompt and does not allow any interactive
117 editing. This type of server is used for (remote)
120 The \a mode parameter selects between these modes. In
121 \c Automatic (the default), a client connection is
122 considered to be interactive if there is no data
123 traffic in the first 500ms after the connection is
126 void stop(); ///< Stop the server
127 /**< All clients will be closed */
133 Server(ServerHandle handle);
135 static Server & start(ServerHandle handle);
136 static boost::scoped_ptr<Server> & instancePtr();
138 void newClient(Scheduler::EventId event);
139 void removeClient(Client & client);
141 ServerHandle handle_;
142 DirectoryNode::ptr root_;
145 typedef std::set< boost::intrusive_ptr<Client> > Clients;
152 /** \brief Server client instance
154 Whenever a new client connects, a new instance of this class is created. This class shows a
155 command prompt, receives the commands, parses them and then passes (using a CommandParser)
156 and passes the commands to an Executor instance.
158 \ingroup console_access
161 : public senf::intrusive_refcount,
162 private boost::base_from_member< detail::NonblockingSocketOStream >,
163 public senf::log::IOStreamTarget
165 typedef boost::base_from_member< detail::NonblockingSocketOStream > out_t;
167 SENF_LOG_CLASS_AREA();
168 SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
170 static const unsigned INTERACTIVE_TIMEOUT = 500; // milliseconds;
173 typedef Server::ServerHandle::ClientSocketHandle ClientHandle;
177 void stop(); ///< Stop the client
178 /**< This will close the client socket. */
180 std::string const & name() const;
181 ClientHandle handle() const;
182 std::ostream & stream();
183 std::string promptString() const;
184 DirectoryNode & root() const;
185 Server::Mode mode() const;
187 static Client & get(std::ostream & os);
192 Client(Server & server, ClientHandle handle);
194 void setInteractive();
195 void setNoninteractive();
197 void translate(std::string & data);
198 unsigned handleInput(std::string input, bool incremental = false);
199 virtual void v_write(senf::log::time_type timestamp, std::string const & stream,
200 std::string const & area, unsigned level,
201 std::string const & message);
204 ClientHandle handle_;
205 SchedulerBinding binding_;
206 SchedulerTimer timer_;
207 CommandParser parser_;
210 std::string lastCommand_;
211 boost::scoped_ptr<detail::ClientReader> reader_;
215 friend class detail::ClientReader;
216 friend class detail::NonblockingSocketSink;
219 /** \brief Output Console Client instance as it's string representation
222 std::ostream & operator<<(std::ostream & os, Client const & client);
224 /** \brief Output Console Client instance as it's string representation
227 std::ostream & operator<<(std::ostream & os, Client * client);
231 ///////////////////////////////hh.e////////////////////////////////////////
232 #include "Server.cci"
233 //#include "Server.ct"
234 //#include "Server.cti"
241 // comment-column: 40
242 // c-file-style: "senf"
243 // indent-tabs-mode: nil
244 // ispell-local-dictionary: "american"
245 // compile-command: "scons -u test"