Exemplo n.º 1
0
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);
}