summaryrefslogtreecommitdiff
path: root/src/stable/protocoltelnet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/stable/protocoltelnet.cpp')
-rw-r--r--src/stable/protocoltelnet.cpp942
1 files changed, 471 insertions, 471 deletions
diff --git a/src/stable/protocoltelnet.cpp b/src/stable/protocoltelnet.cpp
index aed23be..d5465d1 100644
--- a/src/stable/protocoltelnet.cpp
+++ b/src/stable/protocoltelnet.cpp
@@ -11,53 +11,53 @@
11/* We apparently at least want defs for the lower 13, not sure we care about 11/* We apparently at least want defs for the lower 13, not sure we care about
12 * the rest of the chars, maybe escape. 12 * the rest of the chars, maybe escape.
13 */ 13 */
14#define CH_NUL '\x00' /* NUL */ 14#define CH_NUL '\x00' /* NUL */
15#define CH_SOH '\x01' /* Start Of Heading */ 15#define CH_SOH '\x01' /* Start Of Heading */
16#define CH_STX '\x02' /* Start of Text */ 16#define CH_STX '\x02' /* Start of Text */
17#define CH_ETX '\x03' /* End of Text */ 17#define CH_ETX '\x03' /* End of Text */
18#define CH_EOT '\x04' /* End of transmission */ 18#define CH_EOT '\x04' /* End of transmission */
19#define CH_ENQ '\x05' /* Enquiery */ 19#define CH_ENQ '\x05' /* Enquiery */
20#define CH_ACK '\x06' /* Acknowledge */ 20#define CH_ACK '\x06' /* Acknowledge */
21#define CH_BEL '\x07' /* Bell */ 21#define CH_BEL '\x07' /* Bell */
22#define CH_BS '\x08' /* Backspace */ 22#define CH_BS '\x08' /* Backspace */
23#define CH_TAB '\x09' /* Horizontal Tab */ 23#define CH_TAB '\x09' /* Horizontal Tab */
24#define CH_LF '\x0A' /* NL Line feed, new line */ 24#define CH_LF '\x0A' /* NL Line feed, new line */
25#define CH_VT '\x0B' /* Vertical Tab */ 25#define CH_VT '\x0B' /* Vertical Tab */
26#define CH_FF '\x0C' /* Form feed, new page */ 26#define CH_FF '\x0C' /* Form feed, new page */
27#define CH_CR '\x0D' /* Carriage return */ 27#define CH_CR '\x0D' /* Carriage return */
28#define CH_ESC '\x1B' /* Escape */ 28#define CH_ESC '\x1B' /* Escape */
29#define CH_DEL '\x7F' /* Delete */ 29#define CH_DEL '\x7F' /* Delete */
30 30
31#define CODE_SE '\xf0' /* End of subnegotiation params. */ 31#define CODE_SE '\xf0' /* End of subnegotiation params. */
32#define CODE_NOP '\xf1' /* No operation (keep-alive). */ 32#define CODE_NOP '\xf1' /* No operation (keep-alive). */
33#define CODE_DM '\xf2' /* Datastream side of a Synch. */ 33#define CODE_DM '\xf2' /* Datastream side of a Synch. */
34#define CODE_BRK '\xf3' /* Break character. */ 34#define CODE_BRK '\xf3' /* Break character. */
35#define CODE_IP '\xf4' /* Interrupt Process character. */ 35#define CODE_IP '\xf4' /* Interrupt Process character. */
36#define CODE_AO '\xf5' /* Abort Output character. */ 36#define CODE_AO '\xf5' /* Abort Output character. */
37#define CODE_AYT '\xf6' /* Are You There? character. */ 37#define CODE_AYT '\xf6' /* Are You There? character. */
38#define CODE_EC '\xf7' /* Erase Character character. */ 38#define CODE_EC '\xf7' /* Erase Character character. */
39#define CODE_EL '\xf8' /* Erase Line character. */ 39#define CODE_EL '\xf8' /* Erase Line character. */
40#define CODE_GA '\xf9' /* Go Ahead signal. */ 40#define CODE_GA '\xf9' /* Go Ahead signal. */
41#define CODE_SB '\xfa' /* Begin subnegotiation options. */ 41#define CODE_SB '\xfa' /* Begin subnegotiation options. */
42#define CODE_WILL '\xfb' /* Desire to do something. */ 42#define CODE_WILL '\xfb' /* Desire to do something. */
43#define CODE_WONT '\xfc' /* Refuse to perform. */ 43#define CODE_WONT '\xfc' /* Refuse to perform. */
44#define CODE_DO '\xfd' /* Request option. */ 44#define CODE_DO '\xfd' /* Request option. */
45#define CODE_DONT '\xfe' /* Demand a stop. */ 45#define CODE_DONT '\xfe' /* Demand a stop. */
46 46
47#define CODE_IAC '\xff' /* Interpret-As-Command. */ 47#define CODE_IAC '\xff' /* Interpret-As-Command. */
48 48
49#define OPT_BINARY '\x00' /* Binary mode (file transfers?). */ 49#define OPT_BINARY '\x00' /* Binary mode (file transfers?). */
50#define OPT_ECHO '\x01' /* (local) Echo mode. */ 50#define OPT_ECHO '\x01' /* (local) Echo mode. */
51#define OPT_SUPGA '\x03' /* Suppress Go Ahead signals. */ 51#define OPT_SUPGA '\x03' /* Suppress Go Ahead signals. */
52#define OPT_STATUS '\x05' /* Allow status messages. */ 52#define OPT_STATUS '\x05' /* Allow status messages. */
53#define OPT_TIMING '\x06' /* Place a timing mark in the code. */ 53#define OPT_TIMING '\x06' /* Place a timing mark in the code. */
54#define OPT_EXASCII '\x11' /* Extended ASCII. */ 54#define OPT_EXASCII '\x11' /* Extended ASCII. */
55#define OPT_LOGOUT '\x12' /* Logout. */ 55#define OPT_LOGOUT '\x12' /* Logout. */
56#define OPT_TTYPE '\x18' /* Terminal Type. */ 56#define OPT_TTYPE '\x18' /* Terminal Type. */
57#define OPT_NAWS '\x1f' /* Negotiate about window size. */ 57#define OPT_NAWS '\x1f' /* Negotiate about window size. */
58#define OPT_TSPEED '\x20' /* Terminal Speed. */ 58#define OPT_TSPEED '\x20' /* Terminal Speed. */
59#define OPT_NEWENV '\x27' /* New Environment Option. */ 59#define OPT_NEWENV '\x27' /* New Environment Option. */
60#define OPT_EXOPL '\xff' /* Can we, will we, handle extended options. */ 60#define OPT_EXOPL '\xff' /* Can we, will we, handle extended options. */
61 61
62#ifndef __TELNET_DEBUG 62#ifndef __TELNET_DEBUG
63# define printCode( a ) (void)0 63# define printCode( a ) (void)0
@@ -65,12 +65,12 @@
65#endif 65#endif
66 66
67Bu::ProtocolTelnet::ProtocolTelnet() : 67Bu::ProtocolTelnet::ProtocolTelnet() :
68 oBinary( *this, OPT_BINARY ), 68 oBinary( *this, OPT_BINARY ),
69 oEcho( *this, OPT_ECHO ), 69 oEcho( *this, OPT_ECHO ),
70 oNAWS( *this, OPT_NAWS ), 70 oNAWS( *this, OPT_NAWS ),
71 oSuppressGA(*this, OPT_SUPGA ), 71 oSuppressGA(*this, OPT_SUPGA ),
72 bCanonical( true ), 72 bCanonical( true ),
73 bSubOpt( false ) 73 bSubOpt( false )
74{ 74{
75} 75}
76 76
@@ -80,439 +80,439 @@ Bu::ProtocolTelnet::~ProtocolTelnet()
80 80
81void Bu::ProtocolTelnet::onNewConnection( Bu::Client *pClient ) 81void Bu::ProtocolTelnet::onNewConnection( Bu::Client *pClient )
82{ 82{
83 this->pClient = pClient; 83 this->pClient = pClient;
84} 84}
85 85
86void Bu::ProtocolTelnet::onNewData( Bu::Client *pClient ) 86void Bu::ProtocolTelnet::onNewData( Bu::Client *pClient )
87{ 87{
88 char bc; 88 char bc;
89 int iLeft; 89 int iLeft;
90 while( (iLeft = pClient->getInputSize()) ) 90 while( (iLeft = pClient->getInputSize()) )
91 { 91 {
92 if( bSubOpt ) 92 if( bSubOpt )
93 { 93 {
94 pClient->peek( &bc, 1 ); 94 pClient->peek( &bc, 1 );
95 if( bc == CODE_IAC ) 95 if( bc == CODE_IAC )
96 { 96 {
97 if( iLeft <= 1 ) return; 97 if( iLeft <= 1 ) return;
98 char bc2; 98 char bc2;
99 printCode( CODE_IAC ); 99 printCode( CODE_IAC );
100 pClient->peek( &bc2, 1, 1 ); 100 pClient->peek( &bc2, 1, 1 );
101 printCode( bc2 ); 101 printCode( bc2 );
102 if( bc2 == CODE_SE ) 102 if( bc2 == CODE_SE )
103 { 103 {
104 bSubOpt = false; 104 bSubOpt = false;
105 onSubOpt(); 105 onSubOpt();
106 } 106 }
107 else if( bc2 == CODE_IAC ) 107 else if( bc2 == CODE_IAC )
108 { 108 {
109 sSubBuf += CODE_IAC; 109 sSubBuf += CODE_IAC;
110 } 110 }
111 else 111 else
112 { 112 {
113 // Error of some sort. 113 // Error of some sort.
114 } 114 }
115 pClient->seek( 1 ); 115 pClient->seek( 1 );
116 } 116 }
117 else 117 else
118 { 118 {
119 sSubBuf += bc; 119 sSubBuf += bc;
120 } 120 }
121 pClient->seek( 1 ); 121 pClient->seek( 1 );
122 } 122 }
123 else 123 else
124 { 124 {
125 pClient->peek( &bc, 1 ); 125 pClient->peek( &bc, 1 );
126 if( bc == CODE_IAC ) 126 if( bc == CODE_IAC )
127 { 127 {
128 if( iLeft <= 1 ) return; 128 if( iLeft <= 1 ) return;
129 char bc2; 129 char bc2;
130 pClient->peek( &bc2, 1, 1 ); 130 pClient->peek( &bc2, 1, 1 );
131 printCode( bc ); 131 printCode( bc );
132 printCode( bc2 ); 132 printCode( bc2 );
133 133
134 switch( bc2 ) 134 switch( bc2 )
135 { 135 {
136 case CODE_WILL: 136 case CODE_WILL:
137 if( iLeft <= 2 ) return; 137 if( iLeft <= 2 ) return;
138 { 138 {
139 char bc3; 139 char bc3;
140 pClient->peek( &bc3, 1, 2 ); 140 pClient->peek( &bc3, 1, 2 );
141 pClient->seek( 1 ); 141 pClient->seek( 1 );
142 printOpt( bc3 ); 142 printOpt( bc3 );
143 onWill( bc3 ); 143 onWill( bc3 );
144 } 144 }
145 break; 145 break;
146 146
147 case CODE_WONT: 147 case CODE_WONT:
148 if( iLeft <= 2 ) return; 148 if( iLeft <= 2 ) return;
149 { 149 {
150 char bc3; 150 char bc3;
151 pClient->peek( &bc3, 1, 2 ); 151 pClient->peek( &bc3, 1, 2 );
152 pClient->seek( 1 ); 152 pClient->seek( 1 );
153 printOpt( bc3 ); 153 printOpt( bc3 );
154 onWont( bc3 ); 154 onWont( bc3 );
155 } 155 }
156 break; 156 break;
157 157
158 case CODE_DO: 158 case CODE_DO:
159 if( iLeft <= 2 ) return; 159 if( iLeft <= 2 ) return;
160 { 160 {
161 char bc3; 161 char bc3;
162 pClient->peek( &bc3, 1, 2 ); 162 pClient->peek( &bc3, 1, 2 );
163 pClient->seek( 1 ); 163 pClient->seek( 1 );
164 printOpt( bc3 ); 164 printOpt( bc3 );
165 onDo( bc3 ); 165 onDo( bc3 );
166 } 166 }
167 break; 167 break;
168 168
169 case CODE_DONT: 169 case CODE_DONT:
170 if( iLeft <= 2 ) return; 170 if( iLeft <= 2 ) return;
171 { 171 {
172 char bc3; 172 char bc3;
173 pClient->peek( &bc3, 1, 2 ); 173 pClient->peek( &bc3, 1, 2 );
174 pClient->seek( 1 ); 174 pClient->seek( 1 );
175 printOpt( bc3 ); 175 printOpt( bc3 );
176 onDont( bc3 ); 176 onDont( bc3 );
177 } 177 }
178 break; 178 break;
179 179
180 case CODE_SB: 180 case CODE_SB:
181 if( iLeft <= 2 ) return; 181 if( iLeft <= 2 ) return;
182 { 182 {
183 pClient->peek( &cSubOpt, 1, 2 ); 183 pClient->peek( &cSubOpt, 1, 2 );
184 pClient->seek( 1 ); 184 pClient->seek( 1 );
185 printOpt( cSubOpt ); 185 printOpt( cSubOpt );
186 bSubOpt = true; 186 bSubOpt = true;
187 } 187 }
188 break; 188 break;
189 189
190 case CODE_IAC: 190 case CODE_IAC:
191 sDataBuf += CODE_IAC; 191 sDataBuf += CODE_IAC;
192 printCode( CODE_IAC ); 192 printCode( CODE_IAC );
193 break; 193 break;
194 } 194 }
195 pClient->seek( 1 ); 195 pClient->seek( 1 );
196#ifdef __TELNET_DEBUG 196#ifdef __TELNET_DEBUG
197 printf("\n"); 197 printf("\n");
198#endif 198#endif
199 } 199 }
200 else if( bc == CODE_SB ) 200 else if( bc == CODE_SB )
201 { 201 {
202 } 202 }
203 else 203 else
204 { 204 {
205 // This is where control code handling goes 205 // This is where control code handling goes
206 // Also, possibly, character code conversion, although I'm not 206 // Also, possibly, character code conversion, although I'm not
207 // sure that really matters anymore, go ASCII/UTF-8 207 // sure that really matters anymore, go ASCII/UTF-8
208 if( bCanonical ) 208 if( bCanonical )
209 { 209 {
210 if( bc < 0x20 || bc >= CH_DEL ) 210 if( bc < 0x20 || bc >= CH_DEL )
211 { 211 {
212 if( bc == CH_CR ) 212 if( bc == CH_CR )
213 { 213 {
214 if( iLeft <= 1 ) return; 214 if( iLeft <= 1 ) return;
215 char bc2; 215 char bc2;
216 pClient->peek( &bc2, 1, 1 ); 216 pClient->peek( &bc2, 1, 1 );
217 if( bc2 == CH_NUL || bc2 == CH_LF ) 217 if( bc2 == CH_NUL || bc2 == CH_LF )
218 { 218 {
219 onCtlChar( bc ); 219 onCtlChar( bc );
220 gotLine( sDataBuf ); 220 gotLine( sDataBuf );
221 sDataBuf.clear(); 221 sDataBuf.clear();
222 } 222 }
223 pClient->seek( 1 ); 223 pClient->seek( 1 );
224 } 224 }
225 else 225 else
226 { 226 {
227 onCtlChar( bc ); 227 onCtlChar( bc );
228 } 228 }
229 } 229 }
230 else 230 else
231 { 231 {
232 sDataBuf += bc; 232 sDataBuf += bc;
233 if( oEcho.isLocalSet() ) 233 if( oEcho.isLocalSet() )
234 { 234 {
235 pClient->write( &bc, 1 ); 235 pClient->write( &bc, 1 );
236#ifdef __TELNET_DEBUG 236#ifdef __TELNET_DEBUG
237 printf("%c", bc ); 237 printf("%c", bc );
238 fflush( stdout ); 238 fflush( stdout );
239#endif 239#endif
240 } 240 }
241 } 241 }
242 } 242 }
243 else 243 else
244 { 244 {
245 sDataBuf += bc; 245 sDataBuf += bc;
246 if( oEcho.isLocalSet() ) 246 if( oEcho.isLocalSet() )
247 { 247 {
248 pClient->write( &bc, 1 ); 248 pClient->write( &bc, 1 );
249 } 249 }
250 } 250 }
251 } 251 }
252 pClient->seek( 1 ); 252 pClient->seek( 1 );
253 } 253 }
254 } 254 }
255 255
256 // It's true, this code will not be executed if we only have half of an 256 // It's true, this code will not be executed if we only have half of an
257 // IAC code or multibyte escape sequence or something, but then again, it 257 // IAC code or multibyte escape sequence or something, but then again, it
258 // shouldn't be called then, and really, shouldn't be, it'll be called soon 258 // shouldn't be called then, and really, shouldn't be, it'll be called soon
259 // enough, when we get the rest of that code. 259 // enough, when we get the rest of that code.
260 if( !bCanonical ) 260 if( !bCanonical )
261 { 261 {
262 gotData( sDataBuf ); 262 gotData( sDataBuf );
263 } 263 }
264} 264}
265 265
266void Bu::ProtocolTelnet::setCanonical( bool bCon ) 266void Bu::ProtocolTelnet::setCanonical( bool bCon )
267{ 267{
268 bCanonical = bCon; 268 bCanonical = bCon;
269} 269}
270 270
271bool Bu::ProtocolTelnet::isCanonical() 271bool Bu::ProtocolTelnet::isCanonical()
272{ 272{
273 return bCanonical; 273 return bCanonical;
274} 274}
275 275
276void Bu::ProtocolTelnet::write( const Bu::String &sData ) 276void Bu::ProtocolTelnet::write( const Bu::String &sData )
277{ 277{
278 write( sData.getStr(), sData.getSize() ); 278 write( sData.getStr(), sData.getSize() );
279} 279}
280 280
281void Bu::ProtocolTelnet::write( const char *pData, int iSize ) 281void Bu::ProtocolTelnet::write( const char *pData, int iSize )
282{ 282{
283 int iLast = 0, j; 283 int iLast = 0, j;
284 for( j = iLast; j < iSize; j++ ) 284 for( j = iLast; j < iSize; j++ )
285 { 285 {
286 if( pData[j] == '\n' ) 286 if( pData[j] == '\n' )
287 { 287 {
288 if( j+1 >= iSize || 288 if( j+1 >= iSize ||
289 (pData[j+1] != '\r' && pData[j+1] != '\0') ) 289 (pData[j+1] != '\r' && pData[j+1] != '\0') )
290 { 290 {
291 pClient->write( pData+iLast, j-iLast ); 291 pClient->write( pData+iLast, j-iLast );
292 pClient->write( "\n\r", 2 ); 292 pClient->write( "\n\r", 2 );
293 iLast = j+1; 293 iLast = j+1;
294 } 294 }
295 else 295 else
296 { 296 {
297 j++; 297 j++;
298 } 298 }
299 } 299 }
300 } 300 }
301 if( j > iLast ) 301 if( j > iLast )
302 { 302 {
303 pClient->write( pData+iLast, iSize-iLast ); 303 pClient->write( pData+iLast, iSize-iLast );
304 } 304 }
305 //pClient->write( pData, iSize ); 305 //pClient->write( pData, iSize );
306} 306}
307 307
308void Bu::ProtocolTelnet::write( char cData ) 308void Bu::ProtocolTelnet::write( char cData )
309{ 309{
310 write( &cData, 1 ); 310 write( &cData, 1 );
311} 311}
312 312
313void Bu::ProtocolTelnet::onWill( char cCode ) 313void Bu::ProtocolTelnet::onWill( char cCode )
314{ 314{
315 try 315 try
316 { 316 {
317 Option *pOpt = hOpts[cCode]; 317 Option *pOpt = hOpts[cCode];
318 if( pOpt->isRemoteEnabled() ) 318 if( pOpt->isRemoteEnabled() )
319 { 319 {
320 pOpt->fOpts |= Option::fRemoteIs; 320 pOpt->fOpts |= Option::fRemoteIs;
321 char buf[3] = { CODE_IAC, CODE_DO, cCode }; 321 char buf[3] = { CODE_IAC, CODE_DO, cCode };
322 pClient->write( buf, 3 ); 322 pClient->write( buf, 3 );
323 } 323 }
324 else 324 else
325 { 325 {
326 char buf[3] = { CODE_IAC, CODE_DONT, cCode }; 326 char buf[3] = { CODE_IAC, CODE_DONT, cCode };
327 pClient->write( buf, 3 ); 327 pClient->write( buf, 3 );
328 } 328 }
329 329
330 } 330 }
331 catch( Bu::HashException &e ) 331 catch( Bu::HashException &e )
332 { 332 {
333 char buf[3] = { CODE_IAC, CODE_DONT, cCode }; 333 char buf[3] = { CODE_IAC, CODE_DONT, cCode };
334 pClient->write( buf, 3 ); 334 pClient->write( buf, 3 );
335 } 335 }
336} 336}
337 337
338void Bu::ProtocolTelnet::onWont( char cCode ) 338void Bu::ProtocolTelnet::onWont( char cCode )
339{ 339{
340 try 340 try
341 { 341 {
342 Option *pOpt = hOpts[cCode]; 342 Option *pOpt = hOpts[cCode];
343 343
344 pOpt->fOpts &= ~Option::fRemoteIs; 344 pOpt->fOpts &= ~Option::fRemoteIs;
345 char buf[3] = { CODE_IAC, CODE_DONT, cCode }; 345 char buf[3] = { CODE_IAC, CODE_DONT, cCode };
346 pClient->write( buf, 3 ); 346 pClient->write( buf, 3 );
347 } 347 }
348 catch( Bu::HashException &e ) 348 catch( Bu::HashException &e )
349 { 349 {
350 char buf[3] = { CODE_IAC, CODE_DONT, cCode }; 350 char buf[3] = { CODE_IAC, CODE_DONT, cCode };
351 pClient->write( buf, 3 ); 351 pClient->write( buf, 3 );
352 } 352 }
353} 353}
354 354
355void Bu::ProtocolTelnet::onDo( char cCode ) 355void Bu::ProtocolTelnet::onDo( char cCode )
356{ 356{
357 try 357 try
358 { 358 {
359 Option *pOpt = hOpts[cCode]; 359 Option *pOpt = hOpts[cCode];
360 if( pOpt->isLocalEnabled() ) 360 if( pOpt->isLocalEnabled() )
361 { 361 {
362 pOpt->fOpts |= Option::fLocalIs; 362 pOpt->fOpts |= Option::fLocalIs;
363 char buf[3] = { CODE_IAC, CODE_WILL, cCode }; 363 char buf[3] = { CODE_IAC, CODE_WILL, cCode };
364 pClient->write( buf, 3 ); 364 pClient->write( buf, 3 );
365 } 365 }
366 else 366 else
367 { 367 {
368 char buf[3] = { CODE_IAC, CODE_WONT, cCode }; 368 char buf[3] = { CODE_IAC, CODE_WONT, cCode };
369 pClient->write( buf, 3 ); 369 pClient->write( buf, 3 );
370 } 370 }
371 371
372 } 372 }
373 catch( Bu::HashException &e ) 373 catch( Bu::HashException &e )
374 { 374 {
375 char buf[3] = { CODE_IAC, CODE_WONT, cCode }; 375 char buf[3] = { CODE_IAC, CODE_WONT, cCode };
376 pClient->write( buf, 3 ); 376 pClient->write( buf, 3 );
377 } 377 }
378} 378}
379 379
380void Bu::ProtocolTelnet::onDont( char cCode ) 380void Bu::ProtocolTelnet::onDont( char cCode )
381{ 381{
382 try 382 try
383 { 383 {
384 Option *pOpt = hOpts[cCode]; 384 Option *pOpt = hOpts[cCode];
385 385
386 pOpt->fOpts &= ~Option::fLocalIs; 386 pOpt->fOpts &= ~Option::fLocalIs;
387 char buf[3] = { CODE_IAC, CODE_DONT, cCode }; 387 char buf[3] = { CODE_IAC, CODE_DONT, cCode };
388 pClient->write( buf, 3 ); 388 pClient->write( buf, 3 );
389 } 389 }
390 catch( Bu::HashException &e ) 390 catch( Bu::HashException &e )
391 { 391 {
392 char buf[3] = { CODE_IAC, CODE_DONT, cCode }; 392 char buf[3] = { CODE_IAC, CODE_DONT, cCode };
393 pClient->write( buf, 3 ); 393 pClient->write( buf, 3 );
394 } 394 }
395} 395}
396 396
397void Bu::ProtocolTelnet::onSubOpt() 397void Bu::ProtocolTelnet::onSubOpt()
398{ 398{
399 switch( cSubOpt ) 399 switch( cSubOpt )
400 { 400 {
401 case OPT_NAWS: 401 case OPT_NAWS:
402 { 402 {
403 uint16_t iWidth, iHeight; 403 uint16_t iWidth, iHeight;
404 ((char *)&iWidth)[1] = sSubBuf[0]; 404 ((char *)&iWidth)[1] = sSubBuf[0];
405 ((char *)&iWidth)[0] = sSubBuf[1]; 405 ((char *)&iWidth)[0] = sSubBuf[1];
406 ((char *)&iHeight)[1] = sSubBuf[2]; 406 ((char *)&iHeight)[1] = sSubBuf[2];
407 ((char *)&iHeight)[0] = sSubBuf[3]; 407 ((char *)&iHeight)[0] = sSubBuf[3];
408 onSubNAWS( iWidth, iHeight ); 408 onSubNAWS( iWidth, iHeight );
409 } 409 }
410 break; 410 break;
411 411
412 default: 412 default:
413 onSubUnknown( cSubOpt, sSubBuf ); 413 onSubUnknown( cSubOpt, sSubBuf );
414 break; 414 break;
415 } 415 }
416 416
417 sSubBuf.clear(); 417 sSubBuf.clear();
418} 418}
419 419
420void Bu::ProtocolTelnet::onCtlChar( char cChr ) 420void Bu::ProtocolTelnet::onCtlChar( char cChr )
421{ 421{
422#ifdef __TELNET_DEBUG 422#ifdef __TELNET_DEBUG
423 switch( cChr ) 423 switch( cChr )
424 { 424 {
425 case CH_NUL: printf("NUL "); break; 425 case CH_NUL: printf("NUL "); break;
426 case CH_SOH: printf("SOH "); break; 426 case CH_SOH: printf("SOH "); break;
427 case CH_STX: printf("STX "); break; 427 case CH_STX: printf("STX "); break;
428 case CH_ETX: printf("ETX "); break; 428 case CH_ETX: printf("ETX "); break;
429 case CH_EOT: printf("EOT "); break; 429 case CH_EOT: printf("EOT "); break;
430 case CH_ENQ: printf("ENQ "); break; 430 case CH_ENQ: printf("ENQ "); break;
431 case CH_ACK: printf("ACK "); break; 431 case CH_ACK: printf("ACK "); break;
432 case CH_BEL: printf("BEL "); break; 432 case CH_BEL: printf("BEL "); break;
433 case CH_BS: printf("BS "); break; 433 case CH_BS: printf("BS "); break;
434 case CH_TAB: printf("TAB "); break; 434 case CH_TAB: printf("TAB "); break;
435 case CH_LF: printf("LF "); break; 435 case CH_LF: printf("LF "); break;
436 case CH_VT: printf("VT "); break; 436 case CH_VT: printf("VT "); break;
437 case CH_FF: printf("FF "); break; 437 case CH_FF: printf("FF "); break;
438 case CH_CR: printf("CR "); break; 438 case CH_CR: printf("CR "); break;
439 case CH_ESC: printf("ESC "); break; 439 case CH_ESC: printf("ESC "); break;
440 case CH_DEL: printf("DEL "); break; 440 case CH_DEL: printf("DEL "); break;
441 default: printf("!![%02x] ", cChr ); break; 441 default: printf("!![%02x] ", cChr ); break;
442 } 442 }
443 fflush( stdout ); 443 fflush( stdout );
444#endif 444#endif
445 445
446 switch( cChr ) 446 switch( cChr )
447 { 447 {
448 case CH_DEL: 448 case CH_DEL:
449 { 449 {
450 if( sDataBuf.getSize() > 0 ) 450 if( sDataBuf.getSize() > 0 )
451 { 451 {
452 sDataBuf.resize( sDataBuf.getSize()-1 ); 452 sDataBuf.resize( sDataBuf.getSize()-1 );
453 char buf[3] = { CH_BS, ' ', CH_BS }; 453 char buf[3] = { CH_BS, ' ', CH_BS };
454 pClient->write( buf, 3 ); 454 pClient->write( buf, 3 );
455 } 455 }
456 } 456 }
457 break; 457 break;
458 458
459 } 459 }
460} 460}
461 461
462#ifdef __TELNET_DEBUG 462#ifdef __TELNET_DEBUG
463void Bu::ProtocolTelnet::printCode( char cCode ) 463void Bu::ProtocolTelnet::printCode( char cCode )
464{ 464{
465 switch( cCode ) 465 switch( cCode )
466 { 466 {
467 case CODE_SE: printf("SE "); break; 467 case CODE_SE: printf("SE "); break;
468 case CODE_NOP: printf("NOP "); break; 468 case CODE_NOP: printf("NOP "); break;
469 case CODE_DM: printf("DM "); break; 469 case CODE_DM: printf("DM "); break;
470 case CODE_BRK: printf("BRK "); break; 470 case CODE_BRK: printf("BRK "); break;
471 case CODE_IP: printf("IP "); break; 471 case CODE_IP: printf("IP "); break;
472 case CODE_AO: printf("AO "); break; 472 case CODE_AO: printf("AO "); break;
473 case CODE_AYT: printf("AYT "); break; 473 case CODE_AYT: printf("AYT "); break;
474 case CODE_EC: printf("EC "); break; 474 case CODE_EC: printf("EC "); break;
475 case CODE_EL: printf("EL "); break; 475 case CODE_EL: printf("EL "); break;
476 case CODE_GA: printf("GA "); break; 476 case CODE_GA: printf("GA "); break;
477 case CODE_SB: printf("SB "); break; 477 case CODE_SB: printf("SB "); break;
478 case CODE_WILL: printf("WILL "); break; 478 case CODE_WILL: printf("WILL "); break;
479 case CODE_WONT: printf("WONT "); break; 479 case CODE_WONT: printf("WONT "); break;
480 case CODE_DO: printf("DO "); break; 480 case CODE_DO: printf("DO "); break;
481 case CODE_DONT: printf("DONT "); break; 481 case CODE_DONT: printf("DONT "); break;
482 case CODE_IAC: printf("IAC "); break; 482 case CODE_IAC: printf("IAC "); break;
483 default: printf("??%02x ", cCode ); break; 483 default: printf("??%02x ", cCode ); break;
484 } 484 }
485 fflush( stdout ); 485 fflush( stdout );
486} 486}
487 487
488void Bu::ProtocolTelnet::printOpt( char cOpt ) 488void Bu::ProtocolTelnet::printOpt( char cOpt )
489{ 489{
490 switch( cOpt ) 490 switch( cOpt )
491 { 491 {
492 case OPT_BINARY: printf("BINARY "); break; 492 case OPT_BINARY: printf("BINARY "); break;
493 case OPT_ECHO: printf("ECHO "); break; 493 case OPT_ECHO: printf("ECHO "); break;
494 case OPT_SUPGA: printf("SUPGA "); break; 494 case OPT_SUPGA: printf("SUPGA "); break;
495 case OPT_STATUS: printf("STATUS "); break; 495 case OPT_STATUS: printf("STATUS "); break;
496 case OPT_TIMING: printf("TIMING "); break; 496 case OPT_TIMING: printf("TIMING "); break;
497 case OPT_EXASCII: printf("EXASCII "); break; 497 case OPT_EXASCII: printf("EXASCII "); break;
498 case OPT_LOGOUT: printf("LOGOUT "); break; 498 case OPT_LOGOUT: printf("LOGOUT "); break;
499 case OPT_TTYPE: printf("TTYPE "); break; 499 case OPT_TTYPE: printf("TTYPE "); break;
500 case OPT_NAWS: printf("NAWS "); break; 500 case OPT_NAWS: printf("NAWS "); break;
501 case OPT_TSPEED: printf("TSPEED "); break; 501 case OPT_TSPEED: printf("TSPEED "); break;
502 case OPT_NEWENV: printf("NEWENV "); break; 502 case OPT_NEWENV: printf("NEWENV "); break;
503 case OPT_EXOPL: printf("EXOPL "); break; 503 case OPT_EXOPL: printf("EXOPL "); break;
504 default: printf("??%02x ", cOpt); break; 504 default: printf("??%02x ", cOpt); break;
505 } 505 }
506 fflush( stdout ); 506 fflush( stdout );
507} 507}
508#endif 508#endif
509 509
510Bu::ProtocolTelnet::Option::Option( Bu::ProtocolTelnet &rPT, char cCode ) : 510Bu::ProtocolTelnet::Option::Option( Bu::ProtocolTelnet &rPT, char cCode ) :
511 rPT( rPT ), 511 rPT( rPT ),
512 fOpts( 0 ), 512 fOpts( 0 ),
513 cCode( cCode ) 513 cCode( cCode )
514{ 514{
515 rPT.hOpts.insert( cCode, this ); 515 rPT.hOpts.insert( cCode, this );
516} 516}
517 517
518Bu::ProtocolTelnet::Option::~Option() 518Bu::ProtocolTelnet::Option::~Option()
@@ -521,100 +521,100 @@ Bu::ProtocolTelnet::Option::~Option()
521 521
522void Bu::ProtocolTelnet::Option::localEnable( bool bSet ) 522void Bu::ProtocolTelnet::Option::localEnable( bool bSet )
523{ 523{
524 if( bSet == (bool)(!(fOpts&fLocalCant)) ) return; 524 if( bSet == (bool)(!(fOpts&fLocalCant)) ) return;
525 525
526 if( bSet ) 526 if( bSet )
527 fOpts &= ~fLocalCant; 527 fOpts &= ~fLocalCant;
528 else 528 else
529 fOpts |= fLocalCant; 529 fOpts |= fLocalCant;
530} 530}
531 531
532void Bu::ProtocolTelnet::Option::localSet( bool bSet ) 532void Bu::ProtocolTelnet::Option::localSet( bool bSet )
533{ 533{
534 if( bSet == (bool)(fOpts&fLocalIs) ) return; 534 if( bSet == (bool)(fOpts&fLocalIs) ) return;
535 535
536 char buf[3] = { CODE_IAC, 0, cCode }; 536 char buf[3] = { CODE_IAC, 0, cCode };
537 537
538 if( bSet ) 538 if( bSet )
539 { 539 {
540 buf[1] = CODE_WILL; 540 buf[1] = CODE_WILL;
541 rPT.pClient->write( buf, 3 ); 541 rPT.pClient->write( buf, 3 );
542#ifdef __TELNET_DEBUG 542#ifdef __TELNET_DEBUG
543 printf("<= "); 543 printf("<= ");
544 rPT.printCode( buf[0] ); 544 rPT.printCode( buf[0] );
545 rPT.printCode( buf[1] ); 545 rPT.printCode( buf[1] );
546 rPT.printOpt( buf[2] ); 546 rPT.printOpt( buf[2] );
547 printf("\n"); 547 printf("\n");
548#endif 548#endif
549 } 549 }
550 else 550 else
551 { 551 {
552 buf[1] = CODE_WONT; 552 buf[1] = CODE_WONT;
553 rPT.pClient->write( buf, 3 ); 553 rPT.pClient->write( buf, 3 );
554#ifdef __TELNET_DEBUG 554#ifdef __TELNET_DEBUG
555 printf("<= "); 555 printf("<= ");
556 rPT.printCode( buf[0] ); 556 rPT.printCode( buf[0] );
557 rPT.printCode( buf[1] ); 557 rPT.printCode( buf[1] );
558 rPT.printOpt( buf[2] ); 558 rPT.printOpt( buf[2] );
559 printf("\n"); 559 printf("\n");
560#endif 560#endif
561 } 561 }
562} 562}
563 563
564bool Bu::ProtocolTelnet::Option::isLocalEnabled() 564bool Bu::ProtocolTelnet::Option::isLocalEnabled()
565{ 565{
566 return (bool)(!(fOpts&fLocalCant)); 566 return (bool)(!(fOpts&fLocalCant));
567} 567}
568 568
569bool Bu::ProtocolTelnet::Option::isLocalSet() 569bool Bu::ProtocolTelnet::Option::isLocalSet()
570{ 570{
571 return (bool)(fOpts&fLocalIs); 571 return (bool)(fOpts&fLocalIs);
572} 572}
573 573
574void Bu::ProtocolTelnet::Option::remoteEnable( bool /*bSet*/ ) 574void Bu::ProtocolTelnet::Option::remoteEnable( bool /*bSet*/ )
575{ 575{
576 return; 576 return;
577} 577}
578 578
579void Bu::ProtocolTelnet::Option::remoteSet( bool bSet ) 579void Bu::ProtocolTelnet::Option::remoteSet( bool bSet )
580{ 580{
581 //if( bSet == (bool)(fOpts&fRemoteIs) ) return; 581 //if( bSet == (bool)(fOpts&fRemoteIs) ) return;
582 582
583 char buf[3] = { CODE_IAC, 0, cCode }; 583 char buf[3] = { CODE_IAC, 0, cCode };
584 584
585 if( bSet ) 585 if( bSet )
586 { 586 {
587 buf[1] = CODE_DO; 587 buf[1] = CODE_DO;
588 rPT.pClient->write( buf, 3 ); 588 rPT.pClient->write( buf, 3 );
589#ifdef __TELNET_DEBUG 589#ifdef __TELNET_DEBUG
590 printf("<= "); 590 printf("<= ");
591 rPT.printCode( buf[0] ); 591 rPT.printCode( buf[0] );
592 rPT.printCode( buf[1] ); 592 rPT.printCode( buf[1] );
593 rPT.printOpt( buf[2] ); 593 rPT.printOpt( buf[2] );
594 printf("\n"); 594 printf("\n");
595#endif 595#endif
596 } 596 }
597 else 597 else
598 { 598 {
599 buf[1] = CODE_DONT; 599 buf[1] = CODE_DONT;
600 rPT.pClient->write( buf, 3 ); 600 rPT.pClient->write( buf, 3 );
601#ifdef __TELNET_DEBUG 601#ifdef __TELNET_DEBUG
602 printf("<= "); 602 printf("<= ");
603 rPT.printCode( buf[0] ); 603 rPT.printCode( buf[0] );
604 rPT.printCode( buf[1] ); 604 rPT.printCode( buf[1] );
605 rPT.printOpt( buf[2] ); 605 rPT.printOpt( buf[2] );
606 printf("\n"); 606 printf("\n");
607#endif 607#endif
608 } 608 }
609} 609}
610 610
611bool Bu::ProtocolTelnet::Option::isRemoteEnabled() 611bool Bu::ProtocolTelnet::Option::isRemoteEnabled()
612{ 612{
613 return (bool)(!(fOpts&fRemoteCant)); 613 return (bool)(!(fOpts&fRemoteCant));
614} 614}
615 615
616bool Bu::ProtocolTelnet::Option::isRemoteSet() 616bool Bu::ProtocolTelnet::Option::isRemoteSet()
617{ 617{
618 return (bool)(fOpts&fRemoteIs); 618 return (bool)(fOpts&fRemoteIs);
619} 619}
620 620