// Copyright 2019, Chen Shuaihao.
//
//Author: Chen Shuaihao
//
//
#include "HttpServer.h"
#include
#include
#include
#include "TimerManager.h"
HttpServer::HttpServer(EventLoop *loop, const int port, const int iothreadnum, const int workerthreadnum)
: tcpserver_(loop, port, iothreadnum),
threadpool_(workerthreadnum)
{
tcpserver_.SetNewConnCallback(std::bind(&HttpServer::HandleNewConnection, this, std::placeholders::_1));
tcpserver_.SetMessageCallback(std::bind(&HttpServer::HandleMessage, this, std::placeholders::_1, std::placeholders::_2));
tcpserver_.SetSendCompleteCallback(std::bind(&HttpServer::HandleSendComplete, this, std::placeholders::_1));
tcpserver_.SetCloseCallback(std::bind(&HttpServer::HandleClose, this, std::placeholders::_1));
tcpserver_.SetErrorCallback(std::bind(&HttpServer::HandleError, this, std::placeholders::_1));
threadpool_.Start(); //å·¥ä½çº¿ç¨æ± å¯å¨
TimerManager::GetTimerManagerInstance()->Start(); //HttpServer宿¶å¨ç®¡çå¨å¯å¨
}
HttpServer::~HttpServer()
{
}
void HttpServer::HandleNewConnection(const spTcpConnection& sptcpconn)
{
//std::string msg(s);
std::shared_ptr sphttpsession = std::make_shared(); //å建åºç¨å±ä¼è¯
spTimer sptimer = std::make_shared(5000, Timer::TimerType::TIMER_ONCE, std::bind(&TcpConnection::Shutdown, sptcpconn));
sptimer->Start();
//å¯ä»¥ä¼åææ éï¼æ¾å
¥connéé¢å°±è¡
{
std::lock_guard <:mutex> lock(mutex_);
httpsessionnlist_[sptcpconn] = sphttpsession;
timerlist_[sptcpconn] = sptimer;
}
}
void HttpServer::HandleMessage(const spTcpConnection& sptcpconn, std::string &msg)
{
std::shared_ptr sphttpsession;
spTimer sptimer;
{
std::lock_guard <:mutex> lock(mutex_);
sphttpsession = httpsessionnlist_[sptcpconn];
sptimer = timerlist_[sptcpconn];
}
sptimer->Adjust(5000, Timer::TimerType::TIMER_ONCE, std::bind(&TcpConnection::Shutdown, sptcpconn));
if(threadpool_.GetThreadNum() > 0)
{
//Bug20190320ï¼å¤çº¿ç¨ä¸ï¼å¯¹è±¡ç声æå¨æç®¡çé®é¢ï¼å°±åå¨è¿éï¼åçº¿ç¨æ± ä¼ å
¥äºphttpsessionåptcpconnï¼æä¹ç¥éå
¶æå对象æ¯å¦å·²ç»ææäºå¢ï¼
//æä»¥ï¼éè¦éç¨æºè½æéæ¥ç®¡ç对象,æ¿æ¢åå§æé
//çº¿ç¨æ± å¤çä¸å¡ï¼å¤çå®åæé忬IOçº¿ç¨æ§è¡send
//std::cout << "threadpool_.AddTask" << std::endl;
HttpRequestContext httprequestcontext;
std::string responsecontext;
bool result = sphttpsession->PraseHttpRequest(msg, httprequestcontext);
if(result == false)
{
sphttpsession->HttpError(400, "Bad request", httprequestcontext, responsecontext); //è¯·æ±æ¥æè§£æéè¯¯ï¼æ¥400
sptcpconn->Send(responsecontext);
return;
}
sptcpconn->SetAsyncProcessing(true);
threadpool_.AddTask([=]() {
//HttpRequestContext req = httprequestcontext;
std::string responsemsg;
sphttpsession->HttpProcess(httprequestcontext, responsemsg);
sptcpconn->Send(responsemsg); //ä»»å¡å·²ç»å¤çå®æï¼æ§è¡è·¨çº¿ç¨è°åº¦ï¼å³åè°
if(!sphttpsession->KeepAlive())
{
//çè¿æ¥ï¼å¯ä»¥åè¯æ¡æ¶å±æ°æ®åå®å°±å¯ä»¥å
³æTCPè¿æ¥ï¼ä¸è¿è¿é注éæï¼è¿æ¯äº¤ç»å®¢æ·ç«¯ä¸»å¨å
³éå§
//sptcpconn->HandleClose();
}
});
}
else
{
//没æå¼å¯ä¸å¡çº¿ç¨æ± ï¼ä¸å¡è®¡ç®ç´æ¥å¨IOçº¿ç¨æ§è¡
HttpRequestContext httprequestcontext;
std::string responsecontext;
bool result = sphttpsession->PraseHttpRequest(msg, httprequestcontext);
if(result == false)
{
sphttpsession->HttpError(400, "Bad request", httprequestcontext, responsecontext); //è¯·æ±æ¥æè§£æéè¯¯ï¼æ¥400
sptcpconn->Send(responsecontext);
return;
}
sphttpsession->HttpProcess(httprequestcontext, responsecontext);
sptcpconn->Send(responsecontext);
if(!sphttpsession->KeepAlive())
{
//çè¿æ¥ï¼å¯ä»¥åè¯æ¡æ¶å±æ°æ®åå®å°±å¯ä»¥å
³æTCPè¿æ¥ï¼ä¸è¿è¿é注éæï¼è¿æ¯äº¤ç»å®¢æ·ç«¯ä¸»å¨å
³éå§
//sptcpconn->HandleClose();
}
}
}
void HttpServer::HandleSendComplete(const spTcpConnection& sptcpconn)
{
}
void HttpServer::HandleClose(const spTcpConnection& sptcpconn)
{
{
std::lock_guard <:mutex> lock(mutex_);
httpsessionnlist_.erase(sptcpconn);
timerlist_.erase(sptcpconn);
}
}
void HttpServer::HandleError(const spTcpConnection& sptcpconn)
{
{
std::lock_guard <:mutex> lock(mutex_);
httpsessionnlist_.erase(sptcpconn);
timerlist_.erase(sptcpconn);
}
}
void HttpServer::Start()
{
tcpserver_.Start();
}