mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-30 12:49:40 +00:00
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
This commit is contained in:
parent
29c7f95884
commit
1d6160d59c
3 changed files with 142 additions and 55 deletions
|
@ -250,6 +250,7 @@ enum
|
||||||
GET_STATS_SIGNAL,
|
GET_STATS_SIGNAL,
|
||||||
ADD_TRANSCEIVER_SIGNAL,
|
ADD_TRANSCEIVER_SIGNAL,
|
||||||
GET_TRANSCEIVERS_SIGNAL,
|
GET_TRANSCEIVERS_SIGNAL,
|
||||||
|
ADD_TURN_SERVER_SIGNAL,
|
||||||
LAST_SIGNAL,
|
LAST_SIGNAL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3299,6 +3300,17 @@ gst_webrtc_bin_get_transceivers (GstWebRTCBin * webrtc)
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
static gboolean
|
||||||
copy_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data)
|
copy_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data)
|
||||||
{
|
{
|
||||||
|
@ -4078,7 +4090,9 @@ gst_webrtc_bin_class_init (GstWebRTCBinClass * klass)
|
||||||
g_object_class_install_property (gobject_class,
|
g_object_class_install_property (gobject_class,
|
||||||
PROP_TURN_SERVER,
|
PROP_TURN_SERVER,
|
||||||
g_param_spec_string ("turn-server", "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));
|
NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class,
|
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_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
|
||||||
G_CALLBACK (gst_webrtc_bin_get_transceivers), NULL, NULL,
|
G_CALLBACK (gst_webrtc_bin_get_transceivers), NULL, NULL,
|
||||||
g_cclosure_marshal_generic, G_TYPE_ARRAY, 0);
|
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
|
static void
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
* - are locally generated remote candidates meant to be readded to libnice?
|
* - 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
|
#define GST_CAT_DEFAULT gst_webrtc_ice_debug
|
||||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
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]);
|
*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 *
|
GstWebRTCICEStream *
|
||||||
gst_webrtc_ice_add_stream (GstWebRTCICE * ice, guint session_id)
|
gst_webrtc_ice_add_stream (GstWebRTCICE * ice, guint session_id)
|
||||||
{
|
{
|
||||||
struct NiceStreamItem m = NICE_MATCH_INIT;
|
struct NiceStreamItem m = NICE_MATCH_INIT;
|
||||||
struct NiceStreamItem *item;
|
struct NiceStreamItem *item;
|
||||||
|
AddTurnServerData add_data;
|
||||||
|
|
||||||
m.session_id = session_id;
|
m.session_id = session_id;
|
||||||
item = _nice_stream_item_find (ice, (NiceStreamItemFindFunc) _match, &m);
|
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);
|
item = _create_nice_stream_item (ice, session_id);
|
||||||
|
|
||||||
if (ice->turn_server) {
|
if (ice->turn_server) {
|
||||||
gboolean ret;
|
_add_turn_server (ice, item, ice->turn_server);
|
||||||
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_data.ice = ice;
|
||||||
|
add_data.item = item;
|
||||||
|
|
||||||
|
g_hash_table_foreach (ice->turn_servers, (GHFunc) _add_turn_server_func,
|
||||||
|
&add_data);
|
||||||
|
|
||||||
return item->stream;
|
return item->stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,6 +561,23 @@ gst_webrtc_ice_set_remote_credentials (GstWebRTCICE * ice,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
gboolean
|
||||||
gst_webrtc_ice_set_local_credentials (GstWebRTCICE * ice,
|
gst_webrtc_ice_set_local_credentials (GstWebRTCICE * ice,
|
||||||
GstWebRTCICEStream * stream, gchar * ufrag, gchar * pwd)
|
GstWebRTCICEStream * stream, gchar * ufrag, gchar * pwd)
|
||||||
|
@ -600,8 +646,8 @@ _resolve_host (const gchar * host)
|
||||||
return g_inet_address_to_string (addr);
|
return g_inet_address_to_string (addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static GstUri *
|
||||||
_set_turn_server (GstWebRTCICE * ice, const gchar * s)
|
_validate_turn_server (GstWebRTCICE * ice, const gchar * s)
|
||||||
{
|
{
|
||||||
GstUri *uri = gst_uri_from_string (s);
|
GstUri *uri = gst_uri_from_string (s);
|
||||||
const gchar *userinfo, *host, *scheme;
|
const gchar *userinfo, *host, *scheme;
|
||||||
|
@ -610,11 +656,11 @@ _set_turn_server (GstWebRTCICE * ice, const gchar * s)
|
||||||
gboolean turn_tls = FALSE;
|
gboolean turn_tls = FALSE;
|
||||||
guint port;
|
guint port;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (ice, "setting turn server, %s", s);
|
GST_DEBUG_OBJECT (ice, "validating turn server, %s", s);
|
||||||
|
|
||||||
if (!uri) {
|
if (!uri) {
|
||||||
GST_ERROR_OBJECT (ice, "Could not parse turn server '%s'", s);
|
GST_ERROR_OBJECT (ice, "Could not parse turn server '%s'", s);
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
scheme = gst_uri_get_scheme (uri);
|
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 */
|
/* Set the resolved IP as the host since that's what libnice wants */
|
||||||
gst_uri_set_host (uri, ip);
|
gst_uri_set_host (uri, ip);
|
||||||
|
|
||||||
if (ice->turn_server)
|
|
||||||
gst_uri_unref (ice->turn_server);
|
|
||||||
ice->turn_server = uri;
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
g_list_free (keys);
|
g_list_free (keys);
|
||||||
g_free (ip);
|
g_free (ip);
|
||||||
g_free (user);
|
g_free (user);
|
||||||
g_free (pass);
|
g_free (pass);
|
||||||
|
|
||||||
|
return uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -741,7 +785,13 @@ gst_webrtc_ice_set_property (GObject * object, guint prop_id,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PROP_TURN_SERVER:{
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case PROP_CONTROLLER:
|
case PROP_CONTROLLER:
|
||||||
|
@ -807,6 +857,8 @@ gst_webrtc_ice_finalize (GObject * object)
|
||||||
|
|
||||||
g_object_unref (ice->priv->nice_agent);
|
g_object_unref (ice->priv->nice_agent);
|
||||||
|
|
||||||
|
g_hash_table_unref (ice->turn_servers);
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -863,6 +915,10 @@ gst_webrtc_ice_init (GstWebRTCICE * ice)
|
||||||
g_mutex_init (&ice->priv->lock);
|
g_mutex_init (&ice->priv->lock);
|
||||||
g_cond_init (&ice->priv->cond);
|
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);
|
_start_thread (ice);
|
||||||
|
|
||||||
ice->priv->nice_agent = nice_agent_new (ice->priv->main_context,
|
ice->priv->nice_agent = nice_agent_new (ice->priv->main_context,
|
||||||
|
|
|
@ -48,6 +48,8 @@ struct _GstWebRTCICE
|
||||||
GstUri *stun_server;
|
GstUri *stun_server;
|
||||||
GstUri *turn_server;
|
GstUri *turn_server;
|
||||||
|
|
||||||
|
GHashTable *turn_servers;
|
||||||
|
|
||||||
GstWebRTCICEPrivate *priv;
|
GstWebRTCICEPrivate *priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,6 +79,8 @@ gboolean gst_webrtc_ice_set_remote_credentials (GstWebRTCIC
|
||||||
GstWebRTCICEStream * stream,
|
GstWebRTCICEStream * stream,
|
||||||
gchar * ufrag,
|
gchar * ufrag,
|
||||||
gchar * pwd);
|
gchar * pwd);
|
||||||
|
gboolean gst_webrtc_ice_add_turn_server (GstWebRTCICE * ice,
|
||||||
|
const gchar * uri);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue