Status TransportLayerASIO::start() { stdx::lock_guard<stdx::mutex> lk(_mutex); _running.store(true); // If we're in async mode then the ServiceExecutor will handle calling run_one() in a pool // of threads. Otherwise we need a thread to just handle the async_accept calls. if (!_listenerOptions.async) { _listenerThread = stdx::thread([this] { setThreadName("listener"); while (_running.load()) { try { _ioContext->run(); _ioContext->reset(); } catch (...) { severe() << "Uncaught exception in the listener: " << exceptionToStatus(); fassertFailed(40491); } } }); } for (auto& acceptor : _acceptors) { acceptor.listen(); _acceptConnection(acceptor); } return Status::OK(); }
void TransportLayerASIO::_acceptConnection(GenericAcceptor& acceptor) { auto session = createSession(); if (!session) { _acceptConnection(acceptor); return; } auto& socket = session->getSocket(); auto acceptCb = [ this, session = std::move(session), &acceptor ](std::error_code ec) mutable { if (!_running.load()) return; if (ec) { log() << "Error accepting new connection on " << endpointToHostAndPort(acceptor.local_endpoint()) << ": " << ec.message(); _acceptConnection(acceptor); return; } size_t connCount = _currentConnections.addAndFetch(1); if (connCount > _listenerOptions.maxConns) { log() << "connection refused because too many open connections: " << connCount; _currentConnections.subtractAndFetch(1); _acceptConnection(acceptor); return; } session->postAcceptSetup(_listenerOptions.async); _createdConnections.addAndFetch(1); if (!serverGlobalParams.quiet.load()) { const auto word = (connCount == 1 ? " connection"_sd : " connections"_sd); log() << "connection accepted from " << session->remote() << " #" << session->id() << " (" << connCount << word << " now open)"; } _sep->startSession(std::move(session)); _acceptConnection(acceptor); }; acceptor.async_accept(socket, std::move(acceptCb)); }
void HTTPAcceptor::handleEnqueue(Message *message) { if (!message) return; PEGASUS_ASSERT(_rep != 0); switch (message->getType()) { case SOCKET_MESSAGE: { SocketMessage* socketMessage = (SocketMessage*)message; // If this is a connection request: PEGASUS_ASSERT(socketMessage->socket == _rep->socket); PEGASUS_ASSERT(socketMessage->events & SocketMessage::READ); _acceptConnection(); break; } case CLOSE_CONNECTION_MESSAGE: { CloseConnectionMessage* closeConnectionMessage = (CloseConnectionMessage*)message; AutoMutex autoMut(_rep->_connection_mut); for (Uint32 i = 0, n = _rep->connections.size(); i < n; i++) { HTTPConnection* connection = _rep->connections[i]; SocketHandle socket = connection->getSocket(); if (socket == closeConnectionMessage->socket) { _monitor->unsolicitSocketMessages(socket); _rep->connections.remove(i); delete connection; break; } } break; } default: PEGASUS_ASSERT(false); break; } delete message; }
Status TransportLayerASIO::start() { stdx::lock_guard<stdx::mutex> lk(_mutex); _running.store(true); // If we're in async mode then the ServiceExecutor will handle calling run_one() in a pool // of threads. Otherwise we need a thread to just handle the async_accept calls. if (!_listenerOptions.async) { _listenerThread = stdx::thread([this] { setThreadName("listener"); while (_running.load()) { try { _ioContext->run(); _ioContext->reset(); } catch (...) { severe() << "Uncaught exception in the listener: " << exceptionToStatus(); fassertFailed(40491); } } }); } for (auto& acceptor : _acceptors) { acceptor.listen(); _acceptConnection(acceptor); } const char* ssl = ""; #ifdef MONGO_CONFIG_SSL if (_sslMode != SSLParams::SSLMode_disabled) { ssl = " ssl"; } #endif log() << "waiting for connections on port " << _listenerOptions.port << ssl; return Status::OK(); }