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(); }
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; }
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(); }