diff options
author | Mathieu Duponchelle <mathieu@centricular.com> | 2018-08-22 19:05:02 +0200 |
---|---|---|
committer | Mathieu Duponchelle <mathieu@centricular.com> | 2018-09-19 16:17:24 +0200 |
commit | 1d6160d59c9d79b1b9599582412147025aa48a21 (patch) | |
tree | 9a8e5a6de7789183d7b0e0ec26694b7d11cd6609 | |
parent | 29c7f958845369d5e452a05ca9a1390381a4cdeb (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.c | 29 | ||||
-rw-r--r-- | ext/webrtc/gstwebrtcice.c | 164 | ||||
-rw-r--r-- | ext/webrtc/gstwebrtcice.h | 4 |
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 |