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
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
00044 AddCommandParser(transport->GetCommandParser());
00045 }
00046 }
00047 void ConsoleServer::AddCommandParser(CommandParserInterface *commandParserInterface)
00048 {
00049 if (commandParserInterface==0)
00050 return;
00051
00052
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
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
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];
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);
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
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
00151 }
00152 else
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
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
00188 transport->Send(p->systemAddress, "Unknown help topic: %s.\r\n", parameterList[1]);
00189 }
00190
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)
00204 {
00205 unsigned commandParserIndex=(unsigned)-1;
00206
00207 if (**parameterList>='0' && **parameterList<='9')
00208 {
00209 commandParserIndex=atoi(*parameterList);
00210 commandParserIndex--;
00211 if (commandParserIndex >= commandParserList.Size())
00212 {
00213 transport->Send(p->systemAddress, "Invalid index.\r\n");
00214 failed=true;
00215 }
00216 }
00217 else
00218 {
00219
00220 for (i=0; i < commandParserList.Size(); i++)
00221 {
00222 if (_stricmp(parameterList[0], commandParserList[i]->GetName())==0)
00223 {
00224 commandParserIndex=i;
00225 break;
00226 }
00227 }
00228 }
00229
00230 if (failed==false)
00231 {
00232
00233 if (commandParserIndex!=(unsigned)-1)
00234 {
00235
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
00254
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_*