aboutsummaryrefslogtreecommitdiff
path: root/src/stable/protocoltelnet.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/stable/protocoltelnet.h')
-rw-r--r--src/stable/protocoltelnet.h220
1 files changed, 220 insertions, 0 deletions
diff --git a/src/stable/protocoltelnet.h b/src/stable/protocoltelnet.h
new file mode 100644
index 0000000..74d6478
--- /dev/null
+++ b/src/stable/protocoltelnet.h
@@ -0,0 +1,220 @@
1/*
2 * Copyright (C) 2007-2011 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#ifndef BU_PROTOCOL_TELNET_H
9#define BU_PROTOCOL_TELNET_H
10
11#include "bu/protocol.h"
12#include "bu/hash.h"
13#include "bu/string.h"
14
15// #define __TELNET_DEBUG
16
17namespace Bu
18{
19 /**
20 * Telnet Protocol handler. This attempts to provide useful and general
21 * support for most of the most commonly used Telnet extensions in a simple
22 * and easy to use way. The Option variables control the settings that can
23 * be used on the line, and control which virtual "callbacks" will be called
24 * when different events happen.
25 *
26 * To setup initial values and to disable any options you wish override the
27 * onNewConnection function in your own class, like this:
28 *@code
29 class MyTelnet : public Bu::ProtocolTelnet
30 {
31 public:
32 ...
33
34 virtual void onNewConnection( class Bu::Client *pClient )
35 {
36 // Call the parent class' onNewConnection to get everything all
37 // set up.
38 Bu::ProtocolTelnet::onNewConnection( pClient );
39
40 // These functions disable the option to send files via telnet,
41 // disabling the remote option means that we won't accept this
42 // option (binary data being sent to us) from the client.
43 //
44 // Disabling the local option means that the client cannot ask us
45 // to send them binary data.
46 oBinary.enableRemote( false );
47 oBinary.enableLocal( false );
48
49 // This requests that the client send us window size updates
50 // whenever the size of their window changes, and an initial set to
51 // boot.
52 //
53 // To see if this option is set later, try oNAWS.isRemoteSet(), but
54 // wait a little while, asking immediatly will always return false,
55 // since the remote side has yet to receive our request.
56 oNAWS.remoteSet();
57 }
58 }
59 @endcode
60 *
61 *@ingroup Serving
62 */
63 class ProtocolTelnet : public Protocol
64 {
65 public:
66 ProtocolTelnet();
67 virtual ~ProtocolTelnet();
68
69 /**
70 * If you override this function in a child class, make sure to call
71 * this version of it as the very first thing that you do, before you
72 * set any options. See the example in the class docs.
73 */
74 virtual void onNewConnection( class Bu::Client *pClient );
75
76 /**
77 * You should never override this function unless you really, really
78 * know what you're doing. If you want to get data after each line
79 * entered (in canonical mode) or after any data arrives (non canonical
80 * mode) then override the gotLine and gotData functions, respectively.
81 */
82 virtual void onNewData( class Bu::Client *pClient );
83
84 /**
85 * Override this function to be notified of lines being submitted by
86 * the client. This function is only called in canonical mode, after
87 * all edits are performed on the data. In this mode weather you use
88 * the line or not, the data will be cleared from the buffer when this
89 * function returns, any changes made to the buffer will be destroyed.
90 */
91 virtual void gotLine( Bu::String & /*sLine*/ ){};
92
93 /**
94 * Override this function to be notified of any new data that comes in
95 * from the client. This function is only called in non-canonical mode,
96 * and includes all raw data minus telnet control codes and ansi
97 * escape sequences. In this mode control of the buffer is up to the
98 * child class in this function, the buffer will never be cleared unless
99 * it happens in this function's override.
100 */
101 virtual void gotData( Bu::String & /*sData*/ ){};
102
103 /**
104 * Using this function to enable or disable canonical mode only affects
105 * the way the data is processed and which virtual functions are called
106 * during processing. It does not affect options set locally or
107 * remotely. Setting this to false will enable char-at-a-time mode,
108 * effectively disabling internal line-editing code. Characters
109 * such as backspace that are detected will not be handled and will be
110 * sent to the user override. The subclass will also be notified every
111 * time new data is available, not just whole lines.
112 *
113 * When set to true (the default), line editing control codes will be
114 * interpreted and used, and the subclass will only be notified when
115 * complete lines are available in the buffer.
116 */
117 void setCanonical( bool bCon=true );
118 bool isCanonical();
119
120 void write( const Bu::String &sData );
121 void write( const char *pData, int iSize );
122 void write( char cData );
123
124 const Bu::String &getBuffer() { return sDataBuf; }
125
126 public:
127 /**
128 * If you wish to know the current dimensions of the client window,
129 * override this function, it will be called whenever the size changes.
130 */
131 virtual void onSubNAWS( uint16_t /*iWidth*/, uint16_t /*iHeight*/ ){};
132
133 /**
134 * This function is called whenever an unknown sub negotiation option is
135 * sent over the line. This doesn't mean that it's malformatted, it
136 * just means that this class doesn't support that option yet, but you
137 * can handle it yourself if you'd like. Feel free to change the
138 * sSubBuf, it will be cleared as soon as this function returns anyway.
139 */
140 virtual void onSubUnknown( char /*cSubOpt*/,
141 Bu::String & /*sSubBuf*/ ){};
142
143 private:
144 /**
145 * Represents a basic telnet option, either on or off, no parameters.
146 * Each Option can negotiate effectively on it's own, and has two
147 * parameters in each of two classes. Both local and remote can be
148 * enabled/disabled and set/unset. Enabled represents the ability to
149 * set the option, disabling an option should also unset it. Set or
150 * unset represent wether the option is being used, if it is allowed.
151 */
152 class Option
153 {
154 friend class Bu::ProtocolTelnet;
155 private:
156 Option( ProtocolTelnet &rPT, char cCode );
157 virtual ~Option();
158
159 public:
160 void localEnable( bool bSet=true );
161 void localSet( bool bSet=true );
162
163 bool isLocalEnabled();
164 bool isLocalSet();
165
166 void remoteEnable( bool bSet=true );
167 void remoteSet( bool bSet=true );
168
169 bool isRemoteEnabled();
170 bool isRemoteSet();
171
172 private:
173 enum
174 {
175 fLocalCant = 0x01, /**< Local can't/won't allow option. */
176 fLocalIs = 0x02, /**< Local is using option. */
177 fRemoteCant = 0x04, /**< Remote can't/won't allow option. */
178 fRemoteIs = 0x08 /**< Remote is using option. */
179 };
180
181 ProtocolTelnet &rPT;
182 char fOpts;
183 char cCode;
184 };
185 friend class Bu::ProtocolTelnet::Option;
186
187 Hash<char, Option *> hOpts;
188
189 public:
190 Option oBinary;
191 Option oEcho;
192 Option oNAWS;
193 Option oSuppressGA;
194
195 private:
196 void onWill( char cCode );
197 void onWont( char cCode );
198 void onDo( char cCode );
199 void onDont( char cCode );
200 void onSubOpt();
201 void onCtlChar( char cChr );
202
203#ifdef __TELNET_DEBUG
204 void printCode( char cCode );
205 void printOpt( char cOpt );
206#endif
207
208 private:
209 Client *pClient;
210
211 Bu::String sDataBuf; /**< Buffer for regular line data. */
212 Bu::String sSubBuf; /**< Buffer for subnegotiation data. */
213 char cSubOpt; /**< Which suboption are we processing. */
214
215 bool bCanonical; /**< Are we canonicalizing incoming data? */
216 bool bSubOpt; /**< Are we processing a suboption right now? */
217 };
218}
219
220#endif