Commit e0a455b4 authored by Johan Sternerup's avatar Johan Sternerup Committed by Olivier Crête

agent: Support adding optional headers to HTTP proxy client

One use case for this is adding an ALPN header which is a MUST
requirement when a HTTP proxy is used in WebRTC (see RFC8835, section
3.4).
parent 028c4098
...@@ -140,6 +140,7 @@ struct _NiceAgent ...@@ -140,6 +140,7 @@ struct _NiceAgent
NiceProxyType proxy_type; /* property: Proxy type */ NiceProxyType proxy_type; /* property: Proxy type */
gchar *proxy_username; /* property: Proxy username */ gchar *proxy_username; /* property: Proxy username */
gchar *proxy_password; /* property: Proxy password */ gchar *proxy_password; /* property: Proxy password */
GHashTable *proxy_extra_headers;/* property: Proxy extra headers */
gboolean saved_controlling_mode;/* property: controlling-mode */ gboolean saved_controlling_mode;/* property: controlling-mode */
guint timer_ta; /* property: timer Ta */ guint timer_ta; /* property: timer Ta */
guint max_conn_checks; /* property: max connectivity checks */ guint max_conn_checks; /* property: max connectivity checks */
......
...@@ -112,6 +112,7 @@ enum ...@@ -112,6 +112,7 @@ enum
PROP_PROXY_PORT, PROP_PROXY_PORT,
PROP_PROXY_USERNAME, PROP_PROXY_USERNAME,
PROP_PROXY_PASSWORD, PROP_PROXY_PASSWORD,
PROP_PROXY_EXTRA_HEADERS,
PROP_UPNP, PROP_UPNP,
PROP_UPNP_TIMEOUT, PROP_UPNP_TIMEOUT,
PROP_RELIABLE, PROP_RELIABLE,
...@@ -614,6 +615,23 @@ nice_agent_class_init (NiceAgentClass *klass) ...@@ -614,6 +615,23 @@ nice_agent_class_init (NiceAgentClass *klass)
NULL, NULL,
G_PARAM_READWRITE)); G_PARAM_READWRITE));
/**
* NiceAgent:proxy-extra-headers: (type GLib.HashTable(utf8,utf8))
*
* Optional extra headers to append to the HTTP proxy CONNECT request.
* Provided as key/value-pairs in hash table corresponding to
* header-name/header-value.
*
* Since: 0.1.20
*/
g_object_class_install_property (gobject_class, PROP_PROXY_EXTRA_HEADERS,
g_param_spec_boxed (
"proxy-extra-headers",
"Extra headers for HTTP proxy connect",
"Extra headers to append to the HTTP proxy CONNECT request",
G_TYPE_HASH_TABLE,
G_PARAM_READWRITE));
/** /**
* NiceAgent:upnp: * NiceAgent:upnp:
* *
...@@ -1427,6 +1445,10 @@ nice_agent_get_property ( ...@@ -1427,6 +1445,10 @@ nice_agent_get_property (
g_value_set_string (value, agent->proxy_password); g_value_set_string (value, agent->proxy_password);
break; break;
case PROP_PROXY_EXTRA_HEADERS:
g_value_set_boxed (value, agent->proxy_extra_headers);
break;
case PROP_UPNP: case PROP_UPNP:
#ifdef HAVE_GUPNP #ifdef HAVE_GUPNP
g_value_set_boolean (value, agent->upnp_enabled); g_value_set_boolean (value, agent->upnp_enabled);
...@@ -1563,6 +1585,12 @@ nice_agent_reset_all_stun_agents (NiceAgent *agent, gboolean only_software) ...@@ -1563,6 +1585,12 @@ nice_agent_reset_all_stun_agents (NiceAgent *agent, gboolean only_software)
} }
} }
static void
copy_hash_entry (const gchar *key, const gchar *value, GHashTable *hdest)
{
g_hash_table_insert (hdest, g_strdup (key), g_strdup (value));
}
static void static void
nice_agent_set_property ( nice_agent_set_property (
GObject *object, GObject *object,
...@@ -1652,6 +1680,17 @@ nice_agent_set_property ( ...@@ -1652,6 +1680,17 @@ nice_agent_set_property (
agent->proxy_password = g_value_dup_string (value); agent->proxy_password = g_value_dup_string (value);
break; break;
case PROP_PROXY_EXTRA_HEADERS:{
GHashTable *h = g_value_get_boxed (value);
if (agent->proxy_extra_headers) {
g_hash_table_unref (agent->proxy_extra_headers);
}
agent->proxy_extra_headers = g_hash_table_new_full (g_str_hash,
g_str_equal, g_free, g_free);
g_hash_table_foreach (h, (GHFunc)copy_hash_entry,
agent->proxy_extra_headers);
break;
}
case PROP_UPNP_TIMEOUT: case PROP_UPNP_TIMEOUT:
#ifdef HAVE_GUPNP #ifdef HAVE_GUPNP
agent->upnp_timeout = g_value_get_uint (value); agent->upnp_timeout = g_value_get_uint (value);
...@@ -2673,7 +2712,8 @@ agent_create_tcp_turn_socket (NiceAgent *agent, NiceStream *stream, ...@@ -2673,7 +2712,8 @@ agent_create_tcp_turn_socket (NiceAgent *agent, NiceStream *stream,
agent->proxy_username, agent->proxy_password); agent->proxy_username, agent->proxy_password);
} else if (agent->proxy_type == NICE_PROXY_TYPE_HTTP){ } else if (agent->proxy_type == NICE_PROXY_TYPE_HTTP){
nicesock = nice_http_socket_new (nicesock, server, nicesock = nice_http_socket_new (nicesock, server,
agent->proxy_username, agent->proxy_password); agent->proxy_username, agent->proxy_password,
agent->proxy_extra_headers);
} else { } else {
nice_socket_free (nicesock); nice_socket_free (nicesock);
nicesock = NULL; nicesock = NULL;
...@@ -5761,7 +5801,10 @@ nice_agent_dispose (GObject *object) ...@@ -5761,7 +5801,10 @@ nice_agent_dispose (GObject *object)
agent->proxy_username = NULL; agent->proxy_username = NULL;
g_free (agent->proxy_password); g_free (agent->proxy_password);
agent->proxy_password = NULL; agent->proxy_password = NULL;
if (agent->proxy_extra_headers != NULL) {
g_hash_table_unref (agent->proxy_extra_headers);
agent->proxy_extra_headers = NULL;
}
nice_rng_free (agent->rng); nice_rng_free (agent->rng);
agent->rng = NULL; agent->rng = NULL;
......
...@@ -97,9 +97,17 @@ static void socket_set_writable_callback (NiceSocket *sock, ...@@ -97,9 +97,17 @@ static void socket_set_writable_callback (NiceSocket *sock,
NiceSocketWritableCb callback, gpointer user_data); NiceSocketWritableCb callback, gpointer user_data);
static gboolean socket_is_based_on (NiceSocket *sock, NiceSocket *other); static gboolean socket_is_based_on (NiceSocket *sock, NiceSocket *other);
static void
_append_extra_header (gpointer key, gpointer value, gpointer user_data)
{
GString *str = user_data;
g_string_append_printf (str, "%s: %s\r\n", (gchar *)key, (gchar *)value);
}
NiceSocket * NiceSocket *
nice_http_socket_new (NiceSocket *base_socket, nice_http_socket_new (NiceSocket *base_socket,
NiceAddress *addr, gchar *username, gchar *password) NiceAddress *addr, gchar *username, gchar *password,
GHashTable *extra_headers)
{ {
HttpPriv *priv; HttpPriv *priv;
NiceSocket *sock = NULL; NiceSocket *sock = NULL;
...@@ -133,7 +141,7 @@ nice_http_socket_new (NiceSocket *base_socket, ...@@ -133,7 +141,7 @@ nice_http_socket_new (NiceSocket *base_socket,
/* Send HTTP CONNECT */ /* Send HTTP CONNECT */
{ {
gchar *msg = NULL; gchar *msg = NULL;
gchar *credential = NULL; GString *str = NULL;
gchar host[INET6_ADDRSTRLEN]; gchar host[INET6_ADDRSTRLEN];
gint port = nice_address_get_port (&priv->addr); gint port = nice_address_get_port (&priv->addr);
GOutputVector local_bufs; GOutputVector local_bufs;
...@@ -141,25 +149,31 @@ nice_http_socket_new (NiceSocket *base_socket, ...@@ -141,25 +149,31 @@ nice_http_socket_new (NiceSocket *base_socket,
nice_address_to_string (&priv->addr, host); nice_address_to_string (&priv->addr, host);
str = g_string_new (NULL);
g_string_printf (str, "CONNECT %s:%d HTTP/1.0\r\n"
"Host: %s\r\n"
"User-Agent: %s\r\n"
"Content-Length: 0\r\n"
"Proxy-Connection: Keep-Alive\r\n"
"Connection: Keep-Alive\r\n"
"Cache-Control: no-cache\r\n"
"Pragma: no-cache\r\n",
host, port, host, HTTP_USER_AGENT);
if (extra_headers) {
g_hash_table_foreach (extra_headers, _append_extra_header, str);
}
if (username) { if (username) {
gchar * userpass = g_strdup_printf ("%s:%s", username, gchar * userpass = g_strdup_printf ("%s:%s", username,
password ? password : ""); password ? password : "");
gchar * auth = g_base64_encode ((guchar *)userpass, strlen (userpass)); gchar * auth = g_base64_encode ((guchar *)userpass, strlen (userpass));
credential = g_strdup_printf ("Proxy-Authorization: Basic %s\r\n", auth); g_string_append_printf (str, "Proxy-Authorization: Basic %s\r\n", auth);
g_free (auth); g_free (auth);
g_free (userpass); g_free (userpass);
} }
msg = g_strdup_printf ("CONNECT %s:%d HTTP/1.0\r\n" g_string_append_printf (str, "\r\n");
"Host: %s\r\n" msg = g_string_free (str, FALSE);
"User-Agent: %s\r\n"
"Content-Length: 0\r\n"
"Proxy-Connection: Keep-Alive\r\n"
"Connection: Keep-Alive\r\n"
"Cache-Control: no-cache\r\n"
"Pragma: no-cache\r\n"
"%s\r\n", host, port, host, HTTP_USER_AGENT,
credential? credential : "" );
g_free (credential);
local_bufs.buffer = msg; local_bufs.buffer = msg;
local_bufs.size = strlen (msg); local_bufs.size = strlen (msg);
......
...@@ -45,7 +45,8 @@ G_BEGIN_DECLS ...@@ -45,7 +45,8 @@ G_BEGIN_DECLS
NiceSocket * NiceSocket *
nice_http_socket_new (NiceSocket *base_socket, nice_http_socket_new (NiceSocket *base_socket,
NiceAddress *addr, gchar *username, gchar *password); NiceAddress *addr, gchar *username, gchar *password,
GHashTable *extra_headers);
G_END_DECLS G_END_DECLS
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment