mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-07-06 03:28:09 +08:00
全面支持ipv6
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user