优化http分包器性能

This commit is contained in:
xiongziliang 2018-09-23 00:55:00 +08:00
parent 10ef758211
commit 67644a7bad
7 changed files with 97 additions and 98 deletions

View File

@ -7,48 +7,68 @@
#include "Util/util.h" #include "Util/util.h"
using namespace ZL::Util; using namespace ZL::Util;
void HttpRequestSplitter::input(const string &data) { void HttpRequestSplitter::input(const char *data,uint64_t len) {
if(_remain_data.empty()){ const char *ptr = data;
_remain_data = data; if(!_remain_data.empty()){
}else{ _remain_data.append(data,len);
_remain_data.append(data); data = ptr = _remain_data.data();
len = _remain_data.size();
} }
splitPacket: splitPacket:
//数据按照请求头处理 //数据按照请求头处理
size_t index; char *index = nullptr;
while (_content_len == 0 && (index = _remain_data.find("\r\n\r\n")) != std::string::npos ) { while (_content_len == 0 && (index = strstr(ptr,"\r\n\r\n")) != nullptr) {
//_content_len == 0这是请求头 //_content_len == 0这是请求头
_content_len = onRecvHeader(_remain_data.substr(0, index + 4)); _content_len = onRecvHeader(ptr, index - ptr + 4);
_remain_data.erase(0, index + 4); ptr = index + 4;
} }
if(_remain_data.empty()){ uint64_t remain = len - (ptr - data);
if(remain <= 0){
//没有剩余数据,清空缓存
_remain_data.clear();
return; return;
} }
if(_content_len == 0){
//尚未找到http头缓存定位到剩余数据部分
_remain_data.assign(ptr,remain);
return;
}
//已经找到http头了
if(_content_len > 0){ if(_content_len > 0){
//数据按照固定长度content处理 //数据按照固定长度content处理
if(_remain_data.size() < _content_len){ if(remain < _content_len){
//数据不够 //数据不够,缓存定位到剩余数据部分
_remain_data.assign(ptr,remain);
return; return;
} }
//收到content数据并且接受content完毕 //收到content数据并且接受content完毕
onRecvContent(_remain_data.substr(0,_content_len)); onRecvContent(ptr,_content_len);
_remain_data.erase(0,_content_len);
remain -= _content_len;
ptr += _content_len;
//content处理完毕,后面数据当做请求头处理 //content处理完毕,后面数据当做请求头处理
_content_len = 0; _content_len = 0;
if(!_remain_data.empty()){ if(remain > 0){
//还有数据没有处理完毕 //还有数据没有处理完毕
_remain_data.assign(ptr,remain);
data = ptr = (char *)_remain_data.data();
len = _remain_data.size();
goto splitPacket; goto splitPacket;
} }
}else{ return;
//数据按照不固定长度content处理
onRecvContent(_remain_data);
_remain_data.clear();
} }
//_content_len < 0;数据按照不固定长度content处理
onRecvContent(ptr,remain);//消费掉所有剩余数据
_remain_data.clear();
} }
void HttpRequestSplitter::setContentLen(int64_t content_len) { void HttpRequestSplitter::setContentLen(int64_t content_len) {

View File

@ -16,25 +16,29 @@ public:
/** /**
* *
* @param data * @param data
* @param len
*/ */
void input(const string &data); void input(const char *data,uint64_t len);
protected: protected:
/** /**
* *
* @param header * @param data
* @param len
*
* @return content长度, * @return content长度,
* <0 : content * <0 : content
* 0 : , * 0 : ,
* >0 : content, * >0 : content,
*/ */
virtual int64_t onRecvHeader(const string &header) = 0; virtual int64_t onRecvHeader(const char *data,uint64_t len) = 0;
/** /**
* content分片或全部数据 * content分片或全部数据
* onRecvHeader函数返回>0, * onRecvHeader函数返回>0,
* @param content * @param data content分片或全部数据
* @param len
*/ */
virtual void onRecvContent(const string &content) = 0; virtual void onRecvContent(const char *data,uint64_t len) {};
/** /**
* content len * content len

View File

@ -117,7 +117,7 @@ HttpSession::~HttpSession() {
//DebugL; //DebugL;
} }
int64_t HttpSession::onRecvHeader(const string &header) { int64_t HttpSession::onRecvHeader(const char *header,uint64_t len) {
typedef bool (HttpSession::*HttpCMDHandle)(int64_t &); typedef bool (HttpSession::*HttpCMDHandle)(int64_t &);
static unordered_map<string, HttpCMDHandle> g_mapCmdIndex; static unordered_map<string, HttpCMDHandle> g_mapCmdIndex;
static onceToken token([]() { static onceToken token([]() {
@ -125,7 +125,7 @@ int64_t HttpSession::onRecvHeader(const string &header) {
g_mapCmdIndex.emplace("POST",&HttpSession::Handle_Req_POST); g_mapCmdIndex.emplace("POST",&HttpSession::Handle_Req_POST);
}, nullptr); }, nullptr);
m_parser.Parse(header.data()); m_parser.Parse(header);
urlDecode(m_parser); urlDecode(m_parser);
string cmd = m_parser.Method(); string cmd = m_parser.Method();
auto it = g_mapCmdIndex.find(cmd); auto it = g_mapCmdIndex.find(cmd);
@ -148,9 +148,9 @@ int64_t HttpSession::onRecvHeader(const string &header) {
return content_len; return content_len;
} }
void HttpSession::onRecvContent(const string &content) { void HttpSession::onRecvContent(const char *data,uint64_t len) {
if(m_contentCallBack){ if(m_contentCallBack){
if(!m_contentCallBack(content)){ if(!m_contentCallBack(data,len)){
m_contentCallBack = nullptr; m_contentCallBack = nullptr;
} }
} }
@ -161,7 +161,7 @@ void HttpSession::onRecv(const Buffer::Ptr &pBuf) {
} }
void HttpSession::onRecv(const char *data,int size){ void HttpSession::onRecv(const char *data,int size){
m_ticker.resetTime(); m_ticker.resetTime();
input(string(data,size)); input(data,size);
} }
void HttpSession::onError(const SockException& err) { void HttpSession::onError(const SockException& err) {
@ -271,8 +271,8 @@ inline bool HttpSession::Handle_Req_GET(int64_t &content_len) {
if(checkWebSocket()){ if(checkWebSocket()){
content_len = -1; content_len = -1;
auto parserCopy = m_parser; auto parserCopy = m_parser;
m_contentCallBack = [this,parserCopy](const string &data){ m_contentCallBack = [this,parserCopy](const char *data,uint64_t len){
onRecvWebSocketData(parserCopy,data); onRecvWebSocketData(parserCopy,data,len);
//m_contentCallBack是可持续的后面还要处理后续数据 //m_contentCallBack是可持续的后面还要处理后续数据
return true; return true;
}; };
@ -638,11 +638,11 @@ inline bool HttpSession::Handle_Req_POST(int64_t &content_len) {
//返回固定长度的content //返回固定长度的content
content_len = totalContentLen; content_len = totalContentLen;
auto parserCopy = m_parser; auto parserCopy = m_parser;
m_contentCallBack = [this,parserCopy](const string &content){ m_contentCallBack = [this,parserCopy](const char *data,uint64_t len){
//恢复http头 //恢复http头
m_parser = parserCopy; m_parser = parserCopy;
//设置content //设置content
m_parser.setContent(content); m_parser.setContent(string(data,len));
//触发http事件emitHttpEvent内部会选择是否关闭连接 //触发http事件emitHttpEvent内部会选择是否关闭连接
emitHttpEvent(true); emitHttpEvent(true);
//清空数据,节省内存 //清空数据,节省内存
@ -654,13 +654,13 @@ inline bool HttpSession::Handle_Req_POST(int64_t &content_len) {
//返回不固定长度的content //返回不固定长度的content
content_len = -1; content_len = -1;
auto parserCopy = m_parser; auto parserCopy = m_parser;
std::shared_ptr<int64_t> recvedContentLen = std::make_shared<int64_t>(0); std::shared_ptr<uint64_t> recvedContentLen = std::make_shared<uint64_t>(0);
bool bClose = (strcasecmp(m_parser["Connection"].data(),"close") == 0) || ( ++m_iReqCnt > maxReqCnt); bool bClose = (strcasecmp(m_parser["Connection"].data(),"close") == 0) || ( ++m_iReqCnt > maxReqCnt);
m_contentCallBack = [this,parserCopy,totalContentLen,recvedContentLen,bClose](const string &content){ m_contentCallBack = [this,parserCopy,totalContentLen,recvedContentLen,bClose](const char *data,uint64_t len){
*(recvedContentLen) += content.size(); *(recvedContentLen) += len;
onRecvUnlimitedContent(parserCopy,content,totalContentLen,*(recvedContentLen)); onRecvUnlimitedContent(parserCopy,data,len,totalContentLen,*(recvedContentLen));
if(*(recvedContentLen) < totalContentLen){ if(*(recvedContentLen) < totalContentLen){
//数据还没接收完毕 //数据还没接收完毕

View File

@ -70,44 +70,34 @@ protected:
std::shared_ptr<FlvMuxer> getSharedPtr() override; std::shared_ptr<FlvMuxer> getSharedPtr() override;
//HttpRequestSplitter override //HttpRequestSplitter override
/** int64_t onRecvHeader(const char *data,uint64_t len) override;
* void onRecvContent(const char *data,uint64_t len) override;
* @param header
* @return content长度,
* <0 : content
* 0 : ,
* >0 : content,
*/
int64_t onRecvHeader(const string &header) override;
/**
* content分片或全部数据
* onRecvHeader函数返回>0,
* @param content
*/
void onRecvContent(const string &content) override;
/** /**
* content * content
* http-flv推流 * http-flv推流
* @param header http请求头 * @param header http请求头
* @param content content分片数据 * @param data content分片数据
* @param len content分片数据大小
* @param totalSize content总大小,0content * @param totalSize content总大小,0content
* @param recvedSize * @param recvedSize
*/ */
virtual void onRecvUnlimitedContent(const Parser &header,const string &content,int64_t totalSize,int64_t recvedSize){ virtual void onRecvUnlimitedContent(const Parser &header,
const char *data,
uint64_t len,
uint64_t totalSize,
uint64_t recvedSize){
WarnL << "content数据长度过大无法处理,请重载HttpSession::onRecvUnlimitedContent"; WarnL << "content数据长度过大无法处理,请重载HttpSession::onRecvUnlimitedContent";
shutdown(); shutdown();
} }
void onWebSocketDecodeHeader(const WebSocketHeader &packet) override{
DebugL << "默认关闭WebSocket";
shutdown();
};
/** void onRecvWebSocketData(const Parser &header,const char *data,uint64_t len){
* websocket数据 WebSocketSplitter::decode((uint8_t *)data,len);
* @param header http请求头
* @param data websocket数据
*/
virtual void onRecvWebSocketData(const Parser &header,const string &data){
WebSocketSplitter::decode((uint8_t *)data.data(),data.size());
} }
private: private:
Parser m_parser; Parser m_parser;
@ -119,7 +109,7 @@ private:
//flv over http //flv over http
MediaInfo m_mediaInfo; MediaInfo m_mediaInfo;
//处理content数据的callback //处理content数据的callback
function<bool (const string &content) > m_contentCallBack; function<bool (const char *data,uint64_t len) > m_contentCallBack;
private: private:
inline bool Handle_Req_GET(int64_t &content_len); inline bool Handle_Req_GET(int64_t &content_len);
inline bool Handle_Req_POST(int64_t &content_len); inline bool Handle_Req_POST(int64_t &content_len);

View File

@ -90,6 +90,8 @@ begin_decode:
onWebSocketDecodeHeader(*this); onWebSocketDecodeHeader(*this);
} }
//进入后面逻辑代表已经获取到了webSocket协议头
uint64_t remain = len - (ptr - data); uint64_t remain = len - (ptr - data);
if(remain > 0){ if(remain > 0){
uint64_t playload_slice_len = remain; uint64_t playload_slice_len = remain;
@ -101,16 +103,17 @@ begin_decode:
if(_playload_offset == _playload_len){ if(_playload_offset == _playload_len){
//这是下一个包 //这是下一个包
if(remain - playload_slice_len > 0){ remain -= playload_slice_len;
string nextPacket((char *)ptr + playload_slice_len,remain - playload_slice_len); ptr += playload_slice_len;
_got_header = false; _got_header = false;
_remain_data = nextPacket;
if(remain > 0){
//剩余数据是下一个包,把它的数据放置在缓存中
_remain_data.assign((char *)ptr,remain);
data = ptr = (uint8_t *)_remain_data.data(); data = ptr = (uint8_t *)_remain_data.data();
len = _remain_data.size(); len = _remain_data.size();
goto begin_decode; goto begin_decode;
} else{
_got_header = false;
} }
} }
} }

