d813474042559c5b69c4e84e44fbaa009970d082
[senf.git] / Utils / Console / Telnet.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 Telnet public header */
25
26 #ifndef HH_SENF_Scheduler_Console_Telnet_
27 #define HH_SENF_Scheduler_Console_Telnet_ 1
28
29 // Custom includes
30 #include <vector>
31 #include <map>
32 #include <senf/Socket.hh>
33 #include <senf/Scheduler/Scheduler.hh>
34 #include <senf/Scheduler/ClockService.hh>
35
36 //#include "Telnet.mpp"
37 ///////////////////////////////hh.p////////////////////////////////////////
38
39 namespace senf {
40 namespace console {
41 namespace detail {
42
43     /** \brief  Telnet server
44
45         \see 
46             <a href="http://tools.ietf.org/html/rfc854>RFC 854</a> The Telnet protocol \n
47             <a href="http://tools.ietf.org/html/rfc854>RFC 855</a> Telnet option specifications
48
49         \todo SYNCH handling
50      */
51     class BaseTelnetProtocol
52     {
53     public:
54         static unsigned const DEFAULT_REQUEST_TIMEOUT_MS = 500u;
55
56         typedef ClientSocketHandle<senf::MakeSocketPolicy<
57             ConnectedCommunicationPolicy, 
58             StreamFramingPolicy, 
59             ReadablePolicy,
60             WriteablePolicy>::policy> Handle;
61
62         typedef unsigned char option_type;
63
64         struct TelnetHandler;
65
66         void write(std::string const & s);
67         void write(char c);
68
69         void sendNOP();
70         void sendBRK();
71         void sendIP();
72         void sendAO();
73         void sendAYT();
74         void sendEC();
75         void sendEL();
76         void sendGA();
77         
78         void sendOptionParameters(option_type option, std::string const & data);
79
80         void requestLocalOption(option_type option, bool enabled = true);
81         void acceptLocalOption(option_type option, bool enabled = true);
82
83         void requestPeerOption(option_type option, bool enabled = true);
84         void acceptPeerOption(option_type option, bool enabled = true);
85         
86     protected:
87         explicit BaseTelnetProtocol(Handle handle);
88         BaseTelnetProtocol();
89         virtual ~BaseTelnetProtocol();
90
91         template <class Handler>
92         void registerHandler(Handler * h, bool request=true);
93
94         void incrementRequestCounter();
95         void decrementRequestCounter();
96         bool requestsPending();
97
98     private:
99
100 #ifndef DOXYGEN
101     private:
102 #endif
103         virtual void v_setupComplete() = 0;
104         virtual void v_charReceived(char c) = 0;
105         virtual void v_eof() = 0;
106
107         virtual void v_handleNOP();
108         virtual void v_handleBRK();
109         virtual void v_handleIP();
110         virtual void v_handleAO();
111         virtual void v_handleAYT();
112         virtual void v_handleEC();
113         virtual void v_handleEL();
114         virtual void v_handleGA();
115         
116 #ifdef DOXYGEN
117     private:
118 #endif
119         void handleChar(char c);
120         void handleNormalChar(char c);
121         void handleCommand(char c);
122         void handleOption(char c);
123         void handleCR(char c);
124         void handleSBOption(char c);
125         void handleSBData(char c);
126         void handleSBIAC(char c);
127         void emit(char c);
128         void processCommand();
129         void transmit(char c);
130
131         void sendWILL(char option);
132         void sendWONT(char option);
133         void sendDO(char option);
134         void sendDONT(char option);
135
136         void readHandler(int state);
137         void writeHandler(int state);
138         void timeout();
139
140         enum Command { 
141             CMD_NONE = 0,
142             CMD_SE = 240,
143             CMD_NOP = 241,
144             CMD_DM = 242,
145             CMD_BRK = 243,
146             CMD_IP = 244,
147             CMD_AO = 245,
148             CMD_AYT = 246,
149             CMD_EC = 247,
150             CMD_EL = 248,
151             CMD_GA = 249,
152             CMD_SB = 250,
153             CMD_WILL = 251,
154             CMD_WONT = 252,
155             CMD_DO = 253,
156             CMD_DONT = 254,
157             CMD_IAC = 255,
158         };
159
160         struct OptInfo
161         {
162             enum WantState { WANTED, ACCEPTED, DISABLED };
163             enum OptionState { NONE, REQUEST_SENT, ACKNOWLEDGED };
164
165             OptInfo();
166             OptInfo(bool local, option_type option);
167
168             ///////////////////////////////////////////////////////////////
169
170             bool const local;
171             option_type const option;
172
173             WantState wantState;
174             OptionState optionState;
175             bool enabled;
176             
177         };
178
179         OptInfo & getOption(bool local, option_type option);
180         void request(OptInfo & info, bool enabled);
181         void response(OptInfo & info, bool enabled);
182
183         typedef std::map<std::pair<bool, option_type>, OptInfo> OptionsMap;
184         OptionsMap options_;
185
186         typedef std::map<option_type, TelnetHandler*> OptionHandlerMap;
187         OptionHandlerMap handlers_;
188
189         Handle handle_;
190
191         typedef std::vector<char> SendQueue;
192         SendQueue sendQueue_;
193
194         enum CharState { NORMAL, IAC_SEEN, EXPECT_OPTION, CR_SEEN, 
195                          SB_OPTION, SB_DATA, SB_IAC_SEEN };
196         CharState charState_;
197
198         Command command_;
199         option_type option_;
200         std::string data_;
201
202         senf::scheduler::FdEvent inputEvent_;
203         senf::scheduler::FdEvent outputEvent_;
204
205         unsigned pendingRequests_;
206
207         ClockService::clock_type requestTimeout_;
208         scheduler::TimerEvent timeout_;
209
210         friend class TelnetHandler;
211     };
212
213     struct BaseTelnetProtocol::TelnetHandler
214         : public virtual BaseTelnetProtocol
215     {
216         virtual ~TelnetHandler();
217         virtual void v_init() = 0;
218         virtual void v_handleOptionParameters(std::string const & data) = 0;
219     };
220
221     // See http://www.iana.org/assignments/telnet-options for a list of options
222     namespace telnetopt { BaseTelnetProtocol::option_type const ECHO = 1u; }
223     namespace telnetopt { BaseTelnetProtocol::option_type const TRANSMIT_BINARY = 0u; }
224     namespace telnetopt { BaseTelnetProtocol::option_type const SUPPRESS_GO_AHEAD = 3u; }
225     namespace telnetopt { BaseTelnetProtocol::option_type const TERMINAL_TYPE = 24u; }
226     namespace telnetopt { BaseTelnetProtocol::option_type const NAWS = 31u; }
227     namespace telnetopt { BaseTelnetProtocol::option_type const LINEMODE = 34u; }
228
229 namespace telnethandler {
230
231     class TerminalType
232         : public BaseTelnetProtocol::TelnetHandler
233     {
234     public:
235         static option_type const OPTION_CODE = telnetopt::TERMINAL_TYPE;
236
237         void nextTerminalType();
238         std::string const & terminalType() const;
239         
240     protected:
241         TerminalType();
242
243     private:
244         virtual void v_init();
245         virtual void v_handleOptionParameters(std::string const & data);
246
247         std::string type_;
248     };
249
250     class NAWS 
251         : public BaseTelnetProtocol::TelnetHandler
252     {
253     public:
254         static option_type const OPTION_CODE = telnetopt::NAWS;
255
256         unsigned width() const;
257         unsigned height() const;
258
259     protected:
260         NAWS();
261         
262     private:
263         virtual void v_windowSizeChanged() = 0;
264
265         virtual void v_init();
266         virtual void v_handleOptionParameters(std::string const & data);
267
268         unsigned width_;
269         unsigned height_;
270     };
271     
272 }
273
274 }}}
275
276 ///////////////////////////////hh.e////////////////////////////////////////
277 #include "Telnet.cci"
278
279 //#include "Telnet.ct"
280 #include "Telnet.cti"
281 #endif
282
283 \f
284 // Local Variables:
285 // mode: c++
286 // fill-column: 100
287 // comment-column: 40
288 // c-file-style: "senf"
289 // indent-tabs-mode: nil
290 // ispell-local-dictionary: "american"
291 // compile-command: "scons -u test"
292 // End: