void HttpServer::setSessionCallback(HttpSession::PTR httpSession, HTTPPARSER_CALLBACK callback, CLOSE_CALLBACK closeCallback)
{
    /*TODO::keep alive and timeout close */
    TCPSession::PTR session = httpSession->getSession();
    HTTPParser* httpParser = new HTTPParser(HTTP_BOTH);
    session->setUD((int64_t)httpParser);
    session->setCloseCallback([closeCallback, httpSession](TCPSession::PTR session){
        HTTPParser* httpParser = (HTTPParser*)session->getUD();
        delete httpParser;
        if (closeCallback != nullptr)
        {
            closeCallback(httpSession);
        }
    });
    session->setDataCallback([this, callback, httpSession](TCPSession::PTR session, const char* buffer, size_t len){
        int retlen = 0;
        HTTPParser* httpParser = (HTTPParser*)session->getUD();
        if (httpParser->isWebSocket())
        {
            std::string frame(buffer, len);
            std::string payload;
            uint8_t opcode; /*TODO::opcode是否回传给回调函数*/
            if (WebSocketFormat::wsFrameExtract(frame, payload, opcode))
            {
                callback(*httpParser, httpSession, payload.c_str(), payload.size());
                retlen = len;
            }
        }
        else
        {
            retlen = httpParser->tryParse(buffer, len);
            if (httpParser->isCompleted())
            {
                if (httpParser->isWebSocket())
                {
                    std::string response = WebSocketFormat::wsHandshake(httpParser->getValue("Sec-WebSocket-Key"));
                    session->send(response.c_str(), response.size());
                }
                else
                {
                    callback(*httpParser, httpSession, nullptr, 0);
                    if (httpParser->isKeepAlive())
                    {
                        /*清除本次http报文数据,为下一次http报文准备*/
                        httpParser->clearParse();
                    }
                }
            }
        }

        return retlen;
    });
}
Beispiel #2
0
int main(int argc, char **argv)
{
    if (argc != 4)
    {
        fprintf(stderr, "Usage: <listen port> <backend ip> <backend port>");
        exit(-1);
    }

    int bindPort = atoi(argv[1]);
    string backendIP = argv[2];
    int backendPort = atoi(argv[3]);

    auto tcpService = std::make_shared<WrapTcpService>();
    tcpService->startWorkThread(std::thread::hardware_concurrency());

    auto asyncConnector = AsyncConnector::Create();
    asyncConnector->startWorkerThread();

    auto listenThread = ListenThread::Create();

    // listen for front http client
    listenThread->startListen(false, "0.0.0.0", bindPort, [tcpService, asyncConnector, backendIP, backendPort](sock fd) {
        tcpService->addSession(fd, [tcpService, asyncConnector, backendIP, backendPort](const TCPSession::PTR& session) {
            session->setUD(static_cast<int64_t>(1));
            std::shared_ptr<TCPSession::PTR> shareBackendSession = std::make_shared<TCPSession::PTR>(nullptr);
            std::shared_ptr<std::vector<string>> cachePacket = std::make_shared<std::vector<std::string>>();

            /* new connect to backend server */
            asyncConnector->asyncConnect(backendIP.c_str(), backendPort, std::chrono::seconds(10), [tcpService, session, shareBackendSession, cachePacket](sock fd) {
                if (true)
                {
                    tcpService->addSession(fd, [=](const TCPSession::PTR& backendSession) {
                        auto ud = brynet::net::cast<int64_t>(session->getUD());
                        if (*ud == -1)   /*if http client already close*/
                        {
                            backendSession->postDisConnect();
                            return;
                        }

                        *shareBackendSession = backendSession;

                        for (auto& p : *cachePacket)
                        {
                            backendSession->send(p.c_str(), p.size());
                        }
                        cachePacket->clear();

                        backendSession->setDisConnectCallback([=](const TCPSession::PTR& backendSession) {
                            *shareBackendSession = nullptr;
                            auto ud = brynet::net::cast<int64_t>(session->getUD());
                            if (*ud != -1)
                            {
                                session->postDisConnect();
                            }
                        });

                        backendSession->setDataCallback([=](const TCPSession::PTR& backendSession, const char* buffer, size_t size) {
                            /* recieve data from backend server, then send to http client */
                            session->send(buffer, size);
                            return size;
                        });
                    }, false, nullptr, 32 * 1024, false);
                }
            }, nullptr);

            session->setDataCallback([=](const TCPSession::PTR&, const char* buffer, size_t size) {
                TCPSession::PTR backendSession = *shareBackendSession;
                if (backendSession == nullptr)
                {
                    /*cache it*/
                    cachePacket->push_back(std::string(buffer, size));
                }
                else
                {
                    /* receive data from http client, then send to backend server */
                    backendSession->send(buffer, size);
                }

                return size;
            });

            session->setDisConnectCallback([=](const TCPSession::PTR& session) {
                /*if http client close, then close it's backend server */
                TCPSession::PTR backendSession = *shareBackendSession;
                if (backendSession != nullptr)
                {
                    backendSession->postDisConnect();
                }

                session->setUD(-1);
            });
        }, false, nullptr, 32 * 1024);
    });
    
    std::cin.get();
}
int onSessionMsg(TCPSession::PTR session, const char* buffer, size_t len)
{
    session->send(buffer, len);
    return len;
}