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 <ctype.h>
00027 #include "ArExport.h"
00028 #include "ariaOSDef.h"
00029 #include "ArNetServer.h"
00030 #include "ArRobot.h"
00031 #include "ArLog.h"
00032 #include "ariaUtil.h"
00033 #include "ArSyncTask.h"
00034 #include "ArArgumentBuilder.h"
00035 #include "ariaInternal.h"
00036
00037 ArNetServer::ArNetServer(bool addAriaExitCB) :
00038 myTaskCB(this, &ArNetServer::runOnce),
00039 myHelpCB(this, &ArNetServer::internalHelp),
00040 myEchoCB(this, &ArNetServer::internalEcho),
00041 myQuitCB(this, &ArNetServer::internalQuit),
00042 myShutdownServerCB(this, &ArNetServer::internalShutdownServer),
00043 myAriaExitCB(this, &ArNetServer::close)
00044 {
00045 myRobot = NULL;
00046 myPort = 0;
00047 myMultipleClients = false;
00048 myOpened = false;
00049 myWantToClose = false;
00050 myLoggingDataSent = false;
00051 myLoggingDataReceived = false;
00052 mySquelchNormal = false;
00053 addCommand("help", &myHelpCB, "gives the listing of available commands");
00054 addCommand("echo", &myEchoCB, "with no args gets echo, with args sets echo");
00055 addCommand("quit", &myQuitCB, "closes this connection to the server");
00056 addCommand("shutdownServer", &myShutdownServerCB, "shuts down the server");
00057
00058 myAriaExitCB.setName("ArNetServerExit");
00059 if (addAriaExitCB)
00060 Aria::addExitCallback(&myAriaExitCB, 40);
00061 }
00062
00063 ArNetServer::~ArNetServer()
00064 {
00065 ArSyncTask *rootTask = NULL;
00066 ArSyncTask *proc = NULL;
00067
00068 if (myRobot != NULL && (rootTask = myRobot->getSyncTaskRoot()) != NULL)
00069 {
00070 proc = rootTask->findNonRecursive(&myTaskCB);
00071 if (proc != NULL)
00072 delete proc;
00073 }
00074 close();
00075 }
00076
00095 AREXPORT bool ArNetServer::open(ArRobot *robot, unsigned int port,
00096 const char *password, bool multipleClients,
00097 const char *openOnIP)
00098 {
00099 ArSyncTask *rootTask = NULL;
00100 ArSyncTask *proc = NULL;
00101 std::string taskName;
00102
00103 if (myOpened)
00104 {
00105 ArLog::log(ArLog::Terse, "ArNetServer already inited, cannot reinit");
00106 return false;
00107 }
00108
00109 myRobot = robot;
00110 myPort = port;
00111 myPassword = password;
00112 myMultipleClients = multipleClients;
00113
00114 if (myServerSocket.open(myPort, ArSocket::TCP, openOnIP))
00115 {
00116 myServerSocket.setLinger(0);
00117 myServerSocket.setNonBlock();
00118 if (openOnIP != NULL)
00119 ArLog::log(ArLog::Normal, "ArNetServer opened on port %d on ip %s.",
00120 myPort, openOnIP);
00121 else
00122 ArLog::log(ArLog::Normal, "ArNetServer opened on port %d.", myPort);
00123 myOpened = true;
00124 }
00125 else
00126 {
00127 ArLog::log(ArLog::Terse, "ArNetServer failed to open: %s",
00128 myServerSocket.getErrorStr().c_str());
00129 myOpened = false;
00130 return false;
00131 }
00132
00133
00134 if (myRobot != NULL && (rootTask = myRobot->getSyncTaskRoot()) != NULL)
00135 {
00136 proc = rootTask->findNonRecursive(&myTaskCB);
00137 if (proc == NULL)
00138 {
00139
00140 taskName = "Net Servers ";
00141 taskName += myPort;
00142 rootTask->addNewLeaf(taskName.c_str(), 60, &myTaskCB, NULL);
00143 }
00144 }
00145 return true;
00146
00147 }
00148
00154 AREXPORT bool ArNetServer::addCommand(const char *command,
00155 ArFunctor3<char **, int, ArSocket *> *functor,
00156 const char *help)
00157 {
00158 std::map<std::string, ArFunctor3<char **, int, ArSocket *> *, ArStrCaseCmpOp>::iterator it;
00159
00160 if ((it = myFunctorMap.find(command)) != myFunctorMap.end())
00161 {
00162 ArLog::log(ArLog::Normal, "ArNetServer::addCommand: Already a command for %s", command);
00163 return false;
00164 }
00165
00166 myFunctorMap[command] = functor;
00167 myHelpMap[command] = help;
00168 return true;
00169 }
00170
00175 AREXPORT bool ArNetServer::remCommand(const char *command)
00176 {
00177 if (myFunctorMap.find(command) == myFunctorMap.end())
00178 {
00179 return false;
00180 }
00181 myFunctorMap.erase(command);
00182 myHelpMap.erase(command);
00183 return true;
00184 }
00185
00186
00187 AREXPORT void ArNetServer::sendToAllClientsPlain(const char *str)
00188 {
00189 std::list<ArSocket *>::iterator it;
00190
00191 if (myLoggingDataSent)
00192 ArLog::log(ArLog::Terse, "ArNetServer::sendToAllClients: Sending %s", str);
00193 for (it = myConns.begin(); it != myConns.end(); ++it)
00194 {
00195 (*it)->setLogWriteStrings(false);
00196 (*it)->writeString(str);
00197 (*it)->setLogWriteStrings(myLoggingDataSent);
00198 }
00199 }
00200
00205 AREXPORT void ArNetServer::sendToAllClients(const char *str, ...)
00206 {
00207 char buf[2049];
00208 va_list ptr;
00209 va_start(ptr, str);
00210 vsprintf(buf, str, ptr);
00211
00212 sendToAllClientsPlain(buf);
00213
00214 va_end(ptr);
00215 }
00216
00217 AREXPORT bool ArNetServer::isOpen(void)
00218 {
00219 return myOpened;
00220 }
00221
00222
00227 AREXPORT void ArNetServer::setLoggingDataSent(bool loggingData)
00228 {
00229 myLoggingDataSent = loggingData;
00230 std::list<ArSocket *>::iterator it;
00231 for (it = myConnectingConns.begin(); it != myConnectingConns.end(); ++it)
00232 (*it)->setLogWriteStrings(loggingData);
00233 for (it = myConns.begin(); it != myConns.end(); ++it)
00234 (*it)->setLogWriteStrings(loggingData);
00235 }
00236
00241 AREXPORT bool ArNetServer::getLoggingDataSent(void)
00242 {
00243 return myLoggingDataSent;
00244 }
00245
00250 AREXPORT void ArNetServer::setLoggingDataReceived(bool loggingData)
00251 {
00252 myLoggingDataReceived = loggingData;
00253 }
00254
00259 AREXPORT bool ArNetServer::getLoggingDataReceived(void)
00260 {
00261 return myLoggingDataReceived;
00262 }
00263
00264
00265 AREXPORT void ArNetServer::runOnce(void)
00266 {
00267
00268 ArSocket acceptingSocket;
00269 ArSocket *socket;
00270 char *str;
00271 std::list<ArSocket *> removeList;
00272 std::list<ArSocket *>::iterator it;
00273 ArArgumentBuilder *args = NULL;
00274 std::string command;
00275
00276 if (!myOpened)
00277 {
00278 return;
00279 }
00280
00281 lock();
00282
00283 while (myServerSocket.accept(&acceptingSocket) && acceptingSocket.getFD() >= 0)
00284 {
00285 acceptingSocket.setNonBlock();
00286
00287 if (!myMultipleClients && (myConns.size() > 0 ||
00288 myConnectingConns.size() > 0))
00289 {
00290
00291 acceptingSocket.writeString("Conn refused.");
00292 acceptingSocket.writeString(
00293 "Only client allowed and it is already connected.");
00294 acceptingSocket.close();
00295 ArLog::log(ArLog::Terse, "ArNetServer not taking multiple clients and another client tried to connect from %s.", acceptingSocket.getIPString());
00296 }
00297 else
00298 {
00299
00300
00301 socket = new ArSocket;
00302 socket->setLogWriteStrings(myLoggingDataSent);
00303 socket->transfer(&acceptingSocket);
00304 socket->writeString("Enter password:");
00305 myConnectingConns.push_front(socket);
00306 ArLog::log(ArLog::Normal,
00307 "Client connecting from %s.",
00308 socket->getIPString());
00309 }
00310 }
00311
00312
00313
00314 for (it = myConnectingConns.begin(); it != myConnectingConns.end(); ++it)
00315 {
00316 socket = (*it);
00317
00318 if ((str = socket->readString()) != NULL)
00319 {
00320 if (str[0] == '\0')
00321 continue;
00322
00323 if (myPassword == str)
00324 {
00325 ArLog::log(ArLog::Normal,
00326 "Client from %s gave password and connected.",
00327 socket->getIPString());
00328 myConns.push_front(socket);
00329 removeList.push_front(socket);
00330 internalGreeting(socket);
00331 }
00332 else
00333 {
00334 socket->close();
00335 myDeleteList.push_front(socket);
00336 ArLog::log(ArLog::Terse,
00337 "Client from %s gave wrong password and is being disconnected.",
00338 socket->getIPString());
00339 }
00340 }
00341
00342 else
00343 {
00344 ArLog::log(ArLog::Normal,
00345 "Connection to %s lost.", socket->getIPString());
00346 socket->close();
00347 myDeleteList.push_front(socket);
00348 }
00349 }
00350
00351
00352 while ((it = removeList.begin()) != removeList.end())
00353 {
00354 socket = (*it);
00355 myConnectingConns.remove(socket);
00356 removeList.pop_front();
00357 }
00358
00359
00360
00361
00362 for (it = myConns.begin(); it != myConns.end() && myOpened; ++it)
00363 {
00364 socket = (*it);
00365
00366 while ((str = socket->readString()) != NULL)
00367 {
00368
00369 if (str[0] == '\0')
00370 break;
00371
00372
00373
00374 args = new ArArgumentBuilder;
00375 args->addPlain(str);
00376
00377 parseCommandOnSocket(args, socket);
00378 delete args;
00379 args = NULL;
00380 }
00381
00382 if (str == NULL)
00383 {
00384 ArLog::log(ArLog::Normal,
00385 "Connection to %s lost.", socket->getIPString());
00386 socket->close();
00387 myDeleteList.push_front(socket);
00388 }
00389 }
00390
00391
00392
00393 while ((it = myDeleteList.begin()) != myDeleteList.end())
00394 {
00395 socket = (*it);
00396 myConnectingConns.remove(socket);
00397 myConns.remove(socket);
00398 socket->close();
00399 delete socket;
00400 myDeleteList.pop_front();
00401 }
00402
00403 if (myWantToClose)
00404 {
00405 close();
00406 }
00407 unlock();
00408 }
00409
00410 AREXPORT void ArNetServer::close(void)
00411 {
00412 std::list<ArSocket *>::iterator it;
00413 ArSocket *socket;
00414
00415 if (!myOpened)
00416 return;
00417 myWantToClose = false;
00418 ArLog::log(ArLog::Normal, "ArNetServer shutting down server.");
00419 sendToAllClients("Shutting down server");
00420 for (it = myConnectingConns.begin(); it != myConnectingConns.end(); ++it)
00421 {
00422 (*it)->writeString("Shutting down server");
00423 }
00424 myOpened = false;
00425
00426 while ((it = myConnectingConns.begin())!= myConnectingConns.end())
00427 {
00428 socket = (*it);
00429 myConnectingConns.pop_front();
00430 socket->close();
00431 delete socket;
00432 }
00433 while ((it = myConns.begin()) != myConns.end())
00434 {
00435 socket = (*it);
00436 myConns.pop_front();
00437 socket->close();
00438 delete socket;
00439 }
00440 myServerSocket.close();
00441 }
00442
00443 AREXPORT void ArNetServer::internalGreeting(ArSocket *socket)
00444 {
00445 if (mySquelchNormal)
00446 return;
00447 socket->writeString("Welcome to the server.");
00448 socket->writeString("You can type 'help' at any time for the following help list.");
00449 internalHelp(socket);
00450 }
00451
00452 AREXPORT void ArNetServer::internalHelp(ArSocket *socket)
00453 {
00454 std::map<std::string, std::string, ArStrCaseCmpOp>::iterator it;
00455
00456 socket->writeString("Commands:");
00457 for (it = myHelpMap.begin(); it != myHelpMap.end(); ++it)
00458 socket->writeString("%15s%10s%s", it->first.c_str(), "",
00459 it->second.c_str());
00460 }
00461
00462 AREXPORT void ArNetServer::internalHelp(char **argv, int argc,
00463 ArSocket *socket)
00464 {
00465 internalHelp(socket);
00466 }
00467
00468
00469 AREXPORT void ArNetServer::internalEcho(char **argv, int argc,
00470 ArSocket *socket)
00471 {
00472
00473 if (argc == 1)
00474 {
00475 if (socket->getEcho())
00476 socket->writeString("Echo is on.");
00477 else
00478 socket->writeString("Echo is off.");
00479 }
00480
00481 else if (argc == 2 && strcasecmp(argv[1], "on") == 0)
00482 {
00483 socket->writeString("Echo turned on.");
00484 socket->setEcho(true);
00485 }
00486 else if (argc == 2 && strcasecmp(argv[1], "off") == 0)
00487 {
00488 socket->writeString("Echo turned off.");
00489 socket->setEcho(false);
00490 }
00491 else
00492 {
00493 socket->writeString("usage: echo <on/off>");
00494 }
00495 }
00496
00497 AREXPORT void ArNetServer::internalQuit(char **argv, int argc,
00498 ArSocket *socket)
00499 {
00500 socket->writeString("Closing connection");
00501
00502 myDeleteList.push_front(socket);
00503 ArLog::log(ArLog::Normal, "Client from %s quit.", socket->getIPString());
00504 }
00505
00506 AREXPORT void ArNetServer::internalShutdownServer(char **argv, int argc,
00507 ArSocket *socket)
00508 {
00509 sendToAllClients("Shutting down server");
00510 myWantToClose = true;
00511 if (myRobot != NULL)
00512 myRobot->stopRunning();
00513
00514 }
00515
00516 AREXPORT void ArNetServer::parseCommandOnSocket(ArArgumentBuilder *args,
00517 ArSocket *socket, bool allowLog)
00518 {
00519
00520 std::map<std::string, ArFunctor3<char **, int, ArSocket *> *, ArStrCaseCmpOp>::iterator fIt;
00521 char **argv;
00522 int argc;
00523
00524 if (myLoggingDataReceived && !mySquelchNormal && allowLog)
00525 ArLog::log(ArLog::Normal, "Command received from %s: %s",
00526 socket->getIPString(), args->getFullString());
00527 else if (myLoggingDataReceived && mySquelchNormal && allowLog)
00528 ArLog::log(ArLog::Normal, "%s: %s",
00529 socket->getIPString(), args->getFullString());
00530 argv = args->getArgv();
00531 argc = args->getArgc();
00532
00533 if (argc >= 1 &&
00534 (fIt = myFunctorMap.find(argv[0])) != myFunctorMap.end())
00535 {
00536 fIt->second->invoke(argv, argc, socket);
00537 }
00538
00539 else if (argc >= 1)
00540 {
00541 if (!mySquelchNormal)
00542 socket->writeString("Unknown command %s", argv[0]);
00543 }
00544 }
00545
00546 AREXPORT void ArNetServer::internalAddSocketToList(ArSocket *socket)
00547 {
00548 myConns.push_front(socket);
00549 }
00550
00551
00552 AREXPORT void ArNetServer::internalAddSocketToDeleteList(ArSocket *socket)
00553 {
00554 myDeleteList.push_front(socket);
00555 }
00556
00557 AREXPORT void ArNetServer::squelchNormal(void)
00558 {
00559 mySquelchNormal = true;
00560 remCommand("help");
00561 remCommand("echo");
00562 remCommand("quit");
00563 remCommand("shutdownServer");
00564
00565 }
00566
00567 AREXPORT void ArNetServer::sendToClientPlain(
00568 ArSocket *socket, const char *ipString, const char *str)
00569 {
00570 std::list<ArSocket *>::iterator it;
00571
00572 for (it = myConns.begin(); it != myConns.end(); ++it)
00573 {
00574 if ((*it) == socket && strcmp((*it)->getIPString(), ipString) == 0)
00575 {
00576 if (myLoggingDataSent)
00577 ArLog::log(ArLog::Terse,
00578 "ArNetServer::sendToClient: Sending '%s' to %s", str,
00579 ipString);
00580 (*it)->setLogWriteStrings(false);
00581 (*it)->writeString(str);
00582 (*it)->setLogWriteStrings(myLoggingDataSent);
00583 }
00584 }
00585 }
00586
00591 AREXPORT void ArNetServer::sendToClient(ArSocket *socket, const char *ipString,
00592 const char *str, ...)
00593 {
00594 char buf[2049];
00595 va_list ptr;
00596 va_start(ptr, str);
00597 vsprintf(buf, str, ptr);
00598
00599 sendToClientPlain(socket, ipString, buf);
00600
00601 va_end(ptr);
00602 }