Console: Documentation of the configuration support
[senf.git] / 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_Server_
27 #define HH_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 "../Utils/intrusive_refcount.hh"
35 #include "../Socket/Protocols/INet/TCPSocketHandle.hh"
36 #include "../Socket/ServerSocketHandle.hh"
37 #include "../Scheduler/Scheduler.hh"
38 #include "../Scheduler/ReadHelper.hh"
39 #include "Parse.hh"
40 #include "Executor.hh"
41 #include "../Socket/Protocols/INet/INetAddressing.hh"
42 #include "../Utils/Logger.hh"
43
44 //#include "Server.mpp"
45 #include "Server.ih"
46 ///////////////////////////////hh.p////////////////////////////////////////
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         \todo Add interactivity detection using timeout
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.
65         
66         \implementation We do \e not provide an \c instance() member so we can easily later extend
67             the server to allow registering more than one instance, e.g. with each instance on a
68             differently firewalled port and with different security restrictions.
69         
70         \ingroup console_access
71       */
72     class Server
73         : boost::noncopyable
74     {
75         SENF_LOG_CLASS_AREA();
76         SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
77     public:
78         ///////////////////////////////////////////////////////////////////////////
79         // Types
80         
81         typedef detail::ServerHandle ServerHandle;
82
83         ~Server();
84
85         static Server & start(senf::INet4SocketAddress const & address);
86                                         ///< Start server on given IPv4 address/port
87         static Server & start(senf::INet6SocketAddress const & address);
88                                         ///< Start server on given IPv6 address/port
89         Server & name(std::string const & name); ///< Set server name
90                                         /**< This information is used in the prompt string. */
91         
92         void stop();                    ///< Stop the server
93                                         /**< All clients will be closed */
94         
95     protected:
96
97     private:
98         Server(ServerHandle handle);
99
100         static Server & start(ServerHandle handle);
101         static boost::scoped_ptr<Server> & instancePtr();
102
103         void newClient(Scheduler::EventId event);
104         void removeClient(Client & client);
105         
106         ServerHandle handle_;
107         
108         typedef std::set< boost::intrusive_ptr<Client> > Clients;
109         Clients clients_;
110         std::string name_;
111         
112         friend class Client;
113     };
114     
115     /** \brief Server client instance
116
117         Whenever a new client connects, a new instance of this class is created. This class shows a
118         command prompt, receives the commands, parses them and then passes (using a CommandParser)
119         and passes the commands to an Executor instance.
120
121         \ingroup console_access
122      */
123     class Client
124         : public senf::intrusive_refcount, 
125           private boost::base_from_member< detail::NonblockingSocketOStream >,
126           public senf::log::IOStreamTarget
127     {
128         typedef boost::base_from_member< detail::NonblockingSocketOStream > out_t;
129
130         SENF_LOG_CLASS_AREA();
131         SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
132
133     public:
134         typedef Server::ServerHandle::ClientSocketHandle ClientHandle;
135
136         ~Client();
137
138         void stop();                    ///< Stop the client
139                                         /**< This will close the client socket. */
140
141         std::string const & name() const;
142         ClientHandle handle() const;
143         std::ostream & stream();
144         std::string promptString() const;
145
146         static Client & get(std::ostream & os);
147
148     protected:
149         
150     private:
151         Client(Server & server, ClientHandle handle, std::string const & name);
152
153         void translate(std::string & data);
154         void handleInput(std::string input);
155         virtual void v_write(senf::log::time_type timestamp, std::string const & stream, 
156                              std::string const & area, unsigned level, 
157                              std::string const & message);
158         
159         Server & server_;
160         ClientHandle handle_;
161         CommandParser parser_;
162         Executor executor_;
163         std::string name_;
164         std::string lastCommand_;
165         boost::scoped_ptr<detail::ClientReader> reader_;
166
167         friend class Server;
168         friend class detail::ClientReader;
169         friend class detail::NonblockingSocketSink;
170     };
171         
172     /** \brief Output Console Client instance as it's string representation
173         \related Client
174      */
175     std::ostream & operator<<(std::ostream & os, Client const & client);
176
177     /** \brief Output Console Client instance as it's string representation
178         \related Client
179      */
180     std::ostream & operator<<(std::ostream & os, Client * client);
181
182 }}
183
184 ///////////////////////////////hh.e////////////////////////////////////////
185 #include "Server.cci"
186 //#include "Server.ct"
187 //#include "Server.cti"
188 #endif
189
190 \f
191 // Local Variables:
192 // mode: c++
193 // fill-column: 100
194 // comment-column: 40
195 // c-file-style: "senf"
196 // indent-tabs-mode: nil
197 // ispell-local-dictionary: "american"
198 // compile-command: "scons -u test"
199 // End: