void startServer() { int timer; fd_set rdfs; blockGroup* block_group; struct timeval tval; tval.tv_sec = PING_TIMER; tval.tv_usec = 0; block_group = newBlockGroup(); block_group->server_socket = initServer(); block_group->max_socket = block_group->server_socket; printf("[IMPORTANT] : Press Enter to Stop the Boss\n"); for ( ;; ) { FD_ZERO(&rdfs); setHandler(block_group, &rdfs); if( (timer = select(block_group->max_socket + 1, &rdfs, NULL, NULL, &tval)) == -1) { QUIT_MSG("Can't select : "); } if ( timer == 0 ) { tval.tv_sec = handlerPresence(block_group); } #ifdef linux if( FD_ISSET(STDIN_FILENO, &rdfs) ) { break; } else #endif if( FD_ISSET(block_group->server_socket, &rdfs) ) { handleNewClient(block_group); } else { handlerClient(block_group, &rdfs); } } printf("[BYE] Server stop\n\n"); closeServer(block_group); return; }
void Master::acceptClientAsync(bool initial) { if (initial) { BOOST_LOG_SEV(log, LogLevel::Info) << format("Listening for clients at %s.") % clientAcceptor.local_endpoint(); } try { clientAcceptor.async_accept(waitingClient->tcpSocket(), [=](const boost::system::error_code& errorCode) { if (errorCode.value() == boost::asio::error::operation_aborted || disposed) { std::lock_guard<std::mutex> guard(clientAcceptorMutex); clientAcceptorRunning = false; clientAcceptorCV.notify_all(); return; } else if (errorCode) { if (initial) { BOOST_LOG_SEV(log, LogLevel::Fatal) << format("Accepting client connection failed: %s.") % errorCode; } std::lock_guard<std::mutex> guard(clientAcceptorMutex); clientAcceptorRunning = false; clientAcceptorCV.notify_all(); return; } else { // New client connected. auto conn = waitingClient; // Prepare to accept the next client. { std::lock_guard<std::recursive_mutex> lock(clientsMutex); clients[conn->id()] = std::move(waitingClient); waitingClient = std::make_shared<MasterClient>(*this, conn->id() + 1, _parameters.allowVersionSpecification); } std::weak_ptr<MasterClient> weakConn(conn); // Setup "someone needs to respond to me" handler conn->onNeedsResponse.connect([this, weakConn](const std::shared_ptr<MasterClientResponse>& r) { auto conn = weakConn.lock(); if (!conn) { // Unexpected... BOOST_LOG_SEV(log, LogLevel::Error) << "onNeedsResponse raised by unexistent MasterClient."; return; } // Use balancer to choose a server. auto domain = bindClientToDomain(conn); if (!domain) { r->reject("Could not find a suitable domain. Overload possible."); return; } auto version = domain->second; BOOST_LOG_SEV(log, LogLevel::Debug) << format("Bound client '%d' to '%s' at '%s'.") % conn->id() % version % domain->first->nodeInfo().nodeName; // Make sure MasterClientResponse is in pendingClients // until it is done { std::lock_guard<std::recursive_mutex> lock(pendingClientsMutex); PendingClient pend; pend.response = r; pend.version = version; pendingClients.emplace(r->client()->id(), std::move(pend)); } std::function<void(bool)> onResponded = [this, conn](bool) { std::lock_guard<std::recursive_mutex> lock(pendingClientsMutex); pendingClients.erase(conn->id()); }; r->onResponded.connect(onResponded); // It is not impossible that time-out already happened... if (r->isResponded()) { onResponded(false); return; } // Let node process the response. domain->first->acceptClient(r, version); }); // Register client shutdown handler. conn->onShutdown.connect([this, weakConn]() { auto conn = weakConn.lock(); if (!conn) { // Unexpected... BOOST_LOG_SEV(log, LogLevel::Error) << "onShutdown raised by unexistent MasterClient."; return; } removeClient(conn->id()); }); // Start service conn->handleNewClient(); } // Accept next connection acceptClientAsync(false); }); } catch (...) { std::lock_guard<std::mutex> guard(clientAcceptorMutex); clientAcceptorRunning = false; clientAcceptorCV.notify_all(); throw; } }