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 <senf/Scheduler/FdEvent.hh>
34 #include <senf/Scheduler/TimerEvent.hh>
35 #include <senf/Socket/Protocols/INet/INetAddressing.hh>
36 #include <senf/Utils/Logger.hh>
37 #include <senf/Utils/intrusive_refcount.hh>
38 #include "Executor.hh"
40 //#include "Server.mpp"
42 //-/////////////////////////////////////////////////////////////////////////////////////////////////
49 /** \brief Interactive console server
51 This class provides an interactive console TCP server.
53 \idea To support blocking commands, we could give the Client 'suspend()' and 'resume()'
54 members. suspend() would probably throw some kind of exception to transfer control back
55 to the Client instance. on resume(), the command would be called again, maybe setting
56 some flag or something. Example for use: Host name resolution: Here we can just built
57 our own little host-name cache. When the name is not found, we ask the resolver to
58 resolve it and call 'resume' when the name is found. Since it is in the cache now, the
59 command will now complete.
61 \ingroup console_access
64 : public senf::intrusive_refcount
66 SENF_LOG_CLASS_AREA();
67 SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
69 //-////////////////////////////////////////////////////////////////////////
72 typedef detail::ServerHandle ServerHandle;
74 enum Mode { Automatic, Interactive, Noninteractive };
76 //-////////////////////////////////////////////////////////////////////////
78 static Server & start(senf::INet4SocketAddress const & address);
79 ///< Start server on given IPv4 address/port
80 static Server & start(senf::INet6SocketAddress const & address);
81 ///< Start server on given IPv6 address/port
83 std::string const & name() const; ///< Get server name
84 /**< This information is used in the prompt string. */
86 Server & name(std::string const & name); ///< Set server name
87 /**< This information is used in the prompt string. */
89 DirectoryNode & root() const; ///< Get root node
91 Server & root(DirectoryNode & root); ///< Set root node
92 /**< \a node will be the root node for all clients launched
95 Mode mode() const; ///< Get mode
96 /**< \see \ref mode(Mode) */
98 Server & mode(Mode mode); ///< Set mode
99 /**< There are two Server types:
100 \li An interactive server displays a command prompt and
101 optionally supports command-line editing.
102 \li A non-interactive server does not display any
103 prompt and does not allow any interactive
104 editing. This type of server is used for (remote)
107 The \a mode parameter selects between these modes. In
108 \c Automatic (the default), a client connection is
109 considered to be interactive if there is no data
110 traffic in the first 500ms after the connection is
113 void stop(); ///< Stop the server
114 /**< All clients will be closed
115 \warning The Server instance itself will be deleted */
120 Server(ServerHandle handle);
122 static Server & start(ServerHandle handle);
124 void newClient(int event);
125 void removeClient(Client & client);
127 ServerHandle handle_;
128 scheduler::FdEvent event_;
129 DirectoryNode::ptr root_;
132 typedef std::set< boost::intrusive_ptr<Client> > Clients;
139 /** \brief Server client instance
141 Whenever a new client connects, a new instance of this class is created. This class shows a
142 command prompt, receives the commands, parses them and then passes (using a CommandParser)
143 and passes the commands to an Executor instance.
145 \ingroup console_access
148 : public senf::intrusive_refcount,
149 private boost::base_from_member< detail::NonblockingSocketOStream >,
150 public senf::log::IOStreamTarget
152 typedef boost::base_from_member< detail::NonblockingSocketOStream > out_t;
154 SENF_LOG_CLASS_AREA();
155 SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
157 static const unsigned INTERACTIVE_TIMEOUT = 500; // milliseconds;
160 typedef Server::ServerHandle::ClientHandle ClientHandle;
164 void stop(); ///< Stop the client
165 /**< This will close the client socket. */
167 std::string const & name() const; ///< Get name of the client instance
168 /**< This name is used in the prompt string and is set by
170 ClientHandle handle() const; ///< Get the client's network socket handle
171 std::ostream & stream(); ///< Get client's output stream
172 /**< Data sent to this stream is sent out over the network
173 via the client's socket handle. Write operation is
174 non-blocking and data may be dropped. Data is written
175 using Client::write(). */
176 std::string promptString() const; ///< Get the prompt string
177 DirectoryNode & root() const; ///< Get configured root node
178 DirectoryNode & cwd() const; ///< Get current directory
179 /**< This is the directory, the console currently is changed
180 into by the user of the console. */
181 Server::Mode mode() const; ///< Get operation mode
182 /**< \see Server::mode() */
183 void write(std::string const & data) const;
184 ///< Write data to network socket
185 /**< The data is automatically filtered depending on the
186 type of connection (e.g. on a telnet connection,
187 specific bytes are quoted). */
188 std::string const & backtrace() const; ///< Get backtrace of last console error, if any
189 unsigned width() const; ///< Get console width
190 /**< If possible, this will be the width of the connected
191 terminal, otherwise a default value (normally 80) is
194 static Client & get(std::ostream & os);
195 ///< Access client instance
196 /**< Allows to access the client instance from console
197 command implementations. The first argument to a
198 console command is a stream object. \e If this stream
199 object belongs to a network console client, this call
200 will return the associated Client instance reference.
201 \throws std::bad_cast if \a os is not associated with a
203 static unsigned getWidth(std::ostream & os, unsigned defaultWidth = 0,
204 unsigned minWidth = 0);
205 ///< Get width of client console if possible
206 /**< If possible, the width of the client console attached
207 to the stream \a os is returned. If this is not
208 possible, the \a defaultValue will be used.
210 If the width obtained this way is smaller than \a
211 minWidth, \a defaultValue will be returned instead. */
216 Client(Server & server, ClientHandle handle);
218 void setInteractive();
219 void setNoninteractive();
221 size_t handleInput(std::string input, bool incremental = false);
222 virtual void v_write(senf::log::time_type timestamp, std::string const & stream,
223 std::string const & area, unsigned level,
224 std::string const & message);
227 ClientHandle handle_;
228 scheduler::FdEvent readevent_;
229 scheduler::TimerEvent timer_;
230 CommandParser parser_;
233 boost::scoped_ptr<detail::ClientReader> reader_;
235 std::string backtrace_;
238 friend class detail::ClientReader;
239 friend class detail::NonblockingSocketSink;
244 static void backtrace(std::ostream & os);
245 static SysBacktrace instance_;
250 /** \brief Output Console Client instance as it's string representation
253 std::ostream & operator<<(std::ostream & os, Client const & client);
255 /** \brief Output Console Client instance as it's string representation
258 std::ostream & operator<<(std::ostream & os, Client * client);
262 //-/////////////////////////////////////////////////////////////////////////////////////////////////
263 #include "Server.cci"
264 //#include "Server.ct"
265 //#include "Server.cti"
272 // comment-column: 40
273 // c-file-style: "senf"
274 // indent-tabs-mode: nil
275 // ispell-local-dictionary: "american"
276 // compile-command: "scons -u test"