ReactOS 0.4.15-dev-7942-gd23573b
ttelhndl.cpp
Go to the documentation of this file.
1
2//Telnet Win32 : an ANSI telnet client.
3//Copyright (C) 1998 Paul Brannan
4//Copyright (C) 1998 I.Ioannou
5//Copyright (C) 1997 Brad Johnson
6//
7//This program is free software; you can redistribute it and/or
8//modify it under the terms of the GNU General Public License
9//as published by the Free Software Foundation; either version 2
10//of the License, or (at your option) any later version.
11//
12//This program is distributed in the hope that it will be useful,
13//but WITHOUT ANY WARRANTY; without even the implied warranty of
14//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15//GNU General Public License for more details.
16//
17//You should have received a copy of the GNU General Public License
18//along with this program; if not, write to the Free Software
19//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20//
21//I.Ioannou
22//roryt@hol.gr
23//
25
27//
28// Module: ttelhndl.cpp
29//
30// Contents: Telnet Handler
31//
32// Product: telnet
33//
34// Revisions: August 30, 1998 Paul Brannan <pbranna@clemson.edu>
35// June 15, 1998 pbranna@clemson.edu (Paul Brannan)
36//
37// This is code originally from tnnet.cpp and ansiprsr.cpp
38//
40
41#include "precomp.h"
42
43#include "telnet.h"
44
45int naws_string(char *buf, int width, int height);
46
47// This helps make the code more readable (Paul Brannan 1/1/99)
48#ifdef DEBUG_TELOPT
49#define TELOPT_PRINTD(x) printit(x);
50#define TELOPT_PRINTD2(x,n) { \
51 static char buf[20]; \
52 printit(s); \
53 printit(" "); \
54 itoa(d, buf, 10); \
55 printit(buf); \
56 printit("\n"); \
57}
58#else
59#define TELOPT_PRINTD(x) ;
60#define TELOPT_PRINTD2(x,n) ;
61#endif
62
63// A new print function for debugging (Paul Brannan 5/15/98)
64#ifdef DEBUG_TELOPT
65void TTelnetHandler::print_telopt(const char *s, int d) {
66 static char buf[20];
67 printit(s);
68 printit(" ");
69 itoa(d, buf, 10);
70 printit(buf);
71 printit("\n");
72}
73#endif
74
76 TParser &RefParser):
77Network(RefNetwork), Console(RefConsole), Parser(RefParser) {
78 init();
79
80 // Paul Brannan 9/13/98
82 szBuffer = new char [dwBuffer];
84}
85
87 iTermSet = 0;
88 bInBinaryRx = 0;
89 bInBinaryTx = 0;
90 bInEchoTx = 0;
91 bInEchoRx = 0;
93}
94
96 delete[] szBuffer;
97}
98
100 // The size of buffer must be greater than 2 * length to ensure no memory
101 // out of bounds errors. The 0xff is escaped into 0xff 0xff.
102 char * temp;
103 temp = new char [length * 2];
104 int current=0;
105 for (int x=0; x < length; x++){
106 if (buf[x] == (signed char)IAC)
107 temp[current++]=(char)IAC;
108 temp[current++]=buf[x];
109 }
111 delete [] temp;
112 return current;
113}
114
115// This lets us get rid of all the printf's (Paul Brannan 5/15/98)
117 static char buf[2] = {IAC};
118 buf[1] = c;
120}
121void TTelnetHandler::SendIAC(char c1, char c2) {
122 static char buf[3] = {IAC};
123 buf[1] = c1; buf[2] = c2;
125}
127 static char buf[2];
128 buf[0] = c;
129 static int length = escapeIAC(buf, 1);
131}
132void TTelnetHandler::SendIACParams(char c1, char c2) {
133 static char buf[4];
134 buf[0] = c1; buf[1] = c2;
135 static int length = escapeIAC(buf, 2);
137}
138
139int naws_string(char *b, int width, int height) {
140 int l = 0;
141 unsigned char *buf = (unsigned char *)b;
142
143 union {
144 char szResponse[2];
145 int n;
146 };
147
148 buf[l++] = IAC;
149 buf[l++] = SB;
150 buf[l++] = TELOPT_NAWS;
151
152 n = width;
153 buf[l] = szResponse[1];
154 if(buf[l-1] == IAC) buf[l++] = IAC;
155 buf[l++] = szResponse[0];
156 if(buf[l-1] == IAC) buf[l++] = IAC;
157
158 n = height;
159 buf[l++] = szResponse[1];
160 if(buf[l-1] == IAC) buf[l++] = IAC;
161 buf[l++] = szResponse[0];
162 if(buf[l-1] == IAC) buf[l++] = IAC;
163
164 buf[l++] = IAC;
165 buf[l++] = SE;
166
167 return l;
168}
169
170// Ioannou 29 May 1998 : Something strange happens with
171// Borland compiler at this point when it passes the arguments
172// to SendIACParams. It always sends 80 lines to the server !!!
173// There seems to be a bug with optimization (the disassemble shows
174// that it uses an address plus 0xa than the right one).
175// This turns them off for this point.
176#ifdef __BORLANDC__
177#pragma -O-
178#endif
179
180// Removed old printf code that was commented out to clean this function
181// up a bit (Paul brannan 6/15/98)
182char* TTelnetHandler::ParseIAC(char* pszBuffer, char* pszBufferEnd)
183{
184 // int n,l;
185 // char szResponse[40];
186 // Ioannou 29 May 1998 : I prefer the union redefinitions
187 // than the typecasting (used with them from Pascal and Cobol :-) )
188 // FIX ME !!!! Shall we use the winsock routines instead ?
189
190 union {
191 char szResponse[2];
192 int n;
193 };
194
195 // Added support for user-defined term name (Paul Brannan 5/13/98)
196#define LASTTERM 4
197 const char *pszTerms[] = {ini.get_term(), "ANSI","DEC-VT100","DEC-VT52","UNKNOWN"};
198 if(!iTermSet && (pszTerms[0] == 0 || *pszTerms[0] == 0)) iTermSet++;
199
200 if (pszBuffer + 2 < pszBufferEnd) {
201 switch ((unsigned char)pszBuffer[1]) {
202
204 case DO:
205 {
206 switch (pszBuffer[2]){
207 case TELOPT_BINARY:
208 TELOPT_PRINTD("RCVD DO TELOPT_BINARY\n");
209 if (!bInBinaryRx){
211 bInBinaryRx = 1;
212 TELOPT_PRINTD("SENT WILL TELOPT_BINARY\n");
213 }
214 break;
215 case TELOPT_ECHO:
216 // we shouldn't echo for the server! (Paul Brannan 5/30/98)
217 TELOPT_PRINTD2("RCVD DO TELOPT_ECHO", pszBuffer[2]);
219 TELOPT_PRINTD("SENT WONT TELOPT_ECHO\n");
220 break;
221 case TELOPT_TTYPE:
222 TELOPT_PRINTD("RCVD DO TELOPT_TTYPE\n");
224 TELOPT_PRINTD("SENT WILL TELOPT_TTYPE\n");
225 break;
226 case TELOPT_NAWS:
227 TELOPT_PRINTD("RCVD DO TELOPT_NAWS\n");
230
232
233 n = Console.GetWidth();
234 SendIACParams(szResponse[1],szResponse [0]);
235
236 n = Console.GetHeight();
237 SendIACParams(szResponse[1],szResponse[0]);
238
239 SendIAC(SE);
240 TELOPT_PRINTD("SENT WILL TELOPT_NAWS\n");
241 break;
242 case TELOPT_XDISPLOC:
243 TELOPT_PRINTD("RCVD DO TELOPT_XDISPLOC\n");
245 TELOPT_PRINTD("SENT WILL TELOPT_XDISPLOC\n");
246 printit("Retrieving IP...");
247 break;
248 default:
249 TELOPT_PRINTD2("RCVD DO", pszBuffer[2]);
250 SendIAC(WONT, pszBuffer[2]);
251 TELOPT_PRINTD2("SENT WONT", pszBuffer[2]);
252 break;
253 }
254 if (pszBuffer + 2 < pszBufferEnd)
255 pszBuffer += 3;
256 break;
257 }
258
260 case WILL:
261 {
262 switch ((unsigned char)pszBuffer[2]){
263 case TELOPT_BINARY:
264 TELOPT_PRINTD("RCVD WILL TELOPT_BINARY\n");
265 if (!bInBinaryTx){
267 bInBinaryTx = 1;
268 TELOPT_PRINTD("SENT DO TELOPT_BINARY\n");
269 }
270 break;
271 case TELOPT_ECHO:
272 TELOPT_PRINTD2("RCVD WILL TELOPT_ECHO", pszBuffer[2]);
273 if(!bInEchoRx) {
275 bInEchoRx = 1;
276 Network.set_local_echo(0); // Paul Brannan 8/25/98
278 TELOPT_PRINTD2("SENT DO TELOPT_ECHO", pszBuffer[2]);
280 }
281 break;
282
283 // Suppress Go Ahead (Paul Brannan 12/31/98)
284 case TELOPT_SGA:
285 TELOPT_PRINTD("RCVD WILL TELOPT_SGA\n");
286 if(!iWillSGA) {
289 iWillSGA = 1;
290 TELOPT_PRINTD("SENT DO TELOPT_SGA\n");
291 }
292 break;
293
295 default:
296 TELOPT_PRINTD2("RCVD WILL", pszBuffer[2]);
297 SendIAC(DONT, pszBuffer[2]);
298 TELOPT_PRINTD2("SENT DONT", pszBuffer[2]);
299 break;
301 }
302 if (pszBuffer + 2 < pszBufferEnd)
303 pszBuffer += 3;
304 break;
305 }
306
308 case WONT:
309 {
310 switch ((unsigned char)pszBuffer[2]){
311 case TELOPT_ECHO:
312 TELOPT_PRINTD("RCVD WONT TELOPT_ECHO\n");
313 if (bInEchoRx){
315 // bInBinaryRx = 0;
316 bInEchoRx = 0; // Paul Brannan 8/25/98
319 TELOPT_PRINTD("SENT DONT TELOPT_ECHO\n");
320 }
321 break;
322
323 // Suppress Go Ahead (Paul Brannan 12/31/98)
324 case TELOPT_SGA:
325 TELOPT_PRINTD("RCVD WONT TELOPT_SGA\n");
326 if(iWillSGA) {
329 iWillSGA = 0;
330 TELOPT_PRINTD("SENT DONT TELOPT_SGA\n");
331 }
332 break;
333
334 default:
335 TELOPT_PRINTD2("RCVD WONT", pszBuffer[2]);
336 break;
337 }
338 if (pszBuffer + 2 < pszBufferEnd)
339 pszBuffer += 3;
340 break;
341 }
342
344 case DONT:
345 {
346 switch ((unsigned char)pszBuffer[2]){
347 case TELOPT_ECHO:
348 TELOPT_PRINTD("RCVD DONT TELOPT_ECHO\n");
349 if (bInEchoTx){
351 bInEchoTx = 0;
352 TELOPT_PRINTD("SENT WONT TELOPT_ECHO\n");
353 }
354 break;
355 case TELOPT_NAWS:
356 TELOPT_PRINTD("RCVD DONT TELOPT_NAWS\n");
359 TELOPT_PRINTD("SENT WONT TELOPT_NAWS\n");
360 break;
361 default:
362 TELOPT_PRINTD2("RCVD DONT", pszBuffer[2]);
363 break;
364 }
365 if (pszBuffer + 2 < pszBufferEnd)
366 pszBuffer += 3;
367 break;
368 }
369
371 case SB:
372 {
373 switch ((unsigned char)pszBuffer[2]){
374 case TELOPT_TTYPE:
375 if (pszBuffer + 5 < pszBufferEnd) {
376 TELOPT_PRINTD("RCVD SB TELOPT_TTYPE\n");
377 if (pszBuffer[3] == 1){
378 TELOPT_PRINTD("SENT SB TT");
379 TELOPT_PRINTD(pszTerms[iTermSet]);
380 TELOPT_PRINTD("\n");
382 SendIACParams(0);
383 Network.WriteString(pszTerms[iTermSet], strlen(pszTerms[iTermSet]));
384 SendIAC(SE);
385
386 if (iTermSet < LASTTERM )
387 iTermSet+=1;
388 }
389 if (pszBuffer + 5 < pszBufferEnd)
390 pszBuffer += 6;
391 }
392 break;
393 case TELOPT_XDISPLOC:
394 if(pszBuffer + 5 < pszBufferEnd) {
395 TELOPT_PRINTD("RCVD SB XDISPLOC\n");
397 TELOPT_PRINTD("SENT SB XDISPLOC");
398 SendIACParams(0);
402 TELOPT_PRINTD("\n");
403 SendIAC(SE);
404 if (pszBuffer + 5 < pszBufferEnd)
405 pszBuffer += 6;
406 }
407 break;
408 default: break;
409 }
410 break;
411 }
412 default:
413 pszBuffer += 2;
414 break;
415 }
416 }
417 return pszBuffer;
418}
419
420#ifdef __BORLANDC__
421// bring bug optimazations
422#pragma -O.
423#endif
424
425// This is the code from TANSIParser::ParseBuffer. It parses out IACs, and
426// then calls TParser::ParseBuffer to do the terminal emulation.
427// (Paul Brannan 6/15/98)
428// Hopefully eliminating the unnecessary copying should speed things up a
429// little. (Paul Brannan 6/28/98)
430char* TTelnetHandler::ParseBuffer(char* pszBuffer, char* pszBufferEnd){
431 char *pszResult;
432 char *pszHead = pszBuffer;
433
435 while (pszBuffer < pszBufferEnd) {
436 // if IAC then parse IAC
437 if((unsigned char) *pszBuffer == IAC) {
438
439 // check for escaped IAC
440 if((pszBufferEnd >= pszBuffer + 1) &&
441 (unsigned char)*(pszBuffer + 1) == IAC) {
442 // we move data at the front of the buffer to the end so
443 // that if we only have IACs we won't return pszBuffer
444 // even though we did parse something. Returning
445 // pszBuffer is an error condition.
446 memmove(pszHead + 1, pszHead, pszBuffer - pszHead);
447 pszBuffer+=2;
448 pszHead++;
449 }
450 // parse the IAC
451 else {
452 pszResult = ParseIAC(pszBuffer, pszBufferEnd);
453 if(pszBuffer == pszResult) return pszBuffer;
454 // see above regarding moving from front to end.
455 memmove(pszHead + (pszResult - pszBuffer), pszHead,
456 pszBuffer - pszHead);
457 pszHead += (pszResult - pszBuffer);
458 pszBuffer = pszResult;
459 }
460 }
461 // else copy char over to ANSI buffer
462 else {
463 pszBuffer++;
464 }
465 }
466
467 // Not a socket connection, so don't parse out IACs.
468 // (Paul Brannan 3/19/99)
469 } else {
470 pszBuffer = pszBufferEnd;
471 }
472
473 return(Parser.ParseBuffer(pszHead, pszBuffer));
474}
475
476// telProcessNetwork calls the member function TTelnetHandler::Go, since
477// TTelnetHandler::Go is not a static function, and cannot be called with
478// CreateThread(). (Paul Brannan 6/15/98)
480 TelThreadParams *pParams = (TelThreadParams *)lpParameter;
481 return pParams->TelHandler.Go(&pParams->p);
482}
483
484// This function is what used to be telProcessNetwork (Paul Brannan 6/15/98)
486{
487 NetParams *pParams = (NetParams *)pvParams;
488
489 // No longer a need to copy pParams-> socket and create an instance
490 // of TANSIParser (Paul Brannan 6/15/98)
491
492 Console.sync(); // Sync with the parser so the cursor is positioned
493
494 Parser.Init(); // Reset the parser (Paul Brannan 9/19/98)
495 init(); // Turn on local echo (Paul Brannan 9/19/98)
496
497 *pParams->bNetFinished = 0;
498 char* pszHead = szBuffer;
499 char* pszTail = szBuffer;
500 while (!*pParams->bNetFinish) {
501 // Get data from Socket
502 *pParams->bNetPaused = 1; //Pause
503 int Result = Network.ReadString(pszTail, (szBuffer + dwBuffer) - pszTail);
504
505 // Speed up mouse by not going into loop (Paul Brannan 8/10/98)
506 // while(*pParams->bNetPause && !*pParams->bNetFinish) *pParams->bNetPaused = 1; //Pause
507 if(WaitForSingleObject(pParams->hPause, 0) == WAIT_OBJECT_0)
509
510 *pParams->bNetPaused = 0; //UnPause
511
512 if (Result <= 0 || Result > dwBuffer ){
513 break;
514 }
515 pszTail += Result;
516
517 // Process the buffer
518 char* pszNewHead = pszHead;
519 do {
520 // Speed up mouse by not going into loop (Paul Brannan 8/10/98)
521 if(WaitForSingleObject(pParams->hPause, 0) == WAIT_OBJECT_0) {
522 *pParams->bNetPaused = 1;
524 *pParams->bNetPaused = 0;
525 }
526
527 pszHead = pszNewHead;
528 pszNewHead = ParseBuffer(pszHead, pszTail); // Parse buffer
529 } while ((pszNewHead != pszHead) && (pszNewHead < pszTail) && !*pParams->bNetFinish);
530 pszHead = pszNewHead;
531
532 // When we reach the end of the buffer, move contents to the
533 // beginning of the buffer to get free space at the end.
534 if (pszTail == (szBuffer + dwBuffer)) {
535 memmove(szBuffer, pszHead, pszTail - pszHead);
536 pszTail = szBuffer + (pszTail - pszHead);
537 pszHead = szBuffer;
538 }
539 }
540 SetEvent(pParams->hExit);
541
543 *pParams->bNetPaused = 1; //Pause
544 *pParams->bNetFinished = 1;
545 return 0;
546}
CConsole Console
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define MSG_TERMBYREM
Definition: resource.h:15
r l[0]
Definition: byte_order.h:168
const char * get_term() const
Definition: tnconfig.h:37
int get_buffer_size() const
Definition: tnconfig.h:62
int GetWidth()
Definition: tconsole.h:81
void sync()
Definition: tconsole.cpp:109
int GetHeight()
Definition: tconsole.h:82
int ReadString(char *str, const int length)
Definition: tnetwork.cpp:67
void set_line_mode(BOOL b)
Definition: tnetwork.h:44
NetworkType get_net_type()
Definition: tnetwork.h:35
void set_local_echo(BOOL b)
Definition: tnetwork.h:41
int WriteString(const char *str, const int length)
Definition: tnetwork.cpp:53
BOOL get_local_echo()
Definition: tnetwork.h:40
const char * GetLocalAddress()
Definition: tnetwork.h:33
void SetNawsFunc(Naws_func_t func)
Definition: tnetwork.h:31
virtual void Init()=0
virtual char * ParseBuffer(char *pszBuffer, char *pszBufferEnd)=0
void SendIACParams(char c)
Definition: ttelhndl.cpp:126
char * ParseIAC(char *pszBuffer, char *pszBufferEnd)
Definition: ttelhndl.cpp:182
void print_telopt(const char *s, int d)
char * szBuffer
Definition: ttelhndl.h:34
DWORD Go(LPVOID pvParams)
Definition: ttelhndl.cpp:485
TNetwork & Network
Definition: ttelhndl.h:26
TTelnetHandler(TNetwork &RefNetwork, TConsole &RefConsole, TParser &RefParser)
Definition: ttelhndl.cpp:75
void SendIAC(char c)
Definition: ttelhndl.cpp:116
int escapeIAC(char *buf, int length)
Definition: ttelhndl.cpp:99
TConsole & Console
Definition: ttelhndl.h:27
int bInBinaryRx
Definition: ttelhndl.h:11
char * ParseBuffer(char *pszBuffer, char *pszBufferEnd)
Definition: ttelhndl.cpp:430
int bInBinaryTx
Definition: ttelhndl.h:11
TParser & Parser
Definition: ttelhndl.h:28
TTelnetHandler & TelHandler
Definition: tparams.h:20
NetParams p
Definition: tparams.h:19
@ Network
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
unsigned char
Definition: typeof.h:29
#define INFINITE
Definition: serial.h:102
unsigned long DWORD
Definition: ntddk_ex.h:95
#define SE
Definition: ftp_var.h:28
#define WONT
Definition: ftp_var.h:16
#define WILL
Definition: ftp_var.h:17
#define SB
Definition: ftp_var.h:18
#define DO
Definition: ftp_var.h:15
#define DONT
Definition: ftp_var.h:14
#define IAC
Definition: ftp_var.h:13
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLdouble s
Definition: gl.h:2039
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLint GLint GLsizei width
Definition: gl.h:1546
GLdouble n
Definition: glext.h:7729
const GLubyte * c
Definition: glext.h:8905
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
_CRTIMP char *__cdecl itoa(_In_ int _Val, _Pre_notnull_ _Post_z_ char *_DstBuf, _In_ int _Radix)
#define d
Definition: ke_i.h:81
#define c
Definition: ke_i.h:80
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
struct task_struct * current
Definition: linux.c:32
static calc_node_t temp
Definition: rpn_ieee.c:38
volatile int * bNetPaused
Definition: tparams.h:8
HANDLE hExit
Definition: tparams.h:6
volatile int * bNetFinish
Definition: tparams.h:10
HANDLE hPause
Definition: tparams.h:7
volatile int * bNetFinished
Definition: tparams.h:9
HANDLE hUnPause
Definition: tparams.h:7
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
#define TELOPT_BINARY
Definition: telnet.h:70
#define TELOPT_SGA
Definition: telnet.h:73
#define TELOPT_TTYPE
Definition: telnet.h:94
#define TELOPT_XDISPLOC
Definition: telnet.h:105
#define TELOPT_NAWS
Definition: telnet.h:101
#define TELOPT_ECHO
Definition: telnet.h:71
TConfig ini
Definition: tnconfig.cpp:45
int printit(const char *it)
Definition: tnerror.cpp:58
int printm(LPTSTR szModule, BOOL fSystem, DWORD dwMessageId,...)
Definition: tnerror.cpp:84
@ TN_NETSOCKET
Definition: tnetwork.h:8
#define TELOPT_PRINTD(x)
Definition: ttelhndl.cpp:59
#define TELOPT_PRINTD2(x, n)
Definition: ttelhndl.cpp:60
DWORD WINAPI telProcessNetwork(LPVOID lpParameter)
Definition: ttelhndl.cpp:479
#define LASTTERM
int naws_string(char *buf, int width, int height)
Definition: ttelhndl.cpp:139
#define WAIT_OBJECT_0
Definition: winbase.h:406
#define WINAPI
Definition: msvc.h:6
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409