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

ArClientBase.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 "ArClientBase.h"
00029 #include "ArServerCommands.h"
00030 #include "ArClientCommands.h"
00031 #include "md5.h"
00032 
00033 //#define ARDEBUG_CLIENTBASE
00034 
00035 #if (defined(_DEBUG) && defined(ARDEBUG_CLIENTBASE))
00036 #define IFDEBUG(code) {code;}
00037 #else
00038 #define IFDEBUG(code)
00039 #endif 
00040 
00041 AREXPORT ArClientBase::ArClientBase() :
00042   myRobotName(""),
00043   myLogPrefix(""),
00044   myProcessPacketCB(this, &ArClientBase::processPacket, NULL, true),
00045   myProcessPacketUdpCB(this, &ArClientBase::processPacketUdp)
00046 
00047 {
00048   setThreadName("ArClientBase");
00049   myTcpSender.setSocket(&myTcpSocket);
00050   myTcpReceiver.setSocket(&myTcpSocket);
00051   myTcpReceiver.setProcessPacketCB(&myProcessPacketCB);
00052   myUdpReceiver.setSocket(&myUdpSocket);
00053   myUdpReceiver.setProcessPacketCB(&myProcessPacketUdpCB);
00054   clear();
00055 }
00056 
00057 AREXPORT ArClientBase::~ArClientBase()
00058 {
00059   clear();
00060 }
00061 
00067 AREXPORT void ArClientBase::setRobotName(const char *name)
00068 {
00069   myRobotName = ((name != NULL) ? name : "");
00070 
00071   myLogPrefix = "";
00072   if (!myRobotName.empty()) {
00073     myLogPrefix = myRobotName + ": ";
00074   }
00075 }
00076 
00077 AREXPORT const char *ArClientBase::getRobotName() const
00078 {
00079   return myRobotName.c_str();
00080 }
00081 
00082 
00083 void ArClientBase::clear(void)
00084 {
00085   internalSwitchState(STATE_NO_CONNECTION);
00086 
00087   myServerReportedUdpPort = 0;
00088   myUdpConfirmedFrom = false;
00089   myUdpConfirmedTo = false;
00090   myTcpOnlyTo = false;
00091   myTcpOnlyFrom = false;
00092   myTimeoutTime = 3;
00093   myQuiet = false;
00094   myLastPacketReceived.setToNow();
00095 
00096   myRejected = 0;
00097   myRejectedString[0] = '\0';
00098 
00099   myReceivedDataList = false;
00100   myReceivedArgRetList = false;
00101   myReceivedGroupAndFlagsList = false;
00102 
00103   resetTracking();
00104 
00105   myNameIntMap.clear();
00106   ArUtil::deleteSetPairs(myIntDataMap.begin(), myIntDataMap.end());
00107   myIntDataMap.clear();
00108   
00109 }
00110 
00120 AREXPORT void ArClientBase::addCycleCallback(ArFunctor *functor)
00121 {
00122   myCycleCallbackMutex.lock();
00123   myCycleCallbacks.push_front(functor);
00124   myCycleCallbackMutex.unlock();
00125 }
00126 
00134 AREXPORT void ArClientBase::remCycleCallback(ArFunctor *functor)
00135 {
00136   myCycleCallbackMutex.lock();
00137   myCycleCallbacks.remove(functor);
00138   myCycleCallbackMutex.unlock();
00139 }
00140 
00141 
00147 AREXPORT void ArClientBase::setConnectTimeoutTime(int sec)
00148 {
00149   myDataMutex.lock();
00150   if (sec < 0)
00151     myTimeoutTime = 0;
00152   else
00153     myTimeoutTime = sec;
00154   myDataMutex.unlock();
00155 }
00156 
00162 AREXPORT int ArClientBase::getConnectTimeoutTime(void)
00163 {
00164   return myTimeoutTime;
00165 }
00166 
00167 
00168 
00182 AREXPORT bool ArClientBase::blockingConnect(const char *host, int port, 
00183                                             bool print, const char *user,
00184                                             const char *password)
00185 {
00186   return internalBlockingConnect(host, port, print, user, password, NULL);
00187 }
00188 
00189 AREXPORT bool ArClientBase::internalBlockingConnect(
00190         const char *host, int port, bool print, const char *user,
00191         const char *password, ArSocket *tcpSocket)
00192 {
00193   bool ret = false;
00194   ArTime startedUdpWait;
00195   ArNetPacket packet;
00196   bool debugPrinting = false;
00197   myDataMutex.lock();
00198   myHost = host;
00199   myQuiet = !print;
00200   myTcpReceiver.setQuiet(myQuiet);
00201   if (user != NULL)
00202     myUser = user;
00203   else
00204     myUser = "";
00205   if (password != NULL)
00206     myPassword = password;
00207   else
00208     myPassword = "";
00209 
00210   if (myState == STATE_LOST_CONNECTION)
00211   {
00212     ArLog::log(ArLog::Normal, "Trying a connection on a client that'd lost connection.");
00213     clear();
00214   }
00215 
00216   myDataMutex.unlock();
00217     
00218   if (myState != STATE_NO_CONNECTION && myState != STATE_FAILED_CONNECTION)
00219   {
00220     if (!myQuiet)
00221       ArLog::log(ArLog::Terse, 
00222          "ArClientBase: Connection already established or being connected.");
00223     return false;
00224   }
00225 
00226 
00227   if (debugPrinting)
00228     ArLog::log(ArLog::Normal, "0");
00229   myDataMutex.lock();
00230   myStartedConnection.setToNow();
00231   myDataMutex.unlock();
00232   if (tcpSocket != NULL)
00233   {
00234     myDataMutex.lock();
00235     myTcpSocket.transfer(tcpSocket);
00236     internalStartUdp();
00237     myDataMutex.unlock();
00238     internalSwitchState(STATE_OPENED_SOCKET);
00239 
00240   }
00241   else
00242   {
00243     /*
00244     while (1)
00245     {
00246     */
00247     if (debugPrinting)
00248       ArLog::log(ArLog::Normal, "1");
00249     loopOnce();
00250     if (debugPrinting)
00251       ArLog::log(ArLog::Normal, "1.1");
00252     myDataMutex.lock();
00253     if (debugPrinting)
00254       ArLog::log(ArLog::Normal, "1.2");
00255     if (internalConnect(host, port, print))
00256     {
00257       myDataMutex.unlock();
00258       if (debugPrinting)
00259         ArLog::log(ArLog::Normal, "2");
00260       //break;
00261     }
00262     else
00263     {
00264       myTcpSocket.close();
00265       myUdpSocket.close();
00266       internalSwitchState(STATE_FAILED_CONNECTION);
00267       myDataMutex.unlock();
00268       if (debugPrinting)
00269         ArLog::log(ArLog::Normal, "3");
00270       return false;
00271       /*
00272       // see if we didn't get udp from
00273       if (myStartedConnection.mSecSince() > myTimeoutTime * .33 * 1000.0)
00274       {
00275         if (debugPrinting)
00276           ArLog::log(ArLog::Normal, "3");
00277         internalSwitchState(STATE_FAILED_CONNECTION);
00278 
00279         return false;
00280       }
00281       else 
00282       {
00283         if (debugPrinting)
00284           ArLog::log(ArLog::Normal, "4");
00285           internalSwitchState(STATE_FAILED_CONNECTION);
00286         ArUtil::sleep(100);
00287       }
00288       */
00289     }
00290     //}
00291   }
00292 
00293   if (debugPrinting)
00294     ArLog::log(ArLog::Normal, "5");
00295   while (myState != STATE_REJECTED && myState != STATE_CONNECTED && 
00296          myState != STATE_NO_CONNECTION)
00297   {
00298     if (debugPrinting)
00299       ArLog::log(ArLog::Normal, "6");
00300     loopOnce();
00301     if (myTimeoutTime > 0 && 
00302         myStartedConnection.mSecSince() > myTimeoutTime * 1000.0)
00303     {
00304       if (debugPrinting)
00305         ArLog::log(ArLog::Normal, "7");
00306       if (!myQuiet)
00307         ArLog::log(ArLog::Terse, "ArClientBase::blockingConnect: a Connection timed out.");
00308       internalSwitchState(STATE_FAILED_CONNECTION);
00309       //myState = STATE_NO_CONNECTION;
00310       myTcpSocket.close();
00311       myUdpSocket.close();
00312       return false;
00313     }
00314     ArUtil::sleep(1);
00315   }
00316   if (myState == STATE_REJECTED)
00317   {
00318     myTcpSocket.close();
00319     myUdpSocket.close();
00320     return false;
00321   }
00322   if (debugPrinting)
00323     ArLog::log(ArLog::Normal, "8");
00324   startedUdpWait.setToNow();
00325   while ((!myUdpConfirmedFrom && !myTcpOnlyFrom) || 
00326          (!myUdpConfirmedTo && !myTcpOnlyTo))
00327   {
00328     if (debugPrinting)
00329       ArLog::log(ArLog::Normal, "9");
00330     loopOnce();
00331     // see if we didn't get udp from
00332     if (startedUdpWait.mSecSince() > myTimeoutTime * .66 * 1000.0 &&
00333         !myUdpConfirmedFrom && !myTcpOnlyFrom)
00334     {
00335       packet.empty();
00336       packet.setCommand(ArClientCommands::TCP_ONLY);
00337       sendPacketTcp(&packet);
00338       myDataMutex.lock();
00339       myTcpOnlyFrom = true;
00340       myDataMutex.unlock();
00341       if (!myQuiet)
00342         ArLog::log(ArLog::Normal, "ArClientBase: Didn't get confirmation of UDP from server, switching to TCP.");
00343     }
00344     // see if we haven't confirmed udp to
00345     if (startedUdpWait.mSecSince() > myTimeoutTime * .66 * 1000.0 &&
00346         !myUdpConfirmedTo && !myTcpOnlyTo)
00347     {
00348       packet.empty();
00349       myDataMutex.lock();
00350       myTcpOnlyTo = true;
00351       myDataMutex.unlock();
00352       if (!myQuiet)
00353         ArLog::log(ArLog::Normal, "ArClientBase: Didn't get confirmation of UDP to server, switching to TCP.");
00354     }
00355     if (myTimeoutTime > 0 && 
00356         startedUdpWait.mSecSince() > myTimeoutTime * 1000.0)
00357     {
00358       if (!myQuiet)
00359         ArLog::log(ArLog::Terse, "ArClientBase::blockingConnect: b Connection timed out.");
00360       ArLog::log(
00361               ArLog::Normal, "timeout %d startedMSecSince %d startedUdpWaitMSecSince %d udpFrom %d udpTo %d tcpOnlyFrom %d tcpOnlyTo %d", 
00362               myTimeoutTime, myStartedConnection.mSecSince(), 
00363               startedUdpWait.mSecSince(), myUdpConfirmedFrom, 
00364               myUdpConfirmedTo, myTcpOnlyFrom, myTcpOnlyTo);
00365       //myState = STATE_NO_CONNECTION;
00366       internalSwitchState(STATE_FAILED_CONNECTION);
00367     }
00368     ArUtil::sleep(1);
00369   }
00370   if (debugPrinting)
00371     ArLog::log(ArLog::Normal, "10");
00372   if (myState == STATE_CONNECTED)
00373     ret = true;
00374   if (!ret)
00375   {
00376     myTcpSocket.close();
00377     myUdpSocket.close();
00378   }
00379   return ret;  
00380 }
00381 
00382 bool ArClientBase::internalConnect(const char *host, int port, bool obsolete)
00383 {
00384   bool debugPrinting = false;
00385   if (debugPrinting)
00386     ArLog::log(ArLog::Normal, "a");
00387   // if we connect tcp then connect up the udp
00388   if (myTcpSocket.connect(host, port, ArSocket::TCP))
00389   {
00390     if (debugPrinting)
00391       ArLog::log(ArLog::Normal, "b");
00392     if (!myTcpSocket.setNonBlock())
00393     {
00394       ArLog::log(ArLog::Terse,
00395                  "ArClientBase::connect: Failed to set TCP socket nonblock");
00396       return false;
00397     }
00398     if (debugPrinting)
00399       ArLog::log(ArLog::Normal, "c");
00400     internalStartUdp();
00401     if (debugPrinting)
00402       ArLog::log(ArLog::Normal, "d");
00403     if (!myQuiet)
00404       ArLog::log(ArLog::Verbose, 
00405         "Opened client connection to %s on tcp port %d with my udp port of %d",
00406                  host, port, myUdpPort);
00407     // we can't tell if udp connected or not (because its udp) so just
00408     // say we're good
00409     internalSwitchState(STATE_OPENED_SOCKET);
00410     if (debugPrinting)
00411       ArLog::log(ArLog::Normal, "e");
00412     return true;
00413   }
00414   else
00415   {
00416     if (!myQuiet)
00417       ArLog::log(ArLog::Terse,
00418                  "ArClientBase::connect: Failed to open TCP socket");
00419     internalSwitchState(STATE_FAILED_CONNECTION);
00420     return false;
00421   }
00422 }
00423 
00424 void ArClientBase::internalStartUdp(void)
00425 {
00426   // fire up the udp
00427   if (!myUdpSocket.create(ArSocket::UDP) ||
00428       !myUdpSocket.findValidPort(10000) ||
00429       !myUdpSocket.setNonBlock())
00430   {
00431     myUdpSocket.setLinger(0);
00432     if (!myQuiet)
00433       ArLog::log(ArLog::Terse, 
00434                  "ArClientBase::connect: Failed to open udp socket, forcing TCP");
00435     //internalSwitchState(STATE_FAILED_CONNECTION);
00436     //return false;              
00437     myTcpOnlyTo = true;
00438     myTcpOnlyFrom = true;
00439   }
00440   myUdpSinValid = false;
00441   myUdpSin.sin_family=AF_INET;
00442   myUdpSin.sin_addr = *myTcpSocket.inAddr();
00443   myUdpPort = myUdpSocket.netToHostOrder(myUdpSocket.inPort());
00444 }
00445 
00446 AREXPORT bool ArClientBase::disconnect(void)
00447 {
00448   bool ret = startNonBlockingDisconnect();
00449 
00450   ArUtil::sleep(10);
00451 
00452   finishNonBlockingDisconnect();
00453 
00454   return ret;
00455 }
00456 
00457 AREXPORT bool ArClientBase::startNonBlockingDisconnect()
00458 {
00459   if (!myQuiet)
00460     ArLog::log(ArLog::Normal, "Disconnected from server."); 
00461 
00462   bool ret = false;
00463   ArNetPacket packet;
00464 
00465   packet.setCommand(ArClientCommands::SHUTDOWN);
00466   ret = sendPacketTcp(&packet);
00467   myTcpSender.sendData();
00468 
00469   return ret;
00470 }
00471 
00472 AREXPORT void ArClientBase::finishNonBlockingDisconnect()
00473 {
00474   myTcpSocket.close();
00475   myUdpSocket.close();
00476   myState = STATE_NO_CONNECTION;
00477 }
00478 
00479 
00480 
00481 AREXPORT  bool ArClientBase::setupPacket(ArNetPacket *packet)
00482 {
00483   if (myState == STATE_NO_CONNECTION || myState == STATE_FAILED_CONNECTION)
00484     return false;
00485 
00486   packet->finalizePacket();
00487   return true;
00488 } 
00489 
00490 AREXPORT bool ArClientBase::sendPacketTcp(ArNetPacket *packet)
00491 {
00492   if (!setupPacket(packet))
00493   {
00494     return false;
00495   }
00496   else
00497   {
00498     trackPacketSent(packet, true);
00499     myTcpSender.sendPacket(packet);
00500     return true;
00501   }
00502 }
00503 
00504 AREXPORT bool ArClientBase::sendPacketUdp(ArNetPacket *packet)
00505 {
00506   if (!setupPacket(packet))
00507   {
00508     return false;
00509   }
00510   else
00511   {
00512     trackPacketSent(packet, false);
00513     if (myUdpSocket.sendTo(packet->getBuf(), packet->getLength(), &myUdpSin) 
00514         == packet->getLength())
00515     {
00516       return true;
00517     }
00518     else
00519     {
00520       return false;
00521     }
00522   }
00523 }
00524 
00525 AREXPORT void ArClientBase::loopOnce(void)
00526 {
00527   std::list<ArFunctor *>::iterator it;
00528   if (myState != STATE_NO_CONNECTION && myState != STATE_FAILED_CONNECTION &&
00529       myState != STATE_LOST_CONNECTION)
00530   {
00531     // if we couldn't receive tcp data fail
00532     if (!myTcpReceiver.readData())
00533     {
00534       if (!myQuiet)
00535         ArLog::log(ArLog::Normal, 
00536                    "Lost connection to server (couldn't recv).");
00537       myTcpSocket.close();
00538       myUdpSocket.close();
00539       internalSwitchState(STATE_LOST_CONNECTION);
00540       stopRunning();
00541       myCallbackMutex.lock();
00542       for (it = myDisconnectOnErrorCBList.begin(); 
00543            it != myDisconnectOnErrorCBList.end(); 
00544            ++it)
00545         (*it)->invoke();
00546       myCallbackMutex.unlock();
00547   
00548     }
00549     // if we can't receive UDP just make an error log
00550     else if (!myTcpOnlyFrom && !myUdpReceiver.readData())
00551     {
00552       if (!myQuiet)
00553         ArLog::log(ArLog::Normal, "UDP Troubles, continuing");
00554     }
00555     if (!myTcpSender.sendData())
00556     {
00557       if (!myQuiet)
00558         ArLog::log(ArLog::Normal, 
00559                    "Lost connection to server (couldn't send).");
00560       myTcpSocket.close();
00561       myUdpSocket.close();
00562       internalSwitchState(STATE_LOST_CONNECTION);
00563       stopRunning();
00564       myCallbackMutex.lock();
00565       for (it = myDisconnectOnErrorCBList.begin(); 
00566            it != myDisconnectOnErrorCBList.end(); 
00567            ++it)
00568         (*it)->invoke();
00569       myCallbackMutex.unlock();
00570     }
00571   }
00572   myCycleCallbackMutex.lock();
00573   for (it = myCycleCallbacks.begin(); it != myCycleCallbacks.end(); ++it)
00574     (*it)->invoke();
00575   myCycleCallbackMutex.unlock();
00576 
00577 }
00578 
00579 AREXPORT void ArClientBase::run(void)
00580 {
00581   runInThisThread();
00582 }
00583 
00584 AREXPORT void ArClientBase::runAsync(void)
00585 {
00586   create(true, false);
00587 }
00588 
00589 AREXPORT void *ArClientBase::runThread(void *arg)
00590 {
00591   threadStarted();
00592   while (myRunning)
00593   {
00594     loopOnce();
00595     ArUtil::sleep(1);
00596   }
00597   return NULL;
00598 }
00599 
00600 
00601 AREXPORT void ArClientBase::processPacket(ArNetPacket *packet, bool tcp)
00602 {
00603   ArNetPacket retPacket;
00604   char buf[512];
00605   char passwordKey[2048];
00606   std::list<ArFunctor *>::iterator it;
00607 
00608   myDataMutex.lock();
00609   myLastPacketReceived.setToNow();
00610   myDataMutex.unlock();
00611 
00612   // See if we should close our connection
00613   if (packet->getCommand() == ArServerCommands::SHUTDOWN)
00614   {
00615     if (!myQuiet)
00616       ArLog::log(ArLog::Normal, "Server shutting down and closed connection.");
00617     stopRunning();
00618     disconnect();
00619     internalSwitchState(STATE_LOST_CONNECTION);
00620     myCallbackMutex.lock();
00621     for (it = myServerShutdownCBList.begin(); 
00622          it != myServerShutdownCBList.end(); 
00623          ++it)
00624       (*it)->invoke();
00625     myCallbackMutex.unlock();
00626   }
00628   else if (myState == STATE_OPENED_SOCKET && 
00629       packet->getCommand() == ArServerCommands::INTRODUCTION)
00630   {
00631     myDataMutex.lock();
00632     // first read the data from the packet
00633     packet->bufToStr(buf, 512);
00634     myServerReportedUdpPort = packet->bufToUByte2();
00635     if (!myQuiet)
00636       ArLog::log(ArLog::Verbose, "Connection to version %s with udp port %u",
00637                buf, myServerReportedUdpPort);
00638     // set our expected port (its okay if its otherwise)
00639     myUdpSin.sin_port = ArSocket::hostToNetOrder(myServerReportedUdpPort);
00640     // get the keys
00641     myAuthKey = packet->bufToUByte4();
00642     myIntroKey = packet->bufToUByte4();
00643     packet->bufToStr(passwordKey, sizeof(passwordKey));
00644     // introduce ourself normally via tcp
00645     retPacket.empty();
00646     retPacket.setCommand(ArClientCommands::INTRODUCTION);
00647     retPacket.uByte2ToBuf(myUdpPort);
00648     retPacket.strToBuf(myUser.c_str());
00649     // old simple cleartext way
00650     //retPacket.strToBuf(myPassword.c_str());
00651     md5_state_t md5State;
00652     unsigned char md5Digest[16];
00653     
00654     md5_init(&md5State);
00655     md5_append(&md5State, (unsigned char *)myServerKey.c_str(), 
00656                myServerKey.size());
00657     md5_append(&md5State, (unsigned char *)passwordKey, strlen(passwordKey));
00658     md5_append(&md5State, (unsigned char *)myPassword.c_str(), 
00659                myPassword.size());
00660     md5_finish(&md5State, md5Digest);
00661 
00662     retPacket.dataToBuf((const char *)md5Digest, 16);
00663     myPassword = "";
00664     bool tcpOnlyFrom = myTcpOnlyFrom;
00665     myDataMutex.unlock();
00666     if (tcpOnlyFrom)
00667     {
00668       retPacket.empty();
00669       retPacket.setCommand(ArClientCommands::TCP_ONLY);
00670       sendPacketTcp(&retPacket);
00671     }
00672     sendPacketTcp(&retPacket);
00673     internalSwitchState(STATE_EXCHANGED_INTROS);
00674   }
00675   // if we're not at opened socket and got an intro somethings horribly wrong
00676   else if (myState != STATE_OPENED_SOCKET && 
00677       packet->getCommand() == ArServerCommands::INTRODUCTION)
00678   {
00679     if (!myQuiet)
00680       ArLog::log(ArLog::Terse, "ArClientBase: introduction received when not in STATE_OPENED_SOCKET");
00681     return;
00682   }
00683   // if we're at opened socket and received something other than intro
00684   // then somethings horribly wrong
00685   else if (myState == STATE_OPENED_SOCKET && 
00686       packet->getCommand() != ArServerCommands::INTRODUCTION)
00687   {
00688     if (!myQuiet)
00689       ArLog::log(ArLog::Terse, "ArClientBase: packet other than introduction received when in STATE_OPENED_SOCKET");
00690     return;
00691   }
00692   // if we've exchanged intros and are waiting for connection or rejection
00693   else if (myState == STATE_EXCHANGED_INTROS && 
00694            packet->getCommand() == ArServerCommands::CONNECTED)
00695   {
00696     if (!myQuiet)
00697       ArLog::log(ArLog::Terse, "Client now connected to server.");
00698     internalSwitchState(STATE_WAITING_LIST);
00699     // introduce ourself via udp
00700     retPacket.empty();
00701     retPacket.setCommand(ArClientCommands::UDP_INTRODUCTION);
00702     myDataMutex.lock();
00703     retPacket.uByte4ToBuf(myAuthKey);
00704     myDataMutex.unlock();
00705     sendPacketUdp(&retPacket);
00706     return;
00707   }
00708   // if we've received a connected and aren't at exchanging intros
00709   else if (packet->getCommand() == ArServerCommands::CONNECTED)
00710   {
00711     ArLog::log(ArLog::Terse, 
00712  "ArClientBase:: connected packet received not during STATE_EXCHANGED_INTROS");
00713     return;
00714   }
00715   // if we're exchanging intros and were rejected
00716   else if (myState != STATE_CONNECTED &&
00717            packet->getCommand() == ArServerCommands::REJECTED)
00718   {
00719     myRejected = packet->bufToByte2();
00720     packet->bufToStr(myRejectedString, sizeof(myRejectedString));
00721     if (!myQuiet)
00722     {
00723       if (myRejected == 1)
00724         ArLog::log(ArLog::Normal, 
00725                    "Server rejected connection because of bad user/password");
00726       else if (myRejected == 2)
00727         ArLog::log(ArLog::Normal, 
00728                    "Server rejected connection since it is using the centralserver at %s", 
00729                    myRejectedString);
00730       else
00731         ArLog::log(ArLog::Normal, 
00732                    "Server rejected connection for unknown reason %d '%s'",
00733                    myRejected, myRejectedString);
00734     }
00735       
00736     internalSwitchState(STATE_REJECTED);
00737     return;
00738   }
00739   // if we received rejected and aren't at exchanging intros
00740   else if (packet->getCommand() == ArServerCommands::REJECTED)
00741   {
00742     ArLog::log(ArLog::Terse, 
00743                "ArClientBase:: rejected packet received after connected");
00744     return;
00745   }
00746   // if we're waiting for our list and get it we're connected
00747   else if (myState == STATE_WAITING_LIST &&
00748            packet->getCommand() == ArServerCommands::LIST)
00749   {
00750     internalSwitchState(STATE_CONNECTED);
00751     myDataMutex.lock();
00752     md5_state_t md5State;
00753     
00754     md5_init(&md5State);
00755     md5_append(&md5State, (unsigned char *)&myAuthKey, sizeof(myAuthKey));
00756     md5_append(&md5State, (unsigned char *)&myIntroKey, sizeof(myIntroKey));
00757     long rand = ArMath::random();
00758     md5_append(&md5State, (unsigned char *)&rand, sizeof(rand));
00759     unsigned int time = ArUtil::getTime();
00760     md5_append(&md5State, (unsigned char *)&time, sizeof(time));
00761 
00762     md5_finish(&md5State, myClientKey);
00763     myDataMutex.unlock();
00764     myMapsMutex.lock();
00765     buildList(packet);
00766     myMapsMutex.unlock();
00767     return;
00768   }
00769   // see if we got any lists when not waiting for them
00770   else if (packet->getCommand() == ArServerCommands::LIST ||
00771            packet->getCommand() == ArServerCommands::LISTSINGLE || 
00772            packet->getCommand() == ArServerCommands::LISTARGRET ||
00773            packet->getCommand() == ArServerCommands::LISTARGRETSINGLE ||
00774            packet->getCommand() == ArServerCommands::LISTGROUPANDFLAGS ||
00775            packet->getCommand() == ArServerCommands::LISTGROUPANDFLAGSSINGLE)
00776   {
00777     myMapsMutex.lock();
00778     buildList(packet);
00779     myMapsMutex.unlock();
00780     return;
00781   }
00782   // if we're in exhanged intros and receive a packet not for that state
00783   else if (myState == STATE_EXCHANGED_INTROS && 
00784            packet->getCommand() != ArServerCommands::CONNECTED && 
00785            packet->getCommand() != ArServerCommands::REJECTED)
00786   {
00787     ArLog::log(ArLog::Terse, "ArClientBase: we're in STATE_EXCHANGE_INTROS and received something other than connected or rejected.");
00788     return;
00789   }
00790   // if we're connected and got a udp confirmed packet then everything is good
00791   else if (myState == STATE_CONNECTED && 
00792            packet->getCommand() == ArServerCommands::UDP_CONFIRMATION)
00793   {
00794     if (!myQuiet)
00795       ArLog::log(ArLog::Verbose, 
00796                  "Clients udp connection to server confirmed.");
00797     myDataMutex.lock();
00798     myUdpConfirmedTo = true;
00799     myDataMutex.unlock();
00800     return;
00801   }
00802   // if we're not connected and got a udp confirmation it means
00803   // something is wrong
00804   else if (packet->getCommand() == ArServerCommands::UDP_CONFIRMATION)
00805   {
00806     ArLog::log(ArLog::Terse, 
00807         "ArClientBase: Udp Confirmation received when not in STATE_CONNECTED");
00808     return;
00809   }
00810   // if we're connected and got a tcp only packet then everything is good
00811   else if (myState == STATE_CONNECTED && 
00812            packet->getCommand() == ArServerCommands::TCP_ONLY)
00813   {
00814     if (!myQuiet)
00815       ArLog::log(ArLog::Normal, "Client told to only use tcp.");
00816     myDataMutex.lock();
00817     myTcpOnlyTo = true;
00818     myDataMutex.unlock();
00819     return;
00820   }
00821   // if none of the above were triggered its just a normal packet
00822   else if (myState == STATE_CONNECTED)
00823   {
00824     std::map<unsigned int, ArClientData *>::iterator it;
00825     ArClientData *clientData;
00826     // see if we have the command
00827     myMapsMutex.lock();
00828     if ((it = myIntDataMap.find(packet->getCommand())) == myIntDataMap.end())
00829     {
00830       myMapsMutex.unlock();
00831       ArLog::log(ArLog::Terse, 
00832                  "ArClientBase got packet for %d which doesn't exist, packet was %d long", 
00833                  packet->getCommand(), packet->getLength());
00834       packet->log();
00835       int ijk;
00836       ArLog::log(ArLog::Terse, "Packet: ");
00837       for (ijk = 0; ijk < packet->getLength(); ijk++)
00838         ArLog::log(ArLog::Terse, " %d ", 
00839                    (unsigned char) packet->getBuf()[ijk]);
00840     }
00841     else
00842       myMapsMutex.unlock();
00843 
00844     clientData = (*it).second;
00845     if (clientData == NULL)
00846     {
00847       ArLog::log(ArLog::Terse,
00848                  "ArClientBase: null client data for command %d", 
00849                  packet->getCommand());    
00850       return;
00851     }
00852     
00853     clientData->lockFunctorList();
00854     if (clientData->getFunctorList()->begin() == 
00855         clientData->getFunctorList()->end())
00856     {
00857       ArLog::log(ArLog::Verbose, 
00858                  "ArClientBase: No functor to handle command %d",
00859                  packet->getCommand());
00860       clientData->unlockFunctorList();
00861       return;
00862     }
00863     else
00864     {
00865       std::list<ArFunctor1<ArNetPacket *> *>::const_iterator it;
00866       ArFunctor1<ArNetPacket *> *functor;
00867       for (it = clientData->getFunctorList()->begin(); 
00868            it != clientData->getFunctorList()->end();
00869            it++)
00870       {
00871         packet->resetRead();
00872         functor = (*it);
00873         functor->invoke(packet);
00874       }
00875       clientData->unlockFunctorList();
00876       trackPacketReceived(packet, tcp);
00877         
00878     }
00879     
00880 
00881   }
00882   else
00883   {
00884           //packet->bufToStr(&str);
00885     //packet->printHex();
00886     ArLog::log(ArLog::Verbose, "bogus packet of %u command %d long (probably after close)", 
00887                packet->getCommand(),  packet->getLength());
00888   }
00889   //sendPacketTcp(packet);
00890   
00891 }
00892 
00893 void ArClientBase::buildList(ArNetPacket *packet)
00894 {
00895   ArClientData *clientData;
00896   unsigned int listLen;
00897   unsigned int i;
00898   unsigned int command;
00899   char name[512];
00900   char description[512];
00901   char argDesc[512];
00902   char retDesc[512];
00903   char commandGroup[512];
00904   char dataFlags[512];
00905 
00906   // if its a single list snag it and run
00907   if (packet->getCommand() == ArServerCommands::LISTSINGLE)
00908   {
00909     command = packet->bufToUByte2();
00910     packet->bufToStr(name, sizeof(name));
00911     packet->bufToStr(description, sizeof(description));
00912     clientData = new ArClientData(name, description, command, NULL);
00913     ArLog::log(ArLog::Verbose, "ArClientBase: new entry number %d for data %s with description %s", command, name, description);
00914     if (myIntDataMap.find(command) != myIntDataMap.end())
00915       ArLog::log(ArLog::Normal, "ArClientBase: is already an entry for number %d as data %d\n, overwriting", command, myIntDataMap[command]->getName());
00916     myNameIntMap[name] = command;
00917     myIntDataMap[command] = clientData;
00918     return;
00919   }
00920   else if (packet->getCommand() == ArServerCommands::LIST)
00921   {
00922     myReceivedDataList = true;
00923     listLen = packet->bufToUByte2();
00924     // otherwise loop and read them all
00925     for (i = 0; i < listLen; i++)
00926     {
00927       command = packet->bufToUByte2();
00928       packet->bufToStr(name, sizeof(name));
00929       packet->bufToStr(description, sizeof(description));
00930       clientData = new ArClientData(name, description, command, NULL);
00931       ArLog::log(ArLog::Verbose, "ArClientBase: new entry number %d for data %s with description %s", command, name, description);
00932       if (myIntDataMap.find(command) != myIntDataMap.end() && 
00933           strcmp(myIntDataMap[command]->getName(), name))
00934         ArLog::log(ArLog::Normal, "ArClientBase: is already an entry for number %d as data %d\n, overwriting", command, myIntDataMap[command]->getName());
00935       myNameIntMap[name] = command;
00936       myIntDataMap[command] = clientData;
00937     }
00938     return;
00939   }
00940   // if its a single list snag it and run
00941   else if (packet->getCommand() == ArServerCommands::LISTARGRETSINGLE)
00942   {
00943     command = packet->bufToUByte2();
00944     clientData = myIntDataMap[command];
00945     if (clientData == NULL)
00946     {
00947       ArLog::log(ArLog::Normal, 
00948                  "ArClientBase::buildList: Unknown command %s %d", 
00949                  getName(packet->getCommand(), true), packet->getCommand());
00950       return;
00951     }
00952     packet->bufToStr(argDesc, sizeof(argDesc));
00953     packet->bufToStr(retDesc, sizeof(retDesc));
00954     clientData->setArgRetDescs(argDesc, retDesc);
00955     return;
00956   }
00957   else if (packet->getCommand() == ArServerCommands::LISTARGRET)
00958   {
00959     myReceivedArgRetList = true;
00960     listLen = packet->bufToUByte2();
00961     // otherwise loop and read them all
00962     for (i = 0; i < listLen; i++)
00963     {
00964       command = packet->bufToUByte2();
00965       clientData = myIntDataMap[command];
00966       if (clientData == NULL)
00967       {
00968         ArLog::log(ArLog::Normal, 
00969                    "ArClientBase::buildList: Unknown command %s %d", 
00970                    getName(packet->getCommand(), true), packet->getCommand());
00971   // KMC Need to do something here because otherwise it blows up on 
00972   // the setArgRetDescs call below...
00973        return;
00974       }
00975       packet->bufToStr(argDesc, sizeof(argDesc));
00976       packet->bufToStr(retDesc, sizeof(retDesc));
00977       clientData->setArgRetDescs(argDesc, retDesc);
00978     }
00979     return;
00980   }
00981   // if its a single list snag it and run
00982   else if (packet->getCommand() == ArServerCommands::LISTGROUPANDFLAGSSINGLE)
00983   {
00984     command = packet->bufToUByte2();
00985     clientData = myIntDataMap[command];
00986     if (clientData == NULL)
00987     {
00988       ArLog::log(ArLog::Normal, 
00989                  "ArClientBase::buildList: Unknown command %s %d", 
00990                  getName(packet->getCommand(), true), packet->getCommand());
00991       return;
00992     }
00993     packet->bufToStr(commandGroup, sizeof(commandGroup));
00994     packet->bufToStr(dataFlags, sizeof(dataFlags));
00995     clientData->setCommandGroup(commandGroup);
00996     clientData->addDataFlags(dataFlags);
00997     return;
00998   }
00999   else if (packet->getCommand() == ArServerCommands::LISTGROUPANDFLAGS)
01000   {
01001     myReceivedGroupAndFlagsList = true;
01002     listLen = packet->bufToUByte2();
01003     // otherwise loop and read them all
01004     for (i = 0; i < listLen; i++)
01005     {
01006       command = packet->bufToUByte2();
01007       clientData = myIntDataMap[command];
01008       if (clientData == NULL)
01009       {
01010         ArLog::log(ArLog::Normal, 
01011                    "ArClientBase::buildList: Unknown command %s %d", 
01012                    getName(packet->getCommand(), true), packet->getCommand());
01013   // KMC Need to do something here because otherwise it blows up on 
01014   // the setArgRetDescs call below...
01015        return;
01016       }
01017       packet->bufToStr(commandGroup, sizeof(commandGroup));
01018       packet->bufToStr(dataFlags, sizeof(dataFlags));
01019       clientData->setCommandGroup(commandGroup);
01020       clientData->addDataFlags(dataFlags);
01021     }
01022     return;
01023   }
01024   else
01025   {
01026     ArLog::log(ArLog::Terse, 
01027                "ArClientBase::buildList: Unhandled packet type %s %d", 
01028                getName(packet->getCommand(), true), packet->getCommand());
01029   }
01030 }
01031 
01032 AREXPORT void ArClientBase::processPacketUdp(ArNetPacket *packet,
01033                                  struct sockaddr_in *sin)
01034 {
01035   unsigned char *bytes = (unsigned char *)&sin->sin_addr.s_addr;
01036   long introKey;
01037   ArNetPacket retPacket;
01038 
01039   myDataMutex.lock();
01040   myLastPacketReceived.setToNow();
01041   // see if its an intro packet and we're connected (or could be but
01042   // not yet know it)
01043   if ((myState == STATE_CONNECTED || myState == STATE_EXCHANGED_INTROS ||
01044       myState == STATE_WAITING_LIST) && 
01045       packet->getCommand() == ArServerCommands::UDP_INTRODUCTION)
01046   {
01047     // see if we've already confirmed the UDP
01048     if (myUdpConfirmedFrom)
01049     {
01050       myDataMutex.unlock();
01051       return;
01052     }
01053     introKey = packet->bufToByte4();
01054     if (myIntroKey != introKey)
01055     {
01056       ArLog::log(ArLog::Terse, 
01057                  "Udp introduction packet received with wrong introKey");
01058       myDataMutex.unlock();
01059       return;
01060     }
01061     if (myServerReportedUdpPort != ArSocket::netToHostOrder(sin->sin_port))
01062       ArLog::log(ArLog::Verbose,
01063       "ArClientBase: ports don't match, said from server %d and given was %d",
01064              myServerReportedUdpPort, ArSocket::netToHostOrder(sin->sin_port));
01065     myUdpSin.sin_port = sin->sin_port;
01066     myUdpConfirmedFrom = true;
01067     // now confirm to the server we got the UDP packet
01068     retPacket.empty();
01069     retPacket.setCommand(ArClientCommands::UDP_CONFIRMATION);
01070     if (!myQuiet)
01071       ArLog::log(ArLog::Normal, "Server connected to us on udp port %d", 
01072                  ArSocket::netToHostOrder(myUdpSin.sin_port));
01073     myDataMutex.unlock();
01074     sendPacketTcp(&retPacket);
01075     return;
01076   }
01077   // if we receive an intro packet but aren't connected
01078   else if (packet->getCommand() == ArServerCommands::UDP_INTRODUCTION)
01079   {
01080     ArLog::log(ArLog::Terse, 
01081                "Udp introduction packet received while not connected");
01082     myDataMutex.unlock();
01083     return;
01084   }
01085   // if its not an intro, make sure it matchs our server
01086   else if (myUdpSin.sin_port == sin->sin_port &&
01087         myUdpSin.sin_addr.s_addr == sin->sin_addr.s_addr)
01088   {
01089     // TODO make this reject them if they're not in the user area
01090     myDataMutex.unlock();
01091     processPacket(packet, false);
01092     myDataMutex.lock();
01093   }
01094   // if it doesn't warn about it
01095   else
01096   {
01097     ArLog::log(ArLog::Normal, "Bogus UDP packet from %d.%d.%d.%d %d", 
01098                bytes[0], bytes[1], bytes[2], bytes[3], 
01099                ArSocket::netToHostOrder(sin->sin_port));
01100   }
01101   myDataMutex.unlock();
01102 }
01103 
01104 void ArClientBase::internalSwitchState(ClientState state)
01105 {
01106   myState = state;
01107   myStateStarted.setToNow();
01108 }
01109 
01128 AREXPORT bool ArClientBase::addHandler(const char *name, 
01129                                        ArFunctor1 <ArNetPacket *> *functor)
01130 {
01131   if (name == NULL) {
01132    ArLog::log(ArLog::Normal, "ArClientBase::addHandler: Cannot add NULL name");
01133    return false;
01134   }
01135   ArClientData *clientData;
01136   // see if we have this data
01137   myMapsMutex.lock();
01138   if (myNameIntMap.find(name) == myNameIntMap.end())
01139   {
01140     ArLog::log(ArLog::Normal, "ArClientBase::addHandler: There is no data by the name \"%s\" to handle", name);
01141     myMapsMutex.unlock();
01142     return false;
01143   }
01144   // since we have the data get the pointer to it
01145   clientData = myIntDataMap[myNameIntMap[name]];
01146   myMapsMutex.unlock();
01147 
01148   // make sure nothings gone wrong
01149   if (clientData == NULL)
01150   {
01151     ArLog::log(ArLog::Normal, "ArClientBase::addHandler: There was no clientData for data \"%s\"", name);
01152     return false;
01153   }
01154   clientData->lockFunctorList();
01155   // see if it already has a functor
01156   if (clientData->getFunctorList()->begin() != 
01157       clientData->getFunctorList()->end())
01158   {
01159     ArLog::log(ArLog::Verbose, "ArClientBase::addHandler: There is already a functor for data \"%s\", adding anyways", name);
01160     //return false;
01161   }
01162   // addthe functor
01163   clientData->addFunctor(functor);
01164   clientData->unlockFunctorList();
01165   return true;
01166 }
01167 
01184 AREXPORT bool ArClientBase::remHandler(const char *name, 
01185                                        ArFunctor1<ArNetPacket *> *functor)
01186 {
01187   ArClientData *clientData;
01188   myMapsMutex.lock();
01189   // see if we have this client data
01190   if (myNameIntMap.find(name) == myNameIntMap.end())
01191   {
01192     ArLog::log(ArLog::Normal, "ArClientBase::remHandler: There is no data \"%s\"", name);
01193     myMapsMutex.unlock();
01194     return false;
01195   }
01196   if ((clientData = myIntDataMap[myNameIntMap[name]]) == NULL)
01197   {
01198     ArLog::log(ArLog::Normal, "ArClientBase::remHandler: There was no client data for data \"%s\"", name);
01199     myMapsMutex.unlock();
01200     return false;
01201   }
01202   myMapsMutex.unlock();
01203   // set the functor to NULL
01204   clientData->lockFunctorList();
01205   clientData->remFunctor(functor);
01206   clientData->unlockFunctorList();
01207   return true;
01208 }
01209 
01210 
01217 AREXPORT unsigned int ArClientBase::findCommandFromName(const char *name)
01218 {
01219   std::map<std::string, unsigned int>::iterator it;
01220   unsigned int ret;
01221 
01222   myMapsMutex.lock();  
01223   if ((it = myNameIntMap.find(name)) == myNameIntMap.end())
01224   {
01225     ArLog::log(ArLog::Normal, 
01226                "Finding command for \"%s\" but no data with that name exists",
01227                name);
01228     myMapsMutex.unlock();  
01229     return 0;
01230   }
01231   ret = (*it).second;
01232   myMapsMutex.unlock();  
01233   return ret;
01234 }
01235 
01250 AREXPORT bool ArClientBase::request(const char *name, long mSec, 
01251                                     ArNetPacket *packet)
01252 {
01253   ArLog::log(ArLog::Verbose, 
01254              "%sRequesting data for \"%s\"", 
01255              myLogPrefix.c_str(), name);
01256   return requestByCommand(findCommandFromName(name), mSec, packet);
01257 }
01258 
01273 AREXPORT bool ArClientBase::requestByCommand(unsigned int command, 
01274                                              long mSec, ArNetPacket *packet)
01275 {
01276   ArNetPacket sending;
01277 
01278   sending.setCommand(ArClientCommands::REQUEST);
01279   sending.uByte2ToBuf(command);
01280   sending.byte4ToBuf(mSec);
01281   if (packet != NULL)
01282   {
01283     packet->resetRead();
01284     sending.dataToBuf(&packet->getBuf()[packet->getReadLength()],
01285                       packet->getLength() - packet->getReadLength());
01286   }
01287   return sendPacketTcp(&sending);
01288 }
01289 
01290 
01294 AREXPORT bool ArClientBase::requestStop(const char *name)
01295 {
01296   ArLog::log(ArLog::Verbose, 
01297              "%sRequesting stop data for \"%s\"", 
01298              myLogPrefix.c_str(), name);
01299   return requestStopByCommand(findCommandFromName(name));
01300 }
01301 
01305 AREXPORT bool ArClientBase::requestStopByCommand(unsigned int command)
01306 {
01307   ArNetPacket sending;
01308   sending.setCommand(ArClientCommands::REQUESTSTOP);
01309   sending.uByte2ToBuf(command);
01310   return sendPacketTcp(&sending);
01311 }
01312 
01313 
01325 AREXPORT bool ArClientBase::requestOnce(const char *name, 
01326                                         ArNetPacket *packet,
01327                                         bool quiet)
01328 {
01329   if (!quiet) {
01330     ArLog::log(ArLog::Verbose, 
01331                "%sRequesting data once for \"%s\"", myLogPrefix.c_str(), name);
01332   }
01333   return requestOnceByCommand(findCommandFromName(name), packet);
01334 }
01335 
01346 AREXPORT bool ArClientBase::requestOnceUdp(
01347         const char *name, ArNetPacket *packet)
01348 {
01349   ArLog::log(ArLog::Verbose, 
01350              "%sRequesting data once (UDP) for \"%s\"", 
01351              myLogPrefix.c_str(), name);
01352   return requestOnceByCommandUdp(findCommandFromName(name), packet);
01353 }
01354 
01364 AREXPORT bool ArClientBase::requestOnceByCommand(unsigned int command, 
01365                                                  ArNetPacket *packet)
01366 {
01367   if (packet != NULL)
01368   {
01369     packet->setCommand(command);
01370     return sendPacketTcp(packet);
01371   }
01372   else
01373   {
01374     ArNetPacket tempPacket;
01375     tempPacket.setCommand(command);
01376     return sendPacketTcp(&tempPacket);
01377   }
01378 }
01379 
01389 AREXPORT bool ArClientBase::requestOnceByCommandUdp(unsigned int command, 
01390                                                     ArNetPacket *packet)
01391 {
01392   if (packet != NULL)
01393   {
01394     packet->setCommand(command);
01395     if (!myTcpOnlyTo)
01396       return sendPacketUdp(packet);
01397     else
01398       return sendPacketTcp(packet);
01399   }
01400   else
01401   {
01402     ArNetPacket tempPacket;
01403     tempPacket.setCommand(command);
01404     if (!myTcpOnlyTo)
01405       return sendPacketUdp(&tempPacket);
01406     else
01407       return sendPacketTcp(&tempPacket);
01408   }
01409 }
01410 
01420 AREXPORT bool ArClientBase::requestOnceWithString(const char *name, 
01421                                                   const char *str)
01422 {
01423   std::map<std::string, unsigned int>::iterator it;
01424 
01425   myDataMutex.lock();
01426   if ((it = myNameIntMap.find(name)) == myNameIntMap.end())
01427   {
01428     ArLog::log(ArLog::Normal, 
01429                "Requesting data for \"%s\" but no data with that name exists",
01430                name);
01431     myDataMutex.unlock();
01432     return false;
01433   }
01434   myDataMutex.unlock();
01435   ArLog::log(ArLog::Verbose, 
01436              "%sRequesting data once for \"%s\"", 
01437              myLogPrefix.c_str(), name);
01438   
01439   ArNetPacket tempPacket;
01440   tempPacket.strToBuf(str);
01441   tempPacket.setCommand((*it).second);
01442   return sendPacketTcp(&tempPacket);
01443 }
01444 
01448 AREXPORT bool ArClientBase::dataExists(const char *name)
01449 {
01450   bool ret;
01451   myDataMutex.lock();
01452   ret = (myNameIntMap.find(name) != myNameIntMap.end());
01453   myDataMutex.unlock();
01454   return ret;
01455 }
01456 
01457 AREXPORT void ArClientBase::logDataList(void)
01458 {
01459   std::map<unsigned int, ArClientData *>::iterator it;
01460   ArClientData *clientData;
01461 
01462   myDataMutex.lock();
01463   ArLog::log(ArLog::Terse, "");
01464   ArLog::log(ArLog::Terse, "Available data:");
01465   for (it = myIntDataMap.begin(); it != myIntDataMap.end(); it++)
01466   {
01467     clientData = (*it).second;
01468     ArLog::log(ArLog::Terse, "");
01469     ArLog::log(ArLog::Verbose, "Number %d, %d functors", 
01470                clientData->getCommand(),
01471                clientData->getFunctorList()->size());
01472     ArLog::log(ArLog::Terse, "Data: %s", clientData->getName());
01473     ArLog::log(ArLog::Terse, "\tDescription: %s",
01474                clientData->getDescription());
01475     ArLog::log(ArLog::Terse, "\tArgument: %s",
01476                clientData->getArgumentDescription());
01477     ArLog::log(ArLog::Terse, "\tReturn: %s",
01478                clientData->getReturnDescription());
01479     ArLog::log(ArLog::Terse, "\tCommandGroup: %s",
01480                clientData->getCommandGroup());
01481     ArLog::log(ArLog::Terse, "\tDataFlags: %s",
01482                clientData->getDataFlagsString());
01483 
01484   }
01485   myDataMutex.unlock();
01486 }
01487 
01495 AREXPORT void ArClientBase::addDisconnectOnErrorCB(ArFunctor *functor, 
01496                                                    ArListPos::Pos position)
01497 {
01498   myCallbackMutex.lock();
01499   if (position == ArListPos::FIRST)
01500     myDisconnectOnErrorCBList.push_front(functor);
01501   else if (position == ArListPos::LAST)
01502     myDisconnectOnErrorCBList.push_back(functor);
01503   else
01504     ArLog::log(ArLog::Terse, 
01505                "ArClientBase::addDisconnectOnErrorCB: Invalid position");
01506   myCallbackMutex.unlock();
01507 }
01508 
01513 AREXPORT void ArClientBase::remDisconnectOnErrorCB(ArFunctor *functor)
01514 {
01515   myCallbackMutex.lock();
01516   myDisconnectOnErrorCBList.remove(functor);
01517   myCallbackMutex.unlock();
01518 }
01519 
01527 AREXPORT void ArClientBase::addServerShutdownCB(ArFunctor *functor, 
01528                                                    ArListPos::Pos position)
01529 {
01530   myCallbackMutex.lock();
01531   if (position == ArListPos::FIRST)
01532     myServerShutdownCBList.push_front(functor);
01533   else if (position == ArListPos::LAST)
01534     myServerShutdownCBList.push_back(functor);
01535   else
01536     ArLog::log(ArLog::Terse, 
01537                "ArClientBase::addServerShutdownCB: Invalid position");
01538   myCallbackMutex.unlock();
01539 }
01540 
01545 AREXPORT void ArClientBase::remServerShutdownCB(ArFunctor *functor)
01546 {
01547   myCallbackMutex.lock();
01548   myServerShutdownCBList.remove(functor);
01549   myCallbackMutex.unlock();
01550 }
01551 
01552 AREXPORT void ArClientBase::setTcpOnlyFromServer(void)
01553 {
01554   ArNetPacket packet;
01555 
01556   packet.setCommand(ArClientCommands::TCP_ONLY);
01557   sendPacketTcp(&packet);
01558   myDataMutex.lock();
01559   myTcpOnlyFrom = true;
01560   myDataMutex.unlock();
01561 }
01562 
01563 AREXPORT void ArClientBase::setTcpOnlyToServer(void)
01564 {
01565   myDataMutex.lock();
01566   myTcpOnlyTo = true;
01567   myDataMutex.unlock();
01568 }
01569 
01570 AREXPORT bool ArClientBase::isTcpOnlyFromServer(void)
01571 {
01572   bool ret;
01573   myDataMutex.lock();
01574   ret = myTcpOnlyFrom;
01575   myDataMutex.unlock();
01576   return ret;
01577 }
01578   
01579 AREXPORT bool ArClientBase::isTcpOnlyToServer(void)
01580 {
01581   bool ret;
01582   myDataMutex.lock();
01583   ret = myTcpOnlyTo;
01584   myDataMutex.unlock();
01585   return ret;
01586 }
01587 
01588 
01589 AREXPORT ArTime ArClientBase::getLastPacketReceived(void) 
01590 {
01591   ArTime ret;
01592   myDataMutex.lock();
01593   ret = myLastPacketReceived;
01594   myDataMutex.unlock();
01595   return ret;
01596 }
01597 
01598 AREXPORT const char *ArClientBase::getName(ArNetPacket *packet, 
01599                                            bool internalCall)
01600 {
01601   return getName(packet->getCommand(), internalCall);
01602 }
01603 
01604 AREXPORT const char *ArClientBase::getName(unsigned int command,
01605                                            bool internalCall)
01606 {
01607   const char *ret;
01608   if (!internalCall)
01609     myDataMutex.lock();
01610   std::map<unsigned int, ArClientData *>::iterator it;  
01611   if ((it = myIntDataMap.find(command)) == myIntDataMap.end())
01612     ret = NULL;
01613   else
01614     ret = (*it).second->getName(); 
01615   if (!internalCall)
01616     myDataMutex.unlock();
01617   return ret;
01618 }
01619 
01620 AREXPORT void ArClientBase::setServerKey(const char *serverKey, bool print)
01621 {
01622   myDataMutex.lock();
01623   myServerKey = serverKey;
01624   myDataMutex.unlock();
01625   if (print)
01626     ArLog::log(ArLog::Normal, "New server key set");
01627 }
01628 
01632 AREXPORT void ArClientBase::getClientKey(unsigned char key[16])
01633 {
01634   memcpy(key, myClientKey, 16);
01635 }
01636 
01637 AREXPORT const char *ArClientBase::getHost(void)
01638 {
01639   const char *ret;
01640   myDataMutex.lock();
01641   ret = myHost.c_str();
01642   myDataMutex.unlock();
01643   return ret;
01644 }
01645 
01646 void ArClientBase::trackPacketSent(ArNetPacket *packet, bool tcp)
01647 {
01648   myPacketTrackingMutex.lock();
01649   if (myTrackingSentMap.find(packet->getCommand()) == myTrackingSentMap.end())
01650     myTrackingSentMap[packet->getCommand()] = new Tracker;
01651 
01652   if (tcp)
01653   {
01654     myTrackingSentMap[packet->getCommand()]->myPacketsTcp++;
01655     myTrackingSentMap[packet->getCommand()]->myBytesTcp += packet->getLength();
01656   }
01657   else
01658   {
01659     myTrackingSentMap[packet->getCommand()]->myPacketsUdp++;
01660     myTrackingSentMap[packet->getCommand()]->myBytesUdp += packet->getLength();
01661   }
01662   myPacketTrackingMutex.unlock();
01663 }
01664 
01665 void ArClientBase::trackPacketReceived(ArNetPacket *packet, 
01666                                                   bool tcp)
01667 {
01668   myPacketTrackingMutex.lock();
01669   if (myTrackingReceivedMap.find(packet->getCommand()) == 
01670       myTrackingReceivedMap.end())
01671     myTrackingReceivedMap[packet->getCommand()] = new Tracker;
01672 
01673   if (tcp)
01674   {
01675     myTrackingReceivedMap[packet->getCommand()]->myPacketsTcp++;
01676     myTrackingReceivedMap[packet->getCommand()]->myBytesTcp += 
01677                                                   packet->getLength();
01678   }
01679   else
01680   {
01681     myTrackingReceivedMap[packet->getCommand()]->myPacketsUdp++;
01682     myTrackingReceivedMap[packet->getCommand()]->myBytesUdp += 
01683                                                   packet->getLength();
01684   }
01685   myPacketTrackingMutex.unlock();
01686 }
01687 
01688 AREXPORT void ArClientBase::logTracking(bool terse)
01689 {
01690   myDataMutex.lock();
01691   myPacketTrackingMutex.lock();
01692   std::map<unsigned int, Tracker *>::iterator it;
01693 
01694   unsigned int command;
01695   Tracker *tracker = NULL;
01696   long seconds;
01697 
01698   seconds = myTrackingStarted.secSince();
01699   if (seconds == 0)
01700     seconds = 1;
01701 
01702   const char *namePtr;
01703   char name[512];
01704 
01705   long packetsReceivedTcp = 0;
01706   long bytesReceivedTcp = 0;
01707   long packetsReceivedUdp = 0;
01708   long bytesReceivedUdp = 0;
01709 
01710   ArLog::log(ArLog::Terse, "");
01711   ArLog::log(ArLog::Terse, "Received tracking (active %d seconds):", seconds);
01712   for (it = myTrackingReceivedMap.begin(); it != myTrackingReceivedMap.end(); it++)
01713   {
01714     command = (*it).first;
01715     tracker = (*it).second;
01716 
01717     packetsReceivedTcp += tracker->myPacketsTcp;
01718     bytesReceivedTcp += tracker->myBytesTcp;
01719     packetsReceivedUdp += tracker->myPacketsUdp;
01720     bytesReceivedUdp += tracker->myBytesUdp;
01721 
01722     if ((namePtr = getName(command, true)) != NULL && namePtr[0] != '\0')
01723       snprintf(name, sizeof(name), "%s", namePtr);
01724     // if we're command 255 or less and there's no name its probably
01725     // one of the server commands we don't really need to track
01726     else if (command <= 255)
01727       continue;
01728     // we should know what the name of everything other then the
01729     // server command is, but print if we don't, just in case
01730     else
01731       snprintf(name, sizeof(name), "#%d", command);      
01732 
01733     if (terse)
01734     {
01735       ArLog::log(ArLog::Terse, 
01736                  "%35s %7ld pkts %10ld B %7ld B/sec", 
01737                  name, tracker->myPacketsTcp + tracker->myPacketsUdp, 
01738                  tracker->myBytesTcp + tracker->myBytesUdp,
01739                  ((tracker->myBytesTcp + tracker->myBytesUdp)/
01740                   seconds));
01741     }
01742     else
01743     {
01744       ArLog::log(ArLog::Terse, 
01745          "%35s %7ld tcp pkts %10ld tcp B %7ld tcp B/S %7ld udp pkts %10ld udp B %7ld udp B/s ", 
01746                  name, tracker->myPacketsTcp, tracker->myBytesTcp, 
01747                  tracker->myBytesTcp/seconds,
01748                  tracker->myPacketsUdp, tracker->myBytesUdp,
01749                  tracker->myBytesUdp/seconds);
01750     }
01751   }
01752   
01753   ArLog::log(ArLog::Terse, "");
01754   if (terse)
01755   {
01756     ArLog::log(ArLog::Terse, "%-35s %7ld pkts %10ld B %7ld B/sec", 
01757                "Total Received", packetsReceivedTcp + packetsReceivedUdp, 
01758                bytesReceivedTcp + bytesReceivedUdp,
01759                (bytesReceivedTcp + bytesReceivedUdp) / seconds);
01760   }
01761   else
01762   {
01763     ArLog::log(ArLog::Terse, "%-35s %7ld tcp pkts %10ld tcp B %7ld tcp B/S %7ld udp pkts %10ld udp B %7ld udp B/sec",  
01764                "Total Received", packetsReceivedTcp, bytesReceivedTcp, 
01765                bytesReceivedTcp/seconds, packetsReceivedUdp, bytesReceivedUdp, 
01766                bytesReceivedUdp/seconds);
01767     ArLog::log(ArLog::Terse, "%-35s %7ld tcp rcvs %10ld tcp B %7ld tcp B/S %7ld udp rcvs %10ld udp B %7ld udp B/sec",
01768                "Low level Sockets Received", myTcpSocket.getRecvs(), 
01769                myTcpSocket.getBytesRecvd(), 
01770                myTcpSocket.getBytesRecvd()/seconds, myUdpSocket.getRecvs(), 
01771                myUdpSocket.getBytesRecvd(), 
01772                myUdpSocket.getBytesRecvd()/seconds);
01773   }
01774 
01775   long packetsSentTcp = 0;
01776   long bytesSentTcp = 0;
01777   long packetsSentUdp = 0;
01778   long bytesSentUdp = 0;
01779 
01780   ArLog::log(ArLog::Terse, "");
01781   ArLog::log(ArLog::Terse, "Sent tracking (active %d seconds):", seconds);
01782   for (it = myTrackingSentMap.begin(); it != myTrackingSentMap.end(); it++)
01783   {
01784     command = (*it).first;
01785     tracker = (*it).second;
01786 
01787     packetsSentTcp += tracker->myPacketsTcp;
01788     bytesSentTcp += tracker->myBytesTcp;
01789     packetsSentUdp += tracker->myPacketsUdp;
01790     bytesSentUdp += tracker->myBytesUdp;
01791 
01792     if ((namePtr = getName(command, true)) != NULL && namePtr[0] != '\0')
01793       snprintf(name, sizeof(name), "%s", namePtr);
01794     // if we're command 255 or less and there's no name its probably
01795     // one of the server commands we don't really need to track
01796     else if (command <= 255)
01797       continue;
01798     // we should know what the name of everything other then the
01799     // server command is, but print if we don't, just in case
01800     else
01801       snprintf(name, sizeof(name), "#%d", command);      
01802 
01803     if (terse)
01804     {
01805       ArLog::log(ArLog::Terse, 
01806                  "%35s %7ld pkts %10ld B %7ld B/sec", 
01807                  name, tracker->myPacketsTcp + tracker->myPacketsUdp, 
01808                  tracker->myBytesTcp + tracker->myBytesUdp,
01809                  ((tracker->myBytesTcp + tracker->myBytesUdp)/
01810                   seconds));
01811     }
01812     else
01813     {
01814       ArLog::log(ArLog::Terse, 
01815          "%35s %7ld tcp pkts %10ld tcp B %7ld tcp B/S %7ld udp pkts %10ld udp B %7ld udp B/s ", 
01816                  name, tracker->myPacketsTcp, tracker->myBytesTcp, 
01817                  tracker->myBytesTcp/seconds,
01818                  tracker->myPacketsUdp, tracker->myBytesUdp,
01819                  tracker->myBytesUdp/seconds);
01820     }
01821   }
01822 
01823   ArLog::log(ArLog::Terse, "");
01824   if (terse)
01825   {
01826     ArLog::log(ArLog::Terse, "%-35s %7ld pkts %10ld B %7ld B/sec", 
01827                "Total Sent", packetsSentTcp + packetsSentUdp, 
01828                bytesSentTcp + bytesSentUdp,
01829                (bytesSentTcp + bytesSentUdp) / seconds);    
01830     ArLog::log(ArLog::Terse, "");
01831     ArLog::log(ArLog::Terse, "%-35s %7ld pkts %10ld B %7ld B/sec", 
01832                "Total Sent and Received", 
01833                (packetsSentTcp + packetsSentUdp + 
01834                 packetsReceivedTcp + packetsReceivedUdp),
01835                (bytesSentTcp + bytesSentUdp + 
01836                 bytesReceivedTcp + bytesReceivedUdp),
01837                (bytesSentTcp + bytesSentUdp + 
01838                 bytesReceivedTcp + bytesReceivedUdp) / seconds);
01839   }
01840   else
01841   {
01842     ArLog::log(ArLog::Terse, "%-35s %7ld tcp pkts %10ld tcp B %7ld tcp B/S %7ld udp pkts %10ld udp B %7ld udp B/sec",  
01843                "Total Sent", packetsSentTcp, bytesSentTcp, bytesSentTcp / seconds,
01844                packetsSentUdp, bytesSentUdp, bytesSentUdp / seconds);
01845     ArLog::log(ArLog::Terse, "%-35s %7ld tcp snds %10ld tcp B %7ld tcp B/S %7ld udp pkts %10ld udp B %7ld udp B/sec",
01846                "Low level Sockets Sent", myTcpSocket.getSends(), 
01847                myTcpSocket.getBytesSent(), 
01848                myTcpSocket.getBytesSent() / seconds, myUdpSocket.getSends(), 
01849                myUdpSocket.getBytesSent(), 
01850                myUdpSocket.getBytesSent() / seconds);
01851 
01852     ArLog::log(ArLog::Terse, "");
01853     ArLog::log(ArLog::Terse, "%-35s %7ld tcp pkts %10ld tcp B %7ld tcp B/S %7ld udp pkts %10ld udp B %7ld udp B/sec",  
01854                "Total Sent and Received", packetsSentTcp = packetsReceivedTcp, 
01855                bytesSentTcp + bytesReceivedTcp, 
01856                (bytesSentTcp + bytesReceivedTcp) / seconds,
01857                packetsSentUdp + packetsReceivedUdp, 
01858                bytesSentUdp + bytesReceivedUdp, 
01859                (bytesSentUdp + bytesReceivedUdp) / seconds);
01860   }
01861   ArLog::log(ArLog::Terse, "");
01862   myPacketTrackingMutex.unlock();
01863   myDataMutex.unlock();
01864 }
01865 
01866 
01867 AREXPORT void ArClientBase::resetTracking(void)
01868 {
01869   myPacketTrackingMutex.lock();
01870   
01871   std::map<unsigned int, Tracker *>::iterator it;
01872 
01873   myTrackingStarted.setToNow();
01874 
01875   for (it = myTrackingSentMap.begin(); it != myTrackingSentMap.end(); it++)
01876     (*it).second->reset();
01877 
01878   for (it = myTrackingReceivedMap.begin(); 
01879        it != myTrackingReceivedMap.end(); 
01880        it++)
01881     (*it).second->reset();
01882 
01883   myTcpSocket.resetTracking();
01884   myUdpSocket.resetTracking();
01885   myPacketTrackingMutex.unlock();
01886 }

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