Main Page | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages | Examples

ArClientSwitchManager.cpp

Go to the documentation of this file.
00001 /*
00002 MobileRobots Advanced Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004, 2005 ActivMedia Robotics LLC
00004 Copyright (C) 2006, 2007 MobileRobots Inc.
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 MobileRobots for information about a commercial version of ARIA at 
00022 robots@mobilerobots.com or 
00023 MobileRobots Inc, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
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                                               &centralServer) || 
00089       !myParser->checkParameterArgumentString("-cs", &centralServer) || 
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", &centralServerInfoFile, 
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   /* Just don't set it so the server can just set it to the IP
00123   else 
00124   {
00125     int nameLen;
00126     char name[512];
00127     int i;
00128     
00129     nameLen = ArMath::random() % 15 + 1;
00130     for (i = 0; i < nameLen; i++)
00131       name[i] = 'a' + (ArMath::random() % ('z' - 'a'));
00132     name[nameLen] = '\0';
00133     
00134     myIdentifier = name;
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   ArLog::log(ArLog::Terse, "-centralServerUser <user>");
00154   ArLog::log(ArLog::Terse, "-csu <user>");
00155   ArLog::log(ArLog::Terse, "-centralServerPassword <password>");
00156   ArLog::log(ArLog::Terse, "-csp <password>");
00157   ArLog::log(ArLog::Terse, "-centralServerKey <serverKey>");
00158   ArLog::log(ArLog::Terse, "-csk <password>");
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   //myClient.disconnect();
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 }

Generated on Tue Feb 20 10:51:50 2007 for ArNetworking by  doxygen 1.4.0