diff options
Diffstat (limited to 'src/stable/protocoltelnet.h')
-rw-r--r-- | src/stable/protocoltelnet.h | 220 |
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 | |||
17 | namespace 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 | ||