示例#1
0
AREXPORT void ArNetServer::runOnce(void)
{

  ArSocket acceptingSocket;
  ArSocket *socket;
  char *str;
  std::list<ArSocket *> removeList;
  std::list<ArSocket *>::iterator it;
  ArArgumentBuilder *args = NULL;
  std::string command;

  if (!myOpened)
  {
    return;
  }

  lock();
  // get any new sockets that want to connect
  while (myServerSocket.accept(&acceptingSocket) && acceptingSocket.getFD() >= 0)
  {
    acceptingSocket.setNonBlock();
    // see if we want more sockets
    if (!myMultipleClients && (myConns.size() > 0 ||
			       myConnectingConns.size() > 0))
    {
      // we didn't want it, so politely tell it to go away
      acceptingSocket.writeString("Conn refused.");
      acceptingSocket.writeString(
	      "Only client allowed and it is already connected.");
      acceptingSocket.close();
      ArLog::log(ArLog::Terse, "ArNetServer not taking multiple clients and another client tried to connect from %s.", acceptingSocket.getIPString());
    }
    else 
    {
      // we want the client so we put it in our list of connecting
      // sockets, which means that it is waiting to give its password
      socket = new ArSocket;
      socket->setLogWriteStrings(myLoggingDataSent);
      socket->transfer(&acceptingSocket);
      socket->writeString("Enter password:"******"Client connecting from %s.",
		 socket->getIPString());
    }
  }

  // now we read in data from our connecting sockets and see if
  // they've given us the password
  for (it = myConnectingConns.begin(); it != myConnectingConns.end(); ++it)
  {
    socket = (*it);
    // read in what the client has to say
    if ((str = socket->readString()) != NULL)
    {
      if (str[0] == '\0')
	continue;
      // now see if the word matchs the password
      if (myPassword == str)
      {
	ArLog::log(ArLog::Normal, 
		   "Client from %s gave password and connected.",
		   socket->getIPString());
	myConns.push_front(socket);
	removeList.push_front(socket);
	internalGreeting(socket);
      }
      else
      {
	socket->close();
	myDeleteList.push_front(socket);
	ArLog::log(ArLog::Terse, 
		   "Client from %s gave wrong password and is being disconnected.", 
		   socket->getIPString());
      }
    }
    // if we couldn't read a string it means we lost a connection
    else
    {
      ArLog::log(ArLog::Normal, 
		 "Connection to %s lost.", socket->getIPString());
      socket->close();
      myDeleteList.push_front(socket);
    }
  }
  // now we clear out the ones we want to remove from our connecting
  // clients list
  while ((it = removeList.begin()) != removeList.end())
  {
    socket = (*it);
    myConnectingConns.remove(socket);
    removeList.pop_front();
  }


  // now we read in data from our connecting sockets and see if
  // they've given us the password
  for (it = myConns.begin(); it != myConns.end() && myOpened; ++it)
  {
    socket = (*it);
    // read in what the client has to say
    while ((str = socket->readString()) != NULL)
    {
      // if this is null then there wasn't anything said
      if (str[0] == '\0')
	break;
      // make sure we read something
      // set up the arguments and then call the function for the
      // argument
      args = new ArArgumentBuilder;
      args->addPlain(str);
      //args->log();
      parseCommandOnSocket(args, socket);
      delete args;
      args = NULL;
    }
    // if str was NULL we lost connection
    if (str == NULL)
    {
      ArLog::log(ArLog::Normal, 
		 "Connection to %s lost.", socket->getIPString());
      socket->close();
      myDeleteList.push_front(socket);
    }
  }

  // now we delete the ones we want to delete (we could do this above
  // but then it wouldn't be symetrical with above)
  while ((it = myDeleteList.begin()) != myDeleteList.end())
  {
    socket = (*it);
    myConnectingConns.remove(socket);
    myConns.remove(socket);
    socket->close();
    delete socket;
    myDeleteList.pop_front();
  }

  if (myWantToClose)
  {
    close();
  }
  unlock();
}
void ArCentralManager::netServerSwitch(ArServerClient *client, ArNetPacket *packet)
{
  char robotName[512];
  std::string uniqueName;
  
  robotName[0] = '\0';

  //printf("robotName before '%s'\n", robotName);

  packet->bufToStr(robotName, sizeof(robotName));

  ArNetPacket sendPacket;
  /// acknowledge the switch
  client->sendPacketTcp(&sendPacket);

  ArSocket *clientSocket = new ArSocket;
  clientSocket->transfer(client->getTcpSocket());
  
  client->tcpCallback();
  client->forceDisconnect(true);

  
  // make the basis of the unique name
  if (robotName[0] != '\0')
    uniqueName = robotName;
  else
    uniqueName = client->getIPString();

  //printf("Starting with '%s'\n", uniqueName.c_str());

  myDataMutex.lock();
  // walk through and make the name unique
  std::list<ArCentralForwarder *>::iterator fIt;
  ArCentralForwarder *forwarder;
  /* the old code that made the names unique
  bool nameIsUnique = false;
  while (!nameIsUnique)
  {
    nameIsUnique = true;
    for (fIt = myForwarders.begin(); 
	 fIt != myForwarders.end() && nameIsUnique; 
	 fIt++)
    {
      forwarder = (*fIt);
      if (strcasecmp(forwarder->getRobotName(), uniqueName.c_str()) == 0)
	nameIsUnique = false;
    }
    if (!nameIsUnique)
      uniqueName += "_";
  }
  */
  // the new code that drops the duplicates and replaces it with the same name
  for (fIt = myForwarders.begin(); fIt != myForwarders.end(); fIt++)
  {
    forwarder = (*fIt);
    if (strcasecmp(forwarder->getRobotName(), uniqueName.c_str()) == 0)
    {
      ArLog::log(ArLog::Normal, 
		 "ArCentralManager: Will drop old duplicate connection for %s", 
		 uniqueName.c_str());
      forwarder->willReplace();
    }
  }

  // remove any pending client duplicates
  while (removePendingDuplicateConnections(uniqueName.c_str()));

  // end of new code, though it also had reordering down below in the runthread

  myClientSockets.push_back(clientSocket);
  myClientNames.push_back(uniqueName);

  //printf("robotName after '%s'\n", robotName);
  // just print out the switch request name if its the same as it came in as
  if (strcmp(uniqueName.c_str(), robotName) == 0)
    ArLog::log(ArLog::Normal, "Got switch request from %s from %s", 
	       client->getIPString(), uniqueName.c_str());
  // otherwise let them know what the unique name is
  if (strcmp(uniqueName.c_str(), robotName) != 0)
    ArLog::log(ArLog::Normal, 
	       "Got switch request from %s from %s that started as %s", 
	       client->getIPString(), uniqueName.c_str(), robotName);
  //printf("Ended with '%s'\n", uniqueName.c_str());
  myDataMutex.unlock();
}