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
a44334ac
Commit
a44334ac
authored
May 08, 2022
by
ziyue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
全面支持ipv6
parent
a95bf960
隐藏空白字符变更
内嵌
并排
正在显示
11 个修改的文件
包含
126 行增加
和
114 行删除
+126
-114
3rdpart/ZLToolKit
+1
-1
3rdpart/media-server
+1
-1
src/Common/Parser.cpp
+81
-3
src/Common/Parser.h
+24
-2
src/Http/HttpClient.cpp
+4
-11
src/Rtmp/RtmpPlayer.cpp
+4
-9
src/Rtmp/RtmpPusher.cpp
+3
-9
src/Rtsp/Rtsp.cpp
+0
-53
src/Rtsp/Rtsp.h
+0
-21
src/Rtsp/RtspPlayer.cpp
+4
-2
src/Rtsp/RtspPusher.cpp
+4
-2
没有找到文件。
ZLToolKit
@
74ddbaa7
Subproject commit
de2ca7e61cb3154199d909088d8c12e91ecda577
Subproject commit
74ddbaa7e7c6995e94062a5ba1c7f0f2adef43f4
media-server
@
d6034e7e
Subproject commit
4a3cfe9edf0d72b249fb75a855b61be35a8c853a
Subproject commit
d6034e7e3572bcd557fd88438c10b98c5fabdd13
src/Common/Parser.cpp
查看文件 @
a44334ac
...
...
@@ -8,7 +8,10 @@
* may be found in the AUTHORS file in the root of the source tree.
*/
#include <inttypes.h>
#include "Parser.h"
#include "macros.h"
#include "Network/sockutil.h"
using
namespace
std
;
using
namespace
toolkit
;
...
...
@@ -38,9 +41,6 @@ string FindField(const char* buf, const char* start, const char *end ,size_t buf
return
string
(
msg_start
,
msg_end
);
}
Parser
::
Parser
()
{}
Parser
::~
Parser
()
{}
void
Parser
::
Parse
(
const
char
*
buf
)
{
//解析
const
char
*
start
=
buf
;
...
...
@@ -160,4 +160,81 @@ StrCaseMap Parser::parseArgs(const string &str, const char *pair_delim, const ch
return
ret
;
}
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
;
if
(
user_pwd
.
find
(
":"
)
==
string
::
npos
)
{
return
setup
(
is_ssl
,
url
,
user_pwd
,
""
);
}
auto
user
=
FindField
(
user_pwd
.
data
(),
nullptr
,
":"
);
auto
pwd
=
FindField
(
user_pwd
.
data
(),
":"
,
nullptr
);
return
setup
(
is_ssl
,
url
,
user
,
pwd
);
}
void
RtspUrl
::
setup
(
bool
is_ssl
,
const
string
&
url
,
const
string
&
user
,
const
string
&
passwd
)
{
auto
ip
=
FindField
(
url
.
data
(),
"://"
,
"/"
);
if
(
ip
.
empty
())
{
ip
=
split
(
FindField
(
url
.
data
(),
"://"
,
NULL
),
"?"
)[
0
];
}
uint16_t
port
=
is_ssl
?
322
:
554
;
splitUrl
(
ip
,
ip
,
port
);
_url
=
std
::
move
(
url
);
_user
=
std
::
move
(
user
);
_passwd
=
std
::
move
(
passwd
);
_host
=
std
::
move
(
ip
);
_port
=
port
;
_is_ssl
=
is_ssl
;
}
static
void
inline
checkHost
(
std
::
string
&
host
)
{
if
(
host
.
back
()
==
']'
&&
host
.
front
()
==
'['
)
{
// ipv6去除方括号
host
.
pop_back
();
host
.
erase
(
0
,
1
);
CHECK
(
SockUtil
::
is_ipv6
(
host
.
data
()),
"not a ipv6 address:"
,
host
);
}
}
void
splitUrl
(
const
std
::
string
&
url
,
std
::
string
&
host
,
uint16_t
&
port
)
{
auto
pos
=
url
.
rfind
(
':'
);
if
(
pos
==
string
::
npos
||
url
.
back
()
==
']'
)
{
//没有冒号,未指定端口;或者是纯粹的ipv6地址
host
=
url
;
checkHost
(
host
);
return
;
}
CHECK
(
pos
>
0
,
"invalid url:"
,
port
);
CHECK
(
sscanf
(
url
.
data
()
+
pos
+
1
,
"%"
SCNu16
,
&
port
)
==
1
,
"parse port from url failed:"
,
url
);
host
=
url
.
substr
(
0
,
pos
);
checkHost
(
host
);
}
#if 0
//测试代码
static onceToken token([](){
string host;
uint16_t port;
splitUrl("www.baidu.com:8880", host, port);
splitUrl("192.168.1.1:8880", host, port);
splitUrl("[::]:8880", host, port);
splitUrl("[fe80::604d:4173:76e9:1009]:8880", host, port);
});
#endif
}
//
namespace
mediakit
\ No newline at end of file
src/Common/Parser.h
查看文件 @
a44334ac
...
...
@@ -17,7 +17,10 @@
namespace
mediakit
{
//从字符串中提取子字符串
std
::
string
FindField
(
const
char
*
buf
,
const
char
*
start
,
const
char
*
end
,
size_t
bufSize
=
0
);
//把url解析为主机地址和端口号,兼容ipv4/ipv6/dns
void
splitUrl
(
const
std
::
string
&
url
,
std
::
string
&
host
,
uint16_t
&
port
);
struct
StrCaseCompare
{
bool
operator
()(
const
std
::
string
&
__x
,
const
std
::
string
&
__y
)
const
{
...
...
@@ -57,8 +60,8 @@ public:
//rtsp/http/sip解析类
class
Parser
{
public
:
Parser
();
~
Parser
();
Parser
()
=
default
;
~
Parser
()
=
default
;
//解析信令
void
Parse
(
const
char
*
buf
);
...
...
@@ -113,6 +116,25 @@ private:
mutable
StrCaseMap
_mapUrlArgs
;
};
//解析rtsp url的工具类
class
RtspUrl
{
public
:
bool
_is_ssl
;
uint16_t
_port
;
std
::
string
_url
;
std
::
string
_user
;
std
::
string
_passwd
;
std
::
string
_host
;
public
:
RtspUrl
()
=
default
;
~
RtspUrl
()
=
default
;
void
parse
(
const
std
::
string
&
url
);
private
:
void
setup
(
bool
,
const
std
::
string
&
,
const
std
::
string
&
,
const
std
::
string
&
);
};
}
//namespace mediakit
#endif //ZLMEDIAKIT_PARSER_H
src/Http/HttpClient.cpp
查看文件 @
a44334ac
...
...
@@ -22,13 +22,13 @@ void HttpClient::sendRequest(const string &url) {
clearResponse
();
_url
=
url
;
auto
protocol
=
FindField
(
url
.
data
(),
NULL
,
"://"
);
uint16_t
default_
port
;
uint16_t
port
;
bool
is_https
;
if
(
strcasecmp
(
protocol
.
data
(),
"http"
)
==
0
)
{
default_
port
=
80
;
port
=
80
;
is_https
=
false
;
}
else
if
(
strcasecmp
(
protocol
.
data
(),
"https"
)
==
0
)
{
default_
port
=
443
;
port
=
443
;
is_https
=
true
;
}
else
{
auto
strErr
=
StrPrinter
<<
"非法的http url:"
<<
url
<<
endl
;
...
...
@@ -53,14 +53,7 @@ void HttpClient::sendRequest(const string &url) {
_header
.
emplace
(
"Authorization"
,
"Basic "
+
encodeBase64
(
authStr
));
}
auto
host_header
=
host
;
uint16_t
port
=
atoi
(
FindField
(
host
.
data
(),
":"
,
NULL
).
data
());
if
(
port
<=
0
)
{
//默认端口
port
=
default_port
;
}
else
{
//服务器域名
host
=
FindField
(
host
.
data
(),
NULL
,
":"
);
}
splitUrl
(
host
,
host
,
port
);
_header
.
emplace
(
"Host"
,
host_header
);
_header
.
emplace
(
"User-Agent"
,
kServerName
);
_header
.
emplace
(
"Connection"
,
"keep-alive"
);
...
...
src/Rtmp/RtmpPlayer.cpp
查看文件 @
a44334ac
...
...
@@ -57,14 +57,9 @@ void RtmpPlayer::play(const string &strUrl) {
}
DebugL
<<
host_url
<<
" "
<<
_app
<<
" "
<<
_stream_id
;
auto
iPort
=
atoi
(
FindField
(
host_url
.
data
(),
":"
,
NULL
).
data
());
if
(
iPort
<=
0
)
{
//rtmp 默认端口1935
iPort
=
1935
;
}
else
{
//服务器域名
host_url
=
FindField
(
host_url
.
data
(),
NULL
,
":"
);
}
uint16_t
port
=
1935
;
splitUrl
(
host_url
,
host_url
,
port
);
if
(
!
(
*
this
)[
Client
::
kNetAdapter
].
empty
())
{
setNetAdapter
((
*
this
)[
Client
::
kNetAdapter
]);
}
...
...
@@ -81,7 +76,7 @@ void RtmpPlayer::play(const string &strUrl) {
},
getPoller
()));
_metadata_got
=
false
;
startConnect
(
host_url
,
iP
ort
,
play_timeout_sec
);
startConnect
(
host_url
,
p
ort
,
play_timeout_sec
);
}
void
RtmpPlayer
::
onErr
(
const
SockException
&
ex
){
...
...
src/Rtmp/RtmpPusher.cpp
查看文件 @
a44334ac
...
...
@@ -74,14 +74,8 @@ void RtmpPusher::publish(const string &url) {
}
DebugL
<<
host_url
<<
" "
<<
_app
<<
" "
<<
_stream_id
;
auto
iPort
=
atoi
(
FindField
(
host_url
.
data
(),
":"
,
NULL
).
data
());
if
(
iPort
<=
0
)
{
//rtmp 默认端口1935
iPort
=
1935
;
}
else
{
//服务器域名
host_url
=
FindField
(
host_url
.
data
(),
NULL
,
":"
);
}
uint16_t
port
=
1935
;
splitUrl
(
host_url
,
host_url
,
port
);
weak_ptr
<
RtmpPusher
>
weakSelf
=
dynamic_pointer_cast
<
RtmpPusher
>
(
shared_from_this
());
float
publishTimeOutSec
=
(
*
this
)[
Client
::
kTimeoutMS
].
as
<
int
>
()
/
1000.0
f
;
...
...
@@ -98,7 +92,7 @@ void RtmpPusher::publish(const string &url) {
setNetAdapter
((
*
this
)[
Client
::
kNetAdapter
]);
}
startConnect
(
host_url
,
iP
ort
);
startConnect
(
host_url
,
p
ort
);
}
void
RtmpPusher
::
onErr
(
const
SockException
&
ex
){
...
...
src/Rtsp/Rtsp.cpp
查看文件 @
a44334ac
...
...
@@ -312,59 +312,6 @@ string SdpParser::toString() const {
return
title
+
video
+
audio
;
}
bool
RtspUrl
::
parse
(
const
string
&
strUrl
)
{
auto
schema
=
FindField
(
strUrl
.
data
(),
nullptr
,
"://"
);
bool
isSSL
=
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
(
isSSL
,
strUrl
,
""
,
""
);
}
//包含用户名密码
auto
user_pwd
=
middle_url
.
substr
(
0
,
pos
);
auto
suffix
=
strUrl
.
substr
(
schema
.
size
()
+
3
+
pos
+
1
);
auto
url
=
StrPrinter
<<
"rtsp://"
<<
suffix
<<
endl
;
if
(
user_pwd
.
find
(
":"
)
==
string
::
npos
)
{
return
setup
(
isSSL
,
url
,
user_pwd
,
""
);
}
auto
user
=
FindField
(
user_pwd
.
data
(),
nullptr
,
":"
);
auto
pwd
=
FindField
(
user_pwd
.
data
(),
":"
,
nullptr
);
return
setup
(
isSSL
,
url
,
user
,
pwd
);
}
bool
RtspUrl
::
setup
(
bool
isSSL
,
const
string
&
strUrl
,
const
string
&
strUser
,
const
string
&
strPwd
)
{
auto
ip
=
FindField
(
strUrl
.
data
(),
"://"
,
"/"
);
if
(
ip
.
empty
())
{
ip
=
split
(
FindField
(
strUrl
.
data
(),
"://"
,
NULL
),
"?"
)[
0
];
}
auto
port
=
atoi
(
FindField
(
ip
.
data
(),
":"
,
NULL
).
data
());
if
(
port
<=
0
||
port
>
UINT16_MAX
)
{
//rtsp 默认端口554
port
=
isSSL
?
322
:
554
;
}
else
{
//服务器域名
ip
=
FindField
(
ip
.
data
(),
NULL
,
":"
);
}
if
(
ip
.
empty
())
{
return
false
;
}
_url
=
std
::
move
(
strUrl
);
_user
=
std
::
move
(
strUser
);
_passwd
=
std
::
move
(
strPwd
);
_host
=
std
::
move
(
ip
);
_port
=
port
;
_is_ssl
=
isSSL
;
return
true
;
}
class
PortManager
:
public
std
::
enable_shared_from_this
<
PortManager
>
{
public
:
PortManager
()
{
...
...
src/Rtsp/Rtsp.h
查看文件 @
a44334ac
...
...
@@ -253,27 +253,6 @@ private:
};
/**
* 解析rtsp url的工具类
*/
class
RtspUrl
{
public
:
bool
_is_ssl
;
uint16_t
_port
;
std
::
string
_url
;
std
::
string
_user
;
std
::
string
_passwd
;
std
::
string
_host
;
public
:
RtspUrl
()
=
default
;
~
RtspUrl
()
=
default
;
bool
parse
(
const
std
::
string
&
url
);
private
:
bool
setup
(
bool
,
const
std
::
string
&
,
const
std
::
string
&
,
const
std
::
string
&
);
};
/**
* rtsp sdp基类
*/
class
Sdp
:
public
CodecInfo
{
...
...
src/Rtsp/RtspPlayer.cpp
查看文件 @
a44334ac
...
...
@@ -66,8 +66,10 @@ void RtspPlayer::teardown(){
void
RtspPlayer
::
play
(
const
string
&
strUrl
){
RtspUrl
url
;
if
(
!
url
.
parse
(
strUrl
)){
onPlayResult_l
(
SockException
(
Err_other
,
StrPrinter
<<
"illegal rtsp url:"
<<
strUrl
),
false
);
try
{
url
.
parse
(
strUrl
);
}
catch
(
std
::
exception
&
ex
)
{
onPlayResult_l
(
SockException
(
Err_other
,
StrPrinter
<<
"illegal rtsp url:"
<<
ex
.
what
()),
false
);
return
;
}
...
...
src/Rtsp/RtspPusher.cpp
查看文件 @
a44334ac
...
...
@@ -56,8 +56,10 @@ void RtspPusher::teardown() {
void
RtspPusher
::
publish
(
const
string
&
url_str
)
{
RtspUrl
url
;
if
(
!
url
.
parse
(
url_str
))
{
onPublishResult_l
(
SockException
(
Err_other
,
StrPrinter
<<
"illegal rtsp url:"
<<
url_str
),
false
);
try
{
url
.
parse
(
url_str
);
}
catch
(
std
::
exception
&
ex
)
{
onPublishResult_l
(
SockException
(
Err_other
,
StrPrinter
<<
"illegal rtsp url:"
<<
ex
.
what
()),
false
);
return
;
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论