Example #1
0
AREXPORT void ArNetServer::close(void)
{
  std::list<ArSocket *>::iterator it;
  ArSocket *socket;
  
  if (!myOpened)
    return;
  myWantToClose = false;
  ArLog::log(ArLog::Normal, "ArNetServer shutting down server.");
  sendToAllClients("Shutting down server");
  for (it = myConnectingConns.begin(); it != myConnectingConns.end(); ++it)
  {
    (*it)->writeString("Shutting down server");
  }
  myOpened = false;

  while ((it = myConnectingConns.begin())!= myConnectingConns.end())
  {
    socket = (*it);
    myConnectingConns.pop_front();
    socket->close();
    delete socket;
  }
  while ((it = myConns.begin()) != myConns.end())
  {
    socket = (*it);
    myConns.pop_front();
    socket->close();
    delete socket;
  }
  myServerSocket.close();
}
void clientCloseCallback(ArServerClient * serverClient)
{
	clientSock.close();
	serverSock.close();
	ss.runAsync();
	cout << "client is closed, callback is done!" <<endl;
}
Example #3
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();
}
/// This should be its own thread here
void *ArCentralManager::runThread(void *arg)
{
  std::list<ArSocket *>::iterator sIt;
  std::list<std::string>::iterator nIt;
  std::list<ArCentralForwarder *>::iterator fIt;
  ArSocket *socket;
  std::string robotName;
  ArCentralForwarder *forwarder;

  ArNetPacket *packet;
  std::list<ArNetPacket *> addPackets;
  std::list<ArNetPacket *> remPackets;


  threadStarted();
  while (getRunning())
  {
    int numForwarders = 0;
    int numClients = 0;
    
    myDataMutex.lock();
    // this is where the original code to add forwarders was before we
    // changed the unique behavior to drop old ones...


    std::list<ArCentralForwarder *> connectedRemoveList;
    std::list<ArCentralForwarder *> unconnectedRemoveList;
    for (fIt = myForwarders.begin(); fIt != myForwarders.end(); fIt++)
    {
      forwarder = (*fIt);

      numForwarders++;
      if (forwarder->getServer() != NULL)
	numClients += forwarder->getServer()->getNumClients();
      bool connected = forwarder->isConnected();
      bool removed = false;
      if (!forwarder->callOnce(myHeartbeatTimeout, myUdpHeartbeatTimeout,
			       myRobotBackupTimeout, myClientBackupTimeout))
      {
	if (connected)
	{
	  ArLog::log(ArLog::Normal, "Will remove forwarder from %s", 
		     forwarder->getRobotName());
	  connectedRemoveList.push_back(forwarder);
	  removed = true;
	}
	else
	{
	  ArLog::log(ArLog::Normal, "Failed to connect to forwarder from %s", 
		     forwarder->getRobotName());
	  unconnectedRemoveList.push_back(forwarder);
	  removed = true;
	}
      }
      if (!connected && !removed && forwarder->isConnected())
      {
	ArLog::log(ArLog::Normal, "Adding forwarder %s", 
		   forwarder->getRobotName());
	ArTime *newTime = new ArTime;
	newTime->setSec(0);
	myUsedPorts[forwarder->getPort()] = newTime;
	
	std::multimap<int, ArFunctor1<ArCentralForwarder *> *>::iterator it;
	for (it = myForwarderAddedCBList.begin();
	     it != myForwarderAddedCBList.end();
	     it++)
	{
	  if ((*it).second->getName() == NULL || 
	      (*it).second->getName()[0] == '\0')
	    ArLog::log(ArLog::Normal, "Calling unnamed add functor at %d",
		       -(*it).first);
	  else
	    ArLog::log(ArLog::Normal, "Calling %s add functor at %d",
		       (*it).second->getName(), -(*it).first);
	  (*it).second->invoke(forwarder);
	}
	ArLog::log(ArLog::Normal, "Added forwarder %s", 
		   forwarder->getRobotName());      
	ArNetPacket *sendPacket = new ArNetPacket;
	sendPacket->strToBuf("");
	sendPacket->uByte2ToBuf(forwarder->getPort());
	sendPacket->strToBuf(forwarder->getRobotName());
	sendPacket->strToBuf("");
	sendPacket->strToBuf(
		forwarder->getClient()->getTcpSocket()->getIPString());
	addPackets.push_back(sendPacket);
	// MPL added this at the same time as the changes for the deadlock that happened down below
	//myClientServer->broadcastPacketTcp(&sendPacket, "clientAdded");
      }
    }

    while ((fIt = connectedRemoveList.begin()) != connectedRemoveList.end())
    {
      forwarder = (*fIt);

      ArLog::log(ArLog::Normal, "Removing forwarder %s", 
		 forwarder->getRobotName());
      std::multimap<int, ArFunctor1<ArCentralForwarder *> *>::iterator it;
      for (it = myForwarderRemovedCBList.begin();
	   it != myForwarderRemovedCBList.end();
	   it++)
      {
	if ((*it).second->getName() == NULL || 
	    (*it).second->getName()[0] == '\0')
	  ArLog::log(ArLog::Normal, "Calling unnamed remove functor at %d",
		     -(*it).first);
	else
	  ArLog::log(ArLog::Normal, "Calling %s remove functor at %d",
		     (*it).second->getName(), -(*it).first);
	(*it).second->invoke(forwarder);
      }

      ArLog::log(ArLog::Normal, "Called forwarder removed for %s", 
		 forwarder->getRobotName());
      ArNetPacket *sendPacket = new ArNetPacket;
      sendPacket->strToBuf("");
      sendPacket->uByte2ToBuf(forwarder->getPort());
      sendPacket->strToBuf(forwarder->getRobotName());
      sendPacket->strToBuf("");
      sendPacket->strToBuf(
	      forwarder->getClient()->getTcpSocket()->getIPString());
      // MPL making this just push packets into a list to broadcast at the end since this was deadlocking
      //myClientServer->broadcastPacketTcp(&sendPacket, "clientRemoved");
      remPackets.push_back(sendPacket);

      if (myUsedPorts.find(forwarder->getPort()) != myUsedPorts.end() && 
	  myUsedPorts[forwarder->getPort()] != NULL)
	myUsedPorts[forwarder->getPort()]->setToNow();

      myForwarders.remove(forwarder);
      delete forwarder;
      connectedRemoveList.pop_front();
      ArLog::log(ArLog::Normal, "Removed forwarder");

    }

    while ((fIt = unconnectedRemoveList.begin()) != 
	   unconnectedRemoveList.end())
    {
      forwarder = (*fIt);
      ArLog::log(ArLog::Normal, "Removing unconnected forwarder %s", 
		 forwarder->getRobotName());

      if (myUsedPorts.find(forwarder->getPort()) != myUsedPorts.end() && 
	  myUsedPorts[forwarder->getPort()] != NULL)
	myUsedPorts[forwarder->getPort()]->setToNow();      

      myForwarders.remove(forwarder);
      delete forwarder;
      unconnectedRemoveList.pop_front();
      ArLog::log(ArLog::Normal, "Removed unconnected forwarder");
    }


    // this code was up above just after the lock before we changed
    // the behavior for unique names
    while ((sIt = myClientSockets.begin()) != myClientSockets.end() && 
	   (nIt = myClientNames.begin()) != myClientNames.end())
    {
      socket = (*sIt);
      robotName = (*nIt);

      myClientSockets.pop_front();
      myClientNames.pop_front();

      ArLog::log(ArLog::Normal, 
		 "New forwarder for socket from %s with name %s", 
		 socket->getIPString(), robotName.c_str());

      forwarder = new ArCentralForwarder(myClientServer, socket, 
					 robotName.c_str(), 
					 myClientServer->getTcpPort() + 1, 
					 &myUsedPorts, 
					 &myForwarderServerClientRemovedCB,
					 myEnforceProtocolVersion.c_str(),
					 myEnforceType);
      myForwarders.push_back(forwarder);
    }

    numClients += myRobotServer->getNumClients();
    if (myRobotServer != myClientServer)
      numClients += myClientServer->getNumClients();
    // end of code moved for change in unique behavior
    if (numClients > myMostClients)
    {
      ArLog::log(ArLog::Normal, "CentralManager: New most clients: %d", 
		 numClients);
      myMostClients = numClients;
    }

    if (numForwarders > myMostForwarders)
      myMostForwarders = numForwarders;

    if (numClients > myMostClients)
    {
      ArLog::log(ArLog::Normal, "CentralManager: New most forwarders: %d", 
		 numForwarders);
      myMostForwarders = numForwarders;
    }

    myRobotServer->internalSetNumClients(numForwarders + 
					 myClientSockets.size());

    myDataMutex.unlock();

    while (addPackets.begin() != addPackets.end())
    {
      packet = addPackets.front();
      myClientServer->broadcastPacketTcp(packet, "clientAdded");
      addPackets.pop_front();
      delete packet;
    }

    while (remPackets.begin() != remPackets.end())
    {
      packet = remPackets.front();
      myClientServer->broadcastPacketTcp(packet, "clientRemoved");
      remPackets.pop_front();
      delete packet;
    }

    ArUtil::sleep(1); 

    //make this a REALLY long sleep to test the duplicate pending
    //connection code
    //ArUtil::sleep(20000);
  }

  threadFinished();
  return NULL;
}
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();
}
	void* runThread(void*)  
	{
		size_t strSize;


		// The socket objects: one for accepting new client connections,
		// and another for communicating with a client after it connects.
		

		// Open the server socket
		if (serverSock.open(VIDEO_PORT, ArSocket::TCP))
			ArLog::log(ArLog::Normal, " Opened the server port %d.", VIDEO_PORT);
		else
			ArLog::log(ArLog::Normal, " Failed to open the server port: %s.", serverSock.getErrorStr().c_str());

		
		

		if (serverSock.accept(&clientSock))
			ArLog::log(ArLog::Normal, " Client has connected.");
		else
			ArLog::log(ArLog::Terse, " Error in accepting a connection from the client: %s.", serverSock.getErrorStr().c_str());
		
		//.setCloseCallback(new ArGlobalFunctor1<ArNetPacket*>(&clientCloseCallback));
		//serverSock.setCloseCallback(new ArGlobalFunctor1<ArNetPacket*>(&clientCloseCallback));
		while(1)
		{

			//int clinetSocketStatus = serverSock.accept(&clientSock); // MODIFIED By Yang, Try to accept new client.
			//
			//if (clinetSocketStatus > 0){

			//	char buf[1024] = {0};
			//	int recievedInt = clientSock.read(buf, 1024, 0);
			//	cout << recievedInt << endl;

			//	while(true)
			//	{
					/* send the grayscaled frame, thread safe */
					mutex_video.lock();
		
					if (is_data_ready) 
					{
						int grayImgSize=gray_img.rows*gray_img.cols;
						//cout <<" Sending image to the client.grayImgSize= " << grayImgSize;
						if ((strSize = clientSock.write(gray_img.data, grayImgSize))==grayImgSize )
							;//ArLog::log(ArLog::Normal, " Sent image to the client.grayImgSize= %d", grayImgSize);
						// 				else
						// 					ArLog::log(ArLog::Normal, " Error in sending hello string to the client.");

						//ArLog::log(ArLog::Normal, " String Size: \"%d\"", strSize);

						is_data_ready = 0;
					}
					mutex_video.unlock();

					//if(!clientSock.isOpen())
					//{
					//	clientSock.close();
					//	ArLog::log(ArLog::Normal, " Socket to client closed.");
					//	if (serverSock.accept(&clientSock))
					//		ArLog::log(ArLog::Normal, " Client has connected.");
					//	else
					//		ArLog::log(ArLog::Terse, " Error in accepting a connection from the client: %s.", serverSock.getErrorStr().c_str());
					//}
				}
			//}
			
		//}
		// Now lets close the connection to the client
		clientSock.close();
		ArLog::log(ArLog::Normal, " Socket to client closed.");
		// And lets close the server port
		//serverSock.close();
		//ArLog::log(ArLog::Normal, " Server socket closed.");

		// Uninitialize Aria and exit the program
		//Aria::exit(0);

	} //end of runThread
