Older/MediaServer/Http/HttpRequestSplitter.cpp

182 lines
6.2 KiB
C++
Raw Normal View History

2024-09-28 23:55:00 +08:00
/*
* Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved.
*
* This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit).
*
* Use of this source code is governed by MIT-like license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
*/
#include "HttpRequestSplitter.h"
#include "Util/logger.h"
#include "Util/util.h"
using namespace toolkit;
using namespace std;
// 协议解析最大缓存4兆数据 [AUTO-TRANSLATED:75159526]
// Protocol parsing maximum cache 4MB data
static constexpr size_t kMaxCacheSize = 4 * 1024 * 1024;
namespace mediakit {
void HttpRequestSplitter::input(const char *data,size_t len) {
{
auto size = remainDataSize();
if (size > _max_cache_size) {
// 缓存太多数据无法处理则上抛异常 [AUTO-TRANSLATED:30e48e9e]
// If too much data is cached and cannot be processed, throw an exception
reset();
throw std::out_of_range("remain data size is too huge, now cleared:" + to_string(size));
}
}
const char *ptr = data;
if(!_remain_data.empty()){
_remain_data.append(data,len);
data = ptr = _remain_data.data();
len = _remain_data.size();
}
splitPacket:
/*确保ptr最后一个字节是0防止strstr越界
*ZLToolKit确保内存最后一个字节是保留未使用字节并置0
*0
*0
*Ensure the last byte of ptr is 0 to prevent strstr from going out of bounds
* Since ZLToolKit ensures that the last byte of memory is a reserved unused byte and set to 0,
* so there is no need to set it to 0 again here
* But the upper layer data may come from other channels, so it is better to set it to 0 for safety
* [AUTO-TRANSLATED:28ff47a5]
*/
char &tail_ref = ((char *) ptr)[len];
char tail_tmp = tail_ref;
tail_ref = 0;
// 数据按照请求头处理 [AUTO-TRANSLATED:e7a0dbb4]
// Data is processed according to the request header
const char *index = nullptr;
_remain_data_size = len;
while (_content_len == 0 && _remain_data_size > 0 && (index = onSearchPacketTail(ptr,_remain_data_size)) != nullptr) {
if (index == ptr) {
break;
}
if (index < ptr || index > ptr + _remain_data_size) {
throw std::out_of_range("上层分包逻辑异常");
}
// _content_len == 0这是请求头 [AUTO-TRANSLATED:32af637b]
// _content_len == 0, this is the request header
const char *header_ptr = ptr;
ssize_t header_size = index - ptr;
ptr = index;
_remain_data_size = len - (ptr - data);
_content_len = onRecvHeader(header_ptr, header_size);
}
/*
*
* HttpRequestSplitter::reset()
/*
* Restore the last byte
* Move it here to prevent HttpRequestSplitter::reset() from causing memory failure
* [AUTO-TRANSLATED:9c3e0597]
*/
tail_ref = tail_tmp;
if(_remain_data_size <= 0){
// 没有剩余数据,清空缓存 [AUTO-TRANSLATED:16613daa]
// No remaining data, clear the cache
_remain_data.clear();
return;
}
if(_content_len == 0){
// 尚未找到http头缓存定位到剩余数据部分 [AUTO-TRANSLATED:7a9d6205]
// HTTP header not found yet, cache is located at the remaining data part
_remain_data.assign(ptr,_remain_data_size);
return;
}
// 已经找到http头了 [AUTO-TRANSLATED:df166db7]
// HTTP header has been found
if(_content_len > 0){
// 数据按照固定长度content处理 [AUTO-TRANSLATED:7272b7e7]
// Data is processed according to fixed length content
if(_remain_data_size < (size_t)_content_len){
// 数据不够,缓存定位到剩余数据部分 [AUTO-TRANSLATED:61c32f5c]
// Insufficient data, cache is located at the remaining data part
_remain_data.assign(ptr, _remain_data_size);
return;
}
// 收到content数据并且接收content完毕 [AUTO-TRANSLATED:0342dc0e]
// Content data received and content reception completed
onRecvContent(ptr,_content_len);
_remain_data_size -= _content_len;
ptr += _content_len;
// content处理完毕,后面数据当做请求头处理 [AUTO-TRANSLATED:d268dfe4]
// Content processing completed, subsequent data is treated as request header
_content_len = 0;
if(_remain_data_size > 0){
// 还有数据没有处理完毕 [AUTO-TRANSLATED:1cac6727]
// There is still data that has not been processed
_remain_data.assign(ptr,_remain_data_size);
data = ptr = (char *)_remain_data.data();
len = _remain_data.size();
goto splitPacket;
}
_remain_data.clear();
return;
}
// _content_len < 0;数据按照不固定长度content处理 [AUTO-TRANSLATED:68d6a4d0]
// _content_len < 0; Data is processed according to variable length content
onRecvContent(ptr,_remain_data_size);//消费掉所有剩余数据
_remain_data.clear();
}
void HttpRequestSplitter::setContentLen(ssize_t content_len) {
_content_len = content_len;
}
void HttpRequestSplitter::reset() {
_content_len = 0;
_remain_data_size = 0;
_remain_data.clear();
}
const char *HttpRequestSplitter::onSearchPacketTail(const char *data,size_t len) {
auto pos = strstr(data,"\r\n\r\n");
if(pos == nullptr){
return nullptr;
}
return pos + 4;
}
size_t HttpRequestSplitter::remainDataSize() {
return _remain_data_size;
}
const char *HttpRequestSplitter::remainData() const {
return _remain_data.data();
}
void HttpRequestSplitter::setMaxCacheSize(size_t max_cache_size) {
if (!max_cache_size) {
max_cache_size = kMaxCacheSize;
}
_max_cache_size = max_cache_size;
}
HttpRequestSplitter::HttpRequestSplitter() {
setMaxCacheSize(0);
}
} /* namespace mediakit */