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