Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Z
ZLMediaKit
概览
Overview
Details
Activity
Cycle Analytics
版本库
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
问题
0
Issues
0
列表
Board
标记
里程碑
合并请求
0
Merge Requests
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
Snippets
成员
Collapse sidebar
Close sidebar
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
张翔宇
ZLMediaKit
Commits
31944a92
Commit
31944a92
authored
Jun 10, 2023
by
xia-chu
Committed by
夏楚
Jun 10, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
重写Parser代码实现
parent
af0ebf46
隐藏空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
95 行增加
和
86 行删除
+95
-86
src/Common/Parser.cpp
+72
-62
src/Common/Parser.h
+19
-20
src/Http/HttpClient.cpp
+1
-1
src/Http/HttpSession.cpp
+2
-2
src/Rtsp/RtspSplitter.cpp
+1
-1
没有找到文件。
src/Common/Parser.cpp
查看文件 @
31944a92
...
@@ -12,17 +12,18 @@
...
@@ -12,17 +12,18 @@
#include "Parser.h"
#include "Parser.h"
#include "macros.h"
#include "macros.h"
#include "Network/sockutil.h"
#include "Network/sockutil.h"
#include "Common/macros.h"
using
namespace
std
;
using
namespace
std
;
using
namespace
toolkit
;
using
namespace
toolkit
;
namespace
mediakit
{
namespace
mediakit
{
string
FindField
(
const
char
*
buf
,
const
char
*
start
,
const
char
*
end
,
size_t
bufS
ize
)
{
string
FindField
(
const
char
*
buf
,
const
char
*
start
,
const
char
*
end
,
size_t
buf_s
ize
)
{
if
(
bufSize
<=
0
)
{
if
(
buf_size
<=
0
)
{
buf
S
ize
=
strlen
(
buf
);
buf
_s
ize
=
strlen
(
buf
);
}
}
const
char
*
msg_start
=
buf
,
*
msg_end
=
buf
+
buf
S
ize
;
const
char
*
msg_start
=
buf
,
*
msg_end
=
buf
+
buf
_s
ize
;
size_t
len
=
0
;
size_t
len
=
0
;
if
(
start
!=
NULL
)
{
if
(
start
!=
NULL
)
{
len
=
strlen
(
start
);
len
=
strlen
(
start
);
...
@@ -41,48 +42,52 @@ string FindField(const char* buf, const char* start, const char *end ,size_t buf
...
@@ -41,48 +42,52 @@ string FindField(const char* buf, const char* start, const char *end ,size_t buf
return
string
(
msg_start
,
msg_end
);
return
string
(
msg_start
,
msg_end
);
}
}
void
Parser
::
Parse
(
const
char
*
buf
)
{
void
Parser
::
parse
(
const
char
*
buf
,
size_t
size
)
{
//解析
const
char
*
start
=
buf
;
clear
();
clear
();
auto
ptr
=
buf
;
while
(
true
)
{
while
(
true
)
{
auto
line
=
FindField
(
start
,
NULL
,
"
\r\n
"
);
auto
next_line
=
strstr
(
ptr
,
"
\r\n
"
);
if
(
line
.
size
()
==
0
)
{
CHECK
(
next_line
);
break
;
if
(
ptr
==
buf
)
{
}
auto
blank
=
strchr
(
ptr
,
' '
);
if
(
start
==
buf
)
{
CHECK
(
blank
>
ptr
&&
blank
<
next_line
);
_
strMethod
=
FindField
(
line
.
data
(),
NULL
,
" "
);
_
method
=
std
::
string
(
ptr
,
blank
);
auto
strFullUrl
=
FindField
(
line
.
data
(),
" "
,
" "
);
auto
next_blank
=
strchr
(
blank
+
1
,
' '
);
auto
args_pos
=
strFullUrl
.
find
(
'?'
);
CHECK
(
next_blank
&&
next_blank
<
next_line
);
if
(
args_pos
!=
string
::
npos
)
{
_url
.
assign
(
blank
+
1
,
next_blank
);
_strUrl
=
strFullUrl
.
substr
(
0
,
args_pos
);
auto
pos
=
_url
.
find
(
'?'
);
_params
=
strFullUrl
.
substr
(
args_pos
+
1
);
if
(
pos
!=
string
::
npos
)
{
_
mapUrlArgs
=
parseArgs
(
_params
);
_
params
=
_url
.
substr
(
pos
+
1
);
}
else
{
_url_args
=
parseArgs
(
_params
);
_
strUrl
=
strFullUrl
;
_
url
=
_url
.
substr
(
0
,
pos
)
;
}
}
_
strTail
=
FindField
(
line
.
data
(),
(
strFullUrl
+
" "
).
data
(),
NULL
);
_
protocol
=
std
::
string
(
next_blank
+
1
,
next_line
);
}
else
{
}
else
{
auto
field
=
FindField
(
line
.
data
(),
NULL
,
": "
);
auto
pos
=
strchr
(
ptr
,
':'
);
auto
value
=
FindField
(
line
.
data
(),
": "
,
NULL
);
CHECK
(
pos
>
ptr
&&
pos
<
next_line
);
if
(
field
.
size
()
!=
0
)
{
std
::
string
key
{
ptr
,
pos
};
_mapHeaders
.
emplace_force
(
field
,
value
);
std
::
string
value
;
if
(
pos
[
1
]
==
' '
)
{
value
.
assign
(
pos
+
2
,
next_line
);
}
else
{
value
.
assign
(
pos
+
1
,
next_line
);
}
}
_headers
.
emplace_force
(
trim
(
std
::
move
(
key
)),
trim
(
std
::
move
(
value
)));
}
}
start
=
start
+
line
.
size
()
+
2
;
ptr
=
next_line
+
2
;
if
(
strncmp
(
start
,
"
\r\n
"
,
2
)
==
0
)
{
//
协议解析完毕
if
(
strncmp
(
ptr
,
"
\r\n
"
,
2
)
==
0
)
{
//
协议解析完毕
_
strContent
=
FindField
(
start
,
"
\r\n
"
,
NULL
);
_
content
.
assign
(
ptr
+
2
,
buf
+
size
);
break
;
break
;
}
}
}
}
}
}
const
string
&
Parser
::
method
()
const
{
const
string
&
Parser
::
method
()
const
{
return
_
strM
ethod
;
return
_
m
ethod
;
}
}
const
string
&
Parser
::
url
()
const
{
const
string
&
Parser
::
url
()
const
{
return
_
strU
rl
;
return
_
u
rl
;
}
}
const
std
::
string
&
Parser
::
status
()
const
{
const
std
::
string
&
Parser
::
status
()
const
{
...
@@ -91,39 +96,41 @@ const std::string &Parser::status() const {
...
@@ -91,39 +96,41 @@ const std::string &Parser::status() const {
string
Parser
::
fullUrl
()
const
{
string
Parser
::
fullUrl
()
const
{
if
(
_params
.
empty
())
{
if
(
_params
.
empty
())
{
return
_
strU
rl
;
return
_
u
rl
;
}
}
return
_
strU
rl
+
"?"
+
_params
;
return
_
u
rl
+
"?"
+
_params
;
}
}
const
string
&
Parser
::
protocol
()
const
{
const
string
&
Parser
::
protocol
()
const
{
return
_
strTai
l
;
return
_
protoco
l
;
}
}
const
std
::
string
&
Parser
::
statusStr
()
const
{
const
std
::
string
&
Parser
::
statusStr
()
const
{
return
protocol
();
return
protocol
();
}
}
static
std
::
string
kNull
;
const
string
&
Parser
::
operator
[](
const
char
*
name
)
const
{
const
string
&
Parser
::
operator
[](
const
char
*
name
)
const
{
auto
it
=
_
mapH
eaders
.
find
(
name
);
auto
it
=
_
h
eaders
.
find
(
name
);
if
(
it
==
_
mapH
eaders
.
end
())
{
if
(
it
==
_
h
eaders
.
end
())
{
return
_str
Null
;
return
k
Null
;
}
}
return
it
->
second
;
return
it
->
second
;
}
}
const
string
&
Parser
::
content
()
const
{
const
string
&
Parser
::
content
()
const
{
return
_
strC
ontent
;
return
_
c
ontent
;
}
}
void
Parser
::
clear
()
{
void
Parser
::
clear
()
{
_
strM
ethod
.
clear
();
_
m
ethod
.
clear
();
_
strU
rl
.
clear
();
_
u
rl
.
clear
();
_params
.
clear
();
_params
.
clear
();
_
strTai
l
.
clear
();
_
protoco
l
.
clear
();
_
strC
ontent
.
clear
();
_
c
ontent
.
clear
();
_
mapH
eaders
.
clear
();
_
h
eaders
.
clear
();
_
mapUrlA
rgs
.
clear
();
_
url_a
rgs
.
clear
();
}
}
const
string
&
Parser
::
params
()
const
{
const
string
&
Parser
::
params
()
const
{
...
@@ -131,44 +138,46 @@ const string &Parser::params() const {
...
@@ -131,44 +138,46 @@ const string &Parser::params() const {
}
}
void
Parser
::
setUrl
(
string
url
)
{
void
Parser
::
setUrl
(
string
url
)
{
this
->
_strU
rl
=
std
::
move
(
url
);
_u
rl
=
std
::
move
(
url
);
}
}
void
Parser
::
setContent
(
string
content
)
{
void
Parser
::
setContent
(
string
content
)
{
this
->
_strC
ontent
=
std
::
move
(
content
);
_c
ontent
=
std
::
move
(
content
);
}
}
StrCaseMap
&
Parser
::
getHeader
()
const
{
StrCaseMap
&
Parser
::
getHeader
()
const
{
return
_
mapH
eaders
;
return
_
h
eaders
;
}
}
StrCaseMap
&
Parser
::
getUrlArgs
()
const
{
StrCaseMap
&
Parser
::
getUrlArgs
()
const
{
return
_
mapUrlA
rgs
;
return
_
url_a
rgs
;
}
}
StrCaseMap
Parser
::
parseArgs
(
const
string
&
str
,
const
char
*
pair_delim
,
const
char
*
key_delim
)
{
StrCaseMap
Parser
::
parseArgs
(
const
string
&
str
,
const
char
*
pair_delim
,
const
char
*
key_delim
)
{
StrCaseMap
ret
;
StrCaseMap
ret
;
auto
arg_vec
=
split
(
str
,
pair_delim
);
auto
arg_vec
=
split
(
str
,
pair_delim
);
for
(
string
&
key_val
:
arg_vec
)
{
for
(
auto
&
key_val
:
arg_vec
)
{
if
(
key_val
.
empty
())
{
if
(
key_val
.
empty
())
{
//忽略
//
忽略
continue
;
continue
;
}
}
auto
key
=
trim
(
FindField
(
key_val
.
data
(),
NULL
,
key_delim
));
auto
pos
=
key_val
.
find
(
key_delim
);
if
(
!
key
.
empty
())
{
if
(
pos
!=
string
::
npos
)
{
auto
val
=
trim
(
FindField
(
key_val
.
data
(),
key_delim
,
NULL
));
auto
key
=
trim
(
std
::
string
(
key_val
,
0
,
pos
));
ret
.
emplace_force
(
key
,
val
);
auto
val
=
trim
(
key_val
.
substr
(
pos
+
strlen
(
key_delim
)));
ret
.
emplace_force
(
std
::
move
(
key
),
std
::
move
(
val
));
}
else
{
}
else
{
trim
(
key_val
);
trim
(
key_val
);
if
(
!
key_val
.
empty
())
{
if
(
!
key_val
.
empty
())
{
ret
.
emplace_force
(
key_val
,
""
);
ret
.
emplace_force
(
std
::
move
(
key_val
)
,
""
);
}
}
}
}
}
}
return
ret
;
return
ret
;
}
}
std
::
string
Parser
::
mergeUrl
(
const
string
&
base_url
,
const
string
&
path
)
{
std
::
string
Parser
::
mergeUrl
(
const
string
&
base_url
,
const
string
&
path
)
{
//以base_url为基础, 合并path路径生成新的url, path支持相对路径和绝对路径
//
以base_url为基础, 合并path路径生成新的url, path支持相对路径和绝对路径
if
(
base_url
.
empty
())
{
if
(
base_url
.
empty
())
{
return
path
;
return
path
;
}
}
...
@@ -242,21 +251,22 @@ std::string Parser::mergeUrl(const string &base_url, const string &path) {
...
@@ -242,21 +251,22 @@ std::string Parser::mergeUrl(const string &base_url, const string &path) {
}
}
return
final_url
.
str
();
return
final_url
.
str
();
}
}
void
RtspUrl
::
parse
(
const
string
&
strUrl
)
{
void
RtspUrl
::
parse
(
const
string
&
strUrl
)
{
auto
schema
=
FindField
(
strUrl
.
data
(),
nullptr
,
"://"
);
auto
schema
=
FindField
(
strUrl
.
data
(),
nullptr
,
"://"
);
bool
is_ssl
=
strcasecmp
(
schema
.
data
(),
"rtsps"
)
==
0
;
bool
is_ssl
=
strcasecmp
(
schema
.
data
(),
"rtsps"
)
==
0
;
//查找"://"与"/"之间的字符串,用于提取用户名密码
//
查找"://"与"/"之间的字符串,用于提取用户名密码
auto
middle_url
=
FindField
(
strUrl
.
data
(),
"://"
,
"/"
);
auto
middle_url
=
FindField
(
strUrl
.
data
(),
"://"
,
"/"
);
if
(
middle_url
.
empty
())
{
if
(
middle_url
.
empty
())
{
middle_url
=
FindField
(
strUrl
.
data
(),
"://"
,
nullptr
);
middle_url
=
FindField
(
strUrl
.
data
(),
"://"
,
nullptr
);
}
}
auto
pos
=
middle_url
.
rfind
(
'@'
);
auto
pos
=
middle_url
.
rfind
(
'@'
);
if
(
pos
==
string
::
npos
)
{
if
(
pos
==
string
::
npos
)
{
//并没有用户名密码
//
并没有用户名密码
return
setup
(
is_ssl
,
strUrl
,
""
,
""
);
return
setup
(
is_ssl
,
strUrl
,
""
,
""
);
}
}
//包含用户名密码
//
包含用户名密码
auto
user_pwd
=
middle_url
.
substr
(
0
,
pos
);
auto
user_pwd
=
middle_url
.
substr
(
0
,
pos
);
auto
suffix
=
strUrl
.
substr
(
schema
.
size
()
+
3
+
pos
+
1
);
auto
suffix
=
strUrl
.
substr
(
schema
.
size
()
+
3
+
pos
+
1
);
auto
url
=
StrPrinter
<<
"rtsp://"
<<
suffix
<<
endl
;
auto
url
=
StrPrinter
<<
"rtsp://"
<<
suffix
<<
endl
;
...
@@ -297,7 +307,7 @@ void splitUrl(const std::string &url, std::string &host, uint16_t &port) {
...
@@ -297,7 +307,7 @@ void splitUrl(const std::string &url, std::string &host, uint16_t &port) {
CHECK
(
!
url
.
empty
(),
"empty url"
);
CHECK
(
!
url
.
empty
(),
"empty url"
);
auto
pos
=
url
.
rfind
(
':'
);
auto
pos
=
url
.
rfind
(
':'
);
if
(
pos
==
string
::
npos
||
url
.
back
()
==
']'
)
{
if
(
pos
==
string
::
npos
||
url
.
back
()
==
']'
)
{
//没有冒号,未指定端口;或者是纯粹的ipv6地址
//
没有冒号,未指定端口;或者是纯粹的ipv6地址
host
=
url
;
host
=
url
;
checkHost
(
host
);
checkHost
(
host
);
return
;
return
;
...
@@ -320,4 +330,4 @@ static onceToken token([](){
...
@@ -320,4 +330,4 @@ static onceToken token([](){
});
});
#endif
#endif
}
//
namespace mediakit
}
//
namespace mediakit
src/Common/Parser.h
查看文件 @
31944a92
...
@@ -18,7 +18,7 @@
...
@@ -18,7 +18,7 @@
namespace
mediakit
{
namespace
mediakit
{
// 从字符串中提取子字符串
// 从字符串中提取子字符串
std
::
string
FindField
(
const
char
*
buf
,
const
char
*
start
,
const
char
*
end
,
size_t
buf
S
ize
=
0
);
std
::
string
FindField
(
const
char
*
buf
,
const
char
*
start
,
const
char
*
end
,
size_t
buf
_s
ize
=
0
);
// 把url解析为主机地址和端口号,兼容ipv4/ipv6/dns
// 把url解析为主机地址和端口号,兼容ipv4/ipv6/dns
void
splitUrl
(
const
std
::
string
&
url
,
std
::
string
&
host
,
uint16_t
&
port
);
void
splitUrl
(
const
std
::
string
&
url
,
std
::
string
&
host
,
uint16_t
&
port
);
...
@@ -40,18 +40,18 @@ public:
...
@@ -40,18 +40,18 @@ public:
return
it
->
second
;
return
it
->
second
;
}
}
template
<
typename
V
>
template
<
typename
K
,
typename
V
>
void
emplace
(
const
std
::
string
&
k
,
V
&&
v
)
{
void
emplace
(
K
&
&
k
,
V
&&
v
)
{
auto
it
=
find
(
k
);
auto
it
=
find
(
k
);
if
(
it
!=
end
())
{
if
(
it
!=
end
())
{
return
;
return
;
}
}
Super
::
emplace
(
k
,
std
::
forward
<
V
>
(
v
));
Super
::
emplace
(
std
::
forward
<
K
>
(
k
)
,
std
::
forward
<
V
>
(
v
));
}
}
template
<
typename
V
>
template
<
typename
K
,
typename
V
>
void
emplace_force
(
const
std
::
string
k
,
V
&&
v
)
{
void
emplace_force
(
K
&&
k
,
V
&&
v
)
{
Super
::
emplace
(
k
,
std
::
forward
<
V
>
(
v
));
Super
::
emplace
(
std
::
forward
<
K
>
(
k
)
,
std
::
forward
<
V
>
(
v
));
}
}
};
};
...
@@ -61,23 +61,23 @@ public:
...
@@ -61,23 +61,23 @@ public:
Parser
()
=
default
;
Parser
()
=
default
;
~
Parser
()
=
default
;
~
Parser
()
=
default
;
// 解析
信令
// 解析
http/rtsp/sip请求,需要确保buf以\0结尾
void
Parse
(
const
char
*
buf
);
void
parse
(
const
char
*
buf
,
size_t
size
);
// 获取命令字
// 获取命令字
,如GET/POST
const
std
::
string
&
method
()
const
;
const
std
::
string
&
method
()
const
;
// 请求时,获取中间url,不包含?后面的参数
// 请求时,获取中间url,不包含?后面的参数
const
std
::
string
&
url
()
const
;
const
std
::
string
&
url
()
const
;
// 回复时,获取状态码
// 回复时,获取状态码
,如200/404
const
std
::
string
&
status
()
const
;
const
std
::
string
&
status
()
const
;
// 获取中间url,包含?后面的参数
// 获取中间url,包含?后面的参数
std
::
string
fullUrl
()
const
;
std
::
string
fullUrl
()
const
;
// 请求时,获取协议名
// 请求时,获取协议名
,如HTTP/1.1
const
std
::
string
&
protocol
()
const
;
const
std
::
string
&
protocol
()
const
;
// 回复时,获取状态字符串
// 回复时,获取状态字符串
,如 OK/Not Found
const
std
::
string
&
statusStr
()
const
;
const
std
::
string
&
statusStr
()
const
;
// 根据header key名,获取请求header value值
// 根据header key名,获取请求header value值
...
@@ -110,14 +110,13 @@ public:
...
@@ -110,14 +110,13 @@ public:
static
std
::
string
mergeUrl
(
const
std
::
string
&
base_url
,
const
std
::
string
&
path
);
static
std
::
string
mergeUrl
(
const
std
::
string
&
base_url
,
const
std
::
string
&
path
);
private
:
private
:
std
::
string
_strMethod
;
std
::
string
_method
;
std
::
string
_strUrl
;
std
::
string
_url
;
std
::
string
_strTail
;
std
::
string
_protocol
;
std
::
string
_strContent
;
std
::
string
_content
;
std
::
string
_strNull
;
std
::
string
_params
;
std
::
string
_params
;
mutable
StrCaseMap
_
mapH
eaders
;
mutable
StrCaseMap
_
h
eaders
;
mutable
StrCaseMap
_
mapUrlA
rgs
;
mutable
StrCaseMap
_
url_a
rgs
;
};
};
// 解析rtsp url的工具类
// 解析rtsp url的工具类
...
...
src/Http/HttpClient.cpp
查看文件 @
31944a92
...
@@ -181,7 +181,7 @@ void HttpClient::onError(const SockException &ex) {
...
@@ -181,7 +181,7 @@ void HttpClient::onError(const SockException &ex) {
}
}
ssize_t
HttpClient
::
onRecvHeader
(
const
char
*
data
,
size_t
len
)
{
ssize_t
HttpClient
::
onRecvHeader
(
const
char
*
data
,
size_t
len
)
{
_parser
.
Parse
(
data
);
_parser
.
parse
(
data
,
len
);
if
(
_parser
.
status
()
==
"302"
||
_parser
.
status
()
==
"301"
||
_parser
.
status
()
==
"303"
)
{
if
(
_parser
.
status
()
==
"302"
||
_parser
.
status
()
==
"301"
||
_parser
.
status
()
==
"303"
)
{
auto
new_url
=
Parser
::
mergeUrl
(
_url
,
_parser
[
"Location"
]);
auto
new_url
=
Parser
::
mergeUrl
(
_url
,
_parser
[
"Location"
]);
if
(
new_url
.
empty
())
{
if
(
new_url
.
empty
())
{
...
...
src/Http/HttpSession.cpp
查看文件 @
31944a92
...
@@ -63,14 +63,14 @@ ssize_t HttpSession::onRecvHeader(const char *header, size_t len) {
...
@@ -63,14 +63,14 @@ ssize_t HttpSession::onRecvHeader(const char *header, size_t len) {
s_func_map
.
emplace
(
"OPTIONS"
,
&
HttpSession
::
Handle_Req_OPTIONS
);
s_func_map
.
emplace
(
"OPTIONS"
,
&
HttpSession
::
Handle_Req_OPTIONS
);
});
});
_parser
.
Parse
(
header
);
_parser
.
parse
(
header
,
len
);
CHECK
(
_parser
.
url
()[
0
]
==
'/'
);
CHECK
(
_parser
.
url
()[
0
]
==
'/'
);
urlDecode
(
_parser
);
urlDecode
(
_parser
);
string
cmd
=
_parser
.
method
();
string
cmd
=
_parser
.
method
();
auto
it
=
s_func_map
.
find
(
cmd
);
auto
it
=
s_func_map
.
find
(
cmd
);
if
(
it
==
s_func_map
.
end
())
{
if
(
it
==
s_func_map
.
end
())
{
WarnP
(
this
)
<<
"
不支持该命令:
"
<<
cmd
;
WarnP
(
this
)
<<
"
Http method not supported:
"
<<
cmd
;
sendResponse
(
405
,
true
);
sendResponse
(
405
,
true
);
return
0
;
return
0
;
}
}
...
...
src/Rtsp/RtspSplitter.cpp
查看文件 @
31944a92
...
@@ -61,7 +61,7 @@ ssize_t RtspSplitter::onRecvHeader(const char *data, size_t len) {
...
@@ -61,7 +61,7 @@ ssize_t RtspSplitter::onRecvHeader(const char *data, size_t len) {
onRtpPacket
(
data
,
len
);
onRtpPacket
(
data
,
len
);
return
0
;
return
0
;
}
}
_parser
.
Parse
(
data
);
_parser
.
parse
(
data
,
len
);
auto
ret
=
getContentLength
(
_parser
);
auto
ret
=
getContentLength
(
_parser
);
if
(
ret
==
0
){
if
(
ret
==
0
){
onWholeRtspPacket
(
_parser
);
onWholeRtspPacket
(
_parser
);
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论