From 17e0182619f7094f1ca49415db6b58eea56a37dd Mon Sep 17 00:00:00 2001 From: prlanzarin Date: Thu, 10 Sep 2020 21:06:14 +0000 Subject: [PATCH 1/4] Add externalIPv4/externalIPv6 configs and API methods for them This setting follows the same rationale of the externalAddress setting, but the idea here is to make it dual stack friendly by splitting it into IPv4 and IPv6 specific configs and mangling compatible candidates with them For the sake of backwards compatibility, externalAddress has preference over these two. So when it`s set, they will be ignored --- .../webrtcendpoint/kmswebrtcendpoint.c | 44 ++++++++++- .../webrtcendpoint/kmswebrtcsession.c | 47 +++++++++++- .../webrtcendpoint/kmswebrtcsession.h | 2 + src/server/config/WebRtcEndpoint.conf.ini | 28 +++++++ .../objects/WebRtcEndpointImpl.cpp | 74 +++++++++++++++++++ .../objects/WebRtcEndpointImpl.hpp | 6 ++ .../elements.WebRtcEndpoint.kmd.json | 10 +++ 7 files changed, 209 insertions(+), 2 deletions(-) diff --git a/src/gst-plugins/webrtcendpoint/kmswebrtcendpoint.c b/src/gst-plugins/webrtcendpoint/kmswebrtcendpoint.c index 0f8a0fa3b..f6a559040 100644 --- a/src/gst-plugins/webrtcendpoint/kmswebrtcendpoint.c +++ b/src/gst-plugins/webrtcendpoint/kmswebrtcendpoint.c @@ -56,6 +56,8 @@ G_DEFINE_TYPE (KmsWebrtcEndpoint, kms_webrtc_endpoint, #define DEFAULT_PEM_CERTIFICATE NULL #define DEFAULT_NETWORK_INTERFACES NULL #define DEFAULT_EXTERNAL_ADDRESS NULL +#define DEFAULT_EXTERNAL_IPV4 NULL +#define DEFAULT_EXTERNAL_IPV6 NULL enum { @@ -66,6 +68,8 @@ enum PROP_PEM_CERTIFICATE, PROP_NETWORK_INTERFACES, PROP_EXTERNAL_ADDRESS, + PROP_EXTERNAL_IPV4, + PROP_EXTERNAL_IPV6, N_PROPERTIES }; @@ -99,6 +103,8 @@ struct _KmsWebrtcEndpointPrivate gchar *pem_certificate; gchar *network_interfaces; gchar *external_address; + gchar *external_ipv4; + gchar *external_ipv6; }; /* Internal session management begin */ @@ -329,13 +335,19 @@ kms_webrtc_endpoint_create_session_internal (KmsBaseSdpEndpoint * base_sdp, webrtc_sess, "network-interfaces", G_BINDING_DEFAULT); g_object_bind_property (self, "external-address", webrtc_sess, "external-address", G_BINDING_DEFAULT); + g_object_bind_property (self, "external-ipv4", + webrtc_sess, "external-ipv4", G_BINDING_DEFAULT); + g_object_bind_property (self, "external-ipv6", + webrtc_sess, "external-ipv6", G_BINDING_DEFAULT); g_object_set (webrtc_sess, "stun-server", self->priv->stun_server_ip, "stun-server-port", self->priv->stun_server_port, "turn-url", self->priv->turn_url, "pem-certificate", self->priv->pem_certificate, "network-interfaces", self->priv->network_interfaces, - "external-address", self->priv->external_address, NULL); + "external-address", self->priv->external_address, + "external-ipv4", self->priv->external_ipv4, + "external-ipv6", self->priv->external_ipv6, NULL); g_signal_connect (webrtc_sess, "on-ice-candidate", G_CALLBACK (on_ice_candidate), self); @@ -511,6 +523,14 @@ kms_webrtc_endpoint_set_property (GObject * object, guint prop_id, g_free (self->priv->external_address); self->priv->external_address = g_value_dup_string (value); break; + case PROP_EXTERNAL_IPV4: + g_free (self->priv->external_ipv4); + self->priv->external_ipv4 = g_value_dup_string (value); + break; + case PROP_EXTERNAL_IPV6: + g_free (self->priv->external_ipv6); + self->priv->external_ipv6 = g_value_dup_string (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -546,6 +566,12 @@ kms_webrtc_endpoint_get_property (GObject * object, guint prop_id, case PROP_EXTERNAL_ADDRESS: g_value_set_string (value, self->priv->external_address); break; + case PROP_EXTERNAL_IPV4: + g_value_set_string (value, self->priv->external_ipv4); + break; + case PROP_EXTERNAL_IPV6: + g_value_set_string (value, self->priv->external_ipv6); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -583,6 +609,8 @@ kms_webrtc_endpoint_finalize (GObject * object) g_free (self->priv->pem_certificate); g_free (self->priv->network_interfaces); g_free (self->priv->external_address); + g_free (self->priv->external_ipv4); + g_free (self->priv->external_ipv6); g_main_context_unref (self->priv->context); @@ -771,6 +799,18 @@ kms_webrtc_endpoint_class_init (KmsWebrtcEndpointClass * klass) "External (public) IP address of the media server", DEFAULT_EXTERNAL_ADDRESS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_EXTERNAL_IPV4, + g_param_spec_string ("external-ipv4", + "externalIPv4", + "External (public) IPv4 address of the media server", + DEFAULT_EXTERNAL_IPV4, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_EXTERNAL_IPV6, + g_param_spec_string ("external-ipv6", + "externalIPv6", + "External (public) IPv6 address of the media server", + DEFAULT_EXTERNAL_IPV6, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** * KmsWebrtcEndpoint::on-ice-candidate: * @self: the object which received the signal @@ -905,6 +945,8 @@ kms_webrtc_endpoint_init (KmsWebrtcEndpoint * self) self->priv->pem_certificate = DEFAULT_PEM_CERTIFICATE; self->priv->network_interfaces = DEFAULT_NETWORK_INTERFACES; self->priv->external_address = DEFAULT_EXTERNAL_ADDRESS; + self->priv->external_ipv4 = DEFAULT_EXTERNAL_IPV4; + self->priv->external_ipv6 = DEFAULT_EXTERNAL_IPV6; self->priv->loop = kms_loop_new (); g_object_get (self->priv->loop, "context", &self->priv->context, NULL); diff --git a/src/gst-plugins/webrtcendpoint/kmswebrtcsession.c b/src/gst-plugins/webrtcendpoint/kmswebrtcsession.c index ae068c653..8d7649a17 100644 --- a/src/gst-plugins/webrtcendpoint/kmswebrtcsession.c +++ b/src/gst-plugins/webrtcendpoint/kmswebrtcsession.c @@ -56,6 +56,8 @@ G_DEFINE_TYPE (KmsWebrtcSession, kms_webrtc_session, KMS_TYPE_BASE_RTP_SESSION); #define DEFAULT_PEM_CERTIFICATE NULL #define DEFAULT_NETWORK_INTERFACES NULL #define DEFAULT_EXTERNAL_ADDRESS NULL +#define DEFAULT_EXTERNAL_IPV4 NULL +#define DEFAULT_EXTERNAL_IPV6 NULL #define IP_VERSION_6 6 @@ -90,6 +92,8 @@ enum PROP_PEM_CERTIFICATE, PROP_NETWORK_INTERFACES, PROP_EXTERNAL_ADDRESS, + PROP_EXTERNAL_IPV4, + PROP_EXTERNAL_IPV6, N_PROPERTIES }; @@ -583,12 +587,23 @@ kms_webrtc_session_new_candidate (KmsIceBaseAgent * agent, kms_ice_candidate_get_stream_id (candidate), kms_ice_candidate_get_component (candidate)); + gboolean is_candidate_ipv6 = kms_ice_candidate_get_ip_version (candidate) == IP_VERSION_6; + if (self->external_address != NULL) { kms_ice_candidate_set_address (candidate, self->external_address); - GST_DEBUG_OBJECT (self, "[IceCandidateFound] Mangled local: '%s'", kms_ice_candidate_get_candidate (candidate)); + } else if (self->external_ipv4 != NULL && is_candidate_ipv6 == FALSE) { + kms_ice_candidate_set_address (candidate, self->external_ipv4); + GST_DEBUG_OBJECT (self, + "[IceCandidateFound] Mangled local candidate with IPv4: '%s'", + kms_ice_candidate_get_candidate (candidate)); + } else if (self->external_ipv6 != NULL && is_candidate_ipv6 == TRUE) { + kms_ice_candidate_set_address (candidate, self->external_ipv6); + GST_DEBUG_OBJECT (self, + "[IceCandidateFound] Mangled local candidate with IPv6: '%s'", + kms_ice_candidate_get_candidate (candidate)); } kms_webrtc_session_sdp_msg_add_ice_candidate (self, candidate); @@ -1733,6 +1748,14 @@ kms_webrtc_session_set_property (GObject * object, guint prop_id, g_free (self->external_address); self->external_address = g_value_dup_string (value); break; + case PROP_EXTERNAL_IPV4: + g_free (self->external_ipv4); + self->external_ipv4 = g_value_dup_string (value); + break; + case PROP_EXTERNAL_IPV6: + g_free (self->external_ipv6); + self->external_ipv6 = g_value_dup_string (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1771,6 +1794,12 @@ kms_webrtc_session_get_property (GObject * object, guint prop_id, case PROP_EXTERNAL_ADDRESS: g_value_set_string (value, self->external_address); break; + case PROP_EXTERNAL_IPV4: + g_value_set_string (value, self->external_ipv4); + break; + case PROP_EXTERNAL_IPV6: + g_value_set_string (value, self->external_ipv6); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1798,6 +1827,8 @@ kms_webrtc_session_finalize (GObject * object) g_free (self->pem_certificate); g_free (self->network_interfaces); g_free (self->external_address); + g_free (self->external_ipv4); + g_free (self->external_ipv6); if (self->destroy_data != NULL && self->cb_data != NULL) { self->destroy_data (self->cb_data); @@ -1907,6 +1938,8 @@ kms_webrtc_session_init (KmsWebrtcSession * self) self->pem_certificate = DEFAULT_PEM_CERTIFICATE; self->network_interfaces = DEFAULT_NETWORK_INTERFACES; self->external_address = DEFAULT_EXTERNAL_ADDRESS; + self->external_ipv4= DEFAULT_EXTERNAL_IPV4; + self->external_ipv6 = DEFAULT_EXTERNAL_IPV6; self->gather_started = FALSE; self->data_channels = g_hash_table_new_full (g_direct_hash, @@ -2012,6 +2045,18 @@ kms_webrtc_session_class_init (KmsWebrtcSessionClass * klass) "External (public) IP address of the media server", DEFAULT_EXTERNAL_ADDRESS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_EXTERNAL_IPV4, + g_param_spec_string ("external-ipv4", + "externalIPv4", + "External (public) IPv4 address of the media server", + DEFAULT_EXTERNAL_IPV4, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_EXTERNAL_IPV6, + g_param_spec_string ("external-ipv6", + "externalIPv6", + "External (public) IPv6 address of the media server", + DEFAULT_EXTERNAL_IPV6, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_DATA_CHANNEL_SUPPORTED, g_param_spec_boolean ("data-channel-supported", "Data channel supported", diff --git a/src/gst-plugins/webrtcendpoint/kmswebrtcsession.h b/src/gst-plugins/webrtcendpoint/kmswebrtcsession.h index 294c2b1b6..7575f860b 100644 --- a/src/gst-plugins/webrtcendpoint/kmswebrtcsession.h +++ b/src/gst-plugins/webrtcendpoint/kmswebrtcsession.h @@ -72,6 +72,8 @@ struct _KmsWebrtcSession gchar *pem_certificate; gchar *network_interfaces; gchar *external_address; + gchar *external_ipv4; + gchar *external_ipv6; guint16 min_port; guint16 max_port; diff --git a/src/server/config/WebRtcEndpoint.conf.ini b/src/server/config/WebRtcEndpoint.conf.ini index 0a1b0768d..7c974984e 100644 --- a/src/server/config/WebRtcEndpoint.conf.ini +++ b/src/server/config/WebRtcEndpoint.conf.ini @@ -102,3 +102,31 @@ ;; externalAddress=2001:0db8:85a3:0000:0000:8a2e:0370:7334 ;; ;externalAddress=10.20.30.40 + +;; External IPv4 address of the media server. +;; +;; This setting follows the same rationale of the externalAddress setting, but +;; the idea here is to couple it with the externalIPv6 setting to achieve dual +;; stack IPv4+IPv6 candidate mangling. +;; +;; Right now, externalAddress only allows a single IP (which has to be either +;; IPv4 or IPv6), so it's not dual stack friendly. This option will mangle +;; IPv4 candidates with the specified one. +;; +;; For the sake of backwards compatibility, externalAddress has preference over +;; this: when externalAddress is set, this option will be ignored. +;; +;; is an IPv4 address. +;; +; externalIPv4=10.20.30.40 + +;; External IPv6 address of the media server. +;; +;; Refer to the detailing of externalIPv4 which should explain this as well. +;; +;; For the sake of backwards compatibility, externalAddress has preference over +;; this: when externalAddress is set, this option will be ignored. +;; +;; is an IPv6 address. +;; +; externalIPv6=2001:0db8:85a3:0000:0000:8a2e:0370:7334 diff --git a/src/server/implementation/objects/WebRtcEndpointImpl.cpp b/src/server/implementation/objects/WebRtcEndpointImpl.cpp index e1b13a32f..7cd29fa57 100644 --- a/src/server/implementation/objects/WebRtcEndpointImpl.cpp +++ b/src/server/implementation/objects/WebRtcEndpointImpl.cpp @@ -53,9 +53,13 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); #define DEFAULT_PATH "/etc/kurento" #define PARAM_EXTERNAL_ADDRESS "externalAddress" +#define PARAM_EXTERNAL_IPV4 "externalIPv4" +#define PARAM_EXTERNAL_IPV6 "externalIPv6" #define PARAM_NETWORK_INTERFACES "networkInterfaces" #define PROP_EXTERNAL_ADDRESS "external-address" +#define PROP_EXTERNAL_IPV4 "external-ipv4" +#define PROP_EXTERNAL_IPV6 "external-ipv6" #define PROP_NETWORK_INTERFACES "network-interfaces" namespace kurento @@ -510,6 +514,28 @@ WebRtcEndpointImpl::WebRtcEndpointImpl (const boost::property_tree::ptree &conf, //set properties + std::string externalIPv4; + if (getConfigValue (&externalIPv4, + PARAM_EXTERNAL_IPV4)) { + GST_INFO ("Predefined external IPv4 address: %s", externalIPv4.c_str()); + g_object_set (G_OBJECT (element), PROP_EXTERNAL_IPV4, + externalIPv4.c_str(), NULL); + } else { + GST_DEBUG ("No predefined external IPv4 address found in config;" + " you can set one or default to STUN automatic discovery"); + } + + std::string externalIPv6; + if (getConfigValue (&externalIPv6, + PARAM_EXTERNAL_IPV6)) { + GST_INFO ("Predefined external IPv6 address: %s", externalIPv6.c_str()); + g_object_set (G_OBJECT (element), PROP_EXTERNAL_IPV6, + externalIPv6.c_str(), NULL); + } else { + GST_DEBUG ("No predefined external IPv6 address found in config;" + " you can set one or default to STUN automatic discovery"); + } + std::string externalAddress; if (getConfigValue (&externalAddress, PARAM_EXTERNAL_ADDRESS)) { @@ -624,6 +650,54 @@ WebRtcEndpointImpl::~WebRtcEndpointImpl() } } +std::string +WebRtcEndpointImpl::getExternalIPv4 () +{ + std::string externalIPv4; + gchar *ret; + + g_object_get (G_OBJECT (element), PROP_EXTERNAL_IPV4, &ret, NULL); + + if (ret != nullptr) { + externalIPv4 = std::string (ret); + g_free (ret); + } + + return externalIPv4; +} + +void +WebRtcEndpointImpl::setExternalIPv4 (const std::string &externalIPv4) +{ + GST_INFO ("Set external IPv4 address: %s", externalIPv4.c_str()); + g_object_set (G_OBJECT (element), PROP_EXTERNAL_IPV4, + externalIPv4.c_str(), NULL); +} + +std::string +WebRtcEndpointImpl::getExternalIPv6 () +{ + std::string externalIPv6; + gchar *ret; + + g_object_get (G_OBJECT (element), PROP_EXTERNAL_IPV6, &ret, NULL); + + if (ret != nullptr) { + externalIPv6 = std::string (ret); + g_free (ret); + } + + return externalIPv6; +} + +void +WebRtcEndpointImpl::setExternalIPv6 (const std::string &externalIPv6) +{ + GST_INFO ("Set external IPv6 address: %s", externalIPv6.c_str()); + g_object_set (G_OBJECT (element), PROP_EXTERNAL_IPV6, + externalIPv6.c_str(), NULL); +} + std::string WebRtcEndpointImpl::getExternalAddress () { diff --git a/src/server/implementation/objects/WebRtcEndpointImpl.hpp b/src/server/implementation/objects/WebRtcEndpointImpl.hpp index d651d1725..b3f0586b7 100644 --- a/src/server/implementation/objects/WebRtcEndpointImpl.hpp +++ b/src/server/implementation/objects/WebRtcEndpointImpl.hpp @@ -46,6 +46,12 @@ class WebRtcEndpointImpl : public BaseRtpEndpointImpl, ~WebRtcEndpointImpl () override; + std::string getExternalIPv6 () override; + void setExternalIPv6 (const std::string &externalIPv6) override; + + std::string getExternalIPv4() override; + void setExternalIPv4 (const std::string &externalIPv4) override; + std::string getExternalAddress () override; void setExternalAddress (const std::string &externalAddress) override; diff --git a/src/server/interface/elements.WebRtcEndpoint.kmd.json b/src/server/interface/elements.WebRtcEndpoint.kmd.json index d59f589f9..be017c8a2 100644 --- a/src/server/interface/elements.WebRtcEndpoint.kmd.json +++ b/src/server/interface/elements.WebRtcEndpoint.kmd.json @@ -357,6 +357,16 @@ ", "type": "String" }, + { + "name": "externalIPv4", + "doc": "External IPv4 of the media server", + "type": "String" + }, + { + "name": "externalIPv6", + "doc": "External IPv6 of the media server", + "type": "String" + }, { "name": "externalAddress", "doc": "External IP address of the media server. From 6c34c1ecda6996f2cab977d3c21e727f0c748587 Mon Sep 17 00:00:00 2001 From: Juan Navarro Date: Fri, 11 Sep 2020 14:40:15 +0200 Subject: [PATCH 2/4] webrtcendpoint: tests for externalIPv4, externalIPv6 --- tests/check/element/webrtcendpoint.c | 134 +++++++++++++++++++++++++-- 1 file changed, 127 insertions(+), 7 deletions(-) diff --git a/tests/check/element/webrtcendpoint.c b/tests/check/element/webrtcendpoint.c index 28c7108bb..d4d4dbc81 100644 --- a/tests/check/element/webrtcendpoint.c +++ b/tests/check/element/webrtcendpoint.c @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -2357,9 +2358,12 @@ static void on_ice_candidate_check_ip (GstElement * self, gchar * sess_id, KmsIceCandidate * candidate, const gchar * expected_ip) { - gchar *candidate_ip = kms_ice_candidate_get_address (candidate); - assert_equals_string (candidate_ip, expected_ip); - g_free (candidate_ip); + if (kms_ice_candidate_get_ip_version (candidate) + == kms_utils_get_ip_version (expected_ip)) { + gchar *candidate_ip = kms_ice_candidate_get_address (candidate); + assert_equals_string (candidate_ip, expected_ip); + g_free (candidate_ip); + } } /** @@ -2417,7 +2421,7 @@ GST_START_TEST (set_network_interfaces_test) GST_END_TEST /** - * Test setting local network interface to limit ICE candidate gathering. + * Test mangling of ICE candidates to set a custom IP address. */ GST_START_TEST (set_external_address_test) { @@ -2430,9 +2434,10 @@ GST_START_TEST (set_external_address_test) GstSDPMessage *offer = NULL, *answer = NULL; gboolean ret; - // Check that candidates only include the localhost IP - g_object_set (webrtcendpoint, "external-address", "10.20.30.40", NULL); + g_object_set (webrtcendpoint, "external-address", "198.51.100.1", NULL); + // No "ice-ufrag" and "ice-pwd" will cause a warning message "Cannot set + // remote media credentials", which can be ignored. static const gchar *offer_str = "v=0\r\n" "o=mozilla...THIS_IS_SDPARTA-43.0 4115481872190049086 0 IN IP4 0.0.0.0\r\n" "a=ice-options:trickle\r\n" @@ -2453,7 +2458,7 @@ GST_START_TEST (set_external_address_test) g_array_unref (video_codecs_array); g_signal_connect (G_OBJECT (webrtcendpoint), "on-ice-candidate", - G_CALLBACK (on_ice_candidate_check_ip), "10.20.30.40"); + G_CALLBACK (on_ice_candidate_check_ip), "198.51.100.1"); fail_unless (gst_sdp_message_new (&offer) == GST_SDP_OK); fail_unless (gst_sdp_message_parse_buffer ((const guint8 *) @@ -2468,6 +2473,118 @@ GST_START_TEST (set_external_address_test) } GST_END_TEST +/** + * Test mangling of ICE candidates to set a custom IPv4 address. + */ +GST_START_TEST (set_external_ipv4_test) +{ + GArray *audio_codecs_array, *video_codecs_array; + gchar *audio_codecs[] = {"opus/48000/1", NULL}; + gchar *video_codecs[] = {"VP8/90000", NULL}; + GstElement *webrtcendpoint = + gst_element_factory_make ("webrtcendpoint", NULL); + gchar *sess_id; + GstSDPMessage *offer = NULL, *answer = NULL; + gboolean ret; + + g_object_set (webrtcendpoint, "external-ipv4", "198.51.100.1", NULL); + + // No "ice-ufrag" and "ice-pwd" will cause a warning message "Cannot set + // remote media credentials", which can be ignored. + static const gchar *offer_str = + "v=0\r\n" + "o=mozilla...THIS_IS_SDPARTA-43.0 4115481872190049086 0 IN IP4 0.0.0.0\r\n" + "a=ice-options:trickle\r\n" + "a=msid-semantic:WMS *\r\n" + "m=video 9 UDP/TLS/RTP/SAVPF 120\r\n" + "c=IN IP4 0.0.0.0\r\n" + "a=sendrecv\r\n" + "a=mid:sdparta_0\r\n" + "a=rtpmap:120 VP8/90000\r\n"; + + audio_codecs_array = create_codecs_array (audio_codecs); + video_codecs_array = create_codecs_array (video_codecs); + g_object_set (webrtcendpoint, "num-audio-medias", 1, "audio-codecs", + g_array_ref (audio_codecs_array), "num-video-medias", 1, "video-codecs", + g_array_ref (video_codecs_array), NULL); + + g_array_unref (audio_codecs_array); + g_array_unref (video_codecs_array); + + g_signal_connect (G_OBJECT (webrtcendpoint), "on-ice-candidate", + G_CALLBACK (on_ice_candidate_check_ip), "198.51.100.1"); + + fail_unless (gst_sdp_message_new (&offer) == GST_SDP_OK); + fail_unless ( + gst_sdp_message_parse_buffer ((const guint8 *) offer_str, -1, offer) + == GST_SDP_OK); + g_signal_emit_by_name (webrtcendpoint, "create-session", &sess_id); + g_signal_emit_by_name ( + webrtcendpoint, "process-offer", sess_id, offer, &answer); + g_signal_emit_by_name (webrtcendpoint, "gather-candidates", sess_id, &ret); + fail_unless (ret); + g_object_unref (webrtcendpoint); + g_free (sess_id); +} +GST_END_TEST + +/** + * Test mangling of ICE candidates to set a custom IPv6 address. + */ +GST_START_TEST (set_external_ipv6_test) +{ + GArray *audio_codecs_array, *video_codecs_array; + gchar *audio_codecs[] = {"opus/48000/1", NULL}; + gchar *video_codecs[] = {"VP8/90000", NULL}; + GstElement *webrtcendpoint = + gst_element_factory_make ("webrtcendpoint", NULL); + gchar *sess_id; + GstSDPMessage *offer = NULL, *answer = NULL; + gboolean ret; + + g_object_set (webrtcendpoint, "external-ipv6", + "2001:0db8:85a3:0000:0000:8a2e:0370:7334", NULL); + + // No "ice-ufrag" and "ice-pwd" will cause a warning message "Cannot set + // remote media credentials", which can be ignored. + static const gchar *offer_str = + "v=0\r\n" + "o=mozilla...THIS_IS_SDPARTA-43.0 4115481872190049086 0 IN IP4 0.0.0.0\r\n" + "a=ice-options:trickle\r\n" + "a=msid-semantic:WMS *\r\n" + "m=video 9 UDP/TLS/RTP/SAVPF 120\r\n" + "c=IN IP4 0.0.0.0\r\n" + "a=sendrecv\r\n" + "a=mid:sdparta_0\r\n" + "a=rtpmap:120 VP8/90000\r\n"; + + audio_codecs_array = create_codecs_array (audio_codecs); + video_codecs_array = create_codecs_array (video_codecs); + g_object_set (webrtcendpoint, "num-audio-medias", 1, "audio-codecs", + g_array_ref (audio_codecs_array), "num-video-medias", 1, "video-codecs", + g_array_ref (video_codecs_array), NULL); + + g_array_unref (audio_codecs_array); + g_array_unref (video_codecs_array); + + g_signal_connect (G_OBJECT (webrtcendpoint), "on-ice-candidate", + G_CALLBACK (on_ice_candidate_check_ip), + "2001:0db8:85a3:0000:0000:8a2e:0370:7334"); + + fail_unless (gst_sdp_message_new (&offer) == GST_SDP_OK); + fail_unless ( + gst_sdp_message_parse_buffer ((const guint8 *) offer_str, -1, offer) + == GST_SDP_OK); + g_signal_emit_by_name (webrtcendpoint, "create-session", &sess_id); + g_signal_emit_by_name ( + webrtcendpoint, "process-offer", sess_id, offer, &answer); + g_signal_emit_by_name (webrtcendpoint, "gather-candidates", sess_id, &ret); + fail_unless (ret); + g_object_unref (webrtcendpoint); + g_free (sess_id); +} +GST_END_TEST + /* * End of test cases */ @@ -2498,7 +2615,10 @@ webrtcendpoint_test_suite (void) tcase_add_test (tc_chain, process_mid_no_bundle_offer); tcase_add_test (tc_chain, set_network_interfaces_test); + tcase_add_test (tc_chain, set_external_address_test); + tcase_add_test (tc_chain, set_external_ipv4_test); + tcase_add_test (tc_chain, set_external_ipv6_test); return s; } From 674516f670a06610a554e1a75b9ad84ae7c22a9b Mon Sep 17 00:00:00 2001 From: Juan Navarro Date: Fri, 11 Sep 2020 14:40:34 +0200 Subject: [PATCH 3/4] webrtcendpoint: rewrite docs for externalAddress, externalIPv4, externalIPv6 Add Javadoc/Jsdoc texts for new parameters externalIPv4, externalIPv6. Edit externalAddress to make all of them homogeneous. --- src/server/config/WebRtcEndpoint.conf.ini | 68 ++++++++---------- .../elements.WebRtcEndpoint.kmd.json | 71 +++++++++++++++---- 2 files changed, 87 insertions(+), 52 deletions(-) diff --git a/src/server/config/WebRtcEndpoint.conf.ini b/src/server/config/WebRtcEndpoint.conf.ini index 7c974984e..7ee9cb0eb 100644 --- a/src/server/config/WebRtcEndpoint.conf.ini +++ b/src/server/config/WebRtcEndpoint.conf.ini @@ -80,53 +80,45 @@ ;pemCertificateRSA=/path/to/cert+key.pem ;pemCertificateECDSA=/path/to/cert+key.pem -;; External IP address of the media server. -;; -;; This setting is normally NOT needed. Only use it if you know what you're -;; doing, and understand 100% WHY you want it. For the majority of cases, you -;; should prefer configuring STUN or TURN servers over using this setting. +;; External IPv4 and IPv6 addresses of the media server. ;; -;; This setting implements a hack that will mangle all local ICE candidates so -;; that their candidate address is replaced with the provided external address, -;; even for candidates of type 'host'. In doing so, this KMS will not need a -;; STUN or TURN server, but remote peers will still be able to contact it. +;; Forces all local IPv4 and/or IPv6 ICE candidates to have the given address. +;; This is really nothing more than a hack, but it's very effective to force a +;; public IP address when one is known in advance for the media server. In doing +;; so, KMS will not need a STUN or TURN server, but remote peers will still be +;; able to contact it. ;; -;; You can try using this setting if KMS is deployed on a publicly accessible +;; You can try using these settings if KMS is deployed on a publicly accessible ;; server, without NAT, and with a static public IP address. But if it doesn't -;; work for you, just go back to using the STUN or TURN settings above. +;; work for you, just go back to configuring a STUN or TURN server for ICE. ;; -;; is an IPv4 or IPv6 address. +;; Only set this parameter if you know what you're doing, and you understand +;; 100% WHY you need it. For the majority of cases, you should just prefer to +;; configure a STUN or TURN server. ;; -;; Examples: -;; externalAddress=10.20.30.40 -;; externalAddress=2001:0db8:85a3:0000:0000:8a2e:0370:7334 +;; is a single IPv4 address. +;; is a single IPv6 address. ;; -;externalAddress=10.20.30.40 +;externalIPv4=198.51.100.1 +;externalIPv6=2001:0db8:85a3:0000:0000:8a2e:0370:7334 -;; External IPv4 address of the media server. -;; -;; This setting follows the same rationale of the externalAddress setting, but -;; the idea here is to couple it with the externalIPv6 setting to achieve dual -;; stack IPv4+IPv6 candidate mangling. -;; -;; Right now, externalAddress only allows a single IP (which has to be either -;; IPv4 or IPv6), so it's not dual stack friendly. This option will mangle -;; IPv4 candidates with the specified one. -;; -;; For the sake of backwards compatibility, externalAddress has preference over -;; this: when externalAddress is set, this option will be ignored. -;; -;; is an IPv4 address. +;; External IP address of the media server. ;; -; externalIPv4=10.20.30.40 - -;; External IPv6 address of the media server. +;; Forces all local IPv4 and IPv6 ICE candidates to have the given address. This +;; is really nothing more than a hack, but it's very effective to force a public +;; IP address when one is known in advance for the media server. In doing so, +;; KMS will not need a STUN or TURN server, but remote peers will still be able +;; to contact it. ;; -;; Refer to the detailing of externalIPv4 which should explain this as well. +;; You can try using this setting if KMS is deployed on a publicly accessible +;; server, without NAT, and with a static public IP address. But if it doesn't +;; work for you, just go back to configuring a STUN or TURN server for ICE. ;; -;; For the sake of backwards compatibility, externalAddress has preference over -;; this: when externalAddress is set, this option will be ignored. +;; Only set this parameter if you know what you're doing, and you understand +;; 100% WHY you need it. For the majority of cases, you should just prefer to +;; configure a STUN or TURN server. ;; -;; is an IPv6 address. +;; is a single IPv4 or IPv6 address. ;; -; externalIPv6=2001:0db8:85a3:0000:0000:8a2e:0370:7334 +;externalAddress=198.51.100.1 +;externalAddress=2001:0db8:85a3:0000:0000:8a2e:0370:7334 diff --git a/src/server/interface/elements.WebRtcEndpoint.kmd.json b/src/server/interface/elements.WebRtcEndpoint.kmd.json index be017c8a2..5103b804d 100644 --- a/src/server/interface/elements.WebRtcEndpoint.kmd.json +++ b/src/server/interface/elements.WebRtcEndpoint.kmd.json @@ -359,39 +359,82 @@ }, { "name": "externalIPv4", - "doc": "External IPv4 of the media server", + "doc": "External IPv4 address of the media server. +

+ Forces all local IPv4 ICE candidates to have the given address. This is really + nothing more than a hack, but it's very effective to force a public IP address + when one is known in advance for the media server. In doing so, KMS will not + need a STUN or TURN server, but remote peers will still be able to contact it. +

+

+ You can try using this setting if KMS is deployed on a publicly accessible + server, without NAT, and with a static public IP address. But if it doesn't + work for you, just go back to configuring a STUN or TURN server for ICE. +

+

+ Only set this parameter if you know what you're doing, and you understand 100% + WHY you need it. For the majority of cases, you should just prefer to + configure a STUN or TURN server. +

+

externalIPv4 is a single IPv4 address.

+

Example:

+
    +
  • externalIPv4=198.51.100.1
  • +
+ ", "type": "String" }, { "name": "externalIPv6", - "doc": "External IPv6 of the media server", + "doc": "External IPv6 address of the media server. +

+ Forces all local IPv6 ICE candidates to have the given address. This is really + nothing more than a hack, but it's very effective to force a public IP address + when one is known in advance for the media server. In doing so, KMS will not + need a STUN or TURN server, but remote peers will still be able to contact it. +

+

+ You can try using this setting if KMS is deployed on a publicly accessible + server, without NAT, and with a static public IP address. But if it doesn't + work for you, just go back to configuring a STUN or TURN server for ICE. +

+

+ Only set this parameter if you know what you're doing, and you understand 100% + WHY you need it. For the majority of cases, you should just prefer to + configure a STUN or TURN server. +

+

externalIPv6 is a single IPv6 address.

+

Example:

+
    +
  • externalIPv6=2001:0db8:85a3:0000:0000:8a2e:0370:7334
  • +
+ ", "type": "String" }, { "name": "externalAddress", "doc": "External IP address of the media server.

- This setting is normally NOT needed. Only use it if you know what you're - doing, and understand 100% WHY you want it. For the majority of cases, you - should prefer configuring STUN or TURN servers over using this setting. -

-

- This setting implements a hack that will mangle all local ICE candidates so - that their candidate address is replaced with the provided external address, - even for candidates of type 'host'. In doing so, this KMS will not need a - STUN or TURN server, but remote peers will still be able to contact it. + Forces all local IPv4 and IPv6 ICE candidates to have the given address. This + is really nothing more than a hack, but it's very effective to force a public + IP address when one is known in advance for the media server. In doing so, KMS + will not need a STUN or TURN server, but remote peers will still be able to + contact it.

You can try using this setting if KMS is deployed on a publicly accessible server, without NAT, and with a static public IP address. But if it doesn't - work for you, just go back to using the STUN or TURN settings above. + work for you, just go back to configuring a STUN or TURN server for ICE.

- externalAddress is an IPv4 or IPv6 address. + Only set this parameter if you know what you're doing, and you understand 100% + WHY you need it. For the majority of cases, you should just prefer to + configure a STUN or TURN server.

+

externalAddress is a single IPv4 or IPv6 address.

Examples:

    -
  • externalAddress=10.70.35.2
  • +
  • externalAddress=198.51.100.1
  • externalAddress=2001:0db8:85a3:0000:0000:8a2e:0370:7334
", From 82cebc86c036c0e2b9593b2c04e1a59539e25b17 Mon Sep 17 00:00:00 2001 From: Juan Navarro Date: Fri, 11 Sep 2020 14:41:44 +0200 Subject: [PATCH 4/4] webrtcendpoint: deprecate externalAddress This is now superseded by the combination of externalIPv4 and externalIPv6. --- src/server/config/WebRtcEndpoint.conf.ini | 2 ++ src/server/interface/elements.WebRtcEndpoint.kmd.json | 1 + 2 files changed, 3 insertions(+) diff --git a/src/server/config/WebRtcEndpoint.conf.ini b/src/server/config/WebRtcEndpoint.conf.ini index 7ee9cb0eb..145044dbd 100644 --- a/src/server/config/WebRtcEndpoint.conf.ini +++ b/src/server/config/WebRtcEndpoint.conf.ini @@ -104,6 +104,8 @@ ;; External IP address of the media server. ;; +;; DEPRECATED: Use "externalIPv4" and/or "externalIPv6" instead. +;; ;; Forces all local IPv4 and IPv6 ICE candidates to have the given address. This ;; is really nothing more than a hack, but it's very effective to force a public ;; IP address when one is known in advance for the media server. In doing so, diff --git a/src/server/interface/elements.WebRtcEndpoint.kmd.json b/src/server/interface/elements.WebRtcEndpoint.kmd.json index 5103b804d..2938cd367 100644 --- a/src/server/interface/elements.WebRtcEndpoint.kmd.json +++ b/src/server/interface/elements.WebRtcEndpoint.kmd.json @@ -437,6 +437,7 @@
  • externalAddress=198.51.100.1
  • externalAddress=2001:0db8:85a3:0000:0000:8a2e:0370:7334
  • +@deprecated Use externalIPv4 and/or externalIPv6 instead. ", "type": "String" },