Skip to content
This repository has been archived by the owner on Jul 12, 2023. It is now read-only.

Make networkInterfaces work with dual stack environments, add ipIgnoreList config #28

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 120 additions & 19 deletions src/gst-plugins/webrtcendpoint/kmswebrtcbaseconnection.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@

#include <string.h> // strlen()

// Network interfaces and IP fetching for NiceAgent
#include <ifaddrs.h>
#include <net/if.h>

#define GST_CAT_DEFAULT kmswebrtcbaseconnection
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "kmswebrtcbaseconnection"
Expand Down Expand Up @@ -213,43 +217,140 @@ kms_webrtc_base_connection_split_comma (const gchar * str)
return list;
}

gint
kms_webrtc_base_connection_cmp_ifa (const gchar * n1, const gchar * n2) {
return strcmp(n1, n2);
}

gboolean
kms_webrtc_base_connection_agent_is_network_interface_valid (struct ifaddrs * ifa) {
gboolean is_valid = FALSE;
int sa_family;

// No IP address assigned to interface, skip
if (ifa->ifa_addr == NULL) {
goto end;
}

// Interface is either down of not running
if (!(ifa->ifa_flags && IFF_UP) || !(ifa->ifa_flags && IFF_RUNNING)) {
goto end;
}

sa_family = ifa->ifa_addr->sa_family;

// Only traverse through interfaces which are from the AF_INET/AF_INET6 families
if (sa_family != AF_INET && sa_family != AF_INET6) {
goto end;
}

is_valid = TRUE;

end:
return is_valid;
};

gboolean
kms_webrtc_base_connection_agent_is_interface_ip_valid (const gchar * ip_address,
GSList * ip_ignore_list) {
gboolean is_valid = FALSE;

// Link local IPv4, ignore
if (!strncmp(ip_address, "169.254.", 8)) {
goto end;
}

// Link local IPv6, ignore
if (!strncmp(ip_address, "fe80:", 5)) {
goto end;
}

// Check if there's an IP ignore list defined and see if the IP address matches
// one of them
if (ip_ignore_list != NULL) {
if (g_slist_find_custom (ip_ignore_list, ip_address,
(GCompareFunc) kms_webrtc_base_connection_cmp_ifa)) {
goto end;
}
}

is_valid = TRUE;

end:
return is_valid;
};

/**
* Add new local IP address to NiceAgent instance.
*/
static void
kms_webrtc_base_connection_agent_add_net_addr (const gchar * net_name,
NiceAgent * agent)
static void
kms_webrtc_base_connection_agent_add_net_ifs_addrs (NiceAgent * agent,
GSList * net_list, GSList * ip_ignore_list)
{
NiceAddress *nice_address = nice_address_new ();
gchar *ip_address = nice_interfaces_get_ip_for_interface ((gchar *)net_name);
struct ifaddrs *ifaddr, *ifa;
gchar ip_address[INET6_ADDRSTRLEN];
GSList *it;
NiceAddress *nice_address;

if (getifaddrs(&ifaddr) == -1) {
GST_ERROR ("Failed to fetch system network interfaces");
return;
}

for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (!kms_webrtc_base_connection_agent_is_network_interface_valid(ifa)) {
continue;
}

// See if the network interface is in the configuration list
it = g_slist_find_custom (net_list, ifa->ifa_name,
(GCompareFunc) kms_webrtc_base_connection_cmp_ifa);

nice_address_set_from_string (nice_address, ip_address);
nice_agent_add_local_address (agent, nice_address);
// Current interface is not present in config, skip.
if (it == NULL) {
continue;
}

if (ifa->ifa_addr->sa_family == AF_INET) {
struct sockaddr_in *in4 = (struct sockaddr_in*) ifa->ifa_addr;
inet_ntop(AF_INET, &in4->sin_addr, ip_address, sizeof (ip_address));
} else {
struct sockaddr_in6 *in6 = (struct sockaddr_in6*) ifa->ifa_addr;
inet_ntop(AF_INET6, &in6->sin6_addr, ip_address, sizeof (ip_address));
}

GST_INFO_OBJECT (agent, "Added local address: %s", ip_address);
// Check if the IP in the ignore list or is link local
if (!kms_webrtc_base_connection_agent_is_interface_ip_valid(ip_address,
ip_ignore_list)) {
continue;
}

nice_address_free (nice_address);
g_free (ip_address);
nice_address = nice_address_new ();
nice_address_set_from_string (nice_address, ip_address);
nice_agent_add_local_address (agent, nice_address);
nice_address_free (nice_address);

GST_DEBUG_OBJECT (agent, "Added interface %s's IP address: %s",
ifa->ifa_name, ip_address);
}

