2019-12-27 12:22:17 +08:00
/*
2023-12-09 16:23:51 +08:00
* Copyright ( c ) 2016 - present The ZLMediaKit project authors . All Rights Reserved .
2017-09-27 16:20:30 +08:00
*
2023-12-09 16:23:51 +08:00
* This file is part of ZLMediaKit ( https : //github.com/ZLMediaKit/ZLMediaKit).
2017-09-27 16:20:30 +08:00
*
2023-12-09 16:23:51 +08:00
* Use of this source code is governed by MIT - like license that can be found in the
2020-04-04 20:30:09 +08:00
* 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 .
2017-04-01 16:35:56 +08:00
*/
2020-04-04 20:30:09 +08:00
2017-04-01 16:35:56 +08:00
# include <stdio.h>
# include <sys/stat.h>
# include <algorithm>
2017-05-02 17:15:12 +08:00
# include "Common/config.h"
2023-06-10 18:46:30 +08:00
# include "Common/strCoding.h"
2017-04-01 16:35:56 +08:00
# include "HttpSession.h"
2021-01-02 21:24:06 +08:00
# include "HttpConst.h"
2018-09-20 18:20:43 +08:00
# include "Util/base64.h"
# include "Util/SHA1.h"
2022-02-02 20:34:50 +08:00
using namespace std ;
2018-10-24 17:17:55 +08:00
using namespace toolkit ;
2017-08-10 14:06:51 +08:00
2018-10-24 17:17:55 +08:00
namespace mediakit {
2017-04-01 16:35:56 +08:00
2022-11-19 09:33:10 +08:00
HttpSession : : HttpSession ( const Socket : : Ptr & pSock ) : Session ( pSock ) {
2024-09-19 14:53:50 +08:00
// 设置默认参数 [AUTO-TRANSLATED:ae5b72e6]
// Set default parameters
2023-12-09 16:23:51 +08:00
setMaxReqSize ( 0 ) ;
setTimeoutSec ( 0 ) ;
2017-04-01 16:35:56 +08:00
}
2023-06-10 20:49:21 +08:00
void HttpSession : : onHttpRequest_HEAD ( ) {
2024-09-19 14:53:50 +08:00
// 暂时全部返回200 OK, 因为HTTP GET存在按需生成流的操作, 所以不能按照HTTP GET的流程返回 [AUTO-TRANSLATED:0ce05db5]
// Temporarily return 200 OK for all, because HTTP GET has on-demand generation stream operations, so it cannot return according to the HTTP GET process
// 如果直接返回404, 那么又会导致按需生成流的逻辑失效, 所以HTTP HEAD在静态文件或者已存在资源时才有效 [AUTO-TRANSLATED:ea2b6faa]
// If you return 404 directly, it will also cause the on-demand generation stream logic to fail, so HTTP HEAD is only valid for static files or existing resources
// 对于按需生成流的直播场景并不适用 [AUTO-TRANSLATED:5a47bf00]
// Not applicable to live streaming scenarios that generate streams on demand
2021-09-29 00:46:09 +08:00
sendResponse ( 200 , false ) ;
2020-03-11 20:58:41 +08:00
}
2021-06-28 10:09:44 +08:00
2023-06-10 20:49:21 +08:00
void HttpSession : : onHttpRequest_OPTIONS ( ) {
2021-06-28 10:09:44 +08:00
KeyValue header ;
2023-05-12 11:47:22 +08:00
header . emplace ( " Allow " , " GET, POST, HEAD, OPTIONS " ) ;
GET_CONFIG ( bool , allow_cross_domains , Http : : kAllowCrossDomains ) ;
if ( allow_cross_domains ) {
header . emplace ( " Access-Control-Allow-Origin " , " * " ) ;
header . emplace ( " Access-Control-Allow-Headers " , " * " ) ;
header . emplace ( " Access-Control-Allow-Methods " , " GET, POST, HEAD, OPTIONS " ) ;
}
2021-06-28 10:09:44 +08:00
header . emplace ( " Access-Control-Allow-Credentials " , " true " ) ;
header . emplace ( " Access-Control-Request-Methods " , " GET, POST, OPTIONS " ) ;
header . emplace ( " Access-Control-Request-Headers " , " Accept,Accept-Language,Content-Language,Content-Type " ) ;
sendResponse ( 200 , true , nullptr , header ) ;
2021-06-25 10:59:06 +08:00
}
2020-03-11 20:58:41 +08:00
2023-06-10 09:45:46 +08:00
ssize_t HttpSession : : onRecvHeader ( const char * header , size_t len ) {
2023-06-10 20:49:21 +08:00
using func_type = void ( HttpSession : : * ) ( ) ;
2023-06-10 09:45:46 +08:00
static unordered_map < string , func_type > s_func_map ;
2020-03-20 11:51:24 +08:00
static onceToken token ( [ ] ( ) {
2023-06-10 20:49:21 +08:00
s_func_map . emplace ( " GET " , & HttpSession : : onHttpRequest_GET ) ;
s_func_map . emplace ( " POST " , & HttpSession : : onHttpRequest_POST ) ;
2024-09-19 14:53:50 +08:00
// DELETE命令用于whip/whep用, 只用于触发http api [AUTO-TRANSLATED:f3b7aaea]
// DELETE command is used for whip/whep, only used to trigger http api
2023-06-10 20:49:21 +08:00
s_func_map . emplace ( " DELETE " , & HttpSession : : onHttpRequest_POST ) ;
s_func_map . emplace ( " HEAD " , & HttpSession : : onHttpRequest_HEAD ) ;
s_func_map . emplace ( " OPTIONS " , & HttpSession : : onHttpRequest_OPTIONS ) ;
2023-06-10 09:45:46 +08:00
} ) ;
2018-08-10 11:55:18 +08:00
2023-06-10 12:22:28 +08:00
_parser . parse ( header , len ) ;
2023-06-10 11:04:52 +08:00
CHECK ( _parser . url ( ) [ 0 ] = = ' / ' ) ;
2024-01-27 21:29:10 +08:00
_origin = _parser [ " Origin " ] ;
2021-09-03 18:02:31 +08:00
2020-03-20 11:51:24 +08:00
urlDecode ( _parser ) ;
2023-06-10 20:49:21 +08:00
auto & cmd = _parser . method ( ) ;
2020-03-20 11:51:24 +08:00
auto it = s_func_map . find ( cmd ) ;
if ( it = = s_func_map . end ( ) ) {
2023-06-10 12:22:28 +08:00
WarnP ( this ) < < " Http method not supported: " < < cmd ;
2021-01-02 21:24:06 +08:00
sendResponse ( 405 , true ) ;
2019-05-29 18:08:50 +08:00
return 0 ;
2020-03-20 11:51:24 +08:00
}
2018-09-20 17:50:58 +08:00
2023-06-10 20:49:21 +08:00
size_t content_len ;
auto & content_len_str = _parser [ " Content-Length " ] ;
if ( content_len_str . empty ( ) ) {
if ( it - > first = = " POST " ) {
2024-09-19 14:53:50 +08:00
// Http post未指定长度, 我们认为是不定长的body [AUTO-TRANSLATED:3578206b]
// Http post does not specify length, we consider it to be an indefinite length body
2023-06-10 20:49:21 +08:00
WarnL < < " Received http post request without content-length, consider it to be unlimited length " ;
content_len = SIZE_MAX ;
} else {
content_len = 0 ;
}
} else {
2024-09-19 14:53:50 +08:00
// 已经指定长度 [AUTO-TRANSLATED:a360c374]
// Length has been specified
2023-06-10 20:49:21 +08:00
content_len = atoll ( content_len_str . data ( ) ) ;
}
if ( content_len = = 0 ) {
2024-09-19 14:53:50 +08:00
// // 没有body的情况, 直接触发回调 //// [AUTO-TRANSLATED:f2988336]
// // No body case, trigger callback directly ////
2023-06-10 20:49:21 +08:00
( this - > * ( it - > second ) ) ( ) ;
_parser . clear ( ) ;
2024-09-19 14:53:50 +08:00
// 如果设置了_on_recv_body, 那么说明后续要处理body [AUTO-TRANSLATED:2dac5fc2]
// If _on_recv_body is set, it means that the body will be processed later
2023-06-10 20:49:21 +08:00
return _on_recv_body ? - 1 : 0 ;
}
2023-12-09 16:23:51 +08:00
if ( content_len > _max_req_size ) {
2024-09-19 14:53:50 +08:00
// // 不定长body或超大body //// [AUTO-TRANSLATED:8d66ee77]
// // Indefinite length body or oversized body ////
2023-06-10 20:49:21 +08:00
if ( content_len ! = SIZE_MAX ) {
2023-12-09 16:23:51 +08:00
WarnL < < " Http body size is too huge: " < < content_len < < " > " < < _max_req_size
2023-06-10 20:49:21 +08:00
< < " , please set " < < Http : : kMaxReqSize < < " in config.ini file. " ;
}
size_t received = 0 ;
auto parser = std : : move ( _parser ) ;
_on_recv_body = [ this , parser , received , content_len ] ( const char * data , size_t len ) mutable {
received + = len ;
onRecvUnlimitedContent ( parser , data , len , content_len , received ) ;
2023-06-11 09:21:15 +08:00
if ( received < content_len ) {
2024-09-19 14:53:50 +08:00
// 还没收满 [AUTO-TRANSLATED:cecc867e]
// Not yet received
2023-06-10 20:49:21 +08:00
return true ;
}
2024-09-19 14:53:50 +08:00
// 收满了 [AUTO-TRANSLATED:0c9cebd7]
// Received full
2023-06-10 20:49:21 +08:00
setContentLen ( 0 ) ;
return false ;
} ;
2024-09-19 14:53:50 +08:00
// 声明后续都是body; Http body在本对象缓冲, 不通过HttpRequestSplitter保存 [AUTO-TRANSLATED:0012b6c1]
// Declare that the following is all body; Http body is buffered in this object, not saved through HttpRequestSplitter
2023-06-10 20:49:21 +08:00
return - 1 ;
}
2024-09-19 14:53:50 +08:00
// // body size明确指定且小于最大值的情况 //// [AUTO-TRANSLATED:f1f1ee5d]
// // Body size is explicitly specified and less than the maximum value ////
2023-12-23 21:27:28 +08:00
_on_recv_body = [ this , it ] ( const char * data , size_t len ) mutable {
2024-09-19 14:53:50 +08:00
// 收集body完毕 [AUTO-TRANSLATED:981ad2c8]
// Body collection complete
2023-12-23 21:27:28 +08:00
_parser . setContent ( std : : string ( data , len ) ) ;
2023-06-10 20:49:21 +08:00
( this - > * ( it - > second ) ) ( ) ;
_parser . clear ( ) ;
2024-09-19 14:53:50 +08:00
// _on_recv_body置空 [AUTO-TRANSLATED:437a201a]
// _on_recv_body is cleared
2023-06-10 20:49:21 +08:00
return false ;
} ;
2019-05-30 10:59:14 +08:00
2024-09-19 14:53:50 +08:00
// 声明body长度, 通过HttpRequestSplitter缓存然后一次性回调到_on_recv_body [AUTO-TRANSLATED:3b11cfb7]
// Declare the body length, cache it through HttpRequestSplitter and then callback to _on_recv_body at once
2023-12-23 21:27:28 +08:00
return content_len ;
2017-04-01 16:35:56 +08:00
}
2018-09-20 17:50:58 +08:00
2023-06-10 09:45:46 +08:00
void HttpSession : : onRecvContent ( const char * data , size_t len ) {
2023-06-10 20:49:21 +08:00
if ( _on_recv_body & & ! _on_recv_body ( data , len ) ) {
_on_recv_body = nullptr ;
2020-03-20 11:51:24 +08:00
}
2018-09-20 17:50:58 +08:00
}
void HttpSession : : onRecv ( const Buffer : : Ptr & pBuf ) {
2018-10-24 15:43:52 +08:00
_ticker . resetTime ( ) ;
2023-06-10 09:45:46 +08:00
input ( pBuf - > data ( ) , pBuf - > size ( ) ) ;
2018-09-20 17:50:58 +08:00
}
2023-06-10 09:45:46 +08:00
void HttpSession : : onError ( const SockException & err ) {
2021-08-13 10:59:13 +08:00
if ( _is_live_stream ) {
2024-09-19 14:53:50 +08:00
// flv/ts播放器 [AUTO-TRANSLATED:5b444fd9]
// flv/ts player
2021-08-13 10:59:13 +08:00
uint64_t duration = _ticker . createdTime ( ) / 1000 ;
2023-10-19 17:55:30 +08:00
WarnP ( this ) < < " FLV/TS/FMP4播放器( " < < _media_info . shortUrl ( ) < < " )断开: " < < err < < " ,耗时(s): " < < duration ;
2019-10-23 12:00:53 +08:00
2021-08-13 10:59:13 +08:00
GET_CONFIG ( uint32_t , iFlowThreshold , General : : kFlowThreshold ) ;
if ( _total_bytes_usage > = iFlowThreshold * 1024 ) {
2023-10-19 17:55:30 +08:00
NOTICE_EMIT ( BroadcastFlowReportArgs , Broadcast : : kBroadcastFlowReport , _media_info , _total_bytes_usage , duration , true , * this ) ;
2019-10-23 12:00:53 +08:00
}
return ;
}
2017-04-01 16:35:56 +08:00
}
2023-12-09 16:23:51 +08:00
void HttpSession : : setTimeoutSec ( size_t keep_alive_sec ) {
if ( ! keep_alive_sec ) {
GET_CONFIG ( size_t , s_keep_alive_sec , Http : : kKeepAliveSecond ) ;
keep_alive_sec = s_keep_alive_sec ;
}
_keep_alive_sec = keep_alive_sec ;
getSock ( ) - > setSendTimeOutSecond ( keep_alive_sec ) ;
}
2018-02-09 11:42:55 +08:00
2023-12-09 16:23:51 +08:00
void HttpSession : : setMaxReqSize ( size_t max_req_size ) {
if ( ! max_req_size ) {
GET_CONFIG ( size_t , s_max_req_size , Http : : kMaxReqSize ) ;
max_req_size = s_max_req_size ;
}
_max_req_size = max_req_size ;
setMaxCacheSize ( max_req_size ) ;
}
void HttpSession : : onManager ( ) {
if ( _ticker . elapsedTime ( ) > _keep_alive_sec * 1000 ) {
2024-09-19 14:53:50 +08:00
// http超时 [AUTO-TRANSLATED:6f2fdd1f]
// http timeout
2023-06-10 09:45:46 +08:00
shutdown ( SockException ( Err_timeout , " session timeout " ) ) ;
2020-03-20 11:51:24 +08:00
}
2017-04-01 16:35:56 +08:00
}
2018-09-20 18:20:43 +08:00
2023-06-10 09:45:46 +08:00
bool HttpSession : : checkWebSocket ( ) {
2020-03-20 11:51:24 +08:00
auto Sec_WebSocket_Key = _parser [ " Sec-WebSocket-Key " ] ;
2020-08-08 12:17:06 +08:00
if ( Sec_WebSocket_Key . empty ( ) ) {
2020-03-20 11:51:24 +08:00
return false ;
}
2025-02-13 15:18:47 +08:00
_is_websocket = true ;
2020-09-20 00:21:46 +08:00
auto Sec_WebSocket_Accept = encodeBase64 ( SHA1 : : encode_bin ( Sec_WebSocket_Key + " 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 " ) ) ;
2020-03-20 11:51:24 +08:00
KeyValue headerOut ;
headerOut [ " Upgrade " ] = " websocket " ;
headerOut [ " Connection " ] = " Upgrade " ;
headerOut [ " Sec-WebSocket-Accept " ] = Sec_WebSocket_Accept ;
2020-08-08 12:17:06 +08:00
if ( ! _parser [ " Sec-WebSocket-Protocol " ] . empty ( ) ) {
2020-03-20 11:51:24 +08:00
headerOut [ " Sec-WebSocket-Protocol " ] = _parser [ " Sec-WebSocket-Protocol " ] ;
}
2019-08-23 09:45:01 +08:00
2020-08-08 12:17:06 +08:00
auto res_cb = [ this , headerOut ] ( ) {
2020-09-20 00:21:46 +08:00
_live_over_websocket = true ;
2021-01-02 21:24:06 +08:00
sendResponse ( 101 , false , nullptr , headerOut , nullptr , true ) ;
2019-08-23 09:45:01 +08:00
} ;
2023-06-10 09:45:46 +08:00
2023-06-02 21:43:24 +08:00
auto res_cb_flv = [ this , headerOut ] ( ) mutable {
2023-05-31 23:16:16 +08:00
_live_over_websocket = true ;
2023-06-02 21:43:24 +08:00
headerOut . emplace ( " Cache-Control " , " no-store " ) ;
sendResponse ( 101 , false , nullptr , headerOut , nullptr , true ) ;
2023-05-31 23:16:16 +08:00
} ;
2019-08-23 09:45:01 +08:00
2024-09-19 14:53:50 +08:00
// 判断是否为websocket-flv [AUTO-TRANSLATED:31682d7a]
// Determine whether it is websocket-flv
2023-05-31 23:16:16 +08:00
if ( checkLiveStreamFlv ( res_cb_flv ) ) {
2024-09-19 14:53:50 +08:00
// 这里是websocket-flv直播请求 [AUTO-TRANSLATED:4bea5956]
// This is a websocket-flv live request
2019-08-23 09:45:01 +08:00
return true ;
}
2024-09-19 14:53:50 +08:00
// 判断是否为websocket-ts [AUTO-TRANSLATED:9e8eb374]
// Determine whether it is websocket-ts
2020-09-20 00:21:46 +08:00
if ( checkLiveStreamTS ( res_cb ) ) {
2024-09-19 14:53:50 +08:00
// 这里是websocket-ts直播请求 [AUTO-TRANSLATED:8ab08dd6]
// This is a websocket-ts live request
2020-09-20 00:21:46 +08:00
return true ;
}
2024-09-19 14:53:50 +08:00
// 判断是否为websocket-fmp4 [AUTO-TRANSLATED:318f793f]
// Determine whether it is websocket-fmp4
2020-09-20 19:45:37 +08:00
if ( checkLiveStreamFMP4 ( res_cb ) ) {
2024-09-19 14:53:50 +08:00
// 这里是websocket-fmp4直播请求 [AUTO-TRANSLATED:ccf0c1e2]
// This is a websocket-fmp4 live request
2020-09-20 19:45:37 +08:00
return true ;
}
2024-09-19 14:53:50 +08:00
// 这是普通的websocket连接 [AUTO-TRANSLATED:754721f8]
// This is a normal websocket connection
2020-08-08 12:17:06 +08:00
if ( ! onWebSocketConnect ( _parser ) ) {
2021-01-02 21:24:06 +08:00
sendResponse ( 501 , true , nullptr , headerOut ) ;
2019-09-16 17:42:52 +08:00
return true ;
}
2021-01-02 21:24:06 +08:00
sendResponse ( 101 , false , nullptr , headerOut , nullptr , true ) ;
2020-03-20 11:51:24 +08:00
return true ;
2018-09-20 18:20:43 +08:00
}
2019-11-30 11:38:00 +08:00
2023-06-10 09:45:46 +08:00
bool HttpSession : : checkLiveStream ( const string & schema , const string & url_suffix , const function < void ( const MediaSource : : Ptr & src ) > & cb ) {
2023-06-10 11:04:52 +08:00
std : : string url = _parser . url ( ) ;
2022-03-03 19:39:18 +08:00
auto it = _parser . getUrlArgs ( ) . find ( " schema " ) ;
if ( it ! = _parser . getUrlArgs ( ) . end ( ) ) {
if ( strcasecmp ( it - > second . c_str ( ) , schema . c_str ( ) ) ) {
// unsupported schema
return false ;
}
2022-03-12 10:04:36 +08:00
} else {
2022-03-27 21:57:05 +08:00
auto prefix_size = url_suffix . size ( ) ;
2022-03-12 10:04:36 +08:00
if ( url . size ( ) < prefix_size | | strcasecmp ( url . data ( ) + ( url . size ( ) - prefix_size ) , url_suffix . data ( ) ) ) {
2024-09-19 14:53:50 +08:00
// 未找到后缀 [AUTO-TRANSLATED:6635499a]
// Suffix not found
2022-03-03 19:39:18 +08:00
return false ;
}
2024-09-19 14:53:50 +08:00
// url去除特殊后缀 [AUTO-TRANSLATED:31c0c080]
// Remove special suffix from url
2022-03-12 10:04:36 +08:00
url . resize ( url . size ( ) - prefix_size ) ;
2020-03-20 11:51:24 +08:00
}
2024-09-19 14:53:50 +08:00
// 带参数的url [AUTO-TRANSLATED:074764b0]
// Url with parameters
2023-06-10 11:04:52 +08:00
if ( ! _parser . params ( ) . empty ( ) ) {
2022-03-12 10:04:36 +08:00
url + = " ? " ;
2023-06-10 11:04:52 +08:00
url + = _parser . params ( ) ;
2022-03-12 10:04:36 +08:00
}
2022-03-03 19:39:18 +08:00
2024-09-19 14:53:50 +08:00
// 解析带上协议+参数完整的url [AUTO-TRANSLATED:5cdc7e68]
// Parse the complete url with protocol + parameters
2023-10-19 17:55:30 +08:00
_media_info . parse ( schema + " :// " + _parser [ " Host " ] + url ) ;
2021-09-15 15:31:00 +08:00
2023-10-19 17:55:30 +08:00
if ( _media_info . app . empty ( ) | | _media_info . stream . empty ( ) ) {
2024-09-19 14:53:50 +08:00
// url不合法 [AUTO-TRANSLATED:9aad134e]
// URL is invalid
2019-05-27 22:49:30 +08:00
return false ;
2020-03-20 11:51:24 +08:00
}
2021-09-15 15:31:00 +08:00
2025-02-13 15:18:47 +08:00
if ( _is_websocket ) {
_media_info . protocol = overSsl ( ) ? " wss " : " ws " ;
} else {
_media_info . protocol = overSsl ( ) ? " https " : " http " ;
}
2020-09-20 00:21:46 +08:00
bool close_flag = ! strcasecmp ( _parser [ " Connection " ] . data ( ) , " close " ) ;
2023-04-28 22:04:38 +08:00
weak_ptr < HttpSession > weak_self = static_pointer_cast < HttpSession > ( shared_from_this ( ) ) ;
2020-05-25 17:38:36 +08:00
2024-09-19 14:53:50 +08:00
// 鉴权结果回调 [AUTO-TRANSLATED:021df191]
// Authentication result callback
2020-09-20 00:21:46 +08:00
auto onRes = [ cb , weak_self , close_flag ] ( const string & err ) {
auto strong_self = weak_self . lock ( ) ;
if ( ! strong_self ) {
2024-09-19 14:53:50 +08:00
// 本对象已经销毁 [AUTO-TRANSLATED:713e0f23]
// This object has been destroyed
2019-05-27 22:49:30 +08:00
return ;
}
2020-05-25 17:38:36 +08:00
2020-09-20 00:21:46 +08:00
if ( ! err . empty ( ) ) {
2024-09-19 14:53:50 +08:00
// 播放鉴权失败 [AUTO-TRANSLATED:64f99eeb]
// Playback authentication failed
2021-01-02 21:24:06 +08:00
strong_self - > sendResponse ( 401 , close_flag , nullptr , KeyValue ( ) , std : : make_shared < HttpStringBody > ( err ) ) ;
2018-02-05 15:56:44 +08:00
return ;
}
2020-05-25 17:38:36 +08:00
2024-09-19 14:53:50 +08:00
// 异步查找直播流 [AUTO-TRANSLATED:7cde5dac]
// Asynchronously find live stream
2023-10-19 17:55:30 +08:00
MediaSource : : findAsync ( strong_self - > _media_info , strong_self , [ weak_self , close_flag , cb ] ( const MediaSource : : Ptr & src ) {
2020-09-20 00:21:46 +08:00
auto strong_self = weak_self . lock ( ) ;
if ( ! strong_self ) {
2024-09-19 14:53:50 +08:00
// 本对象已经销毁 [AUTO-TRANSLATED:713e0f23]
// This object has been destroyed
2020-05-25 17:38:36 +08:00
return ;
}
2020-09-20 00:21:46 +08:00
if ( ! src ) {
2024-09-19 14:53:50 +08:00
// 未找到该流 [AUTO-TRANSLATED:2699ef82]
// Stream not found
2020-09-20 00:21:46 +08:00
strong_self - > sendNotFound ( close_flag ) ;
2022-03-12 10:04:36 +08:00
} else {
2022-03-03 19:39:18 +08:00
strong_self - > _is_live_stream = true ;
2024-09-19 14:53:50 +08:00
// 触发回调 [AUTO-TRANSLATED:ae2ff258]
// Trigger callback
2022-03-03 19:39:18 +08:00
cb ( src ) ;
}
2020-05-25 17:38:36 +08:00
} ) ;
} ;
2019-05-27 22:49:30 +08:00
2020-09-20 00:21:46 +08:00
Broadcast : : AuthInvoker invoker = [ weak_self , onRes ] ( const string & err ) {
2022-08-30 21:24:25 +08:00
if ( auto strong_self = weak_self . lock ( ) ) {
strong_self - > async ( [ onRes , err ] ( ) { onRes ( err ) ; } ) ;
2019-05-27 22:49:30 +08:00
}
2020-05-25 17:38:36 +08:00
} ;
2023-10-19 17:55:30 +08:00
auto flag = NOTICE_EMIT ( BroadcastMediaPlayedArgs , Broadcast : : kBroadcastMediaPlayed , _media_info , invoker , * this ) ;
2020-05-25 17:38:36 +08:00
if ( ! flag ) {
2024-09-19 14:53:50 +08:00
// 该事件无人监听,默认不鉴权 [AUTO-TRANSLATED:e1fbc6ae]
// No one is listening to this event, no authentication by default
2020-05-25 17:38:36 +08:00
onRes ( " " ) ;
}
2018-02-05 15:56:44 +08:00
return true ;
2017-12-15 16:01:21 +08:00
}
2019-05-16 17:09:29 +08:00
2024-09-19 14:53:50 +08:00
// http-fmp4 链接格式:http://vhost-url:port/app/streamid.live.mp4?key1=value1&key2=value2 [AUTO-TRANSLATED:c0174f8f]
// http-fmp4 link format: http://vhost-url:port/app/streamid.live.mp4?key1=value1&key2=value2
2023-06-10 09:45:46 +08:00
bool HttpSession : : checkLiveStreamFMP4 ( const function < void ( ) > & cb ) {
2020-09-20 19:45:37 +08:00
return checkLiveStream ( FMP4_SCHEMA , " .live.mp4 " , [ this , cb ] ( const MediaSource : : Ptr & src ) {
auto fmp4_src = dynamic_pointer_cast < FMP4MediaSource > ( src ) ;
assert ( fmp4_src ) ;
if ( ! cb ) {
2024-09-19 14:53:50 +08:00
// 找到源, 发送http头, 负载后续发送 [AUTO-TRANSLATED:ac272410]
// Found the source, send the http header, and send the load later
2021-01-02 21:24:06 +08:00
sendResponse ( 200 , false , HttpFileManager : : getContentType ( " .mp4 " ) . data ( ) , KeyValue ( ) , nullptr , true ) ;
2020-09-20 19:45:37 +08:00
} else {
2024-09-19 14:53:50 +08:00
// 自定义发送http头 [AUTO-TRANSLATED:b8a8f683]
// Custom send http header
2020-09-20 19:45:37 +08:00
cb ( ) ;
}
2024-09-19 14:53:50 +08:00
// 直播牺牲延时提升发送性能 [AUTO-TRANSLATED:7c6616c9]
// Live streaming sacrifices delay to improve sending performance
2020-09-20 19:45:37 +08:00
setSocketFlags ( ) ;
onWrite ( std : : make_shared < BufferString > ( fmp4_src - > getInitSegment ( ) ) , true ) ;
2023-04-28 22:04:38 +08:00
weak_ptr < HttpSession > weak_self = static_pointer_cast < HttpSession > ( shared_from_this ( ) ) ;
2021-09-29 00:04:36 +08:00
fmp4_src - > pause ( false ) ;
2020-09-20 19:45:37 +08:00
_fmp4_reader = fmp4_src - > getRing ( ) - > attach ( getPoller ( ) ) ;
2023-09-02 12:06:35 +08:00
_fmp4_reader - > setGetInfoCB ( [ weak_self ] ( ) {
Any ret ;
ret . set ( static_pointer_cast < SockInfo > ( weak_self . lock ( ) ) ) ;
return ret ;
} ) ;
2020-09-20 19:45:37 +08:00
_fmp4_reader - > setDetachCB ( [ weak_self ] ( ) {
auto strong_self = weak_self . lock ( ) ;
if ( ! strong_self ) {
2024-09-19 14:53:50 +08:00
// 本对象已经销毁 [AUTO-TRANSLATED:713e0f23]
// This object has been destroyed
2020-09-20 19:45:37 +08:00
return ;
}
strong_self - > shutdown ( SockException ( Err_shutdown , " fmp4 ring buffer detached " ) ) ;
} ) ;
_fmp4_reader - > setReadCB ( [ weak_self ] ( const FMP4MediaSource : : RingDataType & fmp4_list ) {
auto strong_self = weak_self . lock ( ) ;
if ( ! strong_self ) {
2024-09-19 14:53:50 +08:00
// 本对象已经销毁 [AUTO-TRANSLATED:713e0f23]
// This object has been destroyed
2020-09-20 19:45:37 +08:00
return ;
}
2021-01-17 18:31:50 +08:00
size_t i = 0 ;
auto size = fmp4_list - > size ( ) ;
2023-06-10 09:45:46 +08:00
fmp4_list - > for_each ( [ & ] ( const FMP4Packet : : Ptr & ts ) { strong_self - > onWrite ( ts , + + i = = size ) ; } ) ;
2020-09-20 19:45:37 +08:00
} ) ;
} ) ;
}
2024-09-19 14:53:50 +08:00
// http-ts 链接格式:http://vhost-url:port/app/streamid.live.ts?key1=value1&key2=value2 [AUTO-TRANSLATED:aa1a9151]
// http-ts link format: http://vhost-url:port/app/streamid.live.ts?key1=value1&key2=value2
2023-06-10 09:45:46 +08:00
bool HttpSession : : checkLiveStreamTS ( const function < void ( ) > & cb ) {
2020-09-20 00:55:22 +08:00
return checkLiveStream ( TS_SCHEMA , " .live.ts " , [ this , cb ] ( const MediaSource : : Ptr & src ) {
2020-09-20 00:21:46 +08:00
auto ts_src = dynamic_pointer_cast < TSMediaSource > ( src ) ;
assert ( ts_src ) ;
if ( ! cb ) {
2024-09-19 14:53:50 +08:00
// 找到源, 发送http头, 负载后续发送 [AUTO-TRANSLATED:ac272410]
// Found the source, send the http header, and send the load later
2021-01-02 21:24:06 +08:00
sendResponse ( 200 , false , HttpFileManager : : getContentType ( " .ts " ) . data ( ) , KeyValue ( ) , nullptr , true ) ;
2020-09-20 00:21:46 +08:00
} else {
2024-09-19 14:53:50 +08:00
// 自定义发送http头 [AUTO-TRANSLATED:b8a8f683]
// Custom send http header
2020-09-20 00:21:46 +08:00
cb ( ) ;
}
2024-09-19 14:53:50 +08:00
// 直播牺牲延时提升发送性能 [AUTO-TRANSLATED:7c6616c9]
// Live streaming sacrifices delay to improve sending performance
2020-09-20 00:21:46 +08:00
setSocketFlags ( ) ;
2023-04-28 22:04:38 +08:00
weak_ptr < HttpSession > weak_self = static_pointer_cast < HttpSession > ( shared_from_this ( ) ) ;
2021-09-29 00:04:36 +08:00
ts_src - > pause ( false ) ;
2020-09-20 00:21:46 +08:00
_ts_reader = ts_src - > getRing ( ) - > attach ( getPoller ( ) ) ;
2023-09-02 12:06:35 +08:00
_ts_reader - > setGetInfoCB ( [ weak_self ] ( ) {
Any ret ;
ret . set ( static_pointer_cast < SockInfo > ( weak_self . lock ( ) ) ) ;
return ret ;
} ) ;
2023-06-10 09:45:46 +08:00
_ts_reader - > setDetachCB ( [ weak_self ] ( ) {
2020-09-20 00:57:34 +08:00
auto strong_self = weak_self . lock ( ) ;
if ( ! strong_self ) {
2024-09-19 14:53:50 +08:00
// 本对象已经销毁 [AUTO-TRANSLATED:713e0f23]
// This object has been destroyed
2020-09-20 00:57:34 +08:00
return ;
}
2023-06-10 09:45:46 +08:00
strong_self - > shutdown ( SockException ( Err_shutdown , " ts ring buffer detached " ) ) ;
2020-09-20 00:57:34 +08:00
} ) ;
_ts_reader - > setReadCB ( [ weak_self ] ( const TSMediaSource : : RingDataType & ts_list ) {
auto strong_self = weak_self . lock ( ) ;
if ( ! strong_self ) {
2024-09-19 14:53:50 +08:00
// 本对象已经销毁 [AUTO-TRANSLATED:713e0f23]
// This object has been destroyed
2020-09-20 00:21:46 +08:00
return ;
}
2021-01-17 18:31:50 +08:00
size_t i = 0 ;
auto size = ts_list - > size ( ) ;
2023-06-10 09:45:46 +08:00
ts_list - > for_each ( [ & ] ( const TSPacket : : Ptr & ts ) { strong_self - > onWrite ( ts , + + i = = size ) ; } ) ;
2020-09-20 00:21:46 +08:00
} ) ;
} ) ;
}
2024-09-19 14:53:50 +08:00
// http-flv 链接格式:http://vhost-url:port/app/streamid.live.flv?key1=value1&key2=value2 [AUTO-TRANSLATED:7e78aa20]
// http-flv link format: http://vhost-url:port/app/streamid.live.flv?key1=value1&key2=value2
2023-06-10 09:45:46 +08:00
bool HttpSession : : checkLiveStreamFlv ( const function < void ( ) > & cb ) {
2021-12-28 17:22:16 +08:00
auto start_pts = atoll ( _parser . getUrlArgs ( ) [ " starPts " ] . data ( ) ) ;
2022-02-09 11:48:15 +08:00
return checkLiveStream ( RTMP_SCHEMA , " .live.flv " , [ this , cb , start_pts ] ( const MediaSource : : Ptr & src ) {
2020-09-20 00:21:46 +08:00
auto rtmp_src = dynamic_pointer_cast < RtmpMediaSource > ( src ) ;
assert ( rtmp_src ) ;
if ( ! cb ) {
2024-09-19 14:53:50 +08:00
// 找到源, 发送http头, 负载后续发送 [AUTO-TRANSLATED:ac272410]
// Found the source, send the http header, and send the load later
2023-05-31 23:16:16 +08:00
KeyValue headerOut ;
headerOut [ " Cache-Control " ] = " no-store " ;
sendResponse ( 200 , false , HttpFileManager : : getContentType ( " .flv " ) . data ( ) , headerOut , nullptr , true ) ;
2020-09-20 00:21:46 +08:00
} else {
2024-09-19 14:53:50 +08:00
// 自定义发送http头 [AUTO-TRANSLATED:b8a8f683]
// Custom send http header
2020-09-20 00:21:46 +08:00
cb ( ) ;
}
2024-09-19 14:53:50 +08:00
// 直播牺牲延时提升发送性能 [AUTO-TRANSLATED:7c6616c9]
// Live streaming sacrifices delay to improve sending performance
2020-09-20 00:21:46 +08:00
setSocketFlags ( ) ;
2021-01-09 19:03:02 +08:00
2024-09-19 14:53:50 +08:00
// 非H264/AAC时打印警告日志, 防止用户提无效问题 [AUTO-TRANSLATED:59ee60df]
// Print warning log when it is not H264/AAC, to prevent users from raising invalid issues
2021-01-09 19:03:02 +08:00
auto tracks = src - > getTracks ( false ) ;
for ( auto & track : tracks ) {
switch ( track - > getCodecId ( ) ) {
case CodecH264 :
2023-06-10 09:45:46 +08:00
case CodecAAC : break ;
2021-01-09 19:03:02 +08:00
default : {
WarnP ( this ) < < " flv播放器一般只支持H264和AAC编码,该编码格式可能不被播放器支持: " < < track - > getCodecName ( ) ;
break ;
}
}
}
2021-12-28 17:22:16 +08:00
start ( getPoller ( ) , rtmp_src , start_pts ) ;
2020-09-20 00:21:46 +08:00
} ) ;
}
2023-06-10 20:49:21 +08:00
void HttpSession : : onHttpRequest_GET ( ) {
2024-09-19 14:53:50 +08:00
// 先看看是否为WebSocket请求 [AUTO-TRANSLATED:98cd3a86]
// First check if it is a WebSocket request
2020-09-20 00:21:46 +08:00
if ( checkWebSocket ( ) ) {
2024-09-19 14:53:50 +08:00
// 后续都是websocket body数据 [AUTO-TRANSLATED:c4fcbdcf]
// The following are all websocket body data
2023-06-10 20:49:21 +08:00
_on_recv_body = [ this ] ( const char * data , size_t len ) {
2023-06-10 09:45:46 +08:00
WebSocketSplitter : : decode ( ( uint8_t * ) data , len ) ;
2024-09-19 14:53:50 +08:00
// _contentCallBack是可持续的, 后面还要处理后续数据 [AUTO-TRANSLATED:920e8c23]
// _contentCallBack is sustainable, and subsequent data needs to be processed later
2020-03-20 11:51:24 +08:00
return true ;
} ;
return ;
}
2018-09-20 18:20:43 +08:00
2020-09-20 00:21:46 +08:00
if ( emitHttpEvent ( false ) ) {
2024-09-19 14:53:50 +08:00
// 拦截http api事件 [AUTO-TRANSLATED:2f5e319d]
// Intercept http api events
2020-03-20 11:51:24 +08:00
return ;
}
2018-09-20 18:20:43 +08:00
2020-09-20 00:21:46 +08:00
if ( checkLiveStreamFlv ( ) ) {
2024-09-19 14:53:50 +08:00
// 拦截http-flv播放器 [AUTO-TRANSLATED:299f6449]
// Intercept http-flv player
2019-10-29 09:16:52 +08:00
return ;
}
2020-09-20 00:21:46 +08:00
if ( checkLiveStreamTS ( ) ) {
2024-09-19 14:53:50 +08:00
// 拦截http-ts播放器 [AUTO-TRANSLATED:d9e303e4]
// Intercept http-ts player
2020-09-20 00:21:46 +08:00
return ;
}
2019-05-16 17:31:48 +08:00
2020-09-20 19:45:37 +08:00
if ( checkLiveStreamFMP4 ( ) ) {
2024-09-19 14:53:50 +08:00
// 拦截http-fmp4播放器 [AUTO-TRANSLATED:78cdf3a1]
// Intercept http-fmp4 player
2020-09-20 19:45:37 +08:00
return ;
}
2023-06-10 09:45:46 +08:00
bool bClose = ! strcasecmp ( _parser [ " Connection " ] . data ( ) , " close " ) ;
2023-04-28 22:04:38 +08:00
weak_ptr < HttpSession > weak_self = static_pointer_cast < HttpSession > ( shared_from_this ( ) ) ;
2022-08-30 21:24:25 +08:00
HttpFileManager : : onAccessPath ( * this , _parser , [ weak_self , bClose ] ( int code , const string & content_type ,
2023-06-10 09:45:46 +08:00
const StrCaseMap & responseHeader , const HttpBody : : Ptr & body ) {
2022-08-30 21:24:25 +08:00
auto strong_self = weak_self . lock ( ) ;
if ( ! strong_self ) {
2019-06-12 17:53:48 +08:00
return ;
2019-05-16 17:31:48 +08:00
}
2022-08-30 21:24:25 +08:00
strong_self - > async ( [ weak_self , bClose , code , content_type , responseHeader , body ] ( ) {
auto strong_self = weak_self . lock ( ) ;
if ( ! strong_self ) {
2019-11-30 11:38:00 +08:00
return ;
2019-06-14 18:42:09 +08:00
}
2022-08-30 21:24:25 +08:00
strong_self - > sendResponse ( code , bClose , content_type . data ( ) , responseHeader , body ) ;
2019-11-30 11:38:00 +08:00
} ) ;
2019-06-12 17:53:48 +08:00
} ) ;
2017-04-01 16:35:56 +08:00
}
2019-11-30 11:38:00 +08:00
static string dateStr ( ) {
char buf [ 64 ] ;
time_t tt = time ( NULL ) ;
strftime ( buf , sizeof buf , " %a, %b %d %Y %H:%M:%S GMT " , gmtime ( & tt ) ) ;
return buf ;
2017-04-01 16:35:56 +08:00
}
2019-09-16 17:42:52 +08:00
2019-12-28 13:11:41 +08:00
class AsyncSenderData {
public :
friend class AsyncSender ;
2022-12-02 14:43:06 +08:00
using Ptr = std : : shared_ptr < AsyncSenderData > ;
2023-04-28 22:04:38 +08:00
AsyncSenderData ( HttpSession : : Ptr session , const HttpBody : : Ptr & body , bool close_when_complete ) {
_session = std : : move ( session ) ;
2019-12-28 13:11:41 +08:00
_body = body ;
_close_when_complete = close_when_complete ;
}
2023-04-28 22:04:38 +08:00
2019-12-28 13:11:41 +08:00
private :
std : : weak_ptr < HttpSession > _session ;
HttpBody : : Ptr _body ;
bool _close_when_complete ;
bool _read_complete = false ;
} ;
class AsyncSender {
public :
2022-12-02 14:43:06 +08:00
using Ptr = std : : shared_ptr < AsyncSender > ;
2019-12-28 13:11:41 +08:00
static bool onSocketFlushed ( const AsyncSenderData : : Ptr & data ) {
if ( data - > _read_complete ) {
if ( data - > _close_when_complete ) {
2024-09-19 14:53:50 +08:00
// 发送完毕需要关闭socket [AUTO-TRANSLATED:fe660e55]
// Close socket after sending is complete
2019-12-28 13:11:41 +08:00
shutdown ( data - > _session . lock ( ) ) ;
}
return false ;
}
GET_CONFIG ( uint32_t , sendBufSize , Http : : kSendBufSize ) ;
data - > _body - > readDataAsync ( sendBufSize , [ data ] ( const Buffer : : Ptr & sendBuf ) {
auto session = data - > _session . lock ( ) ;
if ( ! session ) {
2024-09-19 14:53:50 +08:00
// 本对象已经销毁 [AUTO-TRANSLATED:713e0f23]
// This object has been destroyed
2019-12-28 13:11:41 +08:00
return ;
}
session - > async ( [ data , sendBuf ] ( ) {
auto session = data - > _session . lock ( ) ;
if ( ! session ) {
2024-09-19 14:53:50 +08:00
// 本对象已经销毁 [AUTO-TRANSLATED:713e0f23]
// This object has been destroyed
2019-12-28 13:11:41 +08:00
return ;
}
onRequestData ( data , session , sendBuf ) ;
} , false ) ;
} ) ;
return true ;
}
private :
static void onRequestData ( const AsyncSenderData : : Ptr & data , const std : : shared_ptr < HttpSession > & session , const Buffer : : Ptr & sendBuf ) {
session - > _ticker . resetTime ( ) ;
if ( sendBuf & & session - > send ( sendBuf ) ! = - 1 ) {
2024-09-19 14:53:50 +08:00
// 文件还未读完,还需要继续发送 [AUTO-TRANSLATED:c454ca1a]
// The file has not been read completely, and needs to be sent continuously
2019-12-28 13:11:41 +08:00
if ( ! session - > isSocketBusy ( ) ) {
2024-09-19 14:53:50 +08:00
// socket还可写, 继续请求数据 [AUTO-TRANSLATED:041df414]
// Socket can still write, continue to request data
2019-12-28 13:11:41 +08:00
onSocketFlushed ( data ) ;
}
return ;
}
2024-09-19 14:53:50 +08:00
// 文件写完了 [AUTO-TRANSLATED:a9f8c117]
// The file is written
2019-12-28 13:11:41 +08:00
data - > _read_complete = true ;
if ( ! session - > isSocketBusy ( ) & & data - > _close_when_complete ) {
shutdown ( session ) ;
}
}
static void shutdown ( const std : : shared_ptr < HttpSession > & session ) {
2023-06-10 09:45:46 +08:00
if ( session ) {
2019-12-28 13:11:41 +08:00
session - > shutdown ( SockException ( Err_shutdown , StrPrinter < < " close connection after send http body completed. " ) ) ;
}
}
} ;
2021-01-02 21:24:06 +08:00
void HttpSession : : sendResponse ( int code ,
2019-10-29 00:35:44 +08:00
bool bClose ,
const char * pcContentType ,
const HttpSession : : KeyValue & header ,
const HttpBody : : Ptr & body ,
2023-06-10 09:45:46 +08:00
bool no_content_length ) {
GET_CONFIG ( string , charSet , Http : : kCharSet ) ;
GET_CONFIG ( uint32_t , keepAliveSec , Http : : kKeepAliveSecond ) ;
2019-10-29 00:35:44 +08:00
2024-09-19 14:53:50 +08:00
// body默认为空 [AUTO-TRANSLATED:527ccb6f]
// Body defaults to empty
2022-02-10 21:06:51 +08:00
int64_t size = 0 ;
2019-10-29 00:35:44 +08:00
if ( body & & body - > remainSize ( ) ) {
2024-09-19 14:53:50 +08:00
// 有body, 获取body大小 [AUTO-TRANSLATED:0d5f4b9a]
// There is a body, get the body size
2019-10-29 00:35:44 +08:00
size = body - > remainSize ( ) ;
}
2022-02-10 21:06:51 +08:00
if ( no_content_length ) {
2024-09-19 14:53:50 +08:00
// http-flv直播是Keep-Alive类型 [AUTO-TRANSLATED:0ef3adfe]
// Http-flv live broadcast is Keep-Alive type
2019-10-29 00:35:44 +08:00
bClose = false ;
2022-02-10 21:06:51 +08:00
} else if ( ( size_t ) size > = SIZE_MAX | | size < 0 ) {
2024-09-19 14:53:50 +08:00
// 不固定长度的body, 那么发送完body后应该关闭socket, 以便浏览器做下载完毕的判断 [AUTO-TRANSLATED:fc714997]
// If the body is not fixed length, then the socket should be closed after sending the body, so that the browser can judge the download completion
2019-12-24 10:25:28 +08:00
bClose = true ;
2019-10-29 00:35:44 +08:00
}
HttpSession : : KeyValue & headerOut = const_cast < HttpSession : : KeyValue & > ( header ) ;
2023-06-10 10:16:45 +08:00
headerOut . emplace ( " Date " , dateStr ( ) ) ;
headerOut . emplace ( " Server " , kServerName ) ;
headerOut . emplace ( " Connection " , bClose ? " close " : " keep-alive " ) ;
2023-06-17 09:15:50 +08:00
GET_CONFIG ( bool , allow_cross_domains , Http : : kAllowCrossDomains ) ;
2024-01-27 21:29:10 +08:00
if ( allow_cross_domains & & ! _origin . empty ( ) ) {
headerOut . emplace ( " Access-Control-Allow-Origin " , _origin ) ;
2023-06-17 09:15:50 +08:00
headerOut . emplace ( " Access-Control-Allow-Credentials " , " true " ) ;
}
2022-02-10 21:06:51 +08:00
if ( ! bClose ) {
2019-12-26 15:02:28 +08:00
string keepAliveString = " timeout= " ;
keepAliveString + = to_string ( keepAliveSec ) ;
keepAliveString + = " , max=100 " ;
2023-06-10 10:16:45 +08:00
headerOut . emplace ( " Keep-Alive " , std : : move ( keepAliveString ) ) ;
2019-10-29 00:35:44 +08:00
}
2022-02-10 21:06:51 +08:00
if ( ! no_content_length & & size > = 0 & & ( size_t ) size < SIZE_MAX ) {
2024-09-19 14:53:50 +08:00
// 文件长度为固定值,且不是http-flv强制设置Content-Length [AUTO-TRANSLATED:185c02a8]
// The file length is a fixed value, and it is not http-flv that forcibly sets Content-Length
2023-06-10 10:16:45 +08:00
headerOut [ " Content-Length " ] = to_string ( size ) ;
2019-10-29 00:35:44 +08:00
}
2022-02-10 21:06:51 +08:00
if ( size & & ! pcContentType ) {
2024-09-19 14:53:50 +08:00
// 有body时, 设置缺省类型 [AUTO-TRANSLATED:21c9b233]
// When there is a body, set the default type
2019-10-29 00:35:44 +08:00
pcContentType = " text/plain " ;
}
2022-02-10 21:06:51 +08:00
if ( ( size | | no_content_length ) & & pcContentType ) {
2024-09-19 14:53:50 +08:00
// 有body时, 设置文件类型 [AUTO-TRANSLATED:0dcbeecc]
// When there is a body, set the file type
2019-12-26 15:02:28 +08:00
string strContentType = pcContentType ;
strContentType + = " ; charset= " ;
strContentType + = charSet ;
2023-06-10 10:16:45 +08:00
headerOut . emplace ( " Content-Type " , std : : move ( strContentType ) ) ;
2019-10-29 00:35:44 +08:00
}
2024-09-19 14:53:50 +08:00
// 发送http头 [AUTO-TRANSLATED:cca51598]
// Send http header
2019-12-26 15:02:28 +08:00
string str ;
str . reserve ( 256 ) ;
2022-02-10 21:06:51 +08:00
str + = " HTTP/1.1 " ;
2021-01-02 21:26:23 +08:00
str + = to_string ( code ) ;
str + = ' ' ;
2023-06-10 10:16:45 +08:00
str + = HttpConst : : getHttpStatusMessage ( code ) ;
2019-12-26 15:02:28 +08:00
str + = " \r \n " ;
2019-10-28 16:50:15 +08:00
for ( auto & pr : header ) {
2022-02-10 21:06:51 +08:00
str + = pr . first ;
2019-12-26 15:02:28 +08:00
str + = " : " ;
str + = pr . second ;
str + = " \r \n " ;
2019-10-28 16:50:15 +08:00
}
2019-12-26 15:02:28 +08:00
str + = " \r \n " ;
2020-04-23 17:50:12 +08:00
SockSender : : send ( std : : move ( str ) ) ;
2019-10-28 16:50:15 +08:00
_ticker . resetTime ( ) ;
2022-02-10 21:06:51 +08:00
if ( ! size ) {
2024-09-19 14:53:50 +08:00
// 没有body [AUTO-TRANSLATED:bf891e3a]
// No body
2022-02-10 21:06:51 +08:00
if ( bClose ) {
2023-06-10 09:45:46 +08:00
shutdown ( SockException ( Err_shutdown , StrPrinter < < " close connection after send http header completed with status code: " < < code ) ) ;
2019-10-28 16:50:15 +08:00
}
return ;
}
2022-02-11 12:03:45 +08:00
#if 0
2024-09-19 14:53:50 +08:00
// sendfile跟共享mmap相比并没有性能上的优势, 相反, sendfile还有功能上的缺陷, 先屏蔽 [AUTO-TRANSLATED:4de77827]
// Sendfile has no performance advantage over shared mmap, on the contrary, sendfile also has functional defects, so it is blocked first
2022-02-05 01:00:48 +08:00
if ( typeid ( * this ) = = typeid ( HttpSession ) & & ! body - > sendFile ( getSock ( ) - > rawFD ( ) ) ) {
2024-09-19 14:53:50 +08:00
// http支持sendfile优化 [AUTO-TRANSLATED:04f691f1]
// Http supports sendfile optimization
2022-02-04 23:02:19 +08:00
return ;
}
2022-02-11 12:03:45 +08:00
# endif
2022-02-04 23:02:19 +08:00
2019-12-28 13:11:41 +08:00
GET_CONFIG ( uint32_t , sendBufSize , Http : : kSendBufSize ) ;
2022-02-05 01:00:48 +08:00
if ( body - > remainSize ( ) > sendBufSize ) {
2024-09-19 14:53:50 +08:00
// 文件下载提升发送性能 [AUTO-TRANSLATED:500922cc]
// File download improves sending performance
2019-10-28 16:50:15 +08:00
setSocketFlags ( ) ;
}
2019-12-28 13:11:41 +08:00
2024-09-19 14:53:50 +08:00
// 发送http body [AUTO-TRANSLATED:e9fc35d6]
// Send http body
2023-04-28 22:04:38 +08:00
AsyncSenderData : : Ptr data = std : : make_shared < AsyncSenderData > ( static_pointer_cast < HttpSession > ( shared_from_this ( ) ) , body , bClose ) ;
2022-02-10 21:06:51 +08:00
getSock ( ) - > setOnFlush ( [ data ] ( ) { return AsyncSender : : onSocketFlushed ( data ) ; } ) ;
2019-12-28 13:11:41 +08:00
AsyncSender : : onSocketFlushed ( data ) ;
2019-10-28 16:50:15 +08:00
}
2023-06-10 09:45:46 +08:00
void HttpSession : : urlDecode ( Parser & parser ) {
2024-04-20 22:25:21 +08:00
parser . setUrl ( strCoding : : UrlDecodePath ( parser . url ( ) ) ) ;
2023-06-10 09:45:46 +08:00
for ( auto & pr : _parser . getUrlArgs ( ) ) {
2024-04-20 22:25:21 +08:00
const_cast < string & > ( pr . second ) = strCoding : : UrlDecodeComponent ( pr . second ) ;
2020-03-20 11:51:24 +08:00
}
2017-12-08 22:37:17 +08:00
}
2017-04-01 16:35:56 +08:00
2023-06-10 09:45:46 +08:00
bool HttpSession : : emitHttpEvent ( bool doInvoke ) {
bool bClose = ! strcasecmp ( _parser [ " Connection " ] . data ( ) , " close " ) ;
2024-09-19 14:53:50 +08:00
// ///////////////////异步回复Invoker/////////////////////////////// [AUTO-TRANSLATED:6d0c5fda]
// ///////////////////Asynchronous reply Invoker///////////////////////////////
2023-04-28 22:04:38 +08:00
weak_ptr < HttpSession > weak_self = static_pointer_cast < HttpSession > ( shared_from_this ( ) ) ;
2023-06-10 09:45:46 +08:00
HttpResponseInvoker invoker = [ weak_self , bClose ] ( int code , const KeyValue & headerOut , const HttpBody : : Ptr & body ) {
2022-08-30 21:24:25 +08:00
auto strong_self = weak_self . lock ( ) ;
2023-06-10 09:45:46 +08:00
if ( ! strong_self ) {
2020-03-20 11:51:24 +08:00
return ;
}
2022-08-30 21:24:25 +08:00
strong_self - > async ( [ weak_self , bClose , code , headerOut , body ] ( ) {
auto strong_self = weak_self . lock ( ) ;
if ( ! strong_self ) {
2024-09-19 14:53:50 +08:00
// 本对象已经销毁 [AUTO-TRANSLATED:713e0f23]
// This object has been destroyed
2020-03-20 11:51:24 +08:00
return ;
}
2022-08-30 21:24:25 +08:00
strong_self - > sendResponse ( code , bClose , nullptr , headerOut , body ) ;
2020-03-20 11:51:24 +08:00
} ) ;
} ;
2024-09-19 14:53:50 +08:00
// /////////////////广播HTTP事件/////////////////////////// [AUTO-TRANSLATED:fff9769c]
// /////////////////Broadcast HTTP event///////////////////////////
2023-06-10 09:45:46 +08:00
bool consumed = false ; // 该事件是否被消费
2023-09-02 10:52:07 +08:00
NOTICE_EMIT ( BroadcastHttpRequestArgs , Broadcast : : kBroadcastHttpRequest , _parser , invoker , consumed , * this ) ;
2023-06-10 09:45:46 +08:00
if ( ! consumed & & doInvoke ) {
2024-09-19 14:53:50 +08:00
// 该事件无人消费, 所以返回404 [AUTO-TRANSLATED:8a890dec]
// This event is not consumed, so return 404
2023-06-10 09:45:46 +08:00
invoker ( 404 , KeyValue ( ) , HttpBody : : Ptr ( ) ) ;
2020-03-20 11:51:24 +08:00
}
return consumed ;
2017-12-08 22:37:17 +08:00
}
2019-09-16 17:42:52 +08:00
2022-06-18 22:10:46 +08:00
std : : string HttpSession : : get_peer_ip ( ) {
GET_CONFIG ( string , forwarded_ip_header , Http : : kForwardedIpHeader ) ;
2023-06-10 09:45:46 +08:00
if ( ! forwarded_ip_header . empty ( ) & & ! _parser . getHeader ( ) [ forwarded_ip_header ] . empty ( ) ) {
2022-09-06 21:13:11 +08:00
return _parser . getHeader ( ) [ forwarded_ip_header ] ;
}
2022-11-19 09:33:10 +08:00
return Session : : get_peer_ip ( ) ;
2022-06-18 22:10:46 +08:00
}
2023-06-10 20:49:21 +08:00
void HttpSession : : onHttpRequest_POST ( ) {
emitHttpEvent ( true ) ;
2017-04-10 17:24:06 +08:00
}
2019-09-16 17:42:52 +08:00
void HttpSession : : sendNotFound ( bool bClose ) {
2022-03-03 19:39:18 +08:00
GET_CONFIG ( string , notFound , Http : : kNotFound ) ;
sendResponse ( 404 , bClose , " text/html " , KeyValue ( ) , std : : make_shared < HttpStringBody > ( notFound ) ) ;
2017-04-01 16:35:56 +08:00
}
2023-06-10 09:45:46 +08:00
void HttpSession : : setSocketFlags ( ) {
2020-04-29 11:08:43 +08:00
GET_CONFIG ( int , mergeWriteMS , General : : kMergeWriteMS ) ;
2023-06-10 09:45:46 +08:00
if ( mergeWriteMS > 0 ) {
2024-09-19 14:53:50 +08:00
// 推流模式下, 关闭TCP_NODELAY会增加推流端的延时, 但是服务器性能将提高 [AUTO-TRANSLATED:c8ec8fb8]
// In push mode, closing TCP_NODELAY will increase the delay of the push end, but the server performance will be improved
2020-09-12 19:03:52 +08:00
SockUtil : : setNoDelay ( getSock ( ) - > rawFD ( ) , false ) ;
2024-09-19 14:53:50 +08:00
// 播放模式下, 开启MSG_MORE会增加延时, 但是能提高发送性能 [AUTO-TRANSLATED:7b558ab9]
// In playback mode, enabling MSG_MORE will increase the delay, but it can improve sending performance
2020-04-23 17:50:12 +08:00
setSendFlags ( SOCKET_DEFAULE_FLAGS | FLAG_MORE ) ;
2019-09-04 18:57:54 +08:00
}
}
2018-08-30 19:29:54 +08:00
2020-04-09 16:19:03 +08:00
void HttpSession : : onWrite ( const Buffer : : Ptr & buffer , bool flush ) {
2023-06-10 09:45:46 +08:00
if ( flush ) {
2024-09-19 14:53:50 +08:00
// 需要flush那么一次刷新缓存 [AUTO-TRANSLATED:8d1ec961]
// Need to flush, then flush the cache once
2020-04-09 16:19:03 +08:00
HttpSession : : setSendFlushFlag ( true ) ;
}
2020-03-20 11:51:24 +08:00
_ticker . resetTime ( ) ;
2020-09-20 00:21:46 +08:00
if ( ! _live_over_websocket ) {
_total_bytes_usage + = buffer - > size ( ) ;
2019-08-12 18:14:51 +08:00
send ( buffer ) ;
2020-09-20 00:21:46 +08:00
} else {
2020-04-09 16:19:03 +08:00
WebSocketHeader header ;
header . _fin = true ;
header . _reserved = 0 ;
header . _opcode = WebSocketHeader : : BINARY ;
header . _mask_flag = false ;
2020-09-20 00:21:46 +08:00
WebSocketSplitter : : encode ( header , buffer ) ;
2019-08-12 18:14:51 +08:00
}
2020-09-20 00:21:46 +08:00
if ( flush ) {
2024-09-19 14:53:50 +08:00
// 本次刷新缓存后,下次不用刷新缓存 [AUTO-TRANSLATED:f56139f7]
// After this cache flush, the next time you don't need to flush the cache
2020-04-09 16:19:03 +08:00
HttpSession : : setSendFlushFlag ( false ) ;
}
2019-08-12 18:14:51 +08:00
}
2023-06-10 09:45:46 +08:00
void HttpSession : : onWebSocketEncodeData ( Buffer : : Ptr buffer ) {
2020-09-20 00:21:46 +08:00
_total_bytes_usage + = buffer - > size ( ) ;
2020-11-01 03:41:35 +08:00
send ( std : : move ( buffer ) ) ;
2017-12-15 16:01:21 +08:00
}
2023-06-10 09:45:46 +08:00
void HttpSession : : onWebSocketDecodeComplete ( const WebSocketHeader & header_in ) {
WebSocketHeader & header = const_cast < WebSocketHeader & > ( header_in ) ;
2020-08-08 12:17:06 +08:00
header . _mask_flag = false ;
switch ( header . _opcode ) {
case WebSocketHeader : : CLOSE : {
encode ( header , nullptr ) ;
shutdown ( SockException ( Err_shutdown , " recv close request from client " ) ) ;
break ;
}
2023-06-10 09:45:46 +08:00
default : break ;
2020-08-08 12:17:06 +08:00
}
}
2018-08-30 19:29:54 +08:00
void HttpSession : : onDetach ( ) {
2023-06-10 09:45:46 +08:00
shutdown ( SockException ( Err_shutdown , " rtmp ring buffer detached " ) ) ;
2018-08-30 19:29:54 +08:00
}
2023-06-10 09:45:46 +08:00
std : : shared_ptr < FlvMuxer > HttpSession : : getSharedPtr ( ) {
2020-03-20 11:51:24 +08:00
return dynamic_pointer_cast < FlvMuxer > ( shared_from_this ( ) ) ;
2018-01-30 11:47:56 +08:00
}
2018-10-24 17:17:55 +08:00
} /* namespace mediakit */