b6e607f5e43298e0249353074253a8b67445c7b9
[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     class Server
71         : boost::noncopyable
72     {
73         SENF_LOG_CLASS_AREA();
74         SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
75     public:
76         ///////////////////////////////////////////////////////////////////////////
77         // Types
78         
79         typedef detail::ServerHandle ServerHandle;
80
81         ~Server();
82
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
87         Server & name(std::string const & name); ///< Set server name
88                                         /**< This information is used in the prompt string. */
89         
90         void stop();                    ///< Stop the server
91                                         /**< All clients will be closed */
92         
93     protected:
94
95     private:
96         Server(ServerHandle handle);
97
98         static Server & start(ServerHandle handle);
99         static boost::scoped_ptr<Server> & instancePtr();
100
101         void newClient(Scheduler::EventId event);
102         void removeClient(Client & client);
103         
104         ServerHandle handle_;
105         
106         typedef std::set< boost::intrusive_ptr<Client> > Clients;
107         Clients clients_;
108         std::string name_;
109         
110         friend class Client;
111     };
112     
113     /** \brief Server client instance
114
115         Whenever a new client connects, a new instance of this class is created. This class shows a
116         command prompt, receives the commands, parses them and then passes (using a CommandParser)
117         and passes the commands to an Executor instance.
118      */
119     class Client
120         : public senf::intrusive_refcount, 
121           private boost::base_from_member< detail::NonblockingSocketOStream >,
122           public senf::log::IOStreamTarget
123     {
124         typedef boost::base_from_member< detail::NonblockingSocketOStream > out_t;
125
126         SENF_LOG_CLASS_AREA();
127         SENF_LOG_DEFAULT_LEVEL( senf::log::NOTICE );
128
129     public:
130         typedef Server::ServerHandle::ClientSocketHandle ClientHandle;
131
132         ~Client();
133
134         void stop();                    ///< Stop the client
135                                         /**< This will close the client socket. */
136
137         std::string const & name() const;
138         ClientHandle handle() const;
139         std::ostream & stream();
140         std::string promptString() const;
141
142         static Client & get(std::ostream & os);
143
144     protected:
145         
146     private:
147         Client(Server & server, ClientHandle handle, std::string const & name);
148
149         void translate(std::string & data);
150         void handleInput(std::string input);
151         virtual void v_write(senf::log::time_type timestamp, std::string const & stream, 
152                              std::string const & area, unsigned level, 
153                              std::string const & message);
154         
155         Server & server_;
156         ClientHandle handle_;
157         CommandParser parser_;
158         Executor executor_;
159         std::string name_;
160         std::string lastCommand_;
161         boost::scoped_ptr<detail::ClientReader> reader_;
162
163         friend class Server;
164         friend class detail::ClientReader;
165         friend class detail::NonblockingSocketSink;
166     };
167         
168     /** \brief Output Console Client instance as it's string representation
169          */
170     std::ostream & operator<<(std::ostream & os, Client const & client);
171     /** \brief Output Console Client instance as it's string representation
172          */
173     std::ostream & operator<<(std::ostream & os, Client * client);
174
175 }}
176
177 ///////////////////////////////hh.e////////////////////////////////////////
178 #include "Server.cci"
179 //#include "Server.ct"
180 //#include "Server.cti"
181 #endif
182
183 \f
184 // Local Variables:
185 // mode: c++
186 // fill-column: 100
187 // comment-column: 40
188 // c-file-style: "senf"
189 // indent-tabs-mode: nil
190 // ispell-local-dictionary: "american"
191 // compile-command: "scons -u test"
192 // End: