dovecot-2.2: http-client: Added support for using an HTTP proxy ...

dovecot at dovecot.org dovecot at dovecot.org
Sat Aug 29 11:50:16 UTC 2015


details:   http://hg.dovecot.org/dovecot-2.2/rev/8f8f768937f5
changeset: 19039:8f8f768937f5
user:      Stephan Bosch <stephan at rename-it.nl>
date:      Sat Apr 25 11:42:06 2015 +0200
description:
http-client: Added support for using an HTTP proxy running on a unix socket.

diffstat:

 src/lib-http/http-client-connection.c |  31 +++++++---
 src/lib-http/http-client-host.c       |  71 ++++++++++++++++++-------
 src/lib-http/http-client-peer.c       |  58 +++++++++++++++-----
 src/lib-http/http-client-private.h    |  96 +++++++++++++++++++++++-----------
 src/lib-http/http-client-queue.c      |  97 ++++++++++++++++++++++------------
 src/lib-http/http-client-request.c    |  48 +++++++++++++++--
 src/lib-http/http-client.h            |   6 +-
 7 files changed, 286 insertions(+), 121 deletions(-)

diffs (truncated from 781 to 300 lines):

diff -r f8ab4f979e92 -r 8f8f768937f5 src/lib-http/http-client-connection.c
--- a/src/lib-http/http-client-connection.c	Sat Aug 29 14:42:49 2015 +0300
+++ b/src/lib-http/http-client-connection.c	Sat Apr 25 11:42:06 2015 +0200
@@ -1015,7 +1015,7 @@
 http_client_connection_ssl_handshaked(const char **error_r, void *context)
 {
 	struct http_client_connection *conn = context;
-	const char *error, *host = conn->peer->addr.https_name;
+	const char *error, *host = conn->peer->addr.a.tcp.https_name;
 
 	if (ssl_iostream_check_cert_validity(conn->ssl_iostream, host, &error) == 0)
 		http_client_connection_debug(conn, "SSL handshake successful");
@@ -1049,7 +1049,7 @@
 		http_client_connection_debug(conn, "Starting SSL handshake");
 
 	if (io_stream_create_ssl_client(conn->client->ssl_ctx,
-					conn->peer->addr.https_name, &ssl_set,
+					conn->peer->addr.a.tcp.https_name, &ssl_set,
 					&conn->conn.input, &conn->conn.output,
 					&conn->ssl_iostream, &error) < 0) {
 		*error_r = t_strdup_printf(
@@ -1089,7 +1089,7 @@
 	} else {
 		conn->connected_timestamp = ioloop_timeval;
 		http_client_connection_debug(conn, "Connected");
-		if (conn->peer->addr.https_name != NULL) {
+		if (http_client_peer_addr_is_https(&conn->peer->addr)) {
 			if (http_client_connection_ssl_init(conn, &error) < 0) {
 				http_client_peer_connection_failure(conn->peer, error);
 				http_client_connection_debug(conn, "%s", error);
@@ -1104,7 +1104,8 @@
 static const struct connection_settings http_client_connection_set = {
 	.input_max_size = (size_t)-1,
 	.output_max_size = (size_t)-1,
-	.client = TRUE
+	.client = TRUE,
+	.delayed_unix_client_connected_callback = TRUE
 };
 
 static const struct connection_vfuncs http_client_connection_vfuncs = {
@@ -1248,6 +1249,9 @@
 	case HTTP_CLIENT_PEER_ADDR_RAW:
 		conn_type = "Raw";
 		break;
+	case HTTP_CLIENT_PEER_ADDR_UNIX:
+		conn_type = "Unix";
+		break;
 	}
 
 	conn = i_new(struct http_client_connection, 1);
@@ -1258,11 +1262,20 @@
 	if (peer->addr.type != HTTP_CLIENT_PEER_ADDR_RAW)
 		i_array_init(&conn->request_wait_list, 16);
 
-	if (peer->addr.type == HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL) {
-		http_client_connection_connect_tunnel(conn, &addr->ip, addr->port);
-	} else {
-		connection_init_client_ip
-			(peer->client->conn_list, &conn->conn, &addr->ip, addr->port);
+	switch (peer->addr.type) {
+	case HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL:
+		http_client_connection_connect_tunnel
+			(conn, &addr->a.tcp.ip, addr->a.tcp.port);
+		break;
+	case HTTP_CLIENT_PEER_ADDR_UNIX:
+		connection_init_client_unix(peer->client->conn_list, &conn->conn,
+			addr->a.un.path);
+		conn->connect_initialized = TRUE;
+		http_client_connection_connect(conn);
+		break;
+	default:
+		connection_init_client_ip(peer->client->conn_list, &conn->conn,
+			&addr->a.tcp.ip, addr->a.tcp.port);
 		conn->connect_initialized = TRUE;
 		http_client_connection_connect(conn);
 	}
diff -r f8ab4f979e92 -r 8f8f768937f5 src/lib-http/http-client-host.c
--- a/src/lib-http/http-client-host.c	Sat Aug 29 14:42:49 2015 +0300
+++ b/src/lib-http/http-client-host.c	Sat Apr 25 11:42:06 2015 +0200
@@ -137,31 +137,55 @@
 	}
 }
 
+static struct http_client_host *http_client_host_create
+(struct http_client *client)
+{
+	struct http_client_host *host;
+
+	// FIXME: limit the maximum number of inactive cached hosts
+	host = i_new(struct http_client_host, 1);
+	host->client = client;
+	i_array_init(&host->queues, 4);
+	DLLIST_PREPEND(&client->hosts_list, host);
+
+	return host;
+}
+
 struct http_client_host *http_client_host_get
 (struct http_client *client, const struct http_url *host_url)
 {
 	struct http_client_host *host;
-	const char *hostname = host_url->host_name;
 
-	host = hash_table_lookup(client->hosts, hostname);
-	if (host == NULL) {
-		// FIXME: limit the maximum number of inactive cached hosts
-		host = i_new(struct http_client_host, 1);
-		host->client = client;
-		host->name = i_strdup(hostname);
-		i_array_init(&host->queues, 4);
+	if (host_url == NULL) {
+		host = client->unix_host;
+		if (host == NULL) {
+			host = http_client_host_create(client);
+			host->name = i_strdup("[unix]");
+			host->unix_local = TRUE;
 
-		hostname = host->name;
-		hash_table_insert(client->hosts, hostname, host);
-		DLLIST_PREPEND(&client->hosts_list, host);
+			client->unix_host = host;
 
-		if (host_url->have_host_ip) {
-			host->ips_count = 1;
-			host->ips = i_new(struct ip_addr, host->ips_count);
-			host->ips[0] = host_url->host_ip;
+			http_client_host_debug(host, "Unix host created");
 		}
 
-		http_client_host_debug(host, "Host created");
+	} else {
+		const char *hostname = host_url->host_name;
+
+		host = hash_table_lookup(client->hosts, hostname);
+		if (host == NULL) {
+			host = http_client_host_create(client);
+			host->name = i_strdup(hostname);
+			hostname = host->name;
+			hash_table_insert(client->hosts, hostname, host);
+
+			if (host_url->have_host_ip) {
+				host->ips_count = 1;
+				host->ips = i_new(struct ip_addr, host->ips_count);
+				host->ips[0] = host_url->host_ip;
+			}
+
+			http_client_host_debug(host, "Host created");
+		}
 	}
 	return host;
 }
@@ -170,13 +194,14 @@
 	struct http_client_request *req)
 {
 	struct http_client_queue *queue;
-	const struct http_url *host_url = req->host_url;
 	struct http_client_peer_addr addr;
 	const char *error;
 
 	req->host = host;
 
-	if (host_url->have_ssl && host->client->ssl_ctx == NULL) {
+	http_client_request_get_peer_addr(req, &addr);
+	if (http_client_peer_addr_is_https(&addr) &&
+		host->client->ssl_ctx == NULL) {
 		if (http_client_init_ssl_ctx(host->client, &error) < 0) {
 			http_client_request_error(req,
 				HTTP_CLIENT_REQUEST_ERROR_CONNECT_FAILED, error);
@@ -184,12 +209,15 @@
 		}
 	}
 
-	http_client_request_get_peer_addr(req, &addr);
-
 	/* add request to queue (grouped by tcp port) */
 	queue = http_client_queue_create(host, &addr);
 	http_client_queue_submit_request(queue, req);
 
+	if (host->unix_local) {
+		http_client_queue_connection_setup(queue);
+		return;
+	}
+
 	/* start DNS lookup if necessary */
 	if (host->ips_count == 0 && host->dns_lookup == NULL)	
 		http_client_host_lookup(host);
@@ -210,7 +238,8 @@
 	http_client_host_debug(host, "Host destroy");
 
 	DLLIST_REMOVE(&host->client->hosts_list, host);
-	hash_table_remove(host->client->hosts, hostname);
+	if (host != host->client->unix_host)
+		hash_table_remove(host->client->hosts, hostname);
 
 	if (host->dns_lookup != NULL)
 		dns_lookup_abort(&host->dns_lookup);
diff -r f8ab4f979e92 -r 8f8f768937f5 src/lib-http/http-client-peer.c
--- a/src/lib-http/http-client-peer.c	Sat Aug 29 14:42:49 2015 +0300
+++ b/src/lib-http/http-client-peer.c	Sat Apr 25 11:42:06 2015 +0200
@@ -45,13 +45,16 @@
 {
 	switch (peer->type) {
 	case HTTP_CLIENT_PEER_ADDR_RAW:
-		return net_ip_hash(&peer->ip) + peer->port + 1;
+		return net_ip_hash(&peer->a.tcp.ip) + peer->a.tcp.port + 1;
 	case HTTP_CLIENT_PEER_ADDR_HTTP:
-		return net_ip_hash(&peer->ip) + peer->port;
+		return net_ip_hash(&peer->a.tcp.ip) + peer->a.tcp.port;
 	case HTTP_CLIENT_PEER_ADDR_HTTPS:
 	case HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL:
-		return net_ip_hash(&peer->ip) + peer->port +
-			(peer->https_name == NULL ? 0 : str_hash(peer->https_name));
+		return net_ip_hash(&peer->a.tcp.ip) + peer->a.tcp.port +
+			(peer->a.tcp.https_name == NULL ?
+				0 : str_hash(peer->a.tcp.https_name));
+	case HTTP_CLIENT_PEER_ADDR_UNIX:
+		return str_hash(peer->a.un.path);
 	}
 	i_unreached();
 	return 0;
@@ -65,13 +68,24 @@
 
 	if (peer1->type != peer2->type)
 		return (peer1->type > peer2->type ? 1 : -1);
-	if ((ret=net_ip_cmp(&peer1->ip, &peer2->ip)) != 0)
-		return ret;
-	if (peer1->port != peer2->port)
-		return (peer1->port > peer2->port ? 1 : -1);
-	if (peer1->type != HTTP_CLIENT_PEER_ADDR_HTTPS)
-		return 0;
-	return null_strcmp(peer1->https_name, peer2->https_name);
+	switch (peer1->type) {
+	case HTTP_CLIENT_PEER_ADDR_RAW:
+	case HTTP_CLIENT_PEER_ADDR_HTTP:
+	case HTTP_CLIENT_PEER_ADDR_HTTPS:
+	case HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL:
+		if ((ret=net_ip_cmp(&peer1->a.tcp.ip, &peer2->a.tcp.ip)) != 0)
+			return ret;
+		if (peer1->a.tcp.port != peer2->a.tcp.port)
+			return (peer1->a.tcp.port > peer2->a.tcp.port ? 1 : -1);
+		if (peer1->type != HTTP_CLIENT_PEER_ADDR_HTTPS)
+			return 0;
+		return null_strcmp
+			(peer1->a.tcp.https_name, peer2->a.tcp.https_name);
+	case HTTP_CLIENT_PEER_ADDR_UNIX:
+		return null_strcmp(peer1->a.un.path, peer2->a.un.path);
+	}
+	i_unreached();
+	return 0;
 }
 
 /*
@@ -438,13 +452,25 @@
 {
 	struct http_client_peer *peer;
 
-	i_assert(addr->https_name == NULL || client->ssl_ctx != NULL);
-
 	peer = i_new(struct http_client_peer, 1);
 	peer->client = client;
 	peer->addr = *addr;
-	peer->https_name = i_strdup(addr->https_name);
-	peer->addr.https_name = peer->https_name;
+
+	switch (addr->type) {
+	case HTTP_CLIENT_PEER_ADDR_HTTPS:
+	case HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL:
+		i_assert(client->ssl_ctx != NULL);
+		peer->addr_name = i_strdup(addr->a.tcp.https_name);
+		peer->addr.a.tcp.https_name = peer->addr_name;
+		break;
+	case HTTP_CLIENT_PEER_ADDR_UNIX:
+		peer->addr_name = i_strdup(addr->a.un.path);
+		peer->addr.a.un.path = peer->addr_name;
+		break;
+	default:
+		break;
+	}
+
 	i_array_init(&peer->queues, 16);
 	i_array_init(&peer->conns, 16);
 
@@ -479,7 +505,7 @@
 		(peer->client->peers, (const struct http_client_peer_addr *)&peer->addr);
 	DLLIST_REMOVE(&peer->client->peers_list, peer);
 
-	i_free(peer->https_name);
+	i_free(peer->addr_name);
 	i_free(peer);
 	*_peer = NULL;
 }
diff -r f8ab4f979e92 -r 8f8f768937f5 src/lib-http/http-client-private.h
--- a/src/lib-http/http-client-private.h	Sat Aug 29 14:42:49 2015 +0300
+++ b/src/lib-http/http-client-private.h	Sat Apr 25 11:42:06 2015 +0200
@@ -38,14 +38,22 @@
 	HTTP_CLIENT_PEER_ADDR_HTTP = 0,
 	HTTP_CLIENT_PEER_ADDR_HTTPS,
 	HTTP_CLIENT_PEER_ADDR_HTTPS_TUNNEL,
-	HTTP_CLIENT_PEER_ADDR_RAW
+	HTTP_CLIENT_PEER_ADDR_RAW,


More information about the dovecot-cvs mailing list