void TransportSocketCache::close()
{
  qiLogDebug() << "TransportSocketCache is closing";
  ConnectionMap map;
  std::list<TransportSocketPtr> pending;
  {
    boost::mutex::scoped_lock lock(_socketMutex);
    _dying = true;
    std::swap(map, _connections);
    std::swap(pending, _allPendingConnections);
  }
  for (ConnectionMap::iterator mIt = map.begin(), mEnd = map.end(); mIt != mEnd; ++mIt)
  {
    for (std::map<Url, ConnectionAttemptPtr>::iterator uIt = mIt->second.begin(), uEnd = mIt->second.end();
         uIt != uEnd;
         ++uIt)
    {
      TransportSocketPtr endpoint = uIt->second->endpoint;

      // Disconnect any valid socket we were holding.
      if (endpoint)
      {
        endpoint->disconnect();
      }
      else
      {
        uIt->second->state = State_Error;
        uIt->second->promise.setError("TransportSocketCache is closing.");
      }
    }
  }
  for (std::list<TransportSocketPtr>::iterator it = pending.begin(), end = pending.end(); it != end; ++it)
    (*it)->disconnect();
}
Example #2
0
void NetworkServer::CleanupDeadConnections()
{
	// When we acquire the list of client connections, don't hold on to it for long, so that the worker thread can properly detach from it.
	ConnectionMap clientsMap = *clients.Acquire();

	// Clean up all disconnected/timed out connections.
	ConnectionMap::iterator iter = clientsMap.begin();
	while(iter != clientsMap.end())
	{
		ConnectionMap::iterator next = iter;
		++next;
		if (!iter->second->Connected())
		{
			LOG(LogInfo, "Client %s disconnected.", iter->second->ToString().c_str());
			if (networkServerListener)
				networkServerListener->ClientDisconnected(iter->second);
			if (iter->second->GetSocket() && iter->second->GetSocket()->TransportLayer() == SocketOverTCP)
				owner->CloseConnection(iter->second);

			{
				Lockable<ConnectionMap>::LockType clientsLock = clients.Acquire();
				clientsLock->erase(iter->first);
			}
		}
		iter = next;
	}
}
  ConnectionError SOCKS5BytestreamServer::recv( int timeout )
  {
    if( !m_tcpServer )
      return ConnNotConnected;

    ConnectionError ce = m_tcpServer->recv( timeout );
    if( ce != ConnNoError )
      return ce;

    // First take a snapshot of our connections, and then iterate the snapshot
    // (so that the live map can be modified by an erase while we
    // iterate the snapshot of the map)
    ConnectionMap connectionsSnapshot;

    m_mutex.lock();
    connectionsSnapshot.insert( m_connections.begin(), m_connections.end() );
    m_mutex.unlock();

    ConnectionMap::const_iterator it = connectionsSnapshot.begin();
    for( ; it != connectionsSnapshot.end(); ++it )
    {
      (*it).first->recv( timeout );
    }
    connectionsSnapshot.clear();

    m_mutex.lock();
    util::clearList( m_oldConnections );
    m_mutex.unlock();

    return ConnNoError;
  }
Example #4
0
void NetworkServer::Process()
{
	CleanupDeadConnections();

	for(size_t i = 0; i < listenSockets.size(); ++i)
	{
		Socket *listen = listenSockets[i];

		if (listen->TransportLayer() == SocketOverTCP)
		{
			// Accept the first inbound connection.
			Socket *client = AcceptConnections(listen);
			if (client)
			{
				if (!client->Connected())
					LOG(LogError, "Warning: Accepted an already closed connection!");

				LOG(LogInfo, "Client connected from %s.", client->ToString().c_str());

				// Build a MessageConnection on top of the raw socket.
				assert(listen->TransportLayer() == SocketOverTCP);
				Ptr(MessageConnection) clientConnection = new TCPMessageConnection(owner, this, client, ConnectionOK);
				assert(owner);
				owner->AssignConnectionToWorkerThread(clientConnection);

				if (networkServerListener)
					networkServerListener->NewConnectionEstablished(clientConnection);

				{
					PolledTimer timer;
					Lockable<ConnectionMap>::LockType clientsLock = clients.Acquire();
					(*clientsLock)[clientConnection->RemoteEndPoint()] = clientConnection;
					LOG(LogWaits, "NetworkServer::Process: Adding new accepted TCP connection to connection list took %f msecs.",
						timer.MSecsElapsed());
				}

				owner->NewMessageConnectionCreated(clientConnection);
			}
		}
	}

	// Note that the above loop will only accept one new connection/socket/iteration, so if there are multiple
	// pending new connections, they will only get accepted at a rate of one per each frame.

	// Process a new UDP connection attempt.
	ConnectionAttemptDescriptor *desc = udpConnectionAttempts.Front();
	if (desc)
	{
		ProcessNewUDPConnectionAttempt(desc->listenSocket, desc->peer, (const char *)desc->data.data, desc->data.size);
		udpConnectionAttempts.PopFront();
	}

	// Process all new inbound data for each connection handled by this server.
	ConnectionMap clientMap = *clients.Acquire();
	for(ConnectionMap::iterator iter = clientMap.begin(); iter != clientMap.end(); ++iter)
		iter->second->Process();
}