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

ArServerBase.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 "ArServerBase.h"
00029 #include "ArServerCommands.h"
00030 #include "ArClientCommands.h"
00031 
00032 
00033 AREXPORT ArServerBase::ArServerBase(bool addAriaExitCB, 
00034                                     const char * serverName) :
00035   myProcessPacketCB(this, &ArServerBase::processPacket),
00036   mySendUdpCB(this, &ArServerBase::sendUdp),
00037   myAriaExitCB(this, &ArServerBase::close),
00038   myGetFrequencyCB(this, &ArServerBase::getFrequency, 0, true)
00039 {
00040   if (serverName != NULL && serverName[0] > 0)
00041     myServerName = serverName;
00042   else
00043     myServerName = "ArNetServer";
00044   setThreadName("ArServerBase");
00045   myTcpPort = 0;
00046   myUdpPort = 0;
00047   myRejecting = 0;
00048   myOpened = false;
00049   myUdpReceiver.setProcessPacketCB(&myProcessPacketCB);
00050   myNextDataNumber = 256;
00051   myUserInfo = NULL;
00052   myAriaExitCB.setName("ArServerBaseExit");
00053   if (addAriaExitCB)
00054     Aria::addExitCallback(&myAriaExitCB, 20);
00055 }
00056 
00057 AREXPORT ArServerBase::~ArServerBase()
00058 {
00059   close();
00060 }
00061 
00070 AREXPORT bool ArServerBase::open(unsigned int port, const char *openOnIP)
00071 {
00072   myDataMutex.lock();
00073   myTcpPort = port;
00074 
00075   if (myTcpSocket.open(myTcpPort, ArSocket::TCP, openOnIP))
00076   {
00077     myTcpSocket.setLinger(0);
00078     myTcpSocket.setNonBlock();
00079   }
00080   else
00081   {
00082     myOpened = false;
00083     myDataMutex.unlock();
00084     return false;
00085   }
00086 
00087   if (myUdpSocket.create(ArSocket::UDP) &&
00088       myUdpSocket.findValidPort(myTcpPort, openOnIP) &&
00089       myUdpSocket.setNonBlock())
00090   {
00091  // not possible on udp?   myUdpSocket.setLinger(0);
00092     myUdpPort = ArSocket::netToHostOrder(myUdpSocket.inPort());
00093     myUdpReceiver.setSocket(&myUdpSocket);
00094     if (openOnIP != NULL)
00095       ArLog::log(ArLog::Normal, 
00096                  "%s started on tcp port %d and udp port %d on ip %s.", 
00097                  myServerName.c_str(), myTcpPort, myUdpPort, openOnIP);
00098     else
00099       ArLog::log(ArLog::Normal, "%s started on tcp port %d and udp port %d.", 
00100                  myServerName.c_str(), myTcpPort, myUdpPort);
00101   
00102   }
00103   else
00104   {
00105     myOpened = false;
00106     myTcpSocket.close();
00107     myDataMutex.unlock();
00108     return false;
00109   }
00110   myOpened = true;
00111   myDataMutex.unlock();
00112   return true;
00113 }
00114 
00115 AREXPORT void ArServerBase::close(void)
00116 {
00117   std::list<ArServerClient *>::iterator it;
00118   ArServerClient *client;
00119 
00120   myClientsMutex.lock();
00121   if (!myOpened)
00122   {
00123     myClientsMutex.unlock();
00124     return;
00125   }
00126 
00127   ArLog::log(ArLog::Normal, "Server shutting down.");
00128   myOpened = false;
00129   // now send off the client packets to shut down
00130   for (it = myClients.begin(); it != myClients.end(); ++it)
00131   {
00132     client = (*it);
00133     client->shutdown();
00134     printf("Sending shutdown\n");
00135   }
00136 
00137   ArUtil::sleep(10);
00138 
00139   while ((it = myClients.begin()) != myClients.end())
00140   {
00141     client = (*it);
00142     myClients.pop_front();
00143     delete client;
00144   }
00145   myTcpSocket.close();
00146   myUdpSocket.close();
00147   myClientsMutex.unlock();
00148 }
00149 
00150 void ArServerBase::acceptTcpSockets(void)
00151 {
00152   ArSocket socket;
00153 
00154   myClientsMutex.lock();
00155 
00156   // loop while we have new connections to make... we need to make a
00157   // udp auth key for any accepted sockets and send our introduction
00158   // to the client
00159   while (myTcpSocket.accept(&socket) && socket.getFD() >= 0)
00160   {
00161     finishAcceptingSocket(&socket, false);
00162   }
00163   myClientsMutex.unlock();
00164 }
00165 
00166 AREXPORT void ArServerBase::makeNewServerClientFromSocket(ArSocket *socket, 
00167                                                           bool doNotReject)
00168 {
00169   myDataMutex.lock();
00170   finishAcceptingSocket(socket, true, doNotReject);
00171   myDataMutex.unlock();
00172 }
00173 
00174 AREXPORT void ArServerBase::finishAcceptingSocket(ArSocket *socket, 
00175                                                   bool skipPassword, 
00176                                                   bool doNotReject)
00177 {
00178   ArServerClient *client;
00179   bool foundAuthKey;
00180   std::list<ArServerClient *>::iterator it;
00181   bool thisKeyBad;
00182   long authKey;
00183   long introKey;
00184   ArNetPacket packet;
00185   int iterations;
00186 
00187   ArLog::log(ArLog::Verbose, "New connection from %s", socket->getIPString());
00188   
00189   // okay, now loop until we find a key or until we've gone 10000
00190   // times (huge error but not worth locking up on)... basically
00191   // we're making sure that none of the current clients already have
00192   // this key... they should never have it if random is working
00193   // right... but...
00194   for (foundAuthKey = false, authKey = ArMath::random(), iterations = 0; 
00195        !foundAuthKey && iterations < 10000;
00196        iterations++, authKey = ArMath::random())
00197   {
00198     // see if any of the current clients have this authKey
00199     for (thisKeyBad = false, it = myClients.begin(); 
00200          !thisKeyBad && it != myClients.end();
00201          ++it)
00202     {
00203       if (authKey == (*it)->getAuthKey())
00204         thisKeyBad = true;
00205     }
00206     // if the key wasn't found above it means its clean, so we found
00207     // a good one and are done
00208     if (!thisKeyBad)
00209       foundAuthKey = true;
00210   }
00211   if (!foundAuthKey)
00212     authKey = 0;
00213   // now we pick an introKey which introduces the server to the client
00214   // this one isn't critical that it be unique though, so we just
00215   // set it straight out
00216   introKey = ArMath::random();
00217   std::string passwordKey;
00218   int numInPasswordKey = ArMath::random() % 100;
00219   int i;
00220   passwordKey = "";
00221   if (!skipPassword)
00222   {
00223     for (i = 0; i < numInPasswordKey; i++)
00224       passwordKey += '0' + ArMath::random() % ('z' - '0');
00225   }
00226   int reject;
00227   const char *rejectString;
00228   if (doNotReject)
00229   {
00230     reject = 0;
00231     rejectString = "";
00232   }
00233   else
00234   {
00235     reject = myRejecting;
00236     rejectString = myRejectingString.c_str();
00237   }
00238   client = new ArServerClient(socket, myUdpPort, authKey, introKey,
00239                               &mySendUdpCB, &myDataMap, 
00240                               passwordKey.c_str(), myServerKey.c_str(),
00241                               myUserInfo, reject, rejectString);
00242   // put the client onto our list of clients...
00243   myClients.push_front(client);
00244 }
00245 
00246 AREXPORT int ArServerBase::getNumClients(void)
00247 {
00248   int ret;
00249   myClientsMutex.lock();
00250   ret = myClients.size();
00251   myClientsMutex.unlock();
00252   return ret;
00253 }
00254 
00255 AREXPORT void ArServerBase::run(void)
00256 {
00257   runInThisThread();
00258 }
00259 
00260 AREXPORT void ArServerBase::runAsync(void)
00261 {
00262   create();
00263 }
00264 
00265 AREXPORT void *ArServerBase::runThread(void *arg)
00266 {
00267   threadStarted();
00268   while (myRunning)
00269   {
00270     loopOnce();
00271     ArUtil::sleep(1);
00272   }
00273   close();
00274   return NULL;
00275 }
00276 
00277 
00288 AREXPORT bool ArServerBase::broadcastPacketTcp(ArNetPacket *packet, 
00289                                                const char *name)
00290 {
00291   return broadcastPacketTcpWithExclusion(packet, name, NULL);
00292 }
00293 
00304 AREXPORT bool ArServerBase::broadcastPacketTcpWithExclusion(
00305         ArNetPacket *packet, const char *name, ArServerClient *excludeClient)
00306 {
00307   // first find our number so each client doesn't have to
00308   std::map<unsigned int, ArServerData *>::iterator it;  
00309   unsigned int command;
00310   
00311   myDataMutex.lock();  
00312   for (it = myDataMap.begin(); it != myDataMap.end(); it++)
00313   {
00314     if (!strcmp((*it).second->getName(), name))
00315       command = (*it).second->getCommand();
00316   }  
00317   if (command == 0)
00318   {
00319     ArLog::log(ArLog::Terse, "ArServerBase::broadcastPacket: no command by name of \"%s\"", name);
00320     myDataMutex.unlock();  
00321     return false;
00322   }
00323   myDataMutex.unlock();  
00324   return broadcastPacketTcpByCommandWithExclusion(packet, command, 
00325                                                   excludeClient);
00326 }
00327 
00339 AREXPORT bool ArServerBase::broadcastPacketTcpByCommand(
00340         ArNetPacket *packet, unsigned int command)
00341 {
00342   return broadcastPacketTcpByCommandWithExclusion(packet, command, NULL);
00343 }
00344 
00355 AREXPORT bool ArServerBase::broadcastPacketTcpByCommandWithExclusion(
00356         ArNetPacket *packet, unsigned int command, 
00357         ArServerClient *excludeClient)
00358 {
00359   std::list<ArServerClient *>::iterator lit;
00360 
00361   ArNetPacket emptyPacket;
00362 
00363   myClientsMutex.lock();  
00364   emptyPacket.empty();
00365 
00366   if (!myOpened)
00367   {
00368     ArLog::log(ArLog::Verbose, "ArServerBase::broadcastPacket: server not open to send packet.");
00369     myClientsMutex.unlock();  
00370     return false;
00371   }
00372 
00373   if (packet == NULL)
00374     packet = &emptyPacket;
00375 
00376   packet->setCommand(command);
00377   for (lit = myClients.begin(); lit != myClients.end(); ++lit)
00378   {
00379     if (excludeClient == NULL || (*lit) != excludeClient)
00380       (*lit)->broadcastPacketTcp(packet);
00381   }
00382 
00383   myClientsMutex.unlock();  
00384   return true;
00385 }
00386 
00398 AREXPORT bool ArServerBase::broadcastPacketUdp(ArNetPacket *packet, 
00399                                                const char *name)
00400 {
00401   return broadcastPacketUdpWithExclusion(packet, name, NULL);
00402 }
00403 
00415 AREXPORT bool ArServerBase::broadcastPacketUdpWithExclusion(
00416         ArNetPacket *packet, const char *name, ArServerClient *excludeClient)
00417 {
00418   // first find our number so each client doesn't have to
00419   std::map<unsigned int, ArServerData *>::iterator it;  
00420   unsigned int command = 0;
00421 
00422   myDataMutex.lock();  
00423   for (it = myDataMap.begin(); it != myDataMap.end(); it++)
00424   {
00425     if (!strcmp((*it).second->getName(), name))
00426       command = (*it).second->getCommand();
00427   }  
00428   if (command == 0)
00429   {
00430     ArLog::log(ArLog::Terse, "ArServerBase::broadcastPacket: no command by name of \"%s\"", name);
00431     myDataMutex.unlock();  
00432     return false;
00433   }
00434   myDataMutex.unlock();  
00435   return broadcastPacketUdpByCommandWithExclusion(packet, command, 
00436                                                   excludeClient);
00437 }
00438 
00450 AREXPORT bool ArServerBase::broadcastPacketUdpByCommand(
00451         ArNetPacket *packet, unsigned int command)
00452 {
00453   return broadcastPacketUdpByCommandWithExclusion(packet, command, NULL);
00454 }
00455 
00466 AREXPORT bool ArServerBase::broadcastPacketUdpByCommandWithExclusion(
00467         ArNetPacket *packet, unsigned int command,
00468         ArServerClient *excludeClient)
00469 {
00470   std::list<ArServerClient *>::iterator lit;
00471   ArNetPacket emptyPacket;
00472 
00473   myClientsMutex.lock();    
00474   emptyPacket.empty();
00475 
00476   if (!myOpened)
00477   {
00478     ArLog::log(ArLog::Verbose, "ArServerBase::broadcastPacket: server not open to send packet.");
00479     myClientsMutex.unlock();  
00480     return false;
00481   }
00482 
00483   if (packet == NULL)
00484     packet = &emptyPacket;
00485 
00486   packet->setCommand(command);
00487   for (lit = myClients.begin(); lit != myClients.end(); ++lit)
00488   {
00489     if (excludeClient == NULL || (*lit) != excludeClient)
00490       (*lit)->broadcastPacketUdp(packet);
00491   }
00492   myClientsMutex.unlock();  
00493   return true;
00494 }
00495 
00502 AREXPORT unsigned int ArServerBase::findCommandFromName(const char *name)
00503 {
00504   // first find our number so each client doesn't have to
00505   std::map<unsigned int, ArServerData *>::iterator it;  
00506   unsigned int num = 0;
00507   myDataMutex.lock();    
00508 
00509   for (it = myDataMap.begin(); it != myDataMap.end(); it++)
00510   {
00511     if (!strcmp((*it).second->getName(), name))
00512       num = (*it).second->getCommand();
00513   }  
00514   if (num == 0)
00515   {
00516     ArLog::log(ArLog::Verbose, "ArServerBase::findCommandFromName: no command by name of \"%s\"", name);
00517     myDataMutex.unlock();  
00518     return 0;
00519   }
00520   myDataMutex.unlock();  
00521   return num;
00522 }
00523 
00531 AREXPORT void ArServerBase::loopOnce(void)
00532 {
00533   std::list<ArServerClient *>::iterator it;
00534   // for speed we'd use a list of iterators and erase, but for clarity
00535   // this is easier and this won't happen that often
00536   std::list<ArServerClient *> removeList;
00537   ArServerClient *client;
00538 
00539   myDataMutex.lock();  
00540   if (!myOpened)
00541   {
00542     myDataMutex.unlock();
00543     return;
00544   }
00545   myDataMutex.unlock();
00546   acceptTcpSockets();
00547 
00548   myUdpReceiver.readData();
00549 
00550   // need a recursive lock before we can lock here but we should be
00551   //okay without a lock here (and have been for ages)
00552   //myClientsMutex.lock(); first let the clients handle new data
00553   for (it = myClients.begin(); it != myClients.end(); ++it)
00554   {
00555     client = (*it);
00556     if (!client->tcpCallback())
00557     {
00558       removeList.push_front(client);
00559     }
00560   }
00561   while ((it = removeList.begin()) != removeList.end())
00562   {
00563     client = (*it);
00564     myClients.remove(client);
00565     for (std::list<ArFunctor1<ArServerClient*> *>::iterator rci = myClientRemovedCallbacks.begin();
00566          rci != myClientRemovedCallbacks.end();
00567          rci++) {
00568       if (*rci) {
00569         (*rci)->invoke(client);
00570       }
00571     }
00572 
00573     delete client;
00574     removeList.pop_front();
00575   }
00576   // now let the clients send off their packets
00577   for (it = myClients.begin(); it != myClients.end(); ++it)
00578   {
00579     client = (*it);
00580     client->handleRequests();
00581   }
00582   // need a recursive lock before we can lock here but we should be
00583   //okay without a lock here (and have been for ages)
00584   //myClientsMutex.unlock();
00585   myCycleCallbacksMutex.lock();
00586   // call cycle callbacks
00587   for(std::list<ArFunctor*>::const_iterator f = myCycleCallbacks.begin();
00588           f != myCycleCallbacks.end(); f++) 
00589   {
00590     if(*f) (*f)->invoke();
00591   }
00592   myCycleCallbacksMutex.unlock();
00593 }
00594 
00595 AREXPORT void ArServerBase::processPacket(ArNetPacket *packet, struct sockaddr_in *sin)
00596 {
00597   std::list<ArServerClient *>::iterator it;
00598   unsigned char *bytes = (unsigned char *)&sin->sin_addr.s_addr;
00599   ArServerClient *client;
00600   struct sockaddr_in *clientSin;
00601 
00602   myClientsMutex.lock();
00603   // if its a udp packet then see if we have its owner
00604   if (packet->getCommand() == ArClientCommands::UDP_INTRODUCTION)
00605   {
00606     long authKey;
00607     bool matched;
00608 
00609     authKey = packet->bufToUByte4();
00610     for (matched = false, it = myClients.begin();
00611          !matched && it != myClients.end(); ++it)
00612     {
00613       client = (*it);
00614       if (client->getAuthKey() == authKey)
00615       {
00616         packet->resetRead();
00617         client->processAuthPacket(packet, sin);
00618       }
00619     }
00620     myClientsMutex.unlock();
00621     return;
00622   }
00623 
00624   // it wasn't the introduction so handle it the normal way
00625 
00626   // walk through our list of clients and see if it was one of them,
00627   // if so return
00628   for (it = myClients.begin(); it != myClients.end(); ++it)
00629   {
00630     client = (*it);
00631     clientSin = client->getUdpAddress();
00632     if (clientSin->sin_port == sin->sin_port &&
00633         clientSin->sin_addr.s_addr == sin->sin_addr.s_addr)
00634     {
00635       client->processPacket(packet, false);
00636       myClientsMutex.unlock();
00637       return;
00638     }
00639   }
00640   // if it wasn't one of our clients it was from somewhere bogus
00641   printf("UDP Packet from bogus source %d.%d.%d.%d %d\n", bytes[0], 
00642          bytes[1], bytes[2], bytes[3], 
00643          ArSocket::netToHostOrder(sin->sin_port));
00644   myClientsMutex.unlock();
00645 }
00646 
00647 AREXPORT bool ArServerBase::sendUdp(ArNetPacket *packet, struct sockaddr_in *sin)
00648 {
00649   bool ret;
00650   // this doesn't lock since it should only be called from 
00651   ret = myUdpSocket.sendTo(packet->getBuf(), packet->getLength(), sin);
00652   return ret;
00653 }
00654 
00679 AREXPORT bool ArServerBase::addData(
00680         const char *name, const char *description,
00681         ArFunctor2<ArServerClient *, ArNetPacket *> * functor,
00682         const char *argumentDescription, const char *returnDescription, 
00683         const char *commandGroup, const char *dataFlags)
00684 {
00685   return addDataAdvanced(name, description, functor, argumentDescription, 
00686                   returnDescription, commandGroup, dataFlags);
00687 }
00688 
00713 AREXPORT bool ArServerBase::addDataAdvanced(
00714         const char *name, const char *description,
00715         ArFunctor2<ArServerClient *, ArNetPacket *> * functor,
00716         const char *argumentDescription, const char *returnDescription, 
00717         const char *commandGroup, const char *dataFlags,
00718         unsigned int advancedCommandNumber,
00719         ArFunctor2<long, unsigned int> *requestChangedFunctor, 
00720         ArFunctor2<ArServerClient *, ArNetPacket *> *requestOnceFunctor)
00721 {
00722   ArServerData *serverData;
00723   std::map<unsigned int, ArServerData *>::iterator it;
00724 
00725   myDataMutex.lock();
00726 
00727   //printf("%s %s\n", name, description);
00728   // if we already have one we can't do this
00729   for (it = myDataMap.begin(); it != myDataMap.end(); it++)
00730   {
00731     if (!strcmp((*it).second->getName(), name))
00732     {
00733       ArLog::log(ArLog::Verbose, "ArServerBase::addData: already have data for name \"%s\", could not add it.", name);
00734       myDataMutex.unlock();
00735       return false;
00736     }
00737   }
00738   ArLog::log(ArLog::Verbose, "ArServerBase::addData: name \"%s\" mapped to number %d", name, myNextDataNumber);
00739   if (advancedCommandNumber != 0)
00740   {
00741     if (advancedCommandNumber < myNextDataNumber)
00742     {
00743       ArLog::log(ArLog::Normal, "ArServerBase::addData: Advanced command number given for %s but the number is too low, it wasn't added", name);
00744       myDataMutex.unlock();
00745       return false;
00746     }
00747     else
00748       myNextDataNumber = advancedCommandNumber;
00749   }
00750   serverData = new ArServerData(name, description, myNextDataNumber,
00751                                 functor, argumentDescription, 
00752                                 returnDescription, commandGroup, dataFlags,
00753                                 &myGetFrequencyCB, requestChangedFunctor, 
00754                                 requestOnceFunctor);
00755   if (myAdditionalDataFlags.size() > 0)
00756     serverData->addDataFlags(myAdditionalDataFlags.c_str());
00757   myDataMap[myNextDataNumber] = serverData;
00758   myNextDataNumber++;
00759   myDataMutex.unlock();
00760   return true;
00761 }
00762 
00763 
00767 AREXPORT void ArServerBase::addCycleCallback(ArFunctor* functor)
00768 {
00769   myCycleCallbacksMutex.lock();
00770   myCycleCallbacks.push_back(functor);
00771   myCycleCallbacksMutex.unlock();
00772 }
00773 
00778 AREXPORT void ArServerBase::remCycleCallback(ArFunctor* functor)
00779 {
00780   myCycleCallbacksMutex.lock();
00781   myCycleCallbacks.remove(functor);
00782   myCycleCallbacksMutex.unlock();
00783 }
00784 
00789 AREXPORT void ArServerBase::addClientRemovedCallback(ArFunctor1<ArServerClient *> *functor)
00790 {
00791   myDataMutex.lock();
00792   myClientRemovedCallbacks.push_back(functor);
00793   myDataMutex.unlock();
00794 }
00795 
00800 AREXPORT void ArServerBase::remClientRemovedCallback(ArFunctor1<ArServerClient *> *functor)
00801 {
00802   myDataMutex.lock();
00803   myClientRemovedCallbacks.remove(functor);
00804   myDataMutex.unlock();
00805 }
00806 
00807 
00808 AREXPORT bool ArServerBase::loadUserInfo(const char *fileName,
00809                                          const char *baseDirectory)
00810 {
00811   if (myUserInfo != NULL)
00812   {
00813     delete myUserInfo;
00814     myUserInfo = NULL;
00815   }
00816   ArServerUserInfo *userInfo = new ArServerUserInfo;
00817   userInfo->setBaseDirectory(baseDirectory);
00818   if (!userInfo->readFile(fileName))
00819   {
00820     ArLog::log(ArLog::Terse, "ArServerBase::loadUserInfo: Could not load user info for %s", myServerName.c_str());
00821     delete userInfo;
00822     return false;
00823   }
00824   if (!userInfo->doNotUse())
00825   {
00826     ArLog::log(ArLog::Normal, "Loaded user information for %s",
00827                myServerName.c_str());
00828     myDataMutex.lock();
00829     myUserInfo = userInfo;
00830     myDataMutex.unlock();
00831   }
00832   else
00833   {
00834     ArLog::log(ArLog::Normal, 
00835                "Loaded user information for %s but not using it",
00836                myServerName.c_str());
00837     delete userInfo;
00838   }
00839   return true;
00840 }
00841 
00842 AREXPORT void ArServerBase::logUserInfo(void)
00843 {
00844   myDataMutex.lock();
00845   if (myUserInfo == NULL)
00846     ArLog::log(ArLog::Terse, 
00847                "No user name or password needed to connect to %s",
00848                myServerName.c_str());
00849   else
00850     myUserInfo->logUsers();
00851   myDataMutex.unlock();
00852 }
00853 
00859 AREXPORT void ArServerBase::logCommandGroups(void)
00860 {
00861   logCommandGroupsToFile(NULL);
00862 }
00863 
00867 AREXPORT void ArServerBase::logCommandGroupsToFile(const char *fileName)
00868 {
00869   std::map<unsigned int, ArServerData *>::iterator dit;
00870 
00871   std::multimap<std::string, std::string> groups;
00872   std::multimap<std::string, std::string>::iterator git;
00873 
00874   myDataMutex.lock();
00875   for (dit = myDataMap.begin(); dit != myDataMap.end(); dit++)
00876   {
00877     std::string group;
00878     std::string command;
00879     command = (*dit).second->getName();
00880     if ((*dit).second->getCommandGroup() == NULL)
00881       group = "";
00882     else
00883       group = (*dit).second->getCommandGroup();
00884     
00885     groups.insert(std::pair<std::string, std::string>(group, command));
00886   }
00887 
00888   FILE *file = NULL;
00889   if (fileName != NULL)
00890   {
00891     file = fopen(fileName, "w");
00892   }
00893 
00894   char descLine[10000];
00895   std::string line;
00896   std::string lastGroup;
00897   bool first = true;
00898   bool firstGroup = true;
00899   std::map<std::string, std::string>::iterator dIt; 
00900   std::string listOfGroups = "Groups";
00901 
00902   for (git = groups.begin(); git != groups.end(); git++)
00903   {
00904     if (ArUtil::strcasecmp((*git).first, lastGroup) != 0 || firstGroup)
00905     {
00906       if (!firstGroup)
00907       {
00908         if (file != NULL)
00909           fprintf(file, "%s", line.c_str());
00910         else
00911           ArLog::log(ArLog::Terse, "%s", line.c_str());
00912       }
00913       first = true;
00914       firstGroup = false;
00915       lastGroup = (*git).first;
00916       listOfGroups += " ";
00917       if (lastGroup.size() == 0)
00918         listOfGroups += "None";
00919       else
00920         listOfGroups += lastGroup;
00921     }
00922     if (first)
00923     {
00924       line = "CommandGroup ";
00925       if ((*git).first.size() == 0)
00926       {
00927         line += "None";
00928       }
00929       else
00930       {
00931         // output the groups description if therei s one
00932         if ((dIt = myGroupDescription.find((*git).first)) != 
00933             myGroupDescription.end())
00934           snprintf(descLine, sizeof(descLine), 
00935                    "CommandGroup %s has description %s", 
00936                    (*git).first.c_str(), (*dIt).second.c_str());
00937         else
00938           snprintf(descLine, sizeof(descLine), 
00939                    "CommandGroup %s has no description", 
00940                    (*git).first.c_str());
00941         if (file != NULL)
00942           fprintf(file, "%s\n", descLine);
00943         else
00944           ArLog::log(ArLog::Terse, "%s", descLine);
00945 
00946         line += (*git).first.c_str();
00947       }
00948       line += " is";
00949 
00950 
00951       }
00952     line += " ";
00953     line += (*git).second.c_str();
00954     first = false;
00955   }
00956   if (!firstGroup && !first)
00957   {
00958     if (file != NULL)
00959       fprintf(file, "%s\n", line.c_str());
00960     else
00961       ArLog::log(ArLog::Terse, "%s", line.c_str());
00962   }
00963   if (file != NULL)
00964     fprintf(file, "%s\n", listOfGroups.c_str());
00965   else
00966     ArLog::log(ArLog::Terse, "%s", listOfGroups.c_str());
00967   myDataMutex.unlock();
00968 }
00969 
00970 
00984 AREXPORT void ArServerBase::setGroupDescription(const char *cmdGrpName, const char *cmdGrpDesc)
00985 {
00986   myDataMutex.lock();
00987   myGroupDescription.insert(std::pair<std::string, std::string>(cmdGrpName, cmdGrpDesc));
00988   myDataMutex.unlock();
00989 }
00990 
00991 
00992 
00993 
00994 
00995 //   Created:  17-Nov-2005                                                 //
00996 //   Purpose:  
00997 //   Notes:                                                                //
00998 //             Assumption: Command Group Name Map exists already.          //
00999 //                                                                         //
01000 //   Revision History:                                                     //
01001 //      WHEN       WHO         WHAT and/or WHY                             //
01002 //   17-Nov-2005   NJ    Created this function.                            //
01003 
01004 AREXPORT void ArServerBase::logGroupDescriptions(void)
01005 {
01006   // -- This wrapper insures that NULL is the only input passed to the
01007   //    logCommandGroupNamesToFile routine.   
01008   //    This is used if the log is desired over a filename.  
01009   logGroupDescriptionsToFile(NULL);     // NULL is the only value passed.
01010 }
01011 
01012 AREXPORT void ArServerBase::logGroupDescriptionsToFile(const char *fileName)
01013 { 
01014   myDataMutex.lock();
01015   std::map<std::string, std::string>::iterator d_itr;   // establish map iterator               
01016   char line[1024];
01017   FILE *file = NULL;
01018   if (fileName != NULL)
01019     file = fopen(fileName, "w");                        // open file if exists
01020 
01021   // -- Assemble output strings and send to file or log
01022   for (d_itr = myGroupDescription.begin(); d_itr != myGroupDescription.end(); d_itr++)
01023   {
01024     snprintf(line, sizeof(line), "%-29s %s", (*d_itr).first.c_str(), (*d_itr).second.c_str());
01025     
01026     if (file != NULL)
01027       fprintf(file, "%s\n", line);              // send string to file
01028     else
01029       ArLog::log(ArLog::Terse, "%s", line);     // send string to log
01030   }
01031   if (fileName != NULL)                 // task complete notification
01032     fclose (file);
01033   myDataMutex.unlock();
01034 }       
01035 
01036 
01037 
01043 AREXPORT void ArServerBase::setServerKey(const char *serverKey)
01044 {
01045   myDataMutex.lock();
01046   // if this is setting it to empty and its already empty don't print
01047   // a message
01048   if ((serverKey == NULL || serverKey[0] == '\0') && myServerKey.size() > 0)
01049     ArLog::log(ArLog::Normal, "Clearing server key");
01050   if (serverKey != NULL && serverKey[0] != '\0')
01051     ArLog::log(ArLog::Normal, "Setting new server key");
01052   if (serverKey != NULL)
01053     myServerKey = serverKey;
01054   else
01055     myServerKey = "";
01056   myDataMutex.unlock();
01057 }
01058 
01059 AREXPORT void ArServerBase::rejectSinceUsingCentralServer(
01060         const char *centralServerIPString)
01061 {
01062   myDataMutex.lock();
01063   myRejecting = 2;
01064   myRejectingString = centralServerIPString;
01065   myDataMutex.unlock();
01066 }
01067 
01068 AREXPORT void ArServerBase::logTracking(bool terse)
01069 {
01070   std::list<ArServerClient *>::iterator lit;
01071 
01072   myClientsMutex.lock();  
01073 
01074   for (lit = myClients.begin(); lit != myClients.end(); ++lit)
01075     (*lit)->logTracking(terse);
01076 
01077   ArLog::log(ArLog::Terse, "");
01078   
01079   if (!terse)
01080   {
01081     ArLog::log(ArLog::Terse, "%-85s %7ld udp rcvs %10ld udp B",
01082                "Low Level UDP Received (all conns)", myUdpSocket.getRecvs(), 
01083                myUdpSocket.getBytesRecvd());
01084     ArLog::log(ArLog::Terse, "%-85s %7ld udp snds %10ld udp B",
01085                "Low Level UDP Sent (all conns)", myUdpSocket.getSends(), 
01086                myUdpSocket.getBytesSent());
01087 
01088     ArLog::log(ArLog::Terse, "");
01089   }
01090   myClientsMutex.unlock();  
01091 }
01092 
01093 AREXPORT void ArServerBase::resetTracking(void)
01094 {
01095   std::list<ArServerClient *>::iterator lit;
01096 
01097   myClientsMutex.lock();  
01098 
01099   for (lit = myClients.begin(); lit != myClients.end(); ++lit)
01100     (*lit)->resetTracking();
01101   myClientsMutex.unlock();  
01102   myDataMutex.lock();
01103   myUdpSocket.resetTracking();
01104   myDataMutex.unlock();
01105 }
01106 
01107 AREXPORT const ArServerUserInfo* ArServerBase::getUserInfo(void) const
01108 {
01109   return myUserInfo;
01110 }
01111 
01112 AREXPORT void ArServerBase::setUserInfo(const ArServerUserInfo *userInfo)
01113 {
01114   myDataMutex.lock();
01115   myUserInfo = userInfo;
01116   myDataMutex.unlock();
01117 }
01130 AREXPORT long ArServerBase::getFrequency(unsigned int command,
01131                                          bool internalCall)
01132 {
01133   std::list<ArServerClient *>::iterator it;
01134   long ret = -2;
01135   long clientFreq;
01136 
01137   if (!internalCall)
01138     myClientsMutex.lock();
01139   
01140   for (it = myClients.begin(); it != myClients.end(); it++)
01141   {
01142     clientFreq = (*it)->getFrequency(command);
01143     // if the ret is an interval and so is this client but this client
01144     // is a smalelr interval
01145     if (clientFreq >= 0 && (ret < 0 || (ret >= 0 && clientFreq < ret)))
01146       ret = clientFreq;
01147     // if this client just wants the data when pushed but ret is still
01148     // at never then set it to when pushed
01149     else if (clientFreq == -1 && ret == -2)
01150       ret = -1;
01151   }
01152   
01153   if (!internalCall)
01154     myClientsMutex.unlock();
01155 
01156   return ret;
01157 }
01158 
01164 AREXPORT void ArServerBase::setAdditionalDataFlags(
01165         const char *additionalDataFlags)
01166 {
01167   myDataMutex.lock();
01168   if (additionalDataFlags == NULL || additionalDataFlags[0] == '\0')
01169     myAdditionalDataFlags = "";
01170   else  
01171     myAdditionalDataFlags = additionalDataFlags;
01172   myDataMutex.unlock();
01173 }
01174 
01175 
01176 AREXPORT bool ArServerBase::dataHasFlag(const char *name, 
01177                                         const char *dataFlag)
01178 {
01179   unsigned int command;
01180   if ((command = findCommandFromName(name)) == 0)
01181   {
01182     ArLog::log(ArLog::Verbose, 
01183            "ArServerBase::dataHasFlag: %s is not data that is on the server", 
01184                name);
01185     return false;
01186   }
01187 
01188   return dataHasFlagByCommand(findCommandFromName(name), dataFlag);
01189 }
01190 
01191 AREXPORT bool ArServerBase::dataHasFlagByCommand(unsigned int command, 
01192                                                  const char *dataFlag)
01193 {
01194   std::map<unsigned int, ArServerData *>::iterator dIt;
01195   bool ret;
01196 
01197   myDataMutex.lock();
01198   if ((dIt = myDataMap.find(command)) == myDataMap.end())
01199     ret = false;
01200   else
01201     ret = (*dIt).second->hasDataFlag(dataFlag);
01202   myDataMutex.unlock();
01203   
01204   return ret;
01205 }
01206 
01207 AREXPORT unsigned int ArServerBase::getTcpPort(void)
01208 {
01209   return myTcpPort;
01210 }
01211 
01212 AREXPORT unsigned int ArServerBase::getUdpPort(void)
01213 {
01214   return myUdpPort;  
01215 }

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