void TEpoll::dispatchSendData() { TSendData *sd; while (sendRequests.dequeue(sd)) { TEpollSocket *sock = sd->socket; if (Q_UNLIKELY(sock->socketDescriptor() <= 0)) { tSystemDebug("already disconnected: sid:%d", sock->socketId()); continue; } switch (sd->method) { case TSendData::Disconnect: deletePoll(sock); sock->close(); sock->deleteLater(); break; case TSendData::SwitchToWebSocket: { tSystemDebug("Switch to WebSocket"); Q_ASSERT(sd->buffer == nullptr); QByteArray secKey = sd->header.rawHeader("Sec-WebSocket-Key"); tSystemDebug("secKey: %s", secKey.data()); int newsocket = TApplicationServerBase::duplicateSocket(sock->socketDescriptor()); // Switch to WebSocket TEpollWebSocket *ws = new TEpollWebSocket(newsocket, sock->peerAddress(), sd->header); ws->moveToThread(Tf::app()->thread()); addPoll(ws, (EPOLLIN | EPOLLOUT | EPOLLET)); // reset // Stop polling and delete deletePoll(sock); sock->deleteLater(); // WebSocket opening TSession session; QByteArray sessionId = sd->header.cookie(TSession::sessionName()); if (!sessionId.isEmpty()) { // Finds a session session = TSessionManager::instance().findSession(sessionId); } ws->startWorkerForOpening(session); break; } default: tSystemError("Logic error [%s:%d]", __FILE__, __LINE__); if (sd->buffer) { delete sd->buffer; } break; } delete sd; } }
void TMultiplexingServer::run() { QString mpm = Tf::app()->multiProcessingModuleString(); maxWorkers = Tf::app()->appSettings().value(QLatin1String("MPM.") + mpm + ".MaxWorkersPerAppServer").toInt(); if (maxWorkers <= 0) { maxWorkers = Tf::app()->appSettings().value(QLatin1String("MPM.") + mpm + ".MaxWorkersPerServer", "128").toInt(); } tSystemDebug("MaxWorkers: %d", maxWorkers); int appsvrnum = qMax(Tf::app()->maxNumberOfAppServers(), 1); setNoDeleyOption(listenSocket); TEpollSocket *sock = TEpollSocket::create(listenSocket, QHostAddress()); TEpoll::instance()->addPoll(sock, EPOLLIN); int numEvents = 0; for (;;) { if (!numEvents && TActionWorker::workerCount() > 0) { TEpollSocket::waitSendData(5); // mitigation of busy loop } TEpollSocket::dispatchSendData(); // Poll Sending/Receiving/Incoming int timeout = (TActionWorker::workerCount() > 0) ? 0 : 100; numEvents = TEpoll::instance()->wait(timeout); if (numEvents < 0) break; TEpollSocket *epSock; while ( (epSock = TEpoll::instance()->next()) ) { int cltfd = epSock->socketDescriptor(); if (cltfd == listenSocket) { for (;;) { TEpollSocket *sock = TEpollSocket::accept(listenSocket); if (!sock) break; TEpoll::instance()->addPoll(sock, (EPOLLIN | EPOLLOUT | EPOLLET)); if (appsvrnum > 1) { break; // Load smoothing } } continue; } else { if ( TEpoll::instance()->canSend() ) { // Send data int len = epSock->send(); if (len < 0) { TEpoll::instance()->deletePoll(epSock); epSock->close(); epSock->deleteLater(); continue; } } if ( TEpoll::instance()->canReceive() ) { if (TActionWorker::workerCount() >= maxWorkers) { // not receive TEpoll::instance()->modifyPoll(epSock, (EPOLLIN | EPOLLOUT | EPOLLET)); // reset continue; } // Receive data int len = epSock->recv(); if (len < 0) { TEpoll::instance()->deletePoll(epSock); epSock->close(); epSock->deleteLater(); continue; } if (epSock->canReadHttpRequest()) { #if 1 //TODO: delete here for HTTP 2.0 support // Stop receiving, otherwise the responses is sometimes // placed in the wrong order in case of HTTP-pipeline. TEpoll::instance()->modifyPoll(epSock, (EPOLLOUT | EPOLLET)); // reset #endif emit incomingHttpRequest(epSock); } } } } // Check stop flag if (stopped) { break; } } TEpollSocket::releaseAllSockets(); TActionContext::releaseAll(); }
void TMultiplexingServer::run() { QString mpm = Tf::appSettings()->value(Tf::MultiProcessingModule).toString().toLower(); maxWorkers = Tf::appSettings()->readValue(QLatin1String("MPM.") + mpm + ".MaxWorkersPerAppServer").toInt(); if (maxWorkers <= 0) { maxWorkers = Tf::appSettings()->readValue(QLatin1String("MPM.") + mpm + ".MaxWorkersPerServer", "128").toInt(); } tSystemDebug("MaxWorkers: %d", maxWorkers); int appsvrnum = qMax(Tf::app()->maxNumberOfAppServers(), 1); setNoDeleyOption(listenSocket); TEpollSocket *lsn = TEpollSocket::create(listenSocket, QHostAddress()); TEpoll::instance()->addPoll(lsn, EPOLLIN); int numEvents = 0; for (;;) { if (!numEvents && TActionWorker::workerCount() > 0) { TEpoll::instance()->waitSendData(4); // mitigation of busy loop } TEpoll::instance()->dispatchSendData(); // Poll Sending/Receiving/Incoming int timeout = (TActionWorker::workerCount() > 0) ? 0 : 100; numEvents = TEpoll::instance()->wait(timeout); if (numEvents < 0) break; TEpollSocket *sock; while ( (sock = TEpoll::instance()->next()) ) { int cltfd = sock->socketDescriptor(); if (cltfd == listenSocket) { for (;;) { TEpollSocket *acceptedSock = TEpollSocket::accept(listenSocket); if (Q_UNLIKELY(!acceptedSock)) break; TEpoll::instance()->addPoll(acceptedSock, (EPOLLIN | EPOLLOUT | EPOLLET)); if (appsvrnum > 1) { break; // Load smoothing } } continue; } else { if ( TEpoll::instance()->canSend() ) { // Send data int len = TEpoll::instance()->send(sock); if (Q_UNLIKELY(len < 0)) { TEpoll::instance()->deletePoll(sock); sock->close(); sock->deleteLater(); continue; } } if ( TEpoll::instance()->canReceive() ) { if (TActionWorker::workerCount() >= maxWorkers) { // not receive TEpoll::instance()->modifyPoll(sock, (EPOLLIN | EPOLLOUT | EPOLLET)); // reset continue; } if (sock->countWorker() > 0) { // not receive sock->pollIn = true; continue; } // Receive data int len = TEpoll::instance()->recv(sock); if (Q_UNLIKELY(len < 0)) { TEpoll::instance()->deletePoll(sock); sock->close(); sock->deleteLater(); continue; } if (sock->canReadRequest()) { sock->startWorker(); } } } } // Check stop flag if (stopped.load()) { break; } } TEpoll::instance()->releaseAllPollingSockets(); TActionWorker::waitForAllDone(10000); }