webrtcbin: Add settings for HTTP proxy

Pass this to libnice which has a simple HTTP 1.0 proxy with basic
authentication only.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2867>
This commit is contained in:
Johan Sternerup 2020-08-31 14:04:54 +02:00 committed by GStreamer Marge Bot
parent ccb0e6e435
commit e708543039
5 changed files with 243 additions and 0 deletions

View file

@ -236708,6 +236708,18 @@
"type": "GstWebRTCSessionDescription",
"writable": false
},
"http-proxy": {
"blurb": "A HTTP proxy for use with TURN/TCP of the form http://[username:password@]hostname[:port]",
"conditionally-available": false,
"construct": false,
"construct-only": false,
"controllable": false,
"default": "NULL",
"mutable": "null",
"readable": true,
"type": "gchararray",
"writable": true
},
"ice-agent": {
"blurb": "The WebRTC ICE agent",
"conditionally-available": false,

View file

@ -533,6 +533,7 @@ enum
PROP_ICE_AGENT,
PROP_LATENCY,
PROP_SCTP_TRANSPORT,
PROP_HTTP_PROXY
};
static guint gst_webrtc_bin_signals[LAST_SIGNAL] = { 0 };
@ -8058,6 +8059,10 @@ gst_webrtc_bin_set_property (GObject * object, guint prop_id,
case PROP_ICE_AGENT:
webrtc->priv->ice = g_value_get_object (value);
break;
case PROP_HTTP_PROXY:
gst_webrtc_ice_set_http_proxy (webrtc->priv->ice,
g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -8135,6 +8140,10 @@ gst_webrtc_bin_get_property (GObject * object, guint prop_id,
case PROP_SCTP_TRANSPORT:
g_value_set_object (value, webrtc->priv->sctp_transport);
break;
case PROP_HTTP_PROXY:
g_value_take_string (value,
gst_webrtc_ice_get_http_proxy (webrtc->priv->ice));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -8419,6 +8428,21 @@ gst_webrtc_bin_class_init (GstWebRTCBinClass * klass)
0, G_MAXUINT, DEFAULT_JB_LATENCY,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* GstWebRTCBin:http-proxy:
*
* A HTTP proxy for use with TURN/TCP of the form
* http://[username:password@]hostname[:port]
*
* Since: 1.22
*/
g_object_class_install_property (gobject_class,
PROP_HTTP_PROXY,
g_param_spec_string ("http-proxy", "HTTP Proxy",
"A HTTP proxy for use with TURN/TCP of the form "
"http://[username:password@]hostname[:port]",
NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* GstWebRTCBin:sctp-transport:
*

View file

@ -452,6 +452,45 @@ gst_webrtc_ice_get_turn_server (GstWebRTCICE * ice)
return GST_WEBRTC_ICE_GET_CLASS (ice)->get_turn_server (ice);
}
/**
* gst_webrtc_ice_set_http_proxy:
* @ice: The #GstWebRTCICE
* @uri: (transfer none): URI of the HTTP proxy of the form
* http://[username:password@]hostname[:port]
*
* Set HTTP Proxy to be used when connecting to TURN server.
*
* Since: 1.22
*/
void
gst_webrtc_ice_set_http_proxy (GstWebRTCICE * ice, const gchar * uri_s)
{
g_return_if_fail (GST_IS_WEBRTC_ICE (ice));
g_assert (GST_WEBRTC_ICE_GET_CLASS (ice)->set_http_proxy);
GST_WEBRTC_ICE_GET_CLASS (ice)->set_http_proxy (ice, uri_s);
}
/**
* gst_webrtc_ice_get_http_proxy:
* @ice: The #GstWebRTCICE
*
* Returns: (transfer full): URI of the HTTP proxy of the form
* http://[username:password@]hostname[:port]
*
* Get HTTP Proxy to be used when connecting to TURN server.
*
* Since: 1.22
*/
gchar *
gst_webrtc_ice_get_http_proxy (GstWebRTCICE * ice)
{
g_return_val_if_fail (GST_IS_WEBRTC_ICE (ice), NULL);
g_assert (GST_WEBRTC_ICE_GET_CLASS (ice)->get_http_proxy);
return GST_WEBRTC_ICE_GET_CLASS (ice)->get_http_proxy (ice);
}
static void
gst_webrtc_ice_set_property (GObject * object, guint prop_id,
@ -516,6 +555,8 @@ gst_webrtc_ice_class_init (GstWebRTCICEClass * klass)
klass->get_stun_server = NULL;
klass->set_turn_server = NULL;
klass->get_turn_server = NULL;
klass->get_http_proxy = NULL;
klass->set_http_proxy = NULL;
klass->set_tos = NULL;
klass->set_on_ice_candidate = NULL;
klass->get_local_candidates = NULL;

View file

@ -106,6 +106,33 @@ struct _GstWebRTCICEClass {
void (*set_turn_server) (GstWebRTCICE * ice,
const gchar * uri);
gchar * (*get_turn_server) (GstWebRTCICE * ice);
/**
* GstWebRTCICEClass::set_http_proxy:
* @ice: a #GstWebRTCICE
* @uri: (transfer none): URI of the HTTP proxy of the form
* http://[username:password@]hostname[:port]
*
* Set HTTP Proxy to be used when connecting to TURN server.
*
* Since: 1.22
*/
void (*set_http_proxy) (GstWebRTCICE * ice,
const gchar * uri);
/**
* GstWebRTCICEClass::get_http_proxy:
* @ice: a #GstWebRTCICE
*
* Get HTTP Proxy to be used when connecting to TURN server.
*
* Returns: (transfer full): URI of the HTTP proxy of the form
* http://[username:password@]hostname[:port]
*
* Since: 1.22
*/
gchar * (*get_http_proxy) (GstWebRTCICE * ice);
void (*set_tos) (GstWebRTCICE * ice,
GstWebRTCICEStream * stream,
guint tos);
@ -186,6 +213,13 @@ void gst_webrtc_ice_set_turn_server (GstWebRTCIC
GST_WEBRTC_API
gchar * gst_webrtc_ice_get_turn_server (GstWebRTCICE * ice);
GST_WEBRTC_API
void gst_webrtc_ice_set_http_proxy (GstWebRTCICE * ice,
const gchar * uri);
GST_WEBRTC_API
gchar * gst_webrtc_ice_get_http_proxy (GstWebRTCICE * ice);
GST_WEBRTC_API
void gst_webrtc_ice_set_on_ice_candidate (GstWebRTCICE * ice,
GstWebRTCICEOnCandidateFunc func,

View file

@ -34,6 +34,8 @@
NICE_VERSION_MICRO >= (micro)))
#endif
#define HTTP_PROXY_PORT_DEFAULT 3128
/* XXX:
*
* - are locally generated remote candidates meant to be readded to libnice?
@ -74,6 +76,8 @@ struct _GstWebRTCNicePrivate
GstUri *turn_server;
GHashTable *turn_servers;
GstUri *http_proxy;
};
#define gst_webrtc_nice_parent_class parent_class
@ -1390,6 +1394,106 @@ out:
return NULL;
}
static void
on_http_proxy_resolved (GstWebRTCICE * ice, GAsyncResult * res,
gpointer user_data)
{
GstWebRTCNice *nice = GST_WEBRTC_NICE (ice);
GstUri *uri = user_data;
GList *addresses;
GError *error = NULL;
const gchar *userinfo;
gchar *user = NULL;
gchar *pass = NULL;
gchar *ip = NULL;
guint port = GST_URI_NO_PORT;
if (!(addresses = resolve_host_finish (nice, res, &error))) {
GST_WARNING_OBJECT (ice, "Failed to resolve http proxy: %s",
error->message);
g_clear_error (&error);
return;
}
/* XXX: only the first IP is used */
ip = g_inet_address_to_string (addresses->data);
if (!ip) {
GST_ERROR_OBJECT (ice, "failed to resolve host for proxy");
gst_uri_unref (uri);
return;
}
port = gst_uri_get_port (uri);
if (port == GST_URI_NO_PORT) {
port = HTTP_PROXY_PORT_DEFAULT;
GST_DEBUG_OBJECT (ice, "Proxy server has no port, assuming %u",
HTTP_PROXY_PORT_DEFAULT);
}
userinfo = gst_uri_get_userinfo (uri);
_parse_userinfo (userinfo, &user, &pass);
g_object_set (nice->priv->nice_agent,
"proxy-ip", ip, "proxy-port", port, "proxy-type", NICE_PROXY_TYPE_HTTP,
"proxy-username", user, "proxy-password", pass, NULL);
g_free (ip);
g_free (user);
g_free (pass);
}
static GstUri *
_set_http_proxy (GstWebRTCICE * ice, const gchar * s)
{
GstWebRTCNice *nice = GST_WEBRTC_NICE (ice);
GstUri *uri = gst_uri_from_string_escaped (s);
const gchar *msg =
"must be of the form http://[username:password@]<host>[:<port>]";
const gchar *host = NULL;
const gchar *userinfo;
gchar *user = NULL, *pass = NULL;
GST_DEBUG_OBJECT (ice, "setting http proxy %s", s);
if (!uri) {
GST_ERROR_OBJECT (ice, "Couldn't parse http proxy uri '%s', %s", s, msg);
return NULL;
}
if (g_strcmp0 (gst_uri_get_scheme (uri), "http") != 0) {
GST_ERROR_OBJECT (ice,
"Couldn't parse uri scheme for http proxy server '%s', %s", s, msg);
gst_uri_unref (uri);
return NULL;
}
host = gst_uri_get_host (uri);
if (!host) {
GST_ERROR_OBJECT (ice, "http proxy server '%s' has no host, %s", s, msg);
gst_uri_unref (uri);
return NULL;
}
userinfo = gst_uri_get_userinfo (uri);
_parse_userinfo (userinfo, &user, &pass);
if ((pass && pass[0] != '\0') && (!user || user[0] == '\0')) {
GST_ERROR_OBJECT (ice,
"Password specified without user for http proxy '%s', %s", s, msg);
uri = NULL;
goto out;
}
resolve_host_async (nice, host, (GAsyncReadyCallback) on_http_proxy_resolved,
gst_uri_ref (uri), (GDestroyNotify) gst_uri_unref);
out:
g_free (user);
g_free (pass);
return uri;
}
static void
gst_webrtc_nice_set_stun_server (GstWebRTCICE * ice, const gchar * uri_s)
{
@ -1443,6 +1547,30 @@ gst_webrtc_nice_get_turn_server (GstWebRTCICE * ice)
return NULL;
}
static void
gst_webrtc_nice_set_http_proxy (GstWebRTCICE * ice, const gchar * http_proxy)
{
GstWebRTCNice *nice = GST_WEBRTC_NICE (ice);
GstUri *uri = _set_http_proxy (ice, http_proxy);
if (uri) {
if (nice->priv->http_proxy)
gst_uri_unref (nice->priv->http_proxy);
nice->priv->http_proxy = uri;
}
}
static gchar *
gst_webrtc_nice_get_http_proxy (GstWebRTCICE * ice)
{
GstWebRTCNice *nice = GST_WEBRTC_NICE (ice);
if (nice->priv->http_proxy)
return gst_uri_to_string (nice->priv->http_proxy);
else
return NULL;
}
static void
gst_webrtc_nice_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
@ -1526,6 +1654,8 @@ gst_webrtc_nice_finalize (GObject * object)
gst_uri_unref (ice->priv->turn_server);
if (ice->priv->stun_server)
gst_uri_unref (ice->priv->stun_server);
if (ice->priv->http_proxy)
gst_uri_unref (ice->priv->http_proxy);
g_mutex_clear (&ice->priv->lock);
g_cond_clear (&ice->priv->cond);
@ -1573,6 +1703,7 @@ gst_webrtc_nice_class_init (GstWebRTCNiceClass * klass)
gst_webrtc_ice_class->get_is_controller = gst_webrtc_nice_get_is_controller;
gst_webrtc_ice_class->get_stun_server = gst_webrtc_nice_get_stun_server;
gst_webrtc_ice_class->get_turn_server = gst_webrtc_nice_get_turn_server;
gst_webrtc_ice_class->get_http_proxy = gst_webrtc_nice_get_http_proxy;
gst_webrtc_ice_class->set_force_relay = gst_webrtc_nice_set_force_relay;
gst_webrtc_ice_class->set_is_controller = gst_webrtc_nice_set_is_controller;
gst_webrtc_ice_class->set_local_credentials =
@ -1582,6 +1713,7 @@ gst_webrtc_nice_class_init (GstWebRTCNiceClass * klass)
gst_webrtc_ice_class->set_stun_server = gst_webrtc_nice_set_stun_server;
gst_webrtc_ice_class->set_tos = gst_webrtc_nice_set_tos;
gst_webrtc_ice_class->set_turn_server = gst_webrtc_nice_set_turn_server;
gst_webrtc_ice_class->set_http_proxy = gst_webrtc_nice_set_http_proxy;
gst_webrtc_ice_class->set_on_ice_candidate =
gst_webrtc_nice_set_on_ice_candidate;
gst_webrtc_ice_class->get_local_candidates =