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

ConsoleServer.cpp

Go to the documentation of this file.
00001 #include "NativeFeatureIncludes.h"
00002 #if _RAKNET_SUPPORT_ConsoleServer==1
00003 
00004 #include "ConsoleServer.h"
00005 #include "TransportInterface.h"
00006 #include "CommandParserInterface.h"
00007 #include <string.h>
00008 #include <stdlib.h>
00009 
00010 #define COMMAND_DELINATOR ' '
00011 #define COMMAND_DELINATOR_TOGGLE '"'
00012 
00013 #include "LinuxStrings.h"
00014 
00015 ConsoleServer::ConsoleServer()
00016 {
00017         transport=0;
00018         password[0]=0;
00019         prompt=0;
00020 }
00021 ConsoleServer::~ConsoleServer()
00022 {
00023         if (prompt)
00024                 rakFree_Ex(prompt, __FILE__, __LINE__);
00025 }
00026 void ConsoleServer::SetTransportProvider(TransportInterface *transportInterface, unsigned short port)
00027 {
00028         // Replace the current TransportInterface, stopping the old one, if present, and starting the new one.
00029         if (transportInterface)
00030         {
00031                 if (transport)
00032                 {
00033                         RemoveCommandParser(transport->GetCommandParser());
00034                         transport->Stop();
00035                 }
00036                 transport=transportInterface;
00037                 transport->Start(port, true);
00038 
00039                 unsigned i;
00040                 for (i=0; i < commandParserList.Size(); i++)
00041                         commandParserList[i]->OnTransportChange(transport);
00042 
00043                 //  The transport itself might have a command parser - for example password for the RakNet transport
00044                 AddCommandParser(transport->GetCommandParser());
00045         }
00046 }
00047 void ConsoleServer::AddCommandParser(CommandParserInterface *commandParserInterface)
00048 {
00049         if (commandParserInterface==0)
00050                 return;
00051 
00052         // Non-duplicate insertion
00053         unsigned i;
00054         for (i=0; i < commandParserList.Size(); i++)
00055         {
00056                 if (commandParserList[i]==commandParserInterface)
00057                         return;
00058 
00059         if (_stricmp(commandParserList[i]->GetName(), commandParserInterface->GetName())==0)
00060                 {
00061                         // Naming conflict between two command parsers
00062                         RakAssert(0);
00063                         return;
00064                 }
00065         }
00066 
00067         commandParserList.Insert(commandParserInterface, __FILE__, __LINE__);
00068         if (transport)
00069                 commandParserInterface->OnTransportChange(transport);
00070 }
00071 void ConsoleServer::RemoveCommandParser(CommandParserInterface *commandParserInterface)
00072 {
00073         if (commandParserInterface==0)
00074                 return;
00075 
00076         // Overwrite the element we are removing from the back of the list and delete the back of the list
00077         unsigned i;
00078         for (i=0; i < commandParserList.Size(); i++)
00079         {
00080                 if (commandParserList[i]==commandParserInterface)
00081                 {
00082                         commandParserList[i]=commandParserList[commandParserList.Size()-1];
00083                         commandParserList.RemoveFromEnd();
00084                         return;
00085                 }
00086         }
00087 }
00088 void ConsoleServer::Update(void)
00089 {
00090         unsigned i;
00091         char *parameterList[20]; // Up to 20 parameters
00092         unsigned numParameters;
00093         SystemAddress newOrLostConnectionId;
00094         Packet *p;
00095         RegisteredCommand rc;
00096 
00097         p = transport->Receive();
00098         newOrLostConnectionId=transport->HasNewIncomingConnection();
00099 
00100         if (newOrLostConnectionId!=UNASSIGNED_SYSTEM_ADDRESS)
00101         {
00102                 for (i=0; i < commandParserList.Size(); i++)
00103                 {
00104                         commandParserList[i]->OnNewIncomingConnection(newOrLostConnectionId, transport);
00105                 }
00106 
00107                 transport->Send(newOrLostConnectionId, "Connected to remote command console.\r\nType 'help' for help.\r\n");
00108                 ListParsers(newOrLostConnectionId);
00109                 ShowPrompt(newOrLostConnectionId);
00110         }
00111 
00112         newOrLostConnectionId=transport->HasLostConnection();
00113         if (newOrLostConnectionId!=UNASSIGNED_SYSTEM_ADDRESS)
00114         {
00115                 for (i=0; i < commandParserList.Size(); i++)
00116                         commandParserList[i]->OnConnectionLost(newOrLostConnectionId, transport);
00117         }
00118 
00119         while (p)
00120         {
00121                 bool commandParsed=false;
00122                 char copy[REMOTE_MAX_TEXT_INPUT];
00123                 memcpy(copy, p->data, p->length);
00124                 copy[p->length]=0;
00125                 CommandParserInterface::ParseConsoleString((char*)p->data, COMMAND_DELINATOR, COMMAND_DELINATOR_TOGGLE, &numParameters, parameterList, 20); // Up to 20 parameters
00126                 if (numParameters==0)
00127                 {
00128                         transport->DeallocatePacket(p);
00129                         p = transport->Receive();
00130                         continue;
00131                 }
00132                 if (_stricmp(*parameterList, "help")==0 && numParameters<=2)
00133                 {
00134                         // Find the parser specified and display help for it
00135                         if (numParameters==1)
00136                         {
00137                                 transport->Send(p->systemAddress, "\r\nINSTRUCTIONS:\r\n");
00138                                 transport->Send(p->systemAddress, "Enter commands on your keyboard, using spaces to delineate parameters.\r\n");
00139                                 transport->Send(p->systemAddress, "You can use quotation marks to toggle space delineation.\r\n");
00140                                 transport->Send(p->systemAddress, "You can connect multiple times from the same computer.\r\n");
00141                                 transport->Send(p->systemAddress, "You can direct commands to a parser by prefixing the parser name or number.\r\n");
00142                                 transport->Send(p->systemAddress, "COMMANDS:\r\n");
00143                                 transport->Send(p->systemAddress, "help                                        Show this display.\r\n");
00144                                 transport->Send(p->systemAddress, "help <ParserName>                           Show help on a particular parser.\r\n");
00145                                 transport->Send(p->systemAddress, "help <CommandName>                          Show help on a particular command.\r\n");
00146                                 transport->Send(p->systemAddress, "quit                                        Disconnects from the server.\r\n");
00147                                 transport->Send(p->systemAddress, "[<ParserName>]   <Command> [<Parameters>]   Execute a command\r\n");
00148                                 transport->Send(p->systemAddress, "[<ParserNumber>] <Command> [<Parameters>]   Execute a command\r\n");
00149                                 ListParsers(p->systemAddress);
00150                                 //ShowPrompt(p->systemAddress);
00151                         }
00152                         else // numParameters == 2, including the help tag
00153                         {
00154                                 for (i=0; i < commandParserList.Size(); i++)
00155                                 {
00156                                         if (_stricmp(parameterList[1], commandParserList[i]->GetName())==0)
00157                                         {
00158                                                 commandParsed=true;
00159                                                 commandParserList[i]->SendHelp(transport, p->systemAddress);
00160                                                 transport->Send(p->systemAddress, "COMMAND LIST:\r\n");
00161                                                 commandParserList[i]->SendCommandList(transport, p->systemAddress);
00162                                                 transport->Send(p->systemAddress, "\r\n");
00163                                                 break;
00164                                         }
00165                                 }
00166 
00167                                 if (commandParsed==false)
00168                                 {
00169                                         // Try again, for all commands for all parsers.
00170                                         RegisteredCommand rc;
00171                                         for (i=0; i < commandParserList.Size(); i++)
00172                                         {
00173                                                 if (commandParserList[i]->GetRegisteredCommand(parameterList[1], &rc))
00174                                                 {
00175                                                         if (rc.parameterCount==CommandParserInterface::VARIABLE_NUMBER_OF_PARAMETERS)
00176                                                                 transport->Send(p->systemAddress, "(Variable parms): %s %s\r\n", rc.command, rc.commandHelp);
00177                                                         else
00178                                                                 transport->Send(p->systemAddress, "(%i parms): %s %s\r\n", rc.parameterCount, rc.command, rc.commandHelp);
00179                                                         commandParsed=true;
00180                                                         break;
00181                                                 }
00182                                         }
00183                                 }
00184 
00185                                 if (commandParsed==false)
00186                                 {
00187                                         // Don't know what to do
00188                                         transport->Send(p->systemAddress, "Unknown help topic: %s.\r\n", parameterList[1]);
00189                                 }
00190                                 //ShowPrompt(p->systemAddress);
00191                         }
00192                 }
00193                 else if (_stricmp(*parameterList, "quit")==0 && numParameters==1)
00194                 {
00195                         transport->Send(p->systemAddress, "Goodbye!\r\n");
00196                         transport->CloseConnection(p->systemAddress);
00197                 }
00198                 else
00199                 {
00200                         bool tryAllParsers=true;
00201                         bool failed=false;
00202 
00203                         if (numParameters >=2) // At minimum <CommandParserName> <Command>
00204                         {
00205                                 unsigned commandParserIndex=(unsigned)-1;
00206                                 // Prefixing with numbers directs to a particular parser
00207                                 if (**parameterList>='0' && **parameterList<='9')
00208                                 {
00209                                         commandParserIndex=atoi(*parameterList); // Use specified parser unless it's an invalid number
00210                                         commandParserIndex--; // Subtract 1 since we displayed numbers starting at index+1
00211                                         if (commandParserIndex >= commandParserList.Size())
00212                                         {
00213                                                 transport->Send(p->systemAddress, "Invalid index.\r\n");
00214                                                 failed=true;
00215                                         }
00216                                 }
00217                                 else
00218                                 {
00219                                         // // Prefixing with the name of a command parser directs to that parser.  See if the first word matches a parser
00220                                         for (i=0; i < commandParserList.Size(); i++)
00221                                         {
00222                                                 if (_stricmp(parameterList[0], commandParserList[i]->GetName())==0)
00223                                                 {
00224                                                         commandParserIndex=i; // Matches parser at index i
00225                                                         break;
00226                                                 }
00227                                         }
00228                                 }
00229 
00230                                 if (failed==false)
00231                                 {
00232                                         // -1 means undirected, so otherwise this is directed to a target
00233                                         if (commandParserIndex!=(unsigned)-1)
00234                                         {
00235                                                 // Only this parser should use this command
00236                                                 tryAllParsers=false;
00237                                                 if (commandParserList[commandParserIndex]->GetRegisteredCommand(parameterList[1], &rc))
00238                                                 {
00239                                                         commandParsed=true;
00240                                                         if (rc.parameterCount==CommandParserInterface::VARIABLE_NUMBER_OF_PARAMETERS || rc.parameterCount==numParameters-2)
00241                                                                 commandParserList[commandParserIndex]->OnCommand(rc.command, numParameters-2, parameterList+2, transport, p->systemAddress, copy);
00242                                                         else
00243                                                                 transport->Send(p->systemAddress, "Invalid parameter count.\r\n(%i parms): %s %s\r\n", rc.parameterCount, rc.command, rc.commandHelp);
00244                                                 }
00245                                         }
00246                                 }
00247                         }
00248 
00249                         if (failed == false && tryAllParsers)
00250                         {
00251                                 for (i=0; i < commandParserList.Size(); i++)
00252                                 {
00253                                         // Undirected command.  Try all the parsers to see if they understand the command
00254                                         // Pass the 1nd element as the command, and the remainder as the parameter list
00255                                         if (commandParserList[i]->GetRegisteredCommand(parameterList[0], &rc))
00256                                         {
00257                                                 commandParsed=true;
00258 
00259                                                 if (rc.parameterCount==CommandParserInterface::VARIABLE_NUMBER_OF_PARAMETERS || rc.parameterCount==numParameters-1)
00260                                                         commandParserList[i]->OnCommand(rc.command, numParameters-1, parameterList+1, transport, p->systemAddress, copy);
00261                                                 else
00262                                                         transport->Send(p->systemAddress, "Invalid parameter count.\r\n(%i parms): %s %s\r\n", rc.parameterCount, rc.command, rc.commandHelp);
00263                                         }
00264                                 }
00265                         }
00266                         if (commandParsed==false && commandParserList.Size() > 0)
00267                         {
00268                                 transport->Send(p->systemAddress, "Unknown command:  Type 'help' for help.\r\n");
00269                         }
00270 
00271                 }
00272 
00273                 ShowPrompt(p->systemAddress);
00274 
00275                 transport->DeallocatePacket(p);
00276                 p = transport->Receive();
00277         }
00278 }
00279 
00280 void ConsoleServer::ListParsers(SystemAddress systemAddress)
00281 {
00282         transport->Send(systemAddress,"INSTALLED PARSERS:\r\n");
00283         unsigned i;
00284         for (i=0; i < commandParserList.Size(); i++)
00285         {
00286         transport->Send(systemAddress, "%i. %s\r\n", i+1, commandParserList[i]->GetName());
00287         }
00288 }
00289 void ConsoleServer::ShowPrompt(SystemAddress systemAddress)
00290 {
00291          transport->Send(systemAddress, prompt);
00292 }
00293 void ConsoleServer::SetPrompt(const char *_prompt)
00294 {
00295         if (prompt)
00296                 rakFree_Ex(prompt,__FILE__,__LINE__);
00297         if (_prompt && _prompt[0])
00298         {
00299                 size_t len = strlen(_prompt);
00300                 prompt = (char*) rakMalloc_Ex(len+1,__FILE__,__LINE__);
00301                 strcpy(prompt,_prompt);
00302         }
00303         else
00304                 prompt=0;
00305 }
00306 
00307 #endif // _RAKNET_SUPPORT_*

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