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 @@
#include "Parser.h"
#include "macros.h"
#include "Network/sockutil.h"
#include "Common/macros.h"
using
namespace
std
;
using
namespace
toolkit
;
namespace
mediakit
{
namespace
mediakit
{
string
FindField
(
const
char
*
buf
,
const
char
*
start
,
const
char
*
end
,
size_t
bufS
ize
)
{
if
(
bufSize
<=
0
)
{
buf
S
ize
=
strlen
(
buf
);
string
FindField
(
const
char
*
buf
,
const
char
*
start
,
const
char
*
end
,
size_t
buf_s
ize
)
{
if
(
buf_size
<=
0
)
{
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
;
if
(
start
!=
NULL
)
{
len
=
strlen
(
start
);
...
...
@@ -41,48 +42,52 @@ string FindField(const char* buf, const char* start, const char *end ,size_t buf
return
string
(
msg_start
,
msg_end
);
}
void
Parser
::
Parse
(
const
char
*
buf
)
{
//解析
const
char
*
start
=
buf
;
void
Parser
::
parse
(
const
char
*
buf
,
size_t
size
)
{
clear
();
auto
ptr
=
buf
;
while
(
true
)
{
auto
line
=
FindField
(
start
,
NULL
,
"
\r\n
"
);
if
(
line
.
size
()
==
0
)
{
break
;
}
if
(
start
==
buf
)
{
_
strMethod
=
FindField
(
line
.
data
(),
NULL
,
" "
);
auto
strFullUrl
=
FindField
(
line
.
data
(),
" "
,
" "
);
auto
args_pos
=
strFullUrl
.
find
(
'?'
);
if
(
args_pos
!=
string
::
npos
)
{
_strUrl
=
strFullUrl
.
substr
(
0
,
args_pos
);
_params
=
strFullUrl
.
substr
(
args_pos
+
1
);
_
mapUrlArgs
=
parseArgs
(
_params
);
}
else
{
_
strUrl
=
strFullUrl
;
auto
next_line
=
strstr
(
ptr
,
"
\r\n
"
);
CHECK
(
next_line
);
if
(
ptr
==
buf
)
{
auto
blank
=
strchr
(
ptr
,
' '
);
CHECK
(
blank
>
ptr
&&
blank
<
next_line
);
_
method
=
std
::
string
(
ptr
,
blank
);
auto
next_blank
=
strchr
(
blank
+
1
,
' '
);
CHECK
(
next_blank
&&
next_blank
<
next_line
);
_url
.
assign
(
blank
+
1
,
next_blank
);
auto
pos
=
_url
.
find
(
'?'
);
if
(
pos
!=
string
::
npos
)
{
_
params
=
_url
.
substr
(
pos
+
1
);
_url_args
=
parseArgs
(
_params
);
_
url
=
_url
.
substr
(
0
,
pos
)
;
}
_
strTail
=
FindField
(
line
.
data
(),
(
strFullUrl
+
" "
).
data
(),
NULL
);
_
protocol
=
std
::
string
(
next_blank
+
1
,
next_line
);
}
else
{
auto
field
=
FindField
(
line
.
data
(),
NULL
,
": "
);
auto
value
=
FindField
(
line
.
data
(),
": "
,
NULL
);
if
(
field
.
size
()
!=
0
)
{
_mapHeaders
.
emplace_force
(
field
,
value
);
auto
pos
=
strchr
(
ptr
,
':'
);
CHECK
(
pos
>
ptr
&&
pos
<
next_line
);
std
::
string
key
{
ptr
,
pos
};
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
;
if
(
strncmp
(
start
,
"
\r\n
"
,
2
)
==
0
)
{
//
协议解析完毕
_
strContent
=
FindField
(
start
,
"
\r\n
"
,
NULL
);
ptr
=
next_line
+
2
;
if
(
strncmp
(
ptr
,
"
\r\n
"
,
2
)
==
0
)
{
//
协议解析完毕
_
content
.
assign
(
ptr
+
2
,
buf
+
size
);
break
;
}
}
}
const
string
&
Parser
::
method
()
const
{
return
_
strM
ethod
;
return
_
m
ethod
;
}
const
string
&
Parser
::
url
()
const
{
return
_
strU
rl
;
return
_
u
rl
;
}
const
std
::
string
&
Parser
::
status
()
const
{
...
...
@@ -91,39 +96,41 @@ const std::string &Parser::status() const {
string
Parser
::
fullUrl
()
const
{
if
(
_params
.
empty
())
{
return
_
strU
rl
;
return
_
u
rl
;
}
return
_
strU
rl
+
"?"
+
_params
;
return
_
u
rl
+
"?"
+
_params
;
}
const
string
&
Parser
::
protocol
()
const
{
return
_
strTai
l
;
return
_
protoco
l
;
}
const
std
::
string
&
Parser
::
statusStr
()
const
{
return
protocol
();
}
static
std
::
string
kNull
;
const
string
&
Parser
::
operator
[](
const
char
*
name
)
const
{
auto
it
=
_
mapH
eaders
.
find
(
name
);
if
(
it
==
_
mapH
eaders
.
end
())
{
return
_str
Null
;
auto
it
=
_
h
eaders
.
find
(
name
);
if
(
it
==
_
h
eaders
.
end
())
{
return
k
Null
;
}
return
it
->
second
;
}
const
string
&
Parser
::
content
()
const
{
return
_
strC
ontent
;
return
_
c
ontent
;
}
void
Parser
::
clear
()
{
_
strM
ethod
.
clear
();
_
strU
rl
.
clear
();
_
m
ethod
.
clear
();
_
u
rl
.
clear
();
_params
.
clear
();
_
strTai
l
.
clear
();
_
strC
ontent
.
clear
();
_
mapH
eaders
.
clear
();
_
mapUrlA
rgs
.
clear
();
_
protoco
l
.
clear
();
_
c
ontent
.
clear
();
_
h
eaders
.
clear
();
_
url_a
rgs
.
clear
();
}
const
string
&
Parser
::
params
()
const
{
...
...
@@ -131,44 +138,46 @@ const string &Parser::params() const {
}
void
Parser
::
setUrl
(
string
url
)
{
this
->
_strU
rl
=
std
::
move
(
url
);
_u
rl
=
std
::
move
(
url
);
}
void
Parser
::
setContent
(
string
content
)
{
this
->
_strC
ontent
=
std
::
move
(
content
);
_c
ontent
=
std
::
move
(
content
);
}
StrCaseMap
&
Parser
::
getHeader
()
const
{
return
_
mapH
eaders
;
return
_
h
eaders
;
}
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
ret
;
auto
arg_vec
=
split
(
str
,
pair_delim
);
for
(
string
&
key_val
:
arg_vec
)
{
for
(
auto
&
key_val
:
arg_vec
)
{
if
(
key_val
.
empty
())
{
//忽略
//
忽略
continue
;
}
auto
key
=
trim
(
FindField
(
key_val
.
data
(),
NULL
,
key_delim
));
if
(
!
key
.
empty
())
{
auto
val
=
trim
(
FindField
(
key_val
.
data
(),
key_delim
,
NULL
));
ret
.
emplace_force
(
key
,
val
);
auto
pos
=
key_val
.
find
(
key_delim
);
if
(
pos
!=
string
::
npos
)
{
auto
key
=
trim
(
std
::
string
(
key_val
,
0
,
pos
));
auto
val
=
trim
(
key_val
.
substr
(
pos
+
strlen
(
key_delim
)));
ret
.
emplace_force
(
std
::
move
(
key
),
std
::
move
(
val
));
}
else
{
trim
(
key_val
);
if
(
!
key_val
.
empty
())
{
ret
.
emplace_force
(
key_val
,
""
);
ret
.
emplace_force
(
std
::
move
(
key_val
)
,
""
);
}
}
}
return
ret
;
}
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
())
{
return
path
;
}
...
...
@@ -242,21 +251,22 @@ std::string Parser::mergeUrl(const string &base_url, const string &path) {
}
return
final_url
.
str
();
}
void
RtspUrl
::
parse
(
const
string
&
strUrl
)
{
auto
schema
=
FindField
(
strUrl
.
data
(),
nullptr
,
"://"
);
bool
is_ssl
=
strcasecmp
(
schema
.
data
(),
"rtsps"
)
==
0
;
//查找"://"与"/"之间的字符串,用于提取用户名密码
//
查找"://"与"/"之间的字符串,用于提取用户名密码
auto
middle_url
=
FindField
(
strUrl
.
data
(),
"://"
,
"/"
);
if
(
middle_url
.
empty
())
{
middle_url
=
FindField
(
strUrl
.
data
(),
"://"
,
nullptr
);
}
auto
pos
=
middle_url
.
rfind
(
'@'
);
if
(
pos
==
string
::
npos
)
{
//并没有用户名密码
//
并没有用户名密码
return
setup
(
is_ssl
,
strUrl
,
""
,
""
);
}
//包含用户名密码
//
包含用户名密码
auto
user_pwd
=
middle_url
.
substr
(
0
,
pos
);
auto
suffix
=
strUrl
.
substr
(
schema
.
size
()
+
3
+
pos
+
1
);
auto
url
=
StrPrinter
<<
"rtsp://"
<<
suffix
<<
endl
;
...
...
@@ -297,7 +307,7 @@ void splitUrl(const std::string &url, std::string &host, uint16_t &port) {
CHECK
(
!
url
.
empty
(),
"empty url"
);
auto
pos
=
url
.
rfind
(
':'
);
if
(
pos
==
string
::
npos
||
url
.
back
()
==
']'
)
{
//没有冒号,未指定端口;或者是纯粹的ipv6地址
//
没有冒号,未指定端口;或者是纯粹的ipv6地址
host
=
url
;
checkHost
(
host
);
return
;
...
...
@@ -320,4 +330,4 @@ static onceToken token([](){
});
#endif
}
//
namespace mediakit
}
//
namespace mediakit
src/Common/Parser.h
查看文件 @
31944a92
...
...
@@ -18,7 +18,7 @@
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
void
splitUrl
(
const
std
::
string
&
url
,
std
::
string
&
host
,
uint16_t
&
port
);
...
...
@@ -40,18 +40,18 @@ public:
return
it
->
second
;
}
template
<
typename
V
>
void
emplace
(
const
std
::
string
&
k
,
V
&&
v
)
{
template
<
typename
K
,
typename
V
>
void
emplace
(
K
&
&
k
,
V
&&
v
)
{
auto
it
=
find
(
k
);
if
(
it
!=
end
())
{
return
;
}
Super
::
emplace
(
k
,
std
::
forward
<
V
>
(
v
));
Super
::
emplace
(
std
::
forward
<
K
>
(
k
)
,
std
::
forward
<
V
>
(
v
));
}
template
<
typename
V
>
void
emplace_force
(
const
std
::
string
k
,
V
&&
v
)
{
Super
::
emplace
(
k
,
std
::
forward
<
V
>
(
v
));
template
<
typename
K
,
typename
V
>
void
emplace_force
(
K
&&
k
,
V
&&
v
)
{
Super
::
emplace
(
std
::
forward
<
K
>
(
k
)
,
std
::
forward
<
V
>
(
v
));
}
};
...
...
@@ -61,23 +61,23 @@ public:
Parser
()
=
default
;
~
Parser
()
=
default
;
// 解析
信令
void
Parse
(
const
char
*
buf
);
// 解析
http/rtsp/sip请求,需要确保buf以\0结尾
void
parse
(
const
char
*
buf
,
size_t
size
);
// 获取命令字
// 获取命令字
,如GET/POST
const
std
::
string
&
method
()
const
;
// 请求时,获取中间url,不包含?后面的参数
const
std
::
string
&
url
()
const
;
// 回复时,获取状态码
// 回复时,获取状态码
,如200/404
const
std
::
string
&
status
()
const
;
// 获取中间url,包含?后面的参数
std
::
string
fullUrl
()
const
;
// 请求时,获取协议名
// 请求时,获取协议名
,如HTTP/1.1
const
std
::
string
&
protocol
()
const
;
// 回复时,获取状态字符串
// 回复时,获取状态字符串
,如 OK/Not Found
const
std
::
string
&
statusStr
()
const
;
// 根据header key名,获取请求header value值
...
...
@@ -110,14 +110,13 @@ public:
static
std
::
string
mergeUrl
(
const
std
::
string
&
base_url
,
const
std
::
string
&
path
);
private
:
std
::
string
_strMethod
;
std
::
string
_strUrl
;
std
::
string
_strTail
;
std
::
string
_strContent
;
std
::
string
_strNull
;
std
::
string
_method
;
std
::
string
_url
;
std
::
string
_protocol
;
std
::
string
_content
;
std
::
string
_params
;
mutable
StrCaseMap
_
mapH
eaders
;
mutable
StrCaseMap
_
mapUrlA
rgs
;
mutable
StrCaseMap
_
h
eaders
;
mutable
StrCaseMap
_
url_a
rgs
;
};
// 解析rtsp url的工具类
...
...
src/Http/HttpClient.cpp
查看文件 @
31944a92
...
...
@@ -181,7 +181,7 @@ void HttpClient::onError(const SockException &ex) {
}
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"
)
{
auto
new_url
=
Parser
::
mergeUrl
(
_url
,
_parser
[
"Location"
]);
if
(
new_url
.
empty
())
{
...
...
src/Http/HttpSession.cpp
查看文件 @
31944a92
...
...
@@ -63,14 +63,14 @@ ssize_t HttpSession::onRecvHeader(const char *header, size_t len) {
s_func_map
.
emplace
(
"OPTIONS"
,
&
HttpSession
::
Handle_Req_OPTIONS
);
});
_parser
.
Parse
(
header
);
_parser
.
parse
(
header
,
len
);
CHECK
(
_parser
.
url
()[
0
]
==
'/'
);
urlDecode
(
_parser
);
string
cmd
=
_parser
.
method
();
auto
it
=
s_func_map
.
find
(
cmd
);
if
(
it
==
s_func_map
.
end
())
{
WarnP
(
this
)
<<
"
不支持该命令:
"
<<
cmd
;
WarnP
(
this
)
<<
"
Http method not supported:
"
<<
cmd
;
sendResponse
(
405
,
true
);
return
0
;
}
...
...
src/Rtsp/RtspSplitter.cpp
查看文件 @
31944a92
...
...
@@ -61,7 +61,7 @@ ssize_t RtspSplitter::onRecvHeader(const char *data, size_t len) {
onRtpPacket
(
data
,
len
);
return
0
;
}
_parser
.
Parse
(
data
);
_parser
.
parse
(
data
,
len
);
auto
ret
=
getContentLength
(
_parser
);
if
(
ret
==
0
){
onWholeRtspPacket
(
_parser
);
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论