summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathieu Duponchelle <mathieu@centricular.com>2018-08-22 19:05:02 +0200
committerMathieu Duponchelle <mathieu@centricular.com>2018-09-19 16:17:24 +0200
commit1d6160d59c9d79b1b9599582412147025aa48a21 (patch)
tree9a8e5a6de7789183d7b0e0ec26694b7d11cd6609
parent29c7f958845369d5e452a05ca9a1390381a4cdeb (diff)
webrtcbin: New add-turn-server API
It is possible and often desirable to pass multiple ICE relays to libnice agents, the "turn-server" property, while convenient to use from the command line, does not allow that. This adds a new action signal, "add-turn-server" to address that. https://bugzilla.gnome.org/show_bug.cgi?id=797012
-rw-r--r--ext/webrtc/gstwebrtcbin.c29
-rw-r--r--ext/webrtc/gstwebrtcice.c164
-rw-r--r--ext/webrtc/gstwebrtcice.h4
3 files changed, 142 insertions, 55 deletions
diff --git a/ext/webrtc/gstwebrtcbin.c b/ext/webrtc/gstwebrtcbin.c
index 4d7ed8329..c75b1caaa 100644
--- a/ext/webrtc/gstwebrtcbin.c
+++ b/ext/webrtc/gstwebrtcbin.c
@@ -250,6 +250,7 @@ enum
GET_STATS_SIGNAL,
ADD_TRANSCEIVER_SIGNAL,
GET_TRANSCEIVERS_SIGNAL,
+ ADD_TURN_SERVER_SIGNAL,
LAST_SIGNAL,
};
@@ -3300,6 +3301,17 @@ gst_webrtc_bin_get_transceivers (GstWebRTCBin * webrtc)
}
static gboolean
+gst_webrtc_bin_add_turn_server (GstWebRTCBin * webrtc, const gchar * uri)
+{
+ g_return_val_if_fail (GST_IS_WEBRTC_BIN (webrtc), FALSE);
+ g_return_val_if_fail (uri != NULL, FALSE);
+
+ GST_DEBUG_OBJECT (webrtc, "Adding turn server: %s", uri);
+
+ return gst_webrtc_ice_add_turn_server (webrtc->priv->ice, uri);
+}
+
+static gboolean
copy_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data)
{
GstPad *gpad = GST_PAD_CAST (user_data);
@@ -4078,7 +4090,9 @@ gst_webrtc_bin_class_init (GstWebRTCBinClass * klass)
g_object_class_install_property (gobject_class,
PROP_TURN_SERVER,
g_param_spec_string ("turn-server", "TURN Server",
- "The TURN server of the form turn(s)://username:password@host:port",
+ "The TURN server of the form turn(s)://username:password@host:port. "
+ "This is a convenience property, use #GstWebRTCBin::add-turn-server "
+ "if you wish to use multiple TURN servers",
NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
@@ -4309,6 +4323,19 @@ gst_webrtc_bin_class_init (GstWebRTCBinClass * klass)
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_CALLBACK (gst_webrtc_bin_get_transceivers), NULL, NULL,
g_cclosure_marshal_generic, G_TYPE_ARRAY, 0);
+
+ /**
+ * GstWebRTCBin::add-turn-server:
+ * @object: the #GstWebRtcBin
+ * @uri: The uri of the server of the form turn(s)://username:password@host:port
+ *
+ * Add a turn server to obtain ICE candidates from
+ */
+ gst_webrtc_bin_signals[ADD_TURN_SERVER_SIGNAL] =
+ g_signal_new_class_handler ("add-turn-server", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_CALLBACK (gst_webrtc_bin_add_turn_server), NULL, NULL,
+ g_cclosure_marshal_generic, G_TYPE_BOOLEAN, 1, G_TYPE_STRING);
}
static void
diff --git a/ext/webrtc/gstwebrtcice.c b/ext/webrtc/gstwebrtcice.c
index 195a7931a..eb1960f5a 100644
--- a/ext/webrtc/gstwebrtcice.c
+++ b/ext/webrtc/gstwebrtcice.c
@@ -32,6 +32,8 @@
* - are locally generated remote candidates meant to be readded to libnice?
*/
+static GstUri *_validate_turn_server (GstWebRTCICE * ice, const gchar * s);
+
#define GST_CAT_DEFAULT gst_webrtc_ice_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
@@ -292,11 +294,76 @@ _parse_userinfo (const gchar * userinfo, gchar ** user, gchar ** pass)
*pass = g_strdup (&colon[1]);
}
+static void
+_add_turn_server (GstWebRTCICE * ice, struct NiceStreamItem *item,
+ GstUri * turn_server)
+{
+ gboolean ret;
+ gchar *user, *pass;
+ const gchar *userinfo, *transport, *scheme;
+ NiceRelayType relays[4] = { 0, };
+ int i, relay_n = 0;
+
+ scheme = gst_uri_get_scheme (turn_server);
+ transport = gst_uri_get_query_value (turn_server, "transport");
+ userinfo = gst_uri_get_userinfo (turn_server);
+ _parse_userinfo (userinfo, &user, &pass);
+
+ if (g_strcmp0 (scheme, "turns") == 0) {
+ relays[relay_n++] = NICE_RELAY_TYPE_TURN_TLS;
+ } else if (g_strcmp0 (scheme, "turn") == 0) {
+ if (!transport || g_strcmp0 (transport, "udp") == 0)
+ relays[relay_n++] = NICE_RELAY_TYPE_TURN_UDP;
+ if (!transport || g_strcmp0 (transport, "tcp") == 0)
+ relays[relay_n++] = NICE_RELAY_TYPE_TURN_TCP;
+ }
+ g_assert (relay_n < G_N_ELEMENTS (relays));
+
+ for (i = 0; i < relay_n; i++) {
+ ret = nice_agent_set_relay_info (ice->priv->nice_agent,
+ item->nice_stream_id, NICE_COMPONENT_TYPE_RTP,
+ gst_uri_get_host (turn_server),
+ gst_uri_get_port (turn_server), user, pass, relays[i]);
+ if (!ret) {
+ gchar *uri = gst_uri_to_string (turn_server);
+ GST_ERROR_OBJECT (ice, "Failed to set TURN server '%s'", uri);
+ g_free (uri);
+ break;
+ }
+ ret = nice_agent_set_relay_info (ice->priv->nice_agent,
+ item->nice_stream_id, NICE_COMPONENT_TYPE_RTCP,
+ gst_uri_get_host (turn_server),
+ gst_uri_get_port (turn_server), user, pass, relays[i]);
+ if (!ret) {
+ gchar *uri = gst_uri_to_string (turn_server);
+ GST_ERROR_OBJECT (ice, "Failed to set TURN server '%s'", uri);
+ g_free (uri);
+ break;
+ }
+ }
+ g_free (user);
+ g_free (pass);
+}
+
+typedef struct
+{
+ GstWebRTCICE *ice;
+ struct NiceStreamItem *item;
+} AddTurnServerData;
+
+static void
+_add_turn_server_func (const gchar * uri, GstUri * turn_server,
+ AddTurnServerData * data)
+{
+ _add_turn_server (data->ice, data->item, turn_server);
+}
+
GstWebRTCICEStream *
gst_webrtc_ice_add_stream (GstWebRTCICE * ice, guint session_id)
{
struct NiceStreamItem m = NICE_MATCH_INIT;
struct NiceStreamItem *item;
+ AddTurnServerData add_data;
m.session_id = session_id;
item = _nice_stream_item_find (ice, (NiceStreamItemFindFunc) _match, &m);
@@ -309,53 +376,15 @@ gst_webrtc_ice_add_stream (GstWebRTCICE * ice, guint session_id)
item = _create_nice_stream_item (ice, session_id);
if (ice->turn_server) {
- gboolean ret;
- gchar *user, *pass;
- const gchar *userinfo, *transport, *scheme;
- NiceRelayType relays[4] = { 0, };
- int i, relay_n = 0;
-
- scheme = gst_uri_get_scheme (ice->turn_server);
- transport = gst_uri_get_query_value (ice->turn_server, "transport");
- userinfo = gst_uri_get_userinfo (ice->turn_server);
- _parse_userinfo (userinfo, &user, &pass);
-
- if (g_strcmp0 (scheme, "turns") == 0) {
- relays[relay_n++] = NICE_RELAY_TYPE_TURN_TLS;
- } else if (g_strcmp0 (scheme, "turn") == 0) {
- if (!transport || g_strcmp0 (transport, "udp") == 0)
- relays[relay_n++] = NICE_RELAY_TYPE_TURN_UDP;
- if (!transport || g_strcmp0 (transport, "tcp") == 0)
- relays[relay_n++] = NICE_RELAY_TYPE_TURN_TCP;
- }
- g_assert (relay_n < G_N_ELEMENTS (relays));
-
- for (i = 0; i < relay_n; i++) {
- ret = nice_agent_set_relay_info (ice->priv->nice_agent,
- item->nice_stream_id, NICE_COMPONENT_TYPE_RTP,
- gst_uri_get_host (ice->turn_server),
- gst_uri_get_port (ice->turn_server), user, pass, relays[i]);
- if (!ret) {
- gchar *uri = gst_uri_to_string (ice->turn_server);
- GST_ERROR_OBJECT (ice, "Failed to set TURN server '%s'", uri);
- g_free (uri);
- break;
- }
- ret = nice_agent_set_relay_info (ice->priv->nice_agent,
- item->nice_stream_id, NICE_COMPONENT_TYPE_RTCP,
- gst_uri_get_host (ice->turn_server),
- gst_uri_get_port (ice->turn_server), user, pass, relays[i]);
- if (!ret) {
- gchar *uri = gst_uri_to_string (ice->turn_server);
- GST_ERROR_OBJECT (ice, "Failed to set TURN server '%s'", uri);
- g_free (uri);
- break;
- }
- }
- g_free (user);
- g_free (pass);
+ _add_turn_server (ice, item, ice->turn_server);
}
+ add_data.ice = ice;
+ add_data.item = item;
+
+ g_hash_table_foreach (ice->turn_servers, (GHFunc) _add_turn_server_func,
+ &add_data);
+
return item->stream;
}
@@ -533,6 +562,23 @@ gst_webrtc_ice_set_remote_credentials (GstWebRTCICE * ice,
}
gboolean
+gst_webrtc_ice_add_turn_server (GstWebRTCICE * ice, const gchar * uri)
+{
+ gboolean ret = FALSE;
+ GstUri *valid_uri;
+
+ if (!(valid_uri = _validate_turn_server (ice, uri)))
+ goto done;
+
+ g_hash_table_insert (ice->turn_servers, g_strdup (uri), valid_uri);
+
+ ret = TRUE;
+
+done:
+ return ret;
+}
+
+gboolean
gst_webrtc_ice_set_local_credentials (GstWebRTCICE * ice,
GstWebRTCICEStream * stream, gchar * ufrag, gchar * pwd)
{
@@ -600,8 +646,8 @@ _resolve_host (const gchar * host)
return g_inet_address_to_string (addr);
}
-static void
-_set_turn_server (GstWebRTCICE * ice, const gchar * s)
+static GstUri *
+_validate_turn_server (GstWebRTCICE * ice, const gchar * s)
{
GstUri *uri = gst_uri_from_string (s);
const gchar *userinfo, *host, *scheme;
@@ -610,11 +656,11 @@ _set_turn_server (GstWebRTCICE * ice, const gchar * s)
gboolean turn_tls = FALSE;
guint port;
- GST_DEBUG_OBJECT (ice, "setting turn server, %s", s);
+ GST_DEBUG_OBJECT (ice, "validating turn server, %s", s);
if (!uri) {
GST_ERROR_OBJECT (ice, "Could not parse turn server '%s'", s);
- return;
+ return NULL;
}
scheme = gst_uri_get_scheme (uri);
@@ -679,15 +725,13 @@ _set_turn_server (GstWebRTCICE * ice, const gchar * s)
/* Set the resolved IP as the host since that's what libnice wants */
gst_uri_set_host (uri, ip);
- if (ice->turn_server)
- gst_uri_unref (ice->turn_server);
- ice->turn_server = uri;
-
out:
g_list_free (keys);
g_free (ip);
g_free (user);
g_free (pass);
+
+ return uri;
}
static void
@@ -741,7 +785,13 @@ gst_webrtc_ice_set_property (GObject * object, guint prop_id,
break;
}
case PROP_TURN_SERVER:{
- _set_turn_server (ice, g_value_get_string (value));
+ GstUri *uri = _validate_turn_server (ice, g_value_get_string (value));
+
+ if (uri) {
+ if (ice->turn_server)
+ gst_uri_unref (ice->turn_server);
+ ice->turn_server = uri;
+ }
break;
}
case PROP_CONTROLLER:
@@ -807,6 +857,8 @@ gst_webrtc_ice_finalize (GObject * object)
g_object_unref (ice->priv->nice_agent);
+ g_hash_table_unref (ice->turn_servers);
+
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -863,6 +915,10 @@ gst_webrtc_ice_init (GstWebRTCICE * ice)
g_mutex_init (&ice->priv->lock);
g_cond_init (&ice->priv->cond);
+ ice->turn_servers =
+ g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
+ (GDestroyNotify) gst_uri_unref);
+
_start_thread (ice);
ice->priv->nice_agent = nice_agent_new (ice->priv->main_context,
diff --git a/ext/webrtc/gstwebrtcice.h b/ext/webrtc/gstwebrtcice.h
index cacf497a8..4b0cfdce3 100644
--- a/ext/webrtc/gstwebrtcice.h
+++ b/ext/webrtc/gstwebrtcice.h
@@ -48,6 +48,8 @@ struct _GstWebRTCICE
GstUri *stun_server;
GstUri *turn_server;
+ GHashTable *turn_servers;
+
GstWebRTCICEPrivate *priv;
};
@@ -77,6 +79,8 @@ gboolean gst_webrtc_ice_set_remote_credentials (GstWebRTCIC
GstWebRTCICEStream * stream,
gchar * ufrag,
gchar * pwd);
+gboolean gst_webrtc_ice_add_turn_server (GstWebRTCICE * ice,
+ const gchar * uri);
G_END_DECLS