View File

@ -140,15 +140,11 @@ void RtspSession::onManager() {
} }
void RtspSession::onRecvContent(const string &content){ int64_t RtspSession::onRecvHeader(const char *header,uint64_t len) {
}
int64_t RtspSession::onRecvHeader(const string &header) {
char tmp[2 * 1024]; char tmp[2 * 1024];
m_pcBuf = tmp; m_pcBuf = tmp;
m_parser.Parse(header.data()); //rtsp请求解析 m_parser.Parse(header); //rtsp请求解析
string strCmd = m_parser.Method(); //提取出请求命令字 string strCmd = m_parser.Method(); //提取出请求命令字
m_iCseq = atoi(m_parser["CSeq"].data()); m_iCseq = atoi(m_parser["CSeq"].data());
@ -188,18 +184,19 @@ void RtspSession::onRecv(const Buffer::Ptr &pBuf) {
m_ui64TotalBytes += pBuf->size(); m_ui64TotalBytes += pBuf->size();
if (m_bBase64need) { if (m_bBase64need) {
//quicktime 加密后的rtsp请求需要解密 //quicktime 加密后的rtsp请求需要解密
inputRtspOrRtcp(decodeBase64(string(pBuf->data(),pBuf->size()))); auto str = decodeBase64(string(pBuf->data(),pBuf->size()));
inputRtspOrRtcp(str.data(),str.size());
} else { } else {
inputRtspOrRtcp(string(pBuf->data(),pBuf->size())); inputRtspOrRtcp(pBuf->data(),pBuf->size());
} }
} }
void RtspSession::inputRtspOrRtcp(const string &str) { void RtspSession::inputRtspOrRtcp(const char *data,uint64_t len) {
if(str[0] == '$' && m_rtpType == PlayerBase::RTP_TCP){ if(data[0] == '$' && m_rtpType == PlayerBase::RTP_TCP){
//这是rtcp //这是rtcp
return; return;
} }
input(str); input(data,len);
} }
bool RtspSession::handleReq_Options() { bool RtspSession::handleReq_Options() {

View File

@ -1,4 +1,4 @@
/* /*
* MIT License * MIT License
* *
* Copyright (c) 2016 xiongziliang <771730766@qq.com> * Copyright (c) 2016 xiongziliang <771730766@qq.com>
@ -84,24 +84,9 @@ public:
protected: protected:
//HttpRequestSplitter override //HttpRequestSplitter override
/** int64_t onRecvHeader(const char *data,uint64_t len) override ;
*
* @param header
* @return content长度,
* <0 : content
* 0 : ,
* >0 : content,
*/
int64_t onRecvHeader(const string &header) override ;
/**
* content分片或全部数据
* onRecvHeader函数返回>0,
* @param content
*/
void onRecvContent(const string &content) override;
private: private:
void inputRtspOrRtcp(const string &str); void inputRtspOrRtcp(const char *data,uint64_t len);
int send(const string &strBuf) override { int send(const string &strBuf) override {
m_ui64TotalBytes += strBuf.size(); m_ui64TotalBytes += strBuf.size();
return m_pSender->send(strBuf); return m_pSender->send(strBuf);