freeifaddrs(ifaddr);
}

void
kms_webrtc_base_connection_set_network_ifs_info (KmsWebRtcBaseConnection *
self, const gchar * net_names)
self, const gchar * net_names, const gchar * ip_ignore_list)
{
if (KMS_IS_ICE_NICE_AGENT (self->agent)) {
KmsIceNiceAgent *nice_agent = KMS_ICE_NICE_AGENT (self->agent);
NiceAgent *agent = kms_ice_nice_agent_get_agent (nice_agent);

GSList *net_list = kms_webrtc_base_connection_split_comma (
net_names);

if (net_list != NULL) {
g_slist_foreach (net_list,
(GFunc) kms_webrtc_base_connection_agent_add_net_addr,
agent);
}
GSList *net_list = kms_webrtc_base_connection_split_comma (net_names);
GSList *ip_ignore_glist = kms_webrtc_base_connection_split_comma (ip_ignore_list);
kms_webrtc_base_connection_agent_add_net_ifs_addrs (agent, net_list, ip_ignore_glist);

g_slist_free_full (net_list, g_free);
g_slist_free_full (ip_ignore_glist, g_free);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/gst-plugins/webrtcendpoint/kmswebrtcbaseconnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ GType kms_webrtc_base_connection_get_type (void);
gchar *kms_webrtc_base_connection_get_certificate_pem (KmsWebRtcBaseConnection *
self);
void kms_webrtc_base_connection_set_network_ifs_info (KmsWebRtcBaseConnection *
self, const gchar * net_names);
self, const gchar * net_names, const gchar * ip_ignore_list);
void kms_webrtc_base_connection_set_ice_tcp (KmsWebRtcBaseConnection *self,
gboolean ice_tcp);
void kms_webrtc_base_connection_set_stun_server_info (KmsWebRtcBaseConnection * self,
Expand Down
21 changes: 21 additions & 0 deletions src/gst-plugins/webrtcendpoint/kmswebrtcendpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ G_DEFINE_TYPE (KmsWebrtcEndpoint, kms_webrtc_endpoint,
#define DEFAULT_STUN_TURN_URL NULL
#define DEFAULT_PEM_CERTIFICATE NULL
#define DEFAULT_NETWORK_INTERFACES NULL
#define DEFAULT_IP_IGNORE_LIST NULL
#define DEFAULT_EXTERNAL_ADDRESS NULL
#define DEFAULT_EXTERNAL_IPV4 NULL
#define DEFAULT_EXTERNAL_IPV6 NULL
Expand All @@ -68,6 +69,7 @@ enum
PROP_TURN_URL, /* user:password@address:port?transport=[udp|tcp|tls] */
PROP_PEM_CERTIFICATE,
PROP_NETWORK_INTERFACES,
PROP_IP_IGNORE_LIST,
PROP_EXTERNAL_ADDRESS,
PROP_EXTERNAL_IPV4,
PROP_EXTERNAL_IPV6,
Expand Down Expand Up @@ -104,6 +106,7 @@ struct _KmsWebrtcEndpointPrivate
gchar *turn_url;
gchar *pem_certificate;
gchar *network_interfaces;
gchar *ip_ignore_list;
gchar *external_address;
gchar *external_ipv4;
gchar *external_ipv6;
Expand Down Expand Up @@ -338,6 +341,8 @@ kms_webrtc_endpoint_create_session_internal (KmsBaseSdpEndpoint * base_sdp,
webrtc_sess, "pem-certificate", G_BINDING_DEFAULT);
g_object_bind_property (self, "network-interfaces",
webrtc_sess, "network-interfaces", G_BINDING_DEFAULT);
g_object_bind_property (self, "ip-ignore-list",
webrtc_sess, "ip-ignore-list", G_BINDING_DEFAULT);
g_object_bind_property (self, "external-address",
webrtc_sess, "external-address", G_BINDING_DEFAULT);
g_object_bind_property (self, "external-ipv4",
Expand All @@ -352,6 +357,7 @@ kms_webrtc_endpoint_create_session_internal (KmsBaseSdpEndpoint * base_sdp,
"turn-url", self->priv->turn_url,
"pem-certificate", self->priv->pem_certificate,
"network-interfaces", self->priv->network_interfaces,
"ip-ignore-list", self->priv->ip_ignore_list,
"external-address", self->priv->external_address,
"external-ipv4", self->priv->external_ipv4,
"external-ipv6", self->priv->external_ipv6,
Expand Down Expand Up @@ -530,6 +536,10 @@ kms_webrtc_endpoint_set_property (GObject * object, guint prop_id,
g_free (self->priv->network_interfaces);
self->priv->network_interfaces = g_value_dup_string (value);
break;
case PROP_IP_IGNORE_LIST:
g_free (self->priv->ip_ignore_list);
self->priv->ip_ignore_list = g_value_dup_string (value);
break;
case PROP_EXTERNAL_ADDRESS:
g_free (self->priv->external_address);
self->priv->external_address = g_value_dup_string (value);
Expand Down Expand Up @@ -577,6 +587,9 @@ kms_webrtc_endpoint_get_property (GObject * object, guint prop_id,
case PROP_NETWORK_INTERFACES:
g_value_set_string (value, self->priv->network_interfaces);
break;
case PROP_IP_IGNORE_LIST:
g_value_set_string (value, self->priv->ip_ignore_list);
break;
case PROP_EXTERNAL_ADDRESS:
g_value_set_string (value, self->priv->external_address);
break;
Expand Down Expand Up @@ -625,6 +638,7 @@ kms_webrtc_endpoint_finalize (GObject * object)
g_free (self->priv->turn_url);
g_free (self->priv->pem_certificate);
g_free (self->priv->network_interfaces);
g_free (self->priv->ip_ignore_list);
g_free (self->priv->external_address);
g_free (self->priv->external_ipv4);
g_free (self->priv->external_ipv6);
Expand Down Expand Up @@ -810,6 +824,12 @@ kms_webrtc_endpoint_class_init (KmsWebrtcEndpointClass * klass)
"Local network interfaces used for ICE gathering",
DEFAULT_NETWORK_INTERFACES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

g_object_class_install_property (gobject_class, PROP_IP_IGNORE_LIST,
g_param_spec_string ("ip-ignore-list",
"ipIgnoreList",
"IPs to be ignored during libnice's gathering phase",
DEFAULT_IP_IGNORE_LIST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

g_object_class_install_property (gobject_class, PROP_EXTERNAL_ADDRESS,
g_param_spec_string ("external-address",
"externalAddress",
Expand Down Expand Up @@ -967,6 +987,7 @@ kms_webrtc_endpoint_init (KmsWebrtcEndpoint * self)
self->priv->turn_url = DEFAULT_STUN_TURN_URL;
self->priv->pem_certificate = DEFAULT_PEM_CERTIFICATE;
self->priv->network_interfaces = DEFAULT_NETWORK_INTERFACES;
self->priv->ip_ignore_list = DEFAULT_IP_IGNORE_LIST;
self->priv->external_address = DEFAULT_EXTERNAL_ADDRESS;
self->priv->external_ipv4 = DEFAULT_EXTERNAL_IPV4;
self->priv->external_ipv6 = DEFAULT_EXTERNAL_IPV6;
Expand Down
19 changes: 18 additions & 1 deletion src/gst-plugins/webrtcendpoint/kmswebrtcsession.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ G_DEFINE_TYPE (KmsWebrtcSession, kms_webrtc_session, KMS_TYPE_BASE_RTP_SESSION);
#define DEFAULT_DATA_CHANNELS_SUPPORTED FALSE
#define DEFAULT_PEM_CERTIFICATE NULL
#define DEFAULT_NETWORK_INTERFACES NULL
#define DEFAULT_IP_IGNORE_LIST NULL
#define DEFAULT_EXTERNAL_ADDRESS NULL
#define DEFAULT_EXTERNAL_IPV4 NULL
#define DEFAULT_EXTERNAL_IPV6 NULL
Expand Down Expand Up @@ -92,6 +93,7 @@ enum
PROP_DATA_CHANNEL_SUPPORTED,
PROP_PEM_CERTIFICATE,
PROP_NETWORK_INTERFACES,
PROP_IP_IGNORE_LIST,
PROP_EXTERNAL_ADDRESS,
PROP_EXTERNAL_IPV4,
PROP_EXTERNAL_IPV6,
Expand Down Expand Up @@ -803,7 +805,7 @@ kms_webrtc_session_set_network_ifs_info (KmsWebrtcSession * self,
self->network_interfaces);

kms_webrtc_base_connection_set_network_ifs_info (conn,
self->network_interfaces);
self->network_interfaces, self->ip_ignore_list);
}

static void
Expand Down Expand Up @@ -1757,6 +1759,10 @@ kms_webrtc_session_set_property (GObject * object, guint prop_id,
g_free (self->network_interfaces);
self->network_interfaces = g_value_dup_string (value);
break;
case PROP_IP_IGNORE_LIST:
g_free (self->ip_ignore_list);
self->ip_ignore_list = g_value_dup_string (value);
break;
case PROP_EXTERNAL_ADDRESS:
g_free (self->external_address);
self->external_address = g_value_dup_string (value);
Expand Down Expand Up @@ -1807,6 +1813,9 @@ kms_webrtc_session_get_property (GObject * object, guint prop_id,
case PROP_NETWORK_INTERFACES:
g_value_set_string (value, self->network_interfaces);
break;
case PROP_IP_IGNORE_LIST:
g_value_set_string (value, self->ip_ignore_list);
break;
case PROP_EXTERNAL_ADDRESS:
g_value_set_string (value, self->external_address);
break;
Expand Down Expand Up @@ -1845,6 +1854,7 @@ kms_webrtc_session_finalize (GObject * object)
g_free (self->turn_address);
g_free (self->pem_certificate);
g_free (self->network_interfaces);
g_free (self->ip_ignore_list);
g_free (self->external_address);
g_free (self->external_ipv4);
g_free (self->external_ipv6);
Expand Down Expand Up @@ -1956,6 +1966,7 @@ kms_webrtc_session_init (KmsWebrtcSession * self)
self->turn_url = DEFAULT_STUN_TURN_URL;
self->pem_certificate = DEFAULT_PEM_CERTIFICATE;
self->network_interfaces = DEFAULT_NETWORK_INTERFACES;
self->ip_ignore_list = DEFAULT_IP_IGNORE_LIST;
self->external_address = DEFAULT_EXTERNAL_ADDRESS;
self->external_ipv4= DEFAULT_EXTERNAL_IPV4;
self->external_ipv6 = DEFAULT_EXTERNAL_IPV6;
Expand Down Expand Up @@ -2059,6 +2070,12 @@ kms_webrtc_session_class_init (KmsWebrtcSessionClass * klass)
"Local network interfaces used for ICE gathering",
DEFAULT_NETWORK_INTERFACES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

g_object_class_install_property (gobject_class, PROP_IP_IGNORE_LIST,
g_param_spec_string ("ip-ignore-list",
"ipIgnoreList",
"IPs to be ignored during libnice's gathering phase",
DEFAULT_IP_IGNORE_LIST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

g_object_class_install_property (gobject_class, PROP_EXTERNAL_ADDRESS,
g_param_spec_string ("external-address",
"externalAddress",
Expand Down
1 change: 1 addition & 0 deletions src/gst-plugins/webrtcendpoint/kmswebrtcsession.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ struct _KmsWebrtcSession
TurnProtocol turn_transport;
gchar *pem_certificate;
gchar *network_interfaces;
gchar *ip_ignore_list;
gchar *external_address;
gchar *external_ipv4;
gchar *external_ipv6;
Expand Down
18 changes: 18 additions & 0 deletions src/server/config/WebRtcEndpoint.conf.ini
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,24 @@
;;
;networkInterfaces=eth0

;; List of IPs to be ignored during the gathering phase when networkInterfaces
;; is enabled.
;;
;; If you set up the networkInterfaces option and the desired interfaces have
;; IPs that you don't wish to be used by libnice's NiceAgent, you
;; you can define them here.
;;
;; The general use case is filtering out IP addresses which are in the private
;; address ranges in environments where they aren't needed. This allows a fine
;; tuning to the number of server-side candidates generated by Kurento, reducing
;; signalling overhead and potentially speeding up connectivity checks.
;;
;; <ipIgnoreList> is a comma-separated list of IP (IPv4 and IPV6) addresses
;;
;; Examples:
;; ipIgnoreList=10.10.0.254
;; ipIgnoreList=fd12:3456:789a:1::1

;; STUN server IP address.
;;
;; The ICE process uses STUN to punch holes through NAT firewalls.
Expand Down
Loading