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 "ArClientBase.h"
00029 #include "ArServerCommands.h"
00030 #include "ArClientCommands.h"
00031 #include "md5.h"
00032
00033
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
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
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
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
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
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
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
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
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
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
00408
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
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
00436
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
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
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
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
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
00639 myUdpSin.sin_port = ArSocket::hostToNetOrder(myServerReportedUdpPort);
00640
00641 myAuthKey = packet->bufToUByte4();
00642 myIntroKey = packet->bufToUByte4();
00643 packet->bufToStr(passwordKey, sizeof(passwordKey));
00644
00645 retPacket.empty();
00646 retPacket.setCommand(ArClientCommands::INTRODUCTION);
00647 retPacket.uByte2ToBuf(myUdpPort);
00648 retPacket.strToBuf(myUser.c_str());
00649
00650
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
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
00684
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
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
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
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
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
00740 else if (packet->getCommand() == ArServerCommands::REJECTED)
00741 {
00742 ArLog::log(ArLog::Terse,
00743 "ArClientBase:: rejected packet received after connected");
00744 return;
00745 }
00746
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
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
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
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
00803
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
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
00822 else if (myState == STATE_CONNECTED)
00823 {
00824 std::map<unsigned int, ArClientData *>::iterator it;
00825 ArClientData *clientData;
00826
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
00885
00886 ArLog::log(ArLog::Verbose, "bogus packet of %u command %d long (probably after close)",
00887 packet->getCommand(), packet->getLength());
00888 }
00889
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
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
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
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
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
00972
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
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
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
01014
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
01042
01043 if ((myState == STATE_CONNECTED || myState == STATE_EXCHANGED_INTROS ||
01044 myState == STATE_WAITING_LIST) &&
01045 packet->getCommand() == ArServerCommands::UDP_INTRODUCTION)
01046 {
01047
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
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
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
01086 else if (myUdpSin.sin_port == sin->sin_port &&
01087 myUdpSin.sin_addr.s_addr == sin->sin_addr.s_addr)
01088 {
01089
01090 myDataMutex.unlock();
01091 processPacket(packet, false);
01092 myDataMutex.lock();
01093 }
01094
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
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
01145 clientData = myIntDataMap[myNameIntMap[name]];
01146 myMapsMutex.unlock();
01147
01148
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
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
01161 }
01162
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
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
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
01725
01726 else if (command <= 255)
01727 continue;
01728
01729
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
01795
01796 else if (command <= 255)
01797 continue;
01798
01799
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 }