4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at
9 // http://senf.berlios.de/license.html
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on,
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
15 // Software distributed under the License is distributed on an "AS IS" basis,
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
17 // for the specific language governing rights and limitations under the License.
19 // The Original Code is Fraunhofer FOKUS code.
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V.
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
26 // Stefan Bund <g0dil@berlios.de>
29 \brief Server public header */
31 #ifndef HH_SENF_Scheduler_Console_Server_
32 #define HH_SENF_Scheduler_Console_Server_ 1
36 #include <boost/utility.hpp>
37 #include <boost/scoped_ptr.hpp>
38 #include <senf/Scheduler/FdEvent.hh>
39 #include <senf/Scheduler/TimerEvent.hh>
40 #include <senf/Socket/Protocols/INet/INetAddressing.hh>
41 #include <senf/Utils/Logger.hh>
42 #include <senf/Utils/intrusive_refcount.hh>
43 #include "Executor.hh"
45 //#include "Server.mpp"
47 //-/////////////////////////////////////////////////////////////////////////////////////////////////
54 /** \brief Interactive console server
56 This class provides an interactive console TCP server.
58 \idea To support blocking commands, we could give the Client 'suspend()' and 'resume()'
59 members. suspend() would probably throw some kind of exception to transfer control back
60 to the Client instance. on resume(), the command would be called again, maybe setting
61 some flag or something. Example for use: Host name resolution: Here we can just built
62 our own little host-name cache. When the name is not found, we ask the resolver to
63 resolve it and call 'resume' when the name is found. Since it is in the cache now, the
64 command will now complete.
66 \ingroup console_access
69 : public senf::intrusive_refcount
71 SENF_LOG_CLASS_AREA();
72 SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
74 //-////////////////////////////////////////////////////////////////////////
77 typedef detail::ServerHandle ServerHandle;
79 enum Mode { Automatic, Interactive, Noninteractive };
81 //-////////////////////////////////////////////////////////////////////////
83 static Server & start(senf::INet4SocketAddress const & address);
84 ///< Start server on given IPv4 address/port
85 static Server & start(senf::INet6SocketAddress const & address);
86 ///< Start server on given IPv6 address/port
88 std::string const & name() const; ///< Get server name
89 /**< This information is used in the prompt string. */
91 Server & name(std::string const & name); ///< Set server name
92 /**< This information is used in the prompt string. */
94 DirectoryNode & root() const; ///< Get root node
96 Server & root(DirectoryNode & root); ///< Set root node
97 /**< \a node will be the root node for all clients launched
100 Mode mode() const; ///< Get mode
101 /**< \see \ref mode(Mode) */
103 Server & mode(Mode mode); ///< Set mode
104 /**< There are two Server types:
105 \li An interactive server displays a command prompt and
106 optionally supports command-line editing.
107 \li A non-interactive server does not display any
108 prompt and does not allow any interactive
109 editing. This type of server is used for (remote)
112 The \a mode parameter selects between these modes. In
113 \c Automatic (the default), a client connection is
114 considered to be interactive if there is no data
115 traffic in the first 500ms after the connection is
118 void stop(); ///< Stop the server
119 /**< All clients will be closed
120 \warning The Server instance itself will be deleted */
125 Server(ServerHandle handle);
127 static Server & start(ServerHandle handle);
129 void newClient(int event);
130 void removeClient(Client & client);
132 ServerHandle handle_;
133 scheduler::FdEvent event_;
134 DirectoryNode::ptr root_;
137 typedef std::set< boost::intrusive_ptr<Client> > Clients;
144 /** \brief Server client instance
146 Whenever a new client connects, a new instance of this class is created. This class shows a
147 command prompt, receives the commands, parses them and then passes (using a CommandParser)
148 and passes the commands to an Executor instance.
150 \ingroup console_access
153 : public senf::intrusive_refcount,
154 private boost::base_from_member< detail::NonblockingSocketOStream >,
155 public senf::log::IOStreamTarget
157 typedef boost::base_from_member< detail::NonblockingSocketOStream > out_t;
159 SENF_LOG_CLASS_AREA();
160 SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
162 static const unsigned INTERACTIVE_TIMEOUT = 500; // milliseconds;
165 typedef Server::ServerHandle::ClientHandle ClientHandle;
169 void stop(); ///< Stop the client
170 /**< This will close the client socket. */
172 std::string const & name() const; ///< Get name of the client instance
173 /**< This name is used in the prompt string and is set by
175 ClientHandle handle() const; ///< Get the client's network socket handle
176 std::ostream & stream(); ///< Get client's output stream
177 /**< Data sent to this stream is sent out over the network
178 via the client's socket handle. Write operation is
179 non-blocking and data may be dropped. Data is written
180 using Client::write(). */
181 std::string promptString() const; ///< Get the prompt string
182 DirectoryNode & root() const; ///< Get configured root node
183 DirectoryNode & cwd() const; ///< Get current directory
184 /**< This is the directory, the console currently is changed
185 into by the user of the console. */
186 Server::Mode mode() const; ///< Get operation mode
187 /**< \see Server::mode() */
188 void write(std::string const & data) const;
189 ///< Write data to network socket
190 /**< The data is automatically filtered depending on the
191 type of connection (e.g. on a telnet connection,
192 specific bytes are quoted). */
193 std::string const & backtrace() const; ///< Get backtrace of last console error, if any
194 unsigned width() const; ///< Get console width
195 /**< If possible, this will be the width of the connected
196 terminal, otherwise a default value (normally 80) is
199 static Client & get(std::ostream & os);
200 ///< Access client instance
201 /**< Allows to access the client instance from console
202 command implementations. The first argument to a
203 console command is a stream object. \e If this stream
204 object belongs to a network console client, this call
205 will return the associated Client instance reference.
206 \throws std::bad_cast if \a os is not associated with a
208 static unsigned getWidth(std::ostream & os, unsigned defaultWidth = 0,
209 unsigned minWidth = 0);
210 ///< Get width of client console if possible
211 /**< If possible, the width of the client console attached
212 to the stream \a os is returned. If this is not
213 possible, the \a defaultValue will be used.
215 If the width obtained this way is smaller than \a
216 minWidth, \a defaultValue will be returned instead. */
221 Client(Server & server, ClientHandle handle);
223 void setInteractive();
224 void setNoninteractive();
226 size_t handleInput(std::string input, bool incremental = false);
227 virtual void v_write(senf::log::time_type timestamp, std::string const & stream,
228 std::string const & area, unsigned level,
229 std::string const & message);
232 ClientHandle handle_;
233 scheduler::FdEvent readevent_;
234 scheduler::TimerEvent timer_;
235 CommandParser parser_;
238 boost::scoped_ptr<detail::ClientReader> reader_;
240 std::string backtrace_;
243 friend class detail::ClientReader;
244 friend class detail::NonblockingSocketSink;
249 static void backtrace(std::ostream & os);
250 static SysBacktrace instance_;
255 /** \brief Output Console Client instance as it's string representation
258 std::ostream & operator<<(std::ostream & os, Client const & client);
260 /** \brief Output Console Client instance as it's string representation
263 std::ostream & operator<<(std::ostream & os, Client * client);
267 //-/////////////////////////////////////////////////////////////////////////////////////////////////
268 #include "Server.cci"
269 //#include "Server.ct"
270 //#include "Server.cti"
277 // comment-column: 40
278 // c-file-style: "senf"
279 // indent-tabs-mode: nil
280 // ispell-local-dictionary: "american"
281 // compile-command: "scons -u test"