int main()
{
  // The string to send to the server. 
  const char *strToSend="Hello Server";
  // The buffer in which to recieve the hello from the server
  char buff[100];
  // The size of the string the server sent
  size_t strSize;

  // The socket object
  ArSocket sock;

  // Initialize Aria.  It is especially important to do
  // this on Windows, because it will initialize Window's
  // sockets system. 
  Aria::init();

  // Connect to the server
  ArLog::log(ArLog::Normal, "socketClientExample: Connecting to localhost TCP port 7777...");
  if (sock.connect("localhost", 7777, ArSocket::TCP))
    ArLog::log(ArLog::Normal, "socketClientExample: Connected to server at localhost TCP port 7777.");
  else
  {
    ArLog::log(ArLog::Terse, "socketClientExample: Error connecting to server at localhost TCP port 7777: %s", sock.getErrorStr().c_str());
    return(-1);
  }

  // Read data from the socket. read() will block until
  // data is received. 
  strSize=sock.read(buff, sizeof(buff));

  // If the amount read is 0 or less, its an error condition.
  if (strSize > 0)
  {
    buff[strSize]='\0'; // Terminate the string with a NULL character:
    ArLog::log(ArLog::Normal, "socketClientExample: Server said: \"%s\"", buff);
  }
  else
  {
    ArLog::log(ArLog::Terse, "socketClientExample: Error in waiting/reading from the server.");
    Aria::exit(-1);
    return(-1);
  }

  // Send the string 'Hello Server' to the server. write() should
  // return the same number of bytes that we told it to write. Otherwise,
  // its an error condition.
  if (sock.write(strToSend, strlen(strToSend)) == strlen(strToSend))
    ArLog::log(ArLog::Normal, "socketClientExample: Said hello to the server.");
  else
  {
    ArLog::log(ArLog::Terse, "socketClientExample: Error sending hello string to the server.");
    Aria::exit(-1);
    return(-1);
  }

  // Now close the connection to the server
  sock.close();
  ArLog::log(ArLog::Normal, "socketClientExample: Socket to server closed.");

  // Uninitialize Aria and exit
  Aria::exit(0);
  return(0);
}
void* RobotVideo::runThread(void* arg)
{

	cvNamedWindow("Robot", CV_WINDOW_AUTOSIZE);
	moveWindow("Robot", 0, 0);
	// The buffer in which to receive the hello from the server
	//unsigned char buff[12];
	unsigned char imgBuff[480*640];

	//Mat imgRecieve(480,640,CV_8UC1);
	// The size of the string the server sent
	size_t strSize;

	// The socket object
	ArSocket sock;
	unsigned char *ptr;
	// Initialize Aria.  It is especially important to do
	// this on Windows, because it will initialize Window's
	// sockets system. 
	// Aria::init();

	// Connect to the server
	//ArLog::log(ArLog::Normal, "socketClientExample: Connecting to localhost TCP port 7777...");

	if (sock.connect(server_ip, ROBOT_VIDEO_PORT, ArSocket::TCP))
		ArLog::log(ArLog::Normal, "Connected to server at %s TCP port 11000.", server_ip);
	else
	{
		ArLog::log(ArLog::Terse, "Error connecting to server at  %s  TCP port 11000: %s",server_ip, sock.getErrorStr().c_str());
		//return(-1);
	}

	//---------------------------VideoWriter---------------------------------------


	robotVideo.open("robot.avi"  , CV_FOURCC('M','J','P','G') /* CV_FOURCC('P','I','M','1') */, 20/*inputVideo.get(CV_CAP_PROP_FPS)*/,Size(640, 480), false);

	if (!robotVideo.isOpened())
	{
		cout  << "Could not open the output video for write: " /*<< source*/ << endl;
	}


	while(1)
	{
		ptr = &imgBuff[0];
		strSize = 0;
		while (strSize < 640 * 480)
		{
			//ArLog::log(ArLog::Normal, "socketClientExample: String Size: \"%d\"", strSize);
			strSize += sock.read(ptr, 2);
			ptr += 2;
		}

		ptr=robot_img.datastart;
		//ArLog::log(ArLog::Normal, "socketClientExample: String Size: \"%d\"", strSize);

		mutex_robotVideo.lock();
		for (int i = 0,k = 0; i < robot_img.rows*robot_img.cols; i++) 
		{
			*(ptr++) = imgBuff[k++];
		}


		imshow("Robot", robot_img);
		robotVideo << robot_img;


		mutex_robotVideo.unlock();
		waitKey(1);/*0)==27) break;*/
	}
	sock.close();
	//outputVideo.release();
	// Now close the connection to the server

	ArLog::log(ArLog::Normal, "Socket to server closed.");
	destroyWindow("Robot");
	// Uninitialize Aria and exit
	//Aria::exit(0);
	return NULL;
}