ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ttelhndl.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.