Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenttelhndl.cpp
Go to the documentation of this file.
00001 00002 //Telnet Win32 : an ANSI telnet client. 00003 //Copyright (C) 1998 Paul Brannan 00004 //Copyright (C) 1998 I.Ioannou 00005 //Copyright (C) 1997 Brad Johnson 00006 // 00007 //This program is free software; you can redistribute it and/or 00008 //modify it under the terms of the GNU General Public License 00009 //as published by the Free Software Foundation; either version 2 00010 //of the License, or (at your option) any later version. 00011 // 00012 //This program is distributed in the hope that it will be useful, 00013 //but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 //GNU General Public License for more details. 00016 // 00017 //You should have received a copy of the GNU General Public License 00018 //along with this program; if not, write to the Free Software 00019 //Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00020 // 00021 //I.Ioannou 00022 //roryt@hol.gr 00023 // 00025 00027 // 00028 // Module: ttelhndl.cpp 00029 // 00030 // Contents: Telnet Handler 00031 // 00032 // Product: telnet 00033 // 00034 // Revisions: August 30, 1998 Paul Brannan <pbranna@clemson.edu> 00035 // June 15, 1998 pbranna@clemson.edu (Paul Brannan) 00036 // 00037 // This is code originally from tnnet.cpp and ansiprsr.cpp 00038 // 00040 00041 #include "precomp.h" 00042 00043 int naws_string(char *buf, int width, int height); 00044 00045 // This helps make the code more readable (Paul Brannan 1/1/99) 00046 #ifdef DEBUG_TELOPT 00047 #define TELOPT_PRINTD(x) printit(x); 00048 #define TELOPT_PRINTD2(x,n) { \ 00049 static char buf[20]; \ 00050 printit(s); \ 00051 printit(" "); \ 00052 itoa(d, buf, 10); \ 00053 printit(buf); \ 00054 printit("\n"); \ 00055 } 00056 #else 00057 #define TELOPT_PRINTD(x) ; 00058 #define TELOPT_PRINTD2(x,n) ; 00059 #endif 00060 00061 // A new print function for debugging (Paul Brannan 5/15/98) 00062 #ifdef DEBUG_TELOPT 00063 void TTelnetHandler::print_telopt(const char *s, int d) { 00064 static char buf[20]; 00065 printit(s); 00066 printit(" "); 00067 itoa(d, buf, 10); 00068 printit(buf); 00069 printit("\n"); 00070 } 00071 #endif 00072 00073 TTelnetHandler::TTelnetHandler(TNetwork &RefNetwork, TConsole &RefConsole, 00074 TParser &RefParser): 00075 Network(RefNetwork), Console(RefConsole), Parser(RefParser) { 00076 init(); 00077 00078 // Paul Brannan 9/13/98 00079 dwBuffer = ini.get_buffer_size(); 00080 szBuffer = new char [dwBuffer]; 00081 Network.SetNawsFunc(NULL); 00082 } 00083 00084 void TTelnetHandler::init() { 00085 iTermSet = 0; 00086 bInBinaryRx = 0; 00087 bInBinaryTx = 0; 00088 bInEchoTx = 0; 00089 bInEchoRx = 0; 00090 Network.set_local_echo(1); 00091 } 00092 00093 TTelnetHandler::~TTelnetHandler() { 00094 delete[] szBuffer; 00095 } 00096 00097 int TTelnetHandler::escapeIAC(char *buf, int length){ 00098 // The size of buffer must be greater than 2 * length to ensure no memory 00099 // out of bounds errors. The 0xff is escaped into 0xff 0xff. 00100 char * temp; 00101 temp = new char [length * 2]; 00102 int current=0; 00103 for (int x=0; x < length; x++){ 00104 if (buf[x] == (signed char)IAC) 00105 temp[current++]=(char)IAC; 00106 temp[current++]=buf[x]; 00107 } 00108 memcpy( buf, temp, current); 00109 delete [] temp; 00110 return current; 00111 } 00112 00113 // This lets us get rid of all the printf's (Paul Brannan 5/15/98) 00114 void TTelnetHandler::SendIAC(char c) { 00115 static char buf[2] = {IAC}; 00116 buf[1] = c; 00117 Network.WriteString(buf, 2); 00118 } 00119 void TTelnetHandler::SendIAC(char c1, char c2) { 00120 static char buf[3] = {IAC}; 00121 buf[1] = c1; buf[2] = c2; 00122 Network.WriteString(buf, 3); 00123 } 00124 void TTelnetHandler::SendIACParams(char c) { 00125 static char buf[2]; 00126 buf[0] = c; 00127 static int length = escapeIAC(buf, 1); 00128 Network.WriteString(buf, length); 00129 } 00130 void TTelnetHandler::SendIACParams(char c1, char c2) { 00131 static char buf[4]; 00132 buf[0] = c1; buf[1] = c2; 00133 static int length = escapeIAC(buf, 2); 00134 Network.WriteString(buf, length); 00135 } 00136 00137 int naws_string(char *b, int width, int height) { 00138 int l = 0; 00139 unsigned char *buf = (unsigned char *)b; 00140 00141 union { 00142 char szResponse[2]; 00143 int n; 00144 }; 00145 00146 buf[l++] = IAC; 00147 buf[l++] = SB; 00148 buf[l++] = TELOPT_NAWS; 00149 00150 n = width; 00151 buf[l] = szResponse[1]; 00152 if(buf[l-1] == IAC) buf[l++] = IAC; 00153 buf[l++] = szResponse[0]; 00154 if(buf[l-1] == IAC) buf[l++] = IAC; 00155 00156 n = height; 00157 buf[l++] = szResponse[1]; 00158 if(buf[l-1] == IAC) buf[l++] = IAC; 00159 buf[l++] = szResponse[0]; 00160 if(buf[l-1] == IAC) buf[l++] = IAC; 00161 00162 buf[l++] = IAC; 00163 buf[l++] = SE; 00164 00165 return l; 00166 } 00167 00168 // Ioannou 29 May 1998 : Something strange happens with 00169 // Borland compiler at this point when it passes the arguments 00170 // to SendIACParams. It always sends 80 lines to the server !!! 00171 // There seems to be a bug with optimization (the disassemble shows 00172 // that it uses an address plus 0xa than the right one). 00173 // This turns them off for this point. 00174 #ifdef __BORLANDC__ 00175 #pragma -O- 00176 #endif 00177 00178 // Removed old printf code that was commented out to clean this function 00179 // up a bit (Paul brannan 6/15/98) 00180 char* TTelnetHandler::ParseIAC(char* pszBuffer, char* pszBufferEnd) 00181 { 00182 // int n,l; 00183 // char szResponse[40]; 00184 // Ioannou 29 May 1998 : I prefer the union redefinitions 00185 // than the typecasting (used with them from Pascal and Cobol :-) ) 00186 // FIX ME !!!! Shall we use the winsock routines instead ? 00187 00188 union { 00189 char szResponse[2]; 00190 int n; 00191 }; 00192 00193 // Added support for user-defined term name (Paul Brannan 5/13/98) 00194 #define LASTTERM 4 00195 const char *pszTerms[] = {ini.get_term(), "ANSI","DEC-VT100","DEC-VT52","UNKNOWN"}; 00196 if(!iTermSet && (pszTerms[0] == 0 || *pszTerms[0] == 0)) iTermSet++; 00197 00198 if (pszBuffer + 2 < pszBufferEnd) { 00199 switch ((unsigned char)pszBuffer[1]) { 00200 00202 case DO: 00203 { 00204 switch (pszBuffer[2]){ 00205 case TELOPT_BINARY: 00206 TELOPT_PRINTD("RCVD DO TELOPT_BINARY\n"); 00207 if (!bInBinaryRx){ 00208 SendIAC(WILL, TELOPT_BINARY); 00209 bInBinaryRx = 1; 00210 TELOPT_PRINTD("SENT WILL TELOPT_BINARY\n"); 00211 } 00212 break; 00213 case TELOPT_ECHO: 00214 // we shouldn't echo for the server! (Paul Brannan 5/30/98) 00215 TELOPT_PRINTD2("RCVD DO TELOPT_ECHO", pszBuffer[2]); 00216 SendIAC(WONT, TELOPT_ECHO); 00217 TELOPT_PRINTD("SENT WONT TELOPT_ECHO\n"); 00218 break; 00219 case TELOPT_TTYPE: 00220 TELOPT_PRINTD("RCVD DO TELOPT_TTYPE\n"); 00221 SendIAC(WILL, TELOPT_TTYPE); 00222 TELOPT_PRINTD("SENT WILL TELOPT_TTYPE\n"); 00223 break; 00224 case TELOPT_NAWS: 00225 TELOPT_PRINTD("RCVD DO TELOPT_NAWS\n"); 00226 SendIAC(WILL, TELOPT_NAWS); 00227 SendIAC(SB, TELOPT_NAWS); 00228 00229 Network.SetNawsFunc(naws_string); 00230 00231 n = Console.GetWidth(); 00232 SendIACParams(szResponse[1],szResponse [0]); 00233 00234 n = Console.GetHeight(); 00235 SendIACParams(szResponse[1],szResponse[0]); 00236 00237 SendIAC(SE); 00238 TELOPT_PRINTD("SENT WILL TELOPT_NAWS\n"); 00239 break; 00240 case TELOPT_XDISPLOC: 00241 TELOPT_PRINTD("RCVD DO TELOPT_XDISPLOC\n"); 00242 SendIAC(WILL, TELOPT_XDISPLOC); 00243 TELOPT_PRINTD("SENT WILL TELOPT_XDISPLOC\n"); 00244 printit("Retrieving IP..."); 00245 break; 00246 default: 00247 TELOPT_PRINTD2("RCVD DO", pszBuffer[2]); 00248 SendIAC(WONT, pszBuffer[2]); 00249 TELOPT_PRINTD2("SENT WONT", pszBuffer[2]); 00250 break; 00251 } 00252 if (pszBuffer + 2 < pszBufferEnd) 00253 pszBuffer += 3; 00254 break; 00255 } 00256 00258 case WILL: 00259 { 00260 switch ((unsigned char)pszBuffer[2]){ 00261 case TELOPT_BINARY: 00262 TELOPT_PRINTD("RCVD WILL TELOPT_BINARY\n"); 00263 if (!bInBinaryTx){ 00264 SendIAC(DO, TELOPT_BINARY); 00265 bInBinaryTx = 1; 00266 TELOPT_PRINTD("SENT DO TELOPT_BINARY\n"); 00267 } 00268 break; 00269 case TELOPT_ECHO: 00270 TELOPT_PRINTD2("RCVD WILL TELOPT_ECHO", pszBuffer[2]); 00271 if(!bInEchoRx) { 00272 SendIAC(DO, TELOPT_ECHO); 00273 bInEchoRx = 1; 00274 Network.set_local_echo(0); // Paul Brannan 8/25/98 00275 if(iWillSGA) Network.set_line_mode(0); 00276 TELOPT_PRINTD2("SENT DO TELOPT_ECHO", pszBuffer[2]); 00277 if(Network.get_local_echo()) Network.set_line_mode(0); 00278 } 00279 break; 00280 00281 // Suppress Go Ahead (Paul Brannan 12/31/98) 00282 case TELOPT_SGA: 00283 TELOPT_PRINTD("RCVD WILL TELOPT_SGA\n"); 00284 if(!iWillSGA) { 00285 SendIAC(DO, TELOPT_SGA); 00286 if(bInEchoRx) Network.set_line_mode(0); 00287 iWillSGA = 1; 00288 TELOPT_PRINTD("SENT DO TELOPT_SGA\n"); 00289 } 00290 break; 00291 00293 default: 00294 TELOPT_PRINTD2("RCVD WILL", pszBuffer[2]); 00295 SendIAC(DONT, pszBuffer[2]); 00296 TELOPT_PRINTD2("SENT DONT", pszBuffer[2]); 00297 break; 00299 } 00300 if (pszBuffer + 2 < pszBufferEnd) 00301 pszBuffer += 3; 00302 break; 00303 } 00304 00306 case WONT: 00307 { 00308 switch ((unsigned char)pszBuffer[2]){ 00309 case TELOPT_ECHO: 00310 TELOPT_PRINTD("RCVD WONT TELOPT_ECHO\n"); 00311 if (bInEchoRx){ 00312 SendIAC(DONT, TELOPT_ECHO); 00313 // bInBinaryRx = 0; 00314 bInEchoRx = 0; // Paul Brannan 8/25/98 00315 Network.set_local_echo(1); 00316 Network.set_line_mode(0); 00317 TELOPT_PRINTD("SENT DONT TELOPT_ECHO\n"); 00318 } 00319 break; 00320 00321 // Suppress Go Ahead (Paul Brannan 12/31/98) 00322 case TELOPT_SGA: 00323 TELOPT_PRINTD("RCVD WONT TELOPT_SGA\n"); 00324 if(iWillSGA) { 00325 SendIAC(DONT, TELOPT_SGA); 00326 Network.set_line_mode(0); 00327 iWillSGA = 0; 00328 TELOPT_PRINTD("SENT DONT TELOPT_SGA\n"); 00329 } 00330 break; 00331 00332 default: 00333 TELOPT_PRINTD2("RCVD WONT", pszBuffer[2]); 00334 break; 00335 } 00336 if (pszBuffer + 2 < pszBufferEnd) 00337 pszBuffer += 3; 00338 break; 00339 } 00340 00342 case DONT: 00343 { 00344 switch ((unsigned char)pszBuffer[2]){ 00345 case TELOPT_ECHO: 00346 TELOPT_PRINTD("RCVD DONT TELOPT_ECHO\n"); 00347 if (bInEchoTx){ 00348 SendIAC(WONT, TELOPT_ECHO); 00349 bInEchoTx = 0; 00350 TELOPT_PRINTD("SENT WONT TELOPT_ECHO\n"); 00351 } 00352 break; 00353 case TELOPT_NAWS: 00354 TELOPT_PRINTD("RCVD DONT TELOPT_NAWS\n"); 00355 SendIAC(WONT, TELOPT_NAWS); 00356 Network.SetNawsFunc(naws_string); 00357 TELOPT_PRINTD("SENT WONT TELOPT_NAWS\n"); 00358 break; 00359 default: 00360 TELOPT_PRINTD2("RCVD DONT", pszBuffer[2]); 00361 break; 00362 } 00363 if (pszBuffer + 2 < pszBufferEnd) 00364 pszBuffer += 3; 00365 break; 00366 } 00367 00369 case SB: 00370 { 00371 switch ((unsigned char)pszBuffer[2]){ 00372 case TELOPT_TTYPE: 00373 if (pszBuffer + 5 < pszBufferEnd) { 00374 TELOPT_PRINTD("RCVD SB TELOPT_TTYPE\n"); 00375 if (pszBuffer[3] == 1){ 00376 TELOPT_PRINTD("SENT SB TT"); 00377 TELOPT_PRINTD(pszTerms[iTermSet]); 00378 TELOPT_PRINTD("\n"); 00379 SendIAC(SB, TELOPT_TTYPE); 00380 SendIACParams(0); 00381 Network.WriteString(pszTerms[iTermSet], strlen(pszTerms[iTermSet])); 00382 SendIAC(SE); 00383 00384 if (iTermSet < LASTTERM ) 00385 iTermSet+=1; 00386 } 00387 if (pszBuffer + 5 < pszBufferEnd) 00388 pszBuffer += 6; 00389 } 00390 break; 00391 case TELOPT_XDISPLOC: 00392 if(pszBuffer + 5 < pszBufferEnd) { 00393 TELOPT_PRINTD("RCVD SB XDISPLOC\n"); 00394 SendIAC(SB, TELOPT_XDISPLOC); 00395 TELOPT_PRINTD("SENT SB XDISPLOC"); 00396 SendIACParams(0); 00397 if(Network.GetLocalAddress()) Network.WriteString(Network.GetLocalAddress(), 00398 strlen(Network.GetLocalAddress())); 00399 TELOPT_PRINTD(Network.GetLocalAddress()); 00400 TELOPT_PRINTD("\n"); 00401 SendIAC(SE); 00402 if (pszBuffer + 5 < pszBufferEnd) 00403 pszBuffer += 6; 00404 } 00405 break; 00406 default: break; 00407 } 00408 break; 00409 } 00410 default: 00411 pszBuffer += 2; 00412 break; 00413 } 00414 } 00415 return pszBuffer; 00416 } 00417 00418 #ifdef __BORLANDC__ 00419 // bring bug optimazations 00420 #pragma -O. 00421 #endif 00422 00423 // This is the code from TANSIParser::ParseBuffer. It parses out IACs, and 00424 // then calls TParser::ParseBuffer to do the terminal emulation. 00425 // (Paul Brannan 6/15/98) 00426 // Hopefully eliminating the unnecessary copying should speed things up a 00427 // little. (Paul Brannan 6/28/98) 00428 char* TTelnetHandler::ParseBuffer(char* pszBuffer, char* pszBufferEnd){ 00429 char *pszResult; 00430 char *pszHead = pszBuffer; 00431 00432 if(Network.get_net_type() == TN_NETSOCKET) { 00433 while (pszBuffer < pszBufferEnd) { 00434 // if IAC then parse IAC 00435 if((unsigned char) *pszBuffer == IAC) { 00436 00437 // check for escaped IAC 00438 if((pszBufferEnd >= pszBuffer + 1) && 00439 (unsigned char)*(pszBuffer + 1) == IAC) { 00440 // we move data at the front of the buffer to the end so 00441 // that if we only have IACs we won't return pszBuffer 00442 // even though we did parse something. Returning 00443 // pszBuffer is an error condition. 00444 memmove(pszHead + 1, pszHead, pszBuffer - pszHead); 00445 pszBuffer+=2; 00446 pszHead++; 00447 } 00448 // parse the IAC 00449 else { 00450 pszResult = ParseIAC(pszBuffer, pszBufferEnd); 00451 if(pszBuffer == pszResult) return pszBuffer; 00452 // see above regarding moving from front to end. 00453 memmove(pszHead + (pszResult - pszBuffer), pszHead, 00454 pszBuffer - pszHead); 00455 pszHead += (pszResult - pszBuffer); 00456 pszBuffer = pszResult; 00457 } 00458 } 00459 // else copy char over to ANSI buffer 00460 else { 00461 pszBuffer++; 00462 } 00463 } 00464 00465 // Not a socket connection, so don't parse out IACs. 00466 // (Paul Brannan 3/19/99) 00467 } else { 00468 pszBuffer = pszBufferEnd; 00469 } 00470 00471 return(Parser.ParseBuffer(pszHead, pszBuffer)); 00472 } 00473 00474 // telProcessNetwork calls the member function TTelnetHandler::Go, since 00475 // TTelnetHandler::Go is not a static function, and cannot be called with 00476 // CreateThread(). (Paul Brannan 6/15/98) 00477 DWORD WINAPI telProcessNetwork(LPVOID lpParameter) { 00478 TelThreadParams *pParams = (TelThreadParams *)lpParameter; 00479 return pParams->TelHandler.Go(&pParams->p); 00480 } 00481 00482 // This function is what used to be telProcessNetwork (Paul Brannan 6/15/98) 00483 DWORD TTelnetHandler::Go(LPVOID pvParams) 00484 { 00485 NetParams *pParams = (NetParams *)pvParams; 00486 00487 // No longer a need to copy pParams-> socket and create an instance 00488 // of TANSIParser (Paul Brannan 6/15/98) 00489 00490 Console.sync(); // Sync with the parser so the cursor is positioned 00491 00492 Parser.Init(); // Reset the parser (Paul Brannan 9/19/98) 00493 init(); // Turn on local echo (Paul Brannan 9/19/98) 00494 00495 *pParams->bNetFinished = 0; 00496 char* pszHead = szBuffer; 00497 char* pszTail = szBuffer; 00498 while (!*pParams->bNetFinish) { 00499 // Get data from Socket 00500 *pParams->bNetPaused = 1; //Pause 00501 int Result = Network.ReadString(pszTail, (szBuffer + dwBuffer) - pszTail); 00502 00503 // Speed up mouse by not going into loop (Paul Brannan 8/10/98) 00504 // while(*pParams->bNetPause && !*pParams->bNetFinish) *pParams->bNetPaused = 1; //Pause 00505 if(WaitForSingleObject(pParams->hPause, 0) == WAIT_OBJECT_0) 00506 WaitForSingleObject(pParams->hUnPause, INFINITE); 00507 00508 *pParams->bNetPaused = 0; //UnPause 00509 00510 if (Result <= 0 || Result > dwBuffer ){ 00511 break; 00512 } 00513 pszTail += Result; 00514 00515 // Process the buffer 00516 char* pszNewHead = pszHead; 00517 do { 00518 // Speed up mouse by not going into loop (Paul Brannan 8/10/98) 00519 if(WaitForSingleObject(pParams->hPause, 0) == WAIT_OBJECT_0) { 00520 *pParams->bNetPaused = 1; 00521 WaitForSingleObject(pParams->hUnPause, INFINITE); 00522 *pParams->bNetPaused = 0; 00523 } 00524 00525 pszHead = pszNewHead; 00526 pszNewHead = ParseBuffer(pszHead, pszTail); // Parse buffer 00527 } while ((pszNewHead != pszHead) && (pszNewHead < pszTail) && !*pParams->bNetFinish); 00528 pszHead = pszNewHead; 00529 00530 // When we reach the end of the buffer, move contents to the 00531 // beginning of the buffer to get free space at the end. 00532 if (pszTail == (szBuffer + dwBuffer)) { 00533 memmove(szBuffer, pszHead, pszTail - pszHead); 00534 pszTail = szBuffer + (pszTail - pszHead); 00535 pszHead = szBuffer; 00536 } 00537 } 00538 SetEvent(pParams->hExit); 00539 00540 printm(0, FALSE, MSG_TERMBYREM); 00541 *pParams->bNetPaused = 1; //Pause 00542 *pParams->bNetFinished = 1; 00543 return 0; 00544 } Generated on Thu May 24 2012 04:17:30 for ReactOS by
1.7.6.1
|