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 */
26 #ifndef HH_SENF_Scheduler_Console_Server_
27 #define HH_SENF_Scheduler_Console_Server_ 1
31 #include <boost/utility.hpp>
32 #include <boost/scoped_ptr.hpp>
33 #include <boost/shared_ptr.hpp>
34 #include <senf/Utils/intrusive_refcount.hh>
35 #include <senf/Socket/Protocols/INet/TCPSocketHandle.hh>
36 #include <senf/Socket/ServerSocketHandle.hh>
37 #include <senf/Scheduler/Scheduler.hh>
38 #include <senf/Scheduler/ReadHelper.hh>
40 #include "Executor.hh"
41 #include <senf/Socket/Protocols/INet/INetAddressing.hh>
42 #include <senf/Utils/Logger.hh>
44 //#include "Server.mpp"
46 ///////////////////////////////hh.p////////////////////////////////////////
53 /** \brief Interactive console server
55 This class provides an interactive console TCP server.
57 \idea To support blocking commands, we could give the Client 'suspend()' and 'resume()'
58 members. suspend() would probably throw some kind of exception to transfer control back
59 to the Client instance. on resume(), the command would be called again, maybe setting
60 some flag or something. Example for use: Host name resolution: Here we can just built
61 our own little host-name cache. When the name is not found, we ask the resolver to
62 resolve it and call 'resume' when the name is found. Since it is in the cache now, the
63 command will now complete.
65 \ingroup console_access
68 : public senf::intrusive_refcount
70 SENF_LOG_CLASS_AREA();
71 SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
73 ///////////////////////////////////////////////////////////////////////////
76 typedef detail::ServerHandle ServerHandle;
78 enum Mode { Automatic, Interactive, Noninteractive };
80 ///////////////////////////////////////////////////////////////////////////
82 static Server & start(senf::INet4SocketAddress const & address);
83 ///< Start server on given IPv4 address/port
84 static Server & start(senf::INet6SocketAddress const & address);
85 ///< Start server on given IPv6 address/port
87 std::string const & name() const; ///< Get server name
88 /**< This information is used in the prompt string. */
90 Server & name(std::string const & name); ///< Set server name
91 /**< This information is used in the prompt string. */
93 DirectoryNode & root() const; ///< Get root node
95 Server & root(DirectoryNode & root); ///< Set root node
96 /**< \a node will be the root node for all clients launched
99 Mode mode() const; ///< Get mode
100 /**< \see \ref mode(Mode) */
102 Server & mode(Mode mode); ///< Set mode
103 /**< There are two Server types:
104 \li An interactive server displays a command prompt and
105 optionally supports command-line editing.
106 \li A non-interactive server does not display any
107 prompt and does not allow any interactive
108 editing. This type of server is used for (remote)
111 The \a mode parameter selects between these modes. In
112 \c Automatic (the default), a client connection is
113 considered to be interactive if there is no data
114 traffic in the first 500ms after the connection is
117 void stop(); ///< Stop the server
118 /**< All clients will be closed
119 \warning The Server instance itself will be deleted */
124 Server(ServerHandle handle);
126 static Server & start(ServerHandle handle);
128 void newClient(int event);
129 void removeClient(Client & client);
131 ServerHandle handle_;
132 scheduler::FdEvent event_;
133 DirectoryNode::ptr root_;
136 typedef std::set< boost::intrusive_ptr<Client> > Clients;
143 /** \brief Server client instance
145 Whenever a new client connects, a new instance of this class is created. This class shows a
146 command prompt, receives the commands, parses them and then passes (using a CommandParser)
147 and passes the commands to an Executor instance.
149 \ingroup console_access
152 : public senf::intrusive_refcount,
153 private boost::base_from_member< detail::NonblockingSocketOStream >,
154 public senf::log::IOStreamTarget
156 typedef boost::base_from_member< detail::NonblockingSocketOStream > out_t;
158 SENF_LOG_CLASS_AREA();
159 SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
161 static const unsigned INTERACTIVE_TIMEOUT = 500; // milliseconds;
164 typedef Server::ServerHandle::ClientHandle ClientHandle;
168 void stop(); ///< Stop the client
169 /**< This will close the client socket. */
171 std::string const & name() const; ///< Get name of the client instance
172 /**< This name is used in the prompt string and is set by
174 ClientHandle handle() const; ///< Get the client's network socket handle
175 std::ostream & stream(); ///< Get client's output stream
176 /**< Data sent to this stream is sent out over the network
177 via the client's socket handle. Write operation is
178 non-blocking and data may be dropped. Data is written
179 using Client::write(). */
180 std::string promptString() const; ///< Get the prompt string
181 DirectoryNode & root() const; ///< Get configured root node
182 DirectoryNode & cwd() const; ///< Get current directory
183 /**< This is the directory, the console currently is changed
184 into by the user of the console. */
185 Server::Mode mode() const; ///< Get operation mode
186 /**< \see Server::mode() */
187 void write(std::string const & data) const;
188 ///< Write data to network socket
189 /**< The data is automatically filtered depending on the
190 type of connection (e.g. on a telnet connection,
191 specific bytes are quoted). */
192 std::string const & backtrace() const; ///< Get backtrace of last console error, if any
193 unsigned width() const; ///< Get console width
194 /**< If possible, this will be the width of the connected
195 terminal, otherwise a default value (normally 80) is
198 static Client & get(std::ostream & os);
199 ///< Access client instance
200 /**< Allows to access the client instance from console
201 command implementations. The first argument to a
202 console command is a stream object. \e If this stream
203 object belongs to a network console client, this call
204 will return the associated Client instance reference.
205 \throws std::bad_cast if \a os is not associated with a
207 static unsigned getWidth(std::ostream & os, unsigned defaultWidth = 0,
208 unsigned minWidth = 0);
209 ///< Get width of client console if possible
210 /**< If possible, the width of the client console attached
211 to the stream \a os is returned. If this is not
212 possible, the \a defaultValue will be used.
214 If the width obtained this way is smaller than \a
215 minWidth, \a defaultValue will be returned instead. */
220 Client(Server & server, ClientHandle handle);
222 void setInteractive();
223 void setNoninteractive();
225 size_t handleInput(std::string input, bool incremental = false);
226 virtual void v_write(senf::log::time_type timestamp, std::string const & stream,
227 std::string const & area, unsigned level,
228 std::string const & message);
231 ClientHandle handle_;
232 scheduler::FdEvent readevent_;
233 scheduler::TimerEvent timer_;
234 CommandParser parser_;
237 boost::scoped_ptr<detail::ClientReader> reader_;
239 std::string backtrace_;
242 friend class detail::ClientReader;
243 friend class detail::NonblockingSocketSink;
248 static void backtrace(std::ostream & os);
249 static SysBacktrace instance_;
254 /** \brief Output Console Client instance as it's string representation
257 std::ostream & operator<<(std::ostream & os, Client const & client);
259 /** \brief Output Console Client instance as it's string representation
262 std::ostream & operator<<(std::ostream & os, Client * client);
266 ///////////////////////////////hh.e////////////////////////////////////////
267 #include "Server.cci"
268 //#include "Server.ct"
269 //#include "Server.cti"
276 // comment-column: 40
277 // c-file-style: "senf"
278 // indent-tabs-mode: nil
279 // ispell-local-dictionary: "american"
280 // compile-command: "scons -u test"