Fix documentation build under maverick (doxygen 1.7.1)
[senf.git] / senf / Utils / Console / Server.hh
1 // $Id$
2 //
3 // Copyright (C) 2008
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
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.
12 //
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.
17 //
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.
22
23 /** \file
24     \brief Server public header */
25
26 #ifndef HH_SENF_Scheduler_Console_Server_
27 #define HH_SENF_Scheduler_Console_Server_ 1
28
29 // Custom includes
30 #include <set>
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>
39 #include "Parse.hh"
40 #include "Executor.hh"
41 #include <senf/Socket/Protocols/INet/INetAddressing.hh>
42 #include <senf/Utils/Logger.hh>
43
44 //#include "Server.mpp"
45 #include "Server.ih"
46 //-/////////////////////////////////////////////////////////////////////////////////////////////////
47
48 namespace senf {
49 namespace console {
50
51     class Client;
52
53     /** \brief Interactive console server
54
55         This class provides an interactive console TCP server.
56
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.
64
65         \ingroup console_access
66       */
67     class Server
68         : public senf::intrusive_refcount
69     {
70         SENF_LOG_CLASS_AREA();
71         SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
72     public:
73         //-////////////////////////////////////////////////////////////////////////
74         // Types
75
76         typedef detail::ServerHandle ServerHandle;
77
78         enum Mode { Automatic, Interactive, Noninteractive };
79
80         //-////////////////////////////////////////////////////////////////////////
81
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
86
87         std::string const & name() const; ///< Get server name
88                                         /**< This information is used in the prompt string. */
89
90         Server & name(std::string const & name); ///< Set server name
91                                         /**< This information is used in the prompt string. */
92
93         DirectoryNode & root() const;   ///< Get root node
94
95         Server & root(DirectoryNode & root); ///< Set root node
96                                         /**< \a node will be the root node for all clients launched
97                                              from this server. */
98
99         Mode mode() const;              ///< Get mode
100                                         /**< \see \ref mode(Mode) */
101
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)
109                                                  scripting.
110
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
115                                              opened. */
116
117         void stop();                    ///< Stop the server
118                                         /**< All clients will be closed
119                                              \warning The Server instance itself will be deleted */
120
121     protected:
122
123     private:
124         Server(ServerHandle handle);
125
126         static Server & start(ServerHandle handle);
127
128         void newClient(int event);
129         void removeClient(Client & client);
130
131         ServerHandle handle_;
132         scheduler::FdEvent event_;
133         DirectoryNode::ptr root_;
134         Mode mode_;
135
136         typedef std::set< boost::intrusive_ptr<Client> > Clients;
137         Clients clients_;
138         std::string name_;
139
140         friend class Client;
141     };
142
143     /** \brief Server client instance
144
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.
148
149         \ingroup console_access
150      */
151     class Client
152         : public senf::intrusive_refcount,
153           private boost::base_from_member< detail::NonblockingSocketOStream >,
154           public senf::log::IOStreamTarget
155     {
156         typedef boost::base_from_member< detail::NonblockingSocketOStream > out_t;
157
158         SENF_LOG_CLASS_AREA();
159         SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
160
161         static const unsigned INTERACTIVE_TIMEOUT = 500; // milliseconds;
162
163     public:
164         typedef Server::ServerHandle::ClientHandle ClientHandle;
165
166         ~Client();
167
168         void stop();                    ///< Stop the client
169                                         /**< This will close the client socket. */
170
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
173                                              the server. */
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
196                                              returned. */
197
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
206                                                  Client instance. */
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.
213
214                                              If the width obtained this way is smaller than \a
215                                              minWidth, \a defaultValue will be returned instead. */
216
217     protected:
218
219     private:
220         Client(Server & server, ClientHandle handle);
221
222         void setInteractive();
223         void setNoninteractive();
224
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);
229
230         Server & server_;
231         ClientHandle handle_;
232         scheduler::FdEvent readevent_;
233         scheduler::TimerEvent timer_;
234         CommandParser parser_;
235         Executor executor_;
236         std::string name_;
237         boost::scoped_ptr<detail::ClientReader> reader_;
238         Server::Mode mode_;
239         std::string backtrace_;
240
241         friend class Server;
242         friend class detail::ClientReader;
243         friend class detail::NonblockingSocketSink;
244
245         class SysBacktrace
246         {
247             SysBacktrace();
248             static void  backtrace(std::ostream & os);
249             static SysBacktrace instance_;
250         };
251
252     };
253
254     /** \brief Output Console Client instance as it's string representation
255         \related Client
256      */
257     std::ostream & operator<<(std::ostream & os, Client const & client);
258
259     /** \brief Output Console Client instance as it's string representation
260         \related Client
261      */
262     std::ostream & operator<<(std::ostream & os, Client * client);
263
264 }}
265
266 //-/////////////////////////////////////////////////////////////////////////////////////////////////
267 #include "Server.cci"
268 //#include "Server.ct"
269 //#include "Server.cti"
270 #endif
271
272 \f
273 // Local Variables:
274 // mode: c++
275 // fill-column: 100
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"
281 // End: