From 4a225c5640df3910ca2f9fb8e1922b23b15e1942 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 2 Sep 2022 09:46:58 +0800 Subject: [PATCH] For #307: WebRTC: Support use domain name as CANDIDATE. v4.0.259 --- trunk/conf/full.conf | 24 +++++---- trunk/doc/CHANGELOG.md | 1 + trunk/src/app/srs_app_config.cpp | 54 +++++++++++++++++++- trunk/src/app/srs_app_config.hpp | 3 ++ trunk/src/app/srs_app_rtc_server.cpp | 76 ++++++++++++++++------------ trunk/src/core/srs_core_version4.hpp | 2 +- 6 files changed, 116 insertions(+), 44 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index fac4c81cd..d7bc10897 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -394,16 +394,9 @@ rtc_server { listen 8000; # The exposed candidate IPs, response in SDP candidate line. It can be: # * Retrieve server IP automatically, from all network interfaces. - # eth0 Retrieve server IP by specified network interface name. # TODO: Implements it. # $CANDIDATE Read the IP from ENV variable, use * if not set. - # x.x.x.x A specified IP address or DNS name, which can be access by client such as Chrome. - # You can specific more than one interface name: - # eth0 eth1 Use network interface eth0 and eth1. # TODO: Implements it. - # Also by IP or DNS names: - # 192.168.1.3 10.1.2.3 rtc.me # TODO: Implements it. - # And by multiple ENV variables: - # $CANDIDATE $EIP # TODO: Implements it. - # @remark For Firefox, the candidate MUST be IP, MUST NOT be DNS name. + # x.x.x.x A specified IP address or DNS name, use * if 0.0.0.0. + # @remark For Firefox, the candidate MUST be IP, MUST NOT be DNS name, see https://bugzilla.mozilla.org/show_bug.cgi?id=1239006 # @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#config-candidate # default: * candidate *; @@ -412,6 +405,19 @@ rtc_server { # in this case, the r.ossrs.net and 39.107.238.185 will be added as candidates. # Default: on api_as_candidates on; + # If use api as CANDIDATE, whether resolve the api hostname. + # Note that use original domain name as CANDIDATE, which might make Firefox failed, see https://bugzilla.mozilla.org/show_bug.cgi?id=1239006 + # Note that if hostname is IPv4 address, always directly use it. + # Default: on + resolve_api_domain on; + # If use api as CANDIDATE, whether keep original api domain name as CANDIDATE. + # Note that use original domain name as CANDIDATE, which might make Firefox failed, see https://bugzilla.mozilla.org/show_bug.cgi?id=1239006 + # Default: off + keep_api_domain off; + # Whether use network interface IP which is detected automatically, filtered by ip_family. + # Note that browser might fail if no CANDIDATE specified. + # Default: on + use_auto_detect_network_ip on; # The IP family filter for auto discover candidate, it can be: # ipv4 Filter IP v4 candidates. # ipv6 Filter IP v6 candidates. diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index 66a813c85..95683650c 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -8,6 +8,7 @@ The changelog for SRS. ## SRS 4.0 Changelog +* v4.0, 2022-09-02, For [#307](https://github.com/ossrs/srs/issues/307): WebRTC: Support use domain name as CANDIDATE. v4.0.259 * v4.0, 2022-08-29, Copy libxml2-dev for FFmpeg. v4.0.258 * v4.0, 2022-08-24, STAT: Support config server_id and generate one if empty. v4.0.257 * v4.0, 2022-08-24, For [#2136](https://github.com/ossrs/srs/issues/2136): API: Cleanup no active streams for statistics. v4.0.256 diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 50a19cfd6..4619f1180 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -2545,7 +2545,8 @@ srs_error_t SrsConfig::check_normal_config() string n = conf->at(i)->name; if (n != "enabled" && n != "listen" && n != "dir" && n != "candidate" && n != "ecdsa" && n != "encrypt" && n != "reuseport" && n != "merge_nalus" && n != "black_hole" - && n != "ip_family" && n != "api_as_candidates") { + && n != "ip_family" && n != "api_as_candidates" && n != "resolve_api_domain" + && n != "keep_api_domain" && n != "use_auto_detect_network_ip") { return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal rtc_server.%s", n.c_str()); } } @@ -3662,6 +3663,57 @@ bool SrsConfig::get_api_as_candidates() return SRS_CONF_PERFER_TRUE(conf->arg0()); } +bool SrsConfig::get_resolve_api_domain() +{ + static bool DEFAULT = true; + + SrsConfDirective* conf = root->get("rtc_server"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("resolve_api_domain"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return SRS_CONF_PERFER_TRUE(conf->arg0()); +} + +bool SrsConfig::get_keep_api_domain() +{ + static bool DEFAULT = false; + + SrsConfDirective* conf = root->get("rtc_server"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("keep_api_domain"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return SRS_CONF_PERFER_FALSE(conf->arg0()); +} + +bool SrsConfig::get_use_auto_detect_network_ip() +{ + static bool DEFAULT = true; + + SrsConfDirective* conf = root->get("rtc_server"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("use_auto_detect_network_ip"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return SRS_CONF_PERFER_TRUE(conf->arg0()); +} + std::string SrsConfig::get_rtc_server_ip_family() { static string DEFAULT = "ipv4"; diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 9cc71b433..73156d74d 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -473,6 +473,9 @@ public: virtual int get_rtc_server_listen(); virtual std::string get_rtc_server_candidates(); virtual bool get_api_as_candidates(); + virtual bool get_resolve_api_domain(); + virtual bool get_keep_api_domain(); + virtual bool get_use_auto_detect_network_ip(); virtual std::string get_rtc_server_ip_family(); virtual bool get_rtc_server_ecdsa(); virtual bool get_rtc_server_encrypt(); diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index b08db9c04..30f6f7065 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -158,12 +158,7 @@ srs_error_t api_server_as_candidates(string api, set& candidate_ips) return err; } - SrsHttpUri uri; - if ((err = uri.initialize(api)) != srs_success) { - return srs_error_wrap(err, "parse %s", api.c_str()); - } - - string hostname = uri.get_host(); + string hostname = api; if (hostname.empty() || hostname == SRS_CONSTS_LOCALHOST_NAME) { return err; } @@ -171,15 +166,27 @@ srs_error_t api_server_as_candidates(string api, set& candidate_ips) return err; } - // Try to parse the domain name if not IP. - int family = 0; - string ip = srs_dns_resolve(hostname, family); - if (ip.empty() || ip == SRS_CONSTS_LOCALHOST || ip == SRS_CONSTS_LOOPBACK || ip == SRS_CONSTS_LOOPBACK6) { - return err; + // Whether add domain name. + if (!srs_is_ipv4(hostname) && _srs_config->get_keep_api_domain()) { + candidate_ips.insert(hostname); } - // Try to add the API server ip as candidates. - candidate_ips.insert(ip); + // Try to parse the domain name if not IP. + if (!srs_is_ipv4(hostname) && _srs_config->get_resolve_api_domain()) { + int family = 0; + string ip = srs_dns_resolve(hostname, family); + if (ip.empty() || ip == SRS_CONSTS_LOCALHOST || ip == SRS_CONSTS_LOOPBACK || ip == SRS_CONSTS_LOOPBACK6) { + return err; + } + + // Try to add the API server ip as candidates. + candidate_ips.insert(ip); + } + + // If hostname is IP, use it. + if (srs_is_ipv4(hostname)) { + candidate_ips.insert(hostname); + } return err; } @@ -195,8 +202,8 @@ static set discover_candidates(SrsRtcUserConfig* ruc) } // Try to discover from api of request, if api_as_candidates enabled. - if ((err = api_server_as_candidates(ruc->api_, candidate_ips)) != srs_success) { - srs_warn("ignore discovering ip from api %s, err %s", ruc->api_.c_str(), srs_error_summary(err).c_str()); + if ((err = api_server_as_candidates(ruc->req_->host, candidate_ips)) != srs_success) { + srs_warn("ignore discovering ip from api %s, err %s", ruc->req_->host.c_str(), srs_error_summary(err).c_str()); srs_freep(err); } @@ -207,29 +214,32 @@ static set discover_candidates(SrsRtcUserConfig* ruc) return candidate_ips; } - // Discover from local network interface addresses. + // All automatically detected IP list. vector& ips = srs_get_local_ips(); if (ips.empty()) { return candidate_ips; } - // We try to find the best match candidates, no loopback. - string family = _srs_config->get_rtc_server_ip_family(); - for (int i = 0; i < (int)ips.size(); ++i) { - SrsIPAddress* ip = ips[i]; - if (ip->is_loopback) { - continue; - } + // Discover from local network interface addresses. + if (_srs_config->get_use_auto_detect_network_ip()) { + // We try to find the best match candidates, no loopback. + string family = _srs_config->get_rtc_server_ip_family(); + for (int i = 0; i < (int) ips.size(); ++i) { + SrsIPAddress* ip = ips[i]; + if (ip->is_loopback) { + continue; + } - if (family == "ipv4" && !ip->is_ipv4) { - continue; - } - if (family == "ipv6" && ip->is_ipv4) { - continue; - } + if (family == "ipv4" && !ip->is_ipv4) { + continue; + } + if (family == "ipv6" && ip->is_ipv4) { + continue; + } - candidate_ips.insert(ip->ip); - srs_trace("Best matched ip=%s, ifname=%s", ip->ip.c_str(), ip->ifname.c_str()); + candidate_ips.insert(ip->ip); + srs_trace("Best matched ip=%s, ifname=%s", ip->ip.c_str(), ip->ifname.c_str()); + } } if (!candidate_ips.empty()) { @@ -248,7 +258,7 @@ static set discover_candidates(SrsRtcUserConfig* ruc) return candidate_ips; } - // We use the first one. + // We use the first one, to make sure there will be at least one CANDIDATE. if (candidate_ips.empty()) { SrsIPAddress* ip = ips[0]; candidate_ips.insert(ip->ip); @@ -577,7 +587,7 @@ srs_error_t SrsRtcServer::do_create_session(SrsRtcUserConfig* ruc, SrsSdp& local set candidates = discover_candidates(ruc); for (set::iterator it = candidates.begin(); it != candidates.end(); ++it) { string hostname; int port = listen_port; - srs_parse_hostport(*it, hostname,port); + srs_parse_hostport(*it, hostname, port); local_sdp.add_candidate(hostname, port, "host"); } diff --git a/trunk/src/core/srs_core_version4.hpp b/trunk/src/core/srs_core_version4.hpp index f700a6e70..f9a5e16ef 100644 --- a/trunk/src/core/srs_core_version4.hpp +++ b/trunk/src/core/srs_core_version4.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 4 #define VERSION_MINOR 0 -#define VERSION_REVISION 258 +#define VERSION_REVISION 259 #endif