00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "Aria.h"
00027 #include "ArExport.h"
00028 #include "ArClientSwitchManager.h"
00029
00030 AREXPORT ArClientSwitchManager::ArClientSwitchManager(
00031 ArServerBase *serverBase, ArArgumentParser *parser) :
00032 myParseArgsCB(this, &ArClientSwitchManager::parseArgs),
00033 myLogOptionsCB(this, &ArClientSwitchManager::logOptions),
00034 mySocketClosedCB(this, &ArClientSwitchManager::socketClosed),
00035 mySwitchCB(this, &ArClientSwitchManager::clientSwitch),
00036 myNetCentralHeartbeatCB(this, &ArClientSwitchManager::netCentralHeartbeat),
00037 myFileUserCB(this, &ArClientSwitchManager::fileUserCallback),
00038 myFilePasswordCB(this, &ArClientSwitchManager::filePasswordCallback),
00039 myFileServerKeyCB(this, &ArClientSwitchManager::fileServerKeyCallback)
00040 {
00041 myServer = serverBase;
00042 myParser = parser;
00043
00044 setThreadName("ArClientSwitchManager");
00045
00046 mySwitchCB.setName("ArClientSwitchManager");
00047
00048 myParseArgsCB.setName("ArClientSwitchManager");
00049 Aria::addParseArgsCB(&myParseArgsCB, 49);
00050 myLogOptionsCB.setName("ArClientSwitchManager");
00051 Aria::addLogOptionsCB(&myLogOptionsCB, 49);
00052
00053 myNetCentralHeartbeatCB.setName("ArClientSwitchManager");
00054 myServer->addData("centralHeartbeat",
00055 "a packet that is requested and used by the central server to make sure there is still a connection, it should not be used by anyone or anything else, note that this sends a response over tcp and udp at the same time",
00056 &myNetCentralHeartbeatCB, "none", "none", "RobotInfo",
00057 "RETURN_SINGLE");
00058
00059 switchState(IDLE);
00060 myClient = NULL;
00061 myCentralServerPort = 5000;
00062
00063 myFileUserCB.setName("ArClientSwitchManager::user");
00064 myFileParser.addHandler("user", &myFileUserCB);
00065 myFilePasswordCB.setName("ArClientSwitchManager::password");
00066 myFileParser.addHandler("password", &myFilePasswordCB);
00067 myFileServerKeyCB.setName("ArClientSwitchManager::serverKey");
00068 myFileParser.addHandler("serverKey", &myFileServerKeyCB);
00069 }
00070
00071 AREXPORT ArClientSwitchManager::~ArClientSwitchManager()
00072 {
00073 }
00074
00075 AREXPORT void ArClientSwitchManager::switchState(State state)
00076 {
00077 myState = state;
00078 myStartedState.setToNow();
00079 myGaveTimeWarning = false;
00080 }
00081
00082 AREXPORT bool ArClientSwitchManager::parseArgs(void)
00083 {
00084 const char *centralServer = NULL;
00085 const char *identifier = NULL;
00086
00087 if (!myParser->checkParameterArgumentString("-centralServer",
00088 ¢ralServer) ||
00089 !myParser->checkParameterArgumentString("-cs", ¢ralServer) ||
00090 !myParser->checkParameterArgumentInteger("-centralServerPort",
00091 &myCentralServerPort) ||
00092 !myParser->checkParameterArgumentInteger("-csp",
00093 &myCentralServerPort) ||
00094 !myParser->checkParameterArgumentString("-identifier", &identifier) ||
00095 !myParser->checkParameterArgumentString("-id", &identifier))
00096 return false;
00097
00098
00099
00100 bool wasReallySet;
00101 const char *centralServerInfoFile = NULL;
00102 while (myParser->checkParameterArgumentString(
00103 "-centralServerInfoFile", ¢ralServerInfoFile,
00104 &wasReallySet, true) &&
00105 wasReallySet)
00106 {
00107 if (centralServerInfoFile != NULL && !parseFile(centralServerInfoFile))
00108 return false;
00109 }
00110
00111 myDataMutex.lock();
00112 if (centralServer != NULL && centralServer[0] != '\0')
00113 {
00114 myCentralServer = centralServer;
00115 myState = TRYING_CONNECTION;
00116 }
00117
00118 if (identifier != NULL && identifier[0] != '\0')
00119 {
00120 myIdentifier = identifier;
00121 }
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 myDataMutex.unlock();
00138
00139 return true;
00140 }
00141
00142 AREXPORT void ArClientSwitchManager::logOptions(void) const
00143 {
00144 ArLog::log(ArLog::Terse, "ArClientSwitchManager options:");
00145 ArLog::log(ArLog::Terse, "");
00146 ArLog::log(ArLog::Terse, "-centralServer <host>");
00147 ArLog::log(ArLog::Terse, "-cs <host>");
00148 ArLog::log(ArLog::Terse, "-centralServerPort <port>");
00149 ArLog::log(ArLog::Terse, "-csp <port>");
00150 ArLog::log(ArLog::Terse, "-identifier <identifier>");
00151 ArLog::log(ArLog::Terse, "-id <identifier>");
00152
00153
00154
00155
00156
00157
00158
00159
00160 ArLog::log(ArLog::Terse, "-centralServerInfoFile <fileName>");
00161 }
00162
00163 AREXPORT void ArClientSwitchManager::clientSwitch(ArNetPacket *packet)
00164 {
00165 ArLog::log(ArLog::Normal, "Switch acknowledged, switching");
00166
00167 ArClientBase *client;
00168
00169 myDataMutex.lock();
00170
00171 myClient->getTcpSocket()->setCloseCallback(&mySocketClosedCB);
00172 myServer->makeNewServerClientFromSocket(myClient->getTcpSocket(), true);
00173 client = myClient;
00174 myClient = NULL;
00175 switchState(CONNECTED);
00176 myDataMutex.unlock();
00177
00178 client->cancel();
00179 delete client;
00180
00181 printf("Done switching\n");
00182
00183 }
00184
00185 AREXPORT void ArClientSwitchManager::socketClosed(void)
00186 {
00187 myDataMutex.lock();
00188 if (myState == CONNECTED)
00189 {
00190 ArLog::log(ArLog::Normal, "ArClientSwitchManager: Lost connection to central server");
00191 switchState(LOST_CONNECTION);
00192 }
00193 myDataMutex.unlock();
00194 }
00195
00196 AREXPORT void *ArClientSwitchManager::runThread(void *arg)
00197 {
00198 threadStarted();
00199
00200 while (getRunning())
00201 {
00202 myDataMutex.lock();
00203 if (myState == IDLE)
00204 {
00205 }
00206 else if (myState == TRYING_CONNECTION)
00207 {
00208 ArLog::log(ArLog::Normal, "Trying to connect to central server");
00209 myClient = new ArClientBase;
00210 myClient->setServerKey(myServerKey.c_str(), false);
00211 if (!myClient->blockingConnect(myCentralServer.c_str(),
00212 myCentralServerPort, false,
00213 myUser.c_str(), myPassword.c_str()))
00214 {
00215 if (myClient->wasRejected())
00216 ArLog::log(ArLog::Normal,
00217 "Could not connect to %s because it rejected connection (bad user, password, or serverkey)",
00218 myCentralServer.c_str());
00219 else
00220 ArLog::log(ArLog::Verbose,
00221 "Could not connect to %s to switch with, not doing anything",
00222 myCentralServer.c_str());
00223 delete myClient;
00224 myClient = NULL;
00225 switchState(LOST_CONNECTION);
00226 myDataMutex.unlock();
00227 continue;
00228 }
00229
00230 if (!myClient->dataExists("switch"))
00231 {
00232 ArLog::log(ArLog::Normal,
00233 "ArClientSwitchManager: Connected to central server %s but it isn't a central server, going to idle");
00234 myClient->disconnect();
00235 delete myClient;
00236 myClient = NULL;
00237 switchState(IDLE);
00238 myDataMutex.unlock();
00239 continue;
00240 }
00241
00242 ArNetPacket sendPacket;
00243 ArLog::log(ArLog::Normal, "PUtting in %s\n", myIdentifier.c_str());
00244 sendPacket.strToBuf(myIdentifier.c_str());
00245
00246 ArLog::log(ArLog::Normal, "Requesting switch");
00247 myClient->addHandler("switch", &mySwitchCB);
00248 myClient->requestOnce("switch", &sendPacket);
00249 myClient->runAsync();
00250 switchState(CONNECTING);
00251 }
00252 else if (myState == CONNECTING)
00253 {
00254 if (!myGaveTimeWarning && myStartedState.secSince() > 10)
00255 {
00256 ArLog::log(ArLog::Normal, "ArClientSwitchManager: Connecting has taken over 10 seconds, probably a problem");
00257 myGaveTimeWarning = true;
00258 myDataMutex.unlock();
00259 continue;
00260 }
00261 }
00262 else if (myState == CONNECTED)
00263 {
00264 }
00265 else if (myState == LOST_CONNECTION)
00266 {
00267 if (myStartedState.secSince() > 10)
00268 {
00269 switchState(TRYING_CONNECTION);
00270 }
00271 }
00272 myDataMutex.unlock();
00273 ArUtil::sleep(100);
00274 }
00275 return NULL;
00276 }
00277
00278 AREXPORT void ArClientSwitchManager::netCentralHeartbeat(
00279 ArServerClient *client, ArNetPacket *packet)
00280 {
00281 ArNetPacket sending;
00282 client->sendPacketTcp(&sending);
00283 client->sendPacketUdp(&sending);
00284 }
00285
00286 AREXPORT bool ArClientSwitchManager::parseFile(const char *fileName)
00287 {
00288 ArLog::log(ArLog::Normal, "Loading central server user/password from %s",
00289 fileName);
00290 if (!myFileParser.parseFile(fileName))
00291 {
00292
00293 ArLog::log(ArLog::Normal, "Failed parsing central server user/password file %s",
00294 fileName);
00295 return false;
00296 }
00297 return true;
00298 }
00299
00300 bool ArClientSwitchManager::fileUserCallback(ArArgumentBuilder *arg)
00301 {
00302 if (arg->getArgc() > 1)
00303 {
00304 ArLog::log(ArLog::Normal, "Bad user line: %s %s",
00305 arg->getExtraString(), arg->getFullString());
00306 return false;
00307 }
00308 if (arg->getArgc() == 0)
00309 myUser = "";
00310 else
00311 myUser = arg->getArg(0);
00312 return true;
00313 }
00314
00315
00316 bool ArClientSwitchManager::filePasswordCallback(ArArgumentBuilder *arg)
00317 {
00318 if (arg->getArgc() > 1)
00319 {
00320 ArLog::log(ArLog::Normal, "Bad password line: %s %s",
00321 arg->getExtraString(), arg->getFullString());
00322 return false;
00323 }
00324 if (arg->getArgc() == 0)
00325 myPassword = "";
00326 else
00327 myPassword = arg->getArg(0);
00328 return true;
00329 }
00330
00331 bool ArClientSwitchManager::fileServerKeyCallback(ArArgumentBuilder *arg)
00332 {
00333 if (arg->getArgc() > 1)
00334 {
00335 ArLog::log(ArLog::Normal, "Bad serverKey line: %s %s",
00336 arg->getExtraString(), arg->getFullString());
00337 return false;
00338 }
00339 if (arg->getArgc() == 0)
00340 myServerKey = "";
00341 else
00342 myServerKey = arg->getArg(0);
00343 return true;
00344 }
00345
00346 AREXPORT const char *ArClientSwitchManager::getCentralServerHostName(void)
00347 {
00348 if (myCentralServer.size() <= 0)
00349 return NULL;
00350 else
00351 return myCentralServer.c_str();
00352 }