• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

TelnetTransport.cpp

Go to the documentation of this file.
00001 #include "NativeFeatureIncludes.h"
00002 #if _RAKNET_SUPPORT_TelnetTransport==1
00003 
00004 #include "TelnetTransport.h"
00005 #include "TCPInterface.h"
00006 #include <stdio.h>
00007 #include <string.h>
00008 #include <stdarg.h>
00009 #include "LinuxStrings.h"
00010 
00011 // #define _PRINTF_DEBUG
00012 
00013 #define ECHO_INPUT
00014 
00015 #ifdef _MSC_VER
00016 #pragma warning( push )
00017 #endif
00018 
00019 TelnetTransport::TelnetTransport()
00020 {
00021         tcpInterface=0;
00022         sendSuffix=0;
00023         sendPrefix=0;
00024 }
00025 TelnetTransport::~TelnetTransport()
00026 {
00027         Stop();
00028         if (sendSuffix)
00029                 rakFree_Ex(sendSuffix, __FILE__, __LINE__ );
00030         if (sendPrefix)
00031                 rakFree_Ex(sendPrefix, __FILE__, __LINE__ );
00032 }
00033 bool TelnetTransport::Start(unsigned short port, bool serverMode)
00034 {
00035         (void) serverMode;
00036     AutoAllocate();
00037         RakAssert(serverMode);
00038         return tcpInterface->Start(port, 64);
00039 }
00040 void TelnetTransport::Stop(void)
00041 {
00042         if (tcpInterface==0) return;
00043         tcpInterface->Stop();
00044         unsigned i;
00045         for (i=0; i < remoteClients.Size(); i++)
00046                 RakNet::OP_DELETE(remoteClients[i], __FILE__, __LINE__);
00047         remoteClients.Clear(false, __FILE__, __LINE__);
00048         RakNet::OP_DELETE(tcpInterface, __FILE__, __LINE__);
00049         tcpInterface=0;
00050 }
00051 void TelnetTransport::Send(  SystemAddress systemAddress, const char *data,... )
00052 {
00053         if (tcpInterface==0) return;
00054 
00055         if (data==0 || data[0]==0)
00056                 return;
00057 
00058         char text[REMOTE_MAX_TEXT_INPUT];
00059         size_t prefixLength;
00060         if (sendPrefix)
00061         {
00062                 strcpy(text, sendPrefix);
00063                 prefixLength = strlen(sendPrefix);
00064         }
00065         else
00066         {
00067                 text[0]=0;
00068                 prefixLength=0;
00069         }
00070         va_list ap;
00071         va_start(ap, data);
00072         _vsnprintf(text+prefixLength, REMOTE_MAX_TEXT_INPUT-prefixLength, data, ap);
00073         va_end(ap);
00074         text[REMOTE_MAX_TEXT_INPUT-1]=0;
00075 
00076         if (sendSuffix)
00077         {
00078                 size_t length = strlen(text);
00079                 size_t availableChars = REMOTE_MAX_TEXT_INPUT-length-1;
00080                 strncat(text, sendSuffix, availableChars);
00081         }
00082 
00083         tcpInterface->Send(text, (unsigned int) strlen(text), systemAddress, false);
00084 }
00085 void TelnetTransport::CloseConnection( SystemAddress systemAddress )
00086 {
00087         tcpInterface->CloseConnection(systemAddress);
00088 }
00089 Packet* TelnetTransport::Receive( void )
00090 {
00091         if (tcpInterface==0) return 0;
00092         Packet *p = tcpInterface->Receive();
00093         if (p==0)
00094                 return 0;
00095 
00096         /*
00097         if (p->data[0]==255)
00098         {
00099                 unsigned i;
00100                 for (i=0; i < p->length; i++)
00101                 {
00102                         RAKNET_DEBUG_PRINTF("%i ", p->data[i]);
00103                 }
00104                 RAKNET_DEBUG_PRINTF("\n");
00105                 tcpInterface->DeallocatePacket(p);
00106                 return 0;
00107         }
00108         */
00109 
00110         // Get this guy's cursor buffer.  This is real bullcrap that I have to do this.
00111         unsigned i;
00112         TelnetClient *remoteClient=0;
00113         for (i=0; i < remoteClients.Size(); i++)
00114         {
00115                 if (remoteClients[i]->systemAddress==p->systemAddress)
00116                         remoteClient=remoteClients[i];
00117         }
00118         //RakAssert(remoteClient);
00119         if (remoteClient==0)
00120         {
00121                 tcpInterface->DeallocatePacket(p);
00122                 return 0;
00123         }
00124 
00125 
00126         if (p->length==3 && p->data[0]==27 && p->data[1]==91 && p->data[2]==65)
00127         {
00128                 if (remoteClient->lastSentTextInput[0])
00129                 {
00130                         // Up arrow, return last string
00131                         for (int i=0; remoteClient->textInput[i]; i++)
00132                                 remoteClient->textInput[i]=8;
00133                         strcat(remoteClient->textInput, remoteClient->lastSentTextInput);
00134                         tcpInterface->Send((const char *)remoteClient->textInput, strlen(remoteClient->textInput), p->systemAddress, false);
00135                         strcpy(remoteClient->textInput,remoteClient->lastSentTextInput);
00136                         remoteClient->cursorPosition=strlen(remoteClient->textInput);
00137                 }
00138                 
00139                 return 0;
00140         }
00141 
00142 
00143         // 127 is delete - ignore that
00144         // 9 is tab
00145         // 27 is escape
00146         if (p->data[0]>=127 || p->data[0]==9 || p->data[0]==27)
00147         {
00148                 tcpInterface->DeallocatePacket(p);
00149                 return 0;
00150         }
00151 
00152         // Hack - I don't know what the hell this is about but cursor keys send 3 characters at a time.  I can block these
00153         //Up=27,91,65
00154         //Down=27,91,66
00155         //Right=27,91,67
00156         //Left=27,91,68
00157         if (p->length==3 && p->data[0]==27 && p->data[1]==91 && p->data[2]>=65 && p->data[2]<=68)
00158         {
00159                 tcpInterface->DeallocatePacket(p);
00160                 return 0;
00161         }
00162 
00163 
00164 
00165         // Echo
00166 #ifdef ECHO_INPUT
00167         tcpInterface->Send((const char *)p->data, p->length, p->systemAddress, false);
00168 #endif
00169 
00170         bool gotLine;
00171         // Process each character in turn
00172         for (i=0; i < p->length; i++)
00173         {
00174 
00175 #ifdef ECHO_INPUT
00176                 if (p->data[i]==8)
00177                 {
00178                         char spaceThenBack[2];
00179                         spaceThenBack[0]=' ';
00180                         spaceThenBack[1]=8;
00181                         tcpInterface->Send((const char *)spaceThenBack, 2, p->systemAddress, false);
00182                 }
00183 #endif
00184 
00185                 gotLine=ReassembleLine(remoteClient, p->data[i]);
00186                 if (gotLine && remoteClient->textInput[0])
00187                 {
00188 
00189                         Packet *reassembledLine = (Packet*) rakMalloc_Ex(sizeof(Packet), __FILE__, __LINE__);
00190                         reassembledLine->length=(unsigned int) strlen(remoteClient->textInput);
00191                         memcpy(remoteClient->lastSentTextInput, remoteClient->textInput, reassembledLine->length+1);
00192                         RakAssert(reassembledLine->length < REMOTE_MAX_TEXT_INPUT);
00193                         reassembledLine->data= (unsigned char*) rakMalloc_Ex( reassembledLine->length+1, __FILE__, __LINE__ );
00194                         memcpy(reassembledLine->data, remoteClient->textInput, reassembledLine->length);
00195 #ifdef _PRINTF_DEBUG
00196                         memset(remoteClient->textInput, 0, REMOTE_MAX_TEXT_INPUT);
00197 #endif
00198                         reassembledLine->data[reassembledLine->length]=0;
00199                         reassembledLine->systemAddress=p->systemAddress;
00200                         tcpInterface->DeallocatePacket(p);
00201                         return reassembledLine;
00202                 }
00203         }
00204 
00205         tcpInterface->DeallocatePacket(p);
00206         return 0;
00207 }
00208 void TelnetTransport::DeallocatePacket( Packet *packet )
00209 {
00210         if (tcpInterface==0) return;
00211         rakFree_Ex(packet->data, __FILE__, __LINE__ );
00212         rakFree_Ex(packet, __FILE__, __LINE__ );
00213 }
00214 SystemAddress TelnetTransport::HasNewIncomingConnection(void)
00215 {
00216         unsigned i;
00217         SystemAddress newConnection;
00218         newConnection = tcpInterface->HasNewIncomingConnection();
00219         // 03/16/06 Can't force the stupid windows telnet to use line mode or local echo so now I have to track all the remote players and their
00220         // input buffer
00221         if (newConnection != UNASSIGNED_SYSTEM_ADDRESS)
00222         {
00223                 unsigned char command[10];
00224                 // http://www.pcmicro.com/netfoss/RFC857.html
00225                 // IAC WON'T ECHO
00226                 command[0]=255; // IAC
00227                 //command[1]=253; // WON'T
00228                 command[1]=251; // WILL
00229                 command[2]=1; // ECHO
00230                 tcpInterface->Send((const char*)command, 3, newConnection, false);
00231 
00232                 /*
00233                 // Tell the other side to use line mode
00234                 // http://www.faqs.org/rfcs/rfc1184.html
00235                 // IAC DO LINEMODE
00236         //      command[0]=255; // IAC
00237         //      command[1]=252; // DO
00238         //      command[2]=34; // LINEMODE
00239         //      tcpInterface->Send((const char*)command, 3, newConnection);
00240 
00241         */
00242 
00243                 TelnetClient *remoteClient=0;
00244                 for (i=0; i < remoteClients.Size(); i++)
00245                 {
00246                         if (remoteClients[i]->systemAddress==newConnection)
00247                         {
00248                                 remoteClient=remoteClients[i];
00249                                 remoteClient->cursorPosition=0;
00250                         }
00251                 }
00252 
00253                 if (remoteClient==0)
00254                 {
00255                         remoteClient=new TelnetClient;
00256                         remoteClient->lastSentTextInput[0]=0;
00257                         remoteClient->cursorPosition=0;
00258                         remoteClient->systemAddress=newConnection;
00259 #ifdef _PRINTF_DEBUG
00260                         memset(remoteClient->textInput, 0, REMOTE_MAX_TEXT_INPUT);
00261 #endif
00262                 }
00263 
00264                 remoteClients.Insert(remoteClient, __FILE__, __LINE__);
00265         }
00266         return newConnection;
00267 }
00268 SystemAddress TelnetTransport::HasLostConnection(void)
00269 {
00270         SystemAddress systemAddress;
00271         unsigned i;
00272         systemAddress=tcpInterface->HasLostConnection();
00273         if (systemAddress!=UNASSIGNED_SYSTEM_ADDRESS)
00274         {
00275                 for (i=0; i < remoteClients.Size(); i++)
00276                 {
00277                         if (remoteClients[i]->systemAddress==systemAddress)
00278                         {
00279                                 RakNet::OP_DELETE(remoteClients[i], __FILE__, __LINE__);
00280                                 remoteClients[i]=remoteClients[remoteClients.Size()-1];
00281                                 remoteClients.RemoveFromEnd();
00282                         }
00283                 }
00284         }
00285         return systemAddress;
00286 }
00287 CommandParserInterface* TelnetTransport::GetCommandParser(void)
00288 {
00289         return 0;
00290 }
00291 void TelnetTransport::SetSendSuffix(const char *suffix)
00292 {
00293         if (sendSuffix)
00294         {
00295                 rakFree_Ex(sendSuffix, __FILE__, __LINE__ );
00296                 sendSuffix=0;
00297         }
00298         if (suffix)
00299         {
00300                 sendSuffix = (char*) rakMalloc_Ex(strlen(suffix)+1, __FILE__, __LINE__);
00301                 strcpy(sendSuffix, suffix);
00302         }
00303 }
00304 void TelnetTransport::SetSendPrefix(const char *prefix)
00305 {
00306         if (sendPrefix)
00307         {
00308                 rakFree_Ex(sendPrefix, __FILE__, __LINE__ );
00309                 sendPrefix=0;
00310         }
00311         if (prefix)
00312         {
00313                 sendPrefix = (char*) rakMalloc_Ex(strlen(prefix)+1, __FILE__, __LINE__);
00314                 strcpy(sendPrefix, prefix);
00315         }
00316 }
00317 void TelnetTransport::AutoAllocate(void)
00318 {
00319         if (tcpInterface==0)
00320                 tcpInterface=new TCPInterface;
00321 }
00322 bool TelnetTransport::ReassembleLine(TelnetTransport::TelnetClient* remoteClient, unsigned char c)
00323 {
00324         if (c=='\n')
00325         {
00326                 remoteClient->textInput[remoteClient->cursorPosition]=0;
00327                 remoteClient->cursorPosition=0;
00328 #ifdef _PRINTF_DEBUG
00329                 RAKNET_DEBUG_PRINTF("[Done] %s\n", remoteClient->textInput);
00330 #endif
00331                 return true;
00332         }
00333         else if (c==8) // backspace
00334         {
00335                 if (remoteClient->cursorPosition>0)
00336                 {
00337                         remoteClient->textInput[--remoteClient->cursorPosition]=0;
00338 #ifdef _PRINTF_DEBUG
00339                         RAKNET_DEBUG_PRINTF("[Back] %s\n", remoteClient->textInput);
00340 #endif
00341                 }
00342         }
00343         else if (c>=32 && c <127)
00344         {
00345                 if (remoteClient->cursorPosition < REMOTE_MAX_TEXT_INPUT)
00346                 {
00347                         remoteClient->textInput[remoteClient->cursorPosition++]=c;
00348 #ifdef _PRINTF_DEBUG
00349                         RAKNET_DEBUG_PRINTF("[Norm] %s\n", remoteClient->textInput);
00350 #endif
00351                 }
00352         }
00353         return false;
00354 }
00355 
00356 #ifdef _MSC_VER
00357 #pragma warning( pop )
00358 #endif
00359 
00360 #endif // _RAKNET_SUPPORT_*

Generated on Thu Sep 30 2010 01:27:28 for RakNet by  doxygen 1.7.1