Console: Multiple network console server support
[senf.git] / Console / Server.ih
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 internal header */
25
26 #ifndef IH_Server_
27 #define IH_Server_ 1
28
29 // Custom includes
30 #include <boost/iostreams/concepts.hpp>
31 #include <boost/iostreams/stream.hpp>
32 #include <set>
33
34 ///////////////////////////////ih.p////////////////////////////////////////
35
36 namespace senf {
37 namespace console {
38
39     class Server;
40     class Client;
41
42 namespace detail {
43
44     class ServerManager
45         : public senf::singleton<ServerManager>
46     {
47     public:
48         typedef boost::intrusive_ptr<Server> ptr;
49
50     protected:
51
52     private:
53         static void add(ptr server);
54         static void remove(ptr server);
55
56         typedef std::set<ptr> Servers;
57         Servers servers_;
58
59         friend class senf::console::Server;
60     };
61
62     /** \brief Internal: Nonblocking boost::iostreams::sink
63
64         The sink discards data if the output socket would.
65      */
66     class NonblockingSocketSink 
67         : public boost::iostreams::sink
68     {
69     public:
70         typedef ClientSocketHandle< 
71             MakeSocketPolicy<StreamFramingPolicy,
72                              WriteablePolicy,
73                              ConnectedCommunicationPolicy>::policy > Handle;
74
75         NonblockingSocketSink(Client & client);
76         std::streamsize write(const char * s, std::streamsize n);
77
78         Client & client() const;
79         
80     private:
81         Client & client_;
82     };
83
84     typedef boost::iostreams::stream<NonblockingSocketSink> NonblockingSocketOStream;
85
86     typedef senf::ServerSocketHandle<
87         senf::MakeSocketPolicy< senf::TCPv4SocketProtocol::Policy, 
88                                 senf::UnspecifiedAddressingPolicy>::policy > ServerHandle;
89
90     /** \brief Internal: Generic client interface
91
92         The ClientReader encapsulates the interaction of a single network client with the user: It
93         manages prompt display and reading an interactive command.
94      */
95     class ClientReader
96     {
97     public:
98         typedef ServerHandle::ClientSocketHandle ClientHandle;
99
100         virtual ~ClientReader() = 0;
101
102         // Called by subclasses to get information from the Client
103
104         Client & client() const;
105         std::string promptString() const;
106         ClientHandle handle() const;
107         std::ostream & stream() const;
108
109         // Called by subclasses to perform actions in the Client
110
111         void stopClient();
112         std::string::size_type handleInput(std::string const & input, bool incremental=false) const;
113
114         // Called by the Client
115
116         void disablePrompt();
117         void enablePrompt();
118         void translate(std::string & data);
119
120     protected:
121         ClientReader(Client & client);
122
123     private:
124         virtual void v_disablePrompt() = 0;
125         virtual void v_enablePrompt() = 0;
126         virtual void v_translate(std::string & data) = 0;
127
128         Client & client_;
129     };
130
131     /** \brief Internal: Primitive ClientReader implementation
132         
133         This implementation uses the cooked telnet mode to read lines from the console. It does not
134         support explicit line editing or any other advanced features.
135      */
136     class DumbClientReader
137         : public ClientReader
138     {
139     public:
140         DumbClientReader(Client & client);
141
142     private:
143         virtual void v_disablePrompt();
144         virtual void v_enablePrompt();
145         virtual void v_translate(std::string & data);
146
147         void clientData(senf::ReadHelper<ClientHandle>::ptr helper);
148         void showPrompt();
149
150         std::string tail_;
151         unsigned promptLen_;
152         bool promptActive_;
153     };
154
155     /** \brief Internal: Primitive ClientReader implementation
156         
157         This implementation uses the cooked telnet mode to read lines from the console. It does not
158         support explicit line editing or any other advanced features.
159      */
160     class NoninteractiveClientReader
161         : public ClientReader
162     {
163     public:
164         NoninteractiveClientReader(Client & client);
165
166     private:
167         virtual void v_disablePrompt();
168         virtual void v_enablePrompt();
169         virtual void v_translate(std::string & data);
170
171         void newData(senf::Scheduler::EventId event);
172
173         SchedulerBinding binding_;
174         std::string buffer_;
175     };
176     
177 }}}
178
179 ///////////////////////////////ih.e////////////////////////////////////////
180 #endif
181
182 \f
183 // Local Variables:
184 // mode: c++
185 // fill-column: 100
186 // comment-column: 40
187 // c-file-style: "senf"
188 // indent-tabs-mode: nil
189 // ispell-local-dictionary: "american"
190 // compile-command: "scons -u test"
191 // End: