925fd64d01dacb4738d0a5b6e244539675b9e071
[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         \fixme Don't throw exceptions ... set stream error indicator (if at all)
67      */
68     class NonblockingSocketSink 
69         : public boost::iostreams::sink
70     {
71     public:
72         typedef ClientSocketHandle< 
73             MakeSocketPolicy<StreamFramingPolicy,
74                              WriteablePolicy,
75                              ConnectedCommunicationPolicy>::policy > Handle;
76
77         NonblockingSocketSink(Client & client);
78         std::streamsize write(const char * s, std::streamsize n);
79
80         Client & client() const;
81         
82     private:
83         Client & client_;
84     };
85
86     typedef boost::iostreams::stream<NonblockingSocketSink> NonblockingSocketOStream;
87
88     typedef senf::ServerSocketHandle<
89         senf::MakeSocketPolicy< senf::TCPv4SocketProtocol::Policy, 
90                                 senf::UnspecifiedAddressingPolicy>::policy > ServerHandle;
91
92     /** \brief Internal: Generic client interface
93
94         The ClientReader encapsulates the interaction of a single network client with the user: It
95         manages prompt display and reading an interactive command.
96      */
97     class ClientReader
98     {
99     public:
100         typedef ServerHandle::ClientSocketHandle ClientHandle;
101
102         virtual ~ClientReader() = 0;
103
104         // Called by subclasses to get information from the Client
105
106         Client & client() const;
107         std::string promptString() const;
108         ClientHandle handle() const;
109         std::ostream & stream() const;
110
111         // Called by subclasses to perform actions in the Client
112
113         void stopClient();
114         std::string::size_type handleInput(std::string const & input, bool incremental=false) const;
115
116         // Called by the Client
117
118         void disablePrompt();
119         void enablePrompt();
120         void translate(std::string & data);
121
122     protected:
123         ClientReader(Client & client);
124
125     private:
126         virtual void v_disablePrompt() = 0;
127         virtual void v_enablePrompt() = 0;
128         virtual void v_translate(std::string & data) = 0;
129
130         Client & client_;
131     };
132
133     /** \brief Internal: Primitive ClientReader implementation
134         
135         This implementation uses the cooked telnet mode to read lines from the console. It does not
136         support explicit line editing or any other advanced features.
137      */
138     class DumbClientReader
139         : public ClientReader
140     {
141     public:
142         DumbClientReader(Client & client);
143
144     private:
145         virtual void v_disablePrompt();
146         virtual void v_enablePrompt();
147         virtual void v_translate(std::string & data);
148
149         void clientData(senf::ReadHelper<ClientHandle>::ptr helper);
150         void showPrompt();
151
152         std::string tail_;
153         unsigned promptLen_;
154         bool promptActive_;
155     };
156
157     /** \brief Internal: Primitive ClientReader implementation
158         
159         This implementation uses the cooked telnet mode to read lines from the console. It does not
160         support explicit line editing or any other advanced features.
161      */
162     class NoninteractiveClientReader
163         : public ClientReader
164     {
165     public:
166         NoninteractiveClientReader(Client & client);
167
168     private:
169         virtual void v_disablePrompt();
170         virtual void v_enablePrompt();
171         virtual void v_translate(std::string & data);
172
173         void newData(senf::Scheduler::EventId event);
174
175         SchedulerBinding binding_;
176         std::string buffer_;
177     };
178     
179 }}}
180
181 ///////////////////////////////ih.e////////////////////////////////////////
182 #endif
183
184 \f
185 // Local Variables:
186 // mode: c++
187 // fill-column: 100
188 // comment-column: 40
189 // c-file-style: "senf"
190 // indent-tabs-mode: nil
191 // ispell-local-dictionary: "american"
192 // compile-command: "scons -u test"
193 // End: