summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohan Sternerup <johast@axis.com>2020-09-25 17:14:52 +0200
committerOlivier CrĂȘte <olivier.crete@ocrete.ca>2022-05-26 11:43:45 -0400
commite0a455b457935e044adeff453e4c923fe79a6b09 (patch)
tree4f2d11aa49f49c23db51f9edd4cc10d012980be4
parent028c4098771b3584f1fb0845562282c91b40e57a (diff)
downloadlibnice-e0a455b457935e044adeff453e4c923fe79a6b09.tar.gz
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).
-rw-r--r--agent/agent-priv.h1
-rw-r--r--agent/agent.c47
-rw-r--r--socket/http.c42
-rw-r--r--socket/http.h3
4 files changed, 76 insertions, 17 deletions
diff --git a/agent/agent-priv.h b/agent/agent-priv.h
index 1d8b683..35ae5ab 100644
--- a/agent/agent-priv.h
+++ b/agent/agent-priv.h
@@ -140,6 +140,7 @@ struct _NiceAgent
NiceProxyType proxy_type; /* property: Proxy type */
gchar *proxy_username; /* property: Proxy username */
gchar *proxy_password; /* property: Proxy password */
+ GHashTable *proxy_extra_headers;/* property: Proxy extra headers */
gboolean saved_controlling_mode;/* property: controlling-mode */
guint timer_ta; /* property: timer Ta */
guint max_conn_checks; /* property: max connectivity checks */
diff --git a/agent/agent.c b/agent/agent.c
index a2e150f..6278fa7 100644
--- a/agent/agent.c
+++ b/agent/agent.c
@@ -112,6 +112,7 @@ enum
PROP_PROXY_PORT,
PROP_PROXY_USERNAME,
PROP_PROXY_PASSWORD,
+ PROP_PROXY_EXTRA_HEADERS,
PROP_UPNP,
PROP_UPNP_TIMEOUT,
PROP_RELIABLE,
@@ -615,6 +616,23 @@ nice_agent_class_init (NiceAgentClass *klass)
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:
*
* Whether the agent should use UPnP to open a port in the router and
@@ -1427,6 +1445,10 @@ nice_agent_get_property (
g_value_set_string (value, agent->proxy_password);
break;
+ case PROP_PROXY_EXTRA_HEADERS:
+ g_value_set_boxed (value, agent->proxy_extra_headers);
+ break;
+
case PROP_UPNP:
#ifdef HAVE_GUPNP
g_value_set_boolean (value, agent->upnp_enabled);
@@ -1564,6 +1586,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
nice_agent_set_property (
GObject *object,
guint property_id,
@@ -1652,6 +1680,17 @@ nice_agent_set_property (
agent->proxy_password = g_value_dup_string (value);
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:
#ifdef HAVE_GUPNP
agent->upnp_timeout = g_value_get_uint (value);
@@ -2673,7 +2712,8 @@ agent_create_tcp_turn_socket (NiceAgent *agent, NiceStream *stream,
agent->proxy_username, agent->proxy_password);
} else if (agent->proxy_type == NICE_PROXY_TYPE_HTTP){
nicesock = nice_http_socket_new (nicesock, server,
- agent->proxy_username, agent->proxy_password);
+ agent->proxy_username, agent->proxy_password,
+ agent->proxy_extra_headers);
} else {
nice_socket_free (nicesock);
nicesock = NULL;
@@ -5761,7 +5801,10 @@ nice_agent_dispose (GObject *object)
agent->proxy_username = NULL;
g_free (agent->proxy_password);
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);
agent->rng = NULL;
diff --git a/socket/http.c b/socket/http.c
index 96ddfd8..d16b317 100644
--- a/socket/http.c
+++ b/socket/http.c
@@ -97,9 +97,17 @@ static void socket_set_writable_callback (NiceSocket *sock,
NiceSocketWritableCb callback, gpointer user_data);
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 *
nice_http_socket_new (NiceSocket *base_socket,
- NiceAddress *addr, gchar *username, gchar *password)
+ NiceAddress *addr, gchar *username, gchar *password,
+ GHashTable *extra_headers)
{
HttpPriv *priv;
NiceSocket *sock = NULL;
@@ -133,7 +141,7 @@ nice_http_socket_new (NiceSocket *base_socket,
/* Send HTTP CONNECT */
{
gchar *msg = NULL;
- gchar *credential = NULL;
+ GString *str = NULL;
gchar host[INET6_ADDRSTRLEN];
gint port = nice_address_get_port (&priv->addr);
GOutputVector local_bufs;
@@ -141,25 +149,31 @@ nice_http_socket_new (NiceSocket *base_socket,
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) {
gchar * userpass = g_strdup_printf ("%s:%s", username,
password ? password : "");
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 (userpass);
}
- msg = g_strdup_printf ("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"
- "%s\r\n", host, port, host, HTTP_USER_AGENT,
- credential? credential : "" );
- g_free (credential);
+ g_string_append_printf (str, "\r\n");
+ msg = g_string_free (str, FALSE);
local_bufs.buffer = msg;
local_bufs.size = strlen (msg);
diff --git a/socket/http.h b/socket/http.h
index 7f095a0..b2df362 100644
--- a/socket/http.h
+++ b/socket/http.h
@@ -45,7 +45,8 @@ G_BEGIN_DECLS
NiceSocket *
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