]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-http: client: Created basic shared context between clients.
authorStephan Bosch <stephan.bosch@dovecot.fi>
Tue, 29 Nov 2016 15:17:59 +0000 (16:17 +0100)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Thu, 7 Dec 2017 16:40:45 +0000 (18:40 +0200)
In this basic form it only shares default settings.

src/lib-http/http-client-private.h
src/lib-http/http-client.c
src/lib-http/http-client.h

index 87c4f0204d3b41278aef386e488e143f31f410a4..28d3ef2411ad7e701f702f23cec3bbdd0548f534 100644 (file)
@@ -289,7 +289,7 @@ struct http_client_host {
 
 struct http_client {
        pool_t pool;
-
+       struct http_client_context *cctx;
        struct http_client_settings set;
 
        struct ioloop *ioloop;
@@ -310,6 +310,13 @@ struct http_client {
        unsigned int requests_count;
 };
 
+struct http_client_context {
+       pool_t pool;
+       unsigned int refcount;
+
+       struct http_client_settings set;
+};
+
 /*
  * Peer address
  */
index 0aeea72e4978708e646935fe00de689841b5006c..ada2573d0480d069759003d52e43e4ba4585fefb 100644 (file)
@@ -84,7 +84,9 @@ http_client_debug(struct http_client *client,
  * Client
  */
 
-struct http_client *http_client_init(const struct http_client_settings *set)
+struct http_client *
+http_client_init_shared(struct http_client_context *cctx,
+       const struct http_client_settings *set)
 {
        struct http_client *client;
        pool_t pool;
@@ -93,65 +95,97 @@ struct http_client *http_client_init(const struct http_client_settings *set)
        client = p_new(pool, struct http_client, 1);
        client->pool = pool;
 
-       client->set.dns_client = set->dns_client;
-       client->set.dns_client_socket_path =
-               p_strdup_empty(pool, set->dns_client_socket_path);
-       client->set.dns_ttl_msecs = (set->dns_ttl_msecs == 0 ?
-               HTTP_CLIENT_DEFAULT_DNS_TTL_MSECS : set->dns_ttl_msecs);
-       client->set.user_agent = p_strdup_empty(pool, set->user_agent);
-       client->set.rawlog_dir = p_strdup_empty(pool, set->rawlog_dir);
+       /* create private context if none is provided */
+       if (cctx != NULL) {
+               client->cctx = cctx;
+               http_client_context_ref(cctx);
+       } else {
+               client->cctx = cctx = http_client_context_create(set);
+       }
 
-       if (set->ssl != NULL)
-               client->set.ssl = ssl_iostream_settings_dup(client->pool, set->ssl);
+       /* merge provided settings with context defaults */
+       i_assert(cctx != NULL || set != NULL);
+       client->set = cctx->set;
+       if (cctx != NULL && set != NULL) {
+               if (set->dns_client != NULL)
+                       client->set.dns_client = set->dns_client;
+               if (set->dns_client_socket_path != NULL &&
+                       *set->dns_client_socket_path != '\0') {
+                       client->set.dns_client_socket_path =
+                               p_strdup_empty(pool, set->dns_client_socket_path);
+               }
+               if (set->dns_ttl_msecs > 0)
+                       client->set.dns_ttl_msecs = set->dns_ttl_msecs;
+               if (set->user_agent != NULL && *set->user_agent != '\0')
+                       client->set.user_agent = p_strdup_empty(pool, set->user_agent);
+               if (set->rawlog_dir != NULL && *set->rawlog_dir != '\0')
+                       client->set.rawlog_dir = p_strdup_empty(pool, set->rawlog_dir);
+
+               if (set->ssl != NULL)
+                       client->set.ssl = ssl_iostream_settings_dup(pool, set->ssl);
+
+               if (set->proxy_socket_path != NULL && *set->proxy_socket_path != '\0') {
+                       client->set.proxy_socket_path = p_strdup(pool, set->proxy_socket_path);
+                       client->set.proxy_url = NULL;
+               } else if (set->proxy_url != NULL) {
+                       client->set.proxy_url = http_url_clone(pool, set->proxy_url);
+                       client->set.proxy_socket_path = NULL;
+               }
+               if (set->proxy_username != NULL && *set->proxy_username != '\0') {
+                       client->set.proxy_username = p_strdup_empty(pool, set->proxy_username);
+                       client->set.proxy_password = p_strdup(pool, set->proxy_password);
+               } else if (set->proxy_url != NULL && set->proxy_url->user != NULL &&
+                       *set->proxy_url->user != '\0') {
+                       client->set.proxy_username =
+                               p_strdup_empty(pool, set->proxy_url->user);
+                       client->set.proxy_password =
+                               p_strdup(pool, set->proxy_url->password);
+               }
 
-       if (set->proxy_socket_path != NULL && *set->proxy_socket_path != '\0') {
-               client->set.proxy_socket_path = p_strdup(pool, set->proxy_socket_path);
-       } else if (set->proxy_url != NULL) {
-               client->set.proxy_url = http_url_clone(pool, set->proxy_url);
-       }
-       if (set->proxy_username != NULL && *set->proxy_username != '\0') {
-               client->set.proxy_username = p_strdup_empty(pool, set->proxy_username);
-               client->set.proxy_password = p_strdup(pool, set->proxy_password);
-       } else if (set->proxy_url != NULL) {
-               client->set.proxy_username =
-                       p_strdup_empty(pool, set->proxy_url->user);
-               client->set.proxy_password =
-                       p_strdup(pool, set->proxy_url->password);
+               if (set->max_idle_time_msecs > 0)
+                       client->set.max_idle_time_msecs = set->max_idle_time_msecs;
+               if (set->max_parallel_connections > 0)
+                       client->set.max_parallel_connections = set->max_parallel_connections;
+               if (set->max_pipelined_requests > 0)
+                       client->set.max_pipelined_requests = set->max_pipelined_requests;
+               if (set->max_attempts > 0)
+                       client->set.max_attempts = set->max_attempts;
+               if (set->max_connect_attempts > 0)
+                       client->set.max_connect_attempts = set->max_connect_attempts;
+               if (set->connect_backoff_time_msecs > 0) {
+                       client->set.connect_backoff_time_msecs =
+                               set->connect_backoff_time_msecs;
+               }
+               if (set->connect_backoff_max_time_msecs > 0) {
+                       client->set.connect_backoff_max_time_msecs =
+                               set->connect_backoff_max_time_msecs;
+               }
+               client->set.no_auto_redirect =
+                       client->set.no_auto_redirect || set->no_auto_redirect;
+               client->set.no_auto_retry =
+                       client->set.no_auto_retry || set->no_auto_retry;
+               client->set.no_ssl_tunnel =
+                       client->set.no_ssl_tunnel || set->no_ssl_tunnel;
+               if (set->max_redirects > 0)
+                       client->set.max_redirects = set->max_redirects;
+               client->set.response_hdr_limits = set->response_hdr_limits;
+               if (set->request_absolute_timeout_msecs > 0) {
+                       client->set.request_absolute_timeout_msecs =
+                               set->request_absolute_timeout_msecs;
+               }
+               if (set->request_timeout_msecs > 0)
+                       client->set.request_timeout_msecs = set->request_timeout_msecs;
+               if (set->connect_timeout_msecs > 0)
+                       client->set.connect_timeout_msecs = set->connect_timeout_msecs;
+               if (set->soft_connect_timeout_msecs > 0)
+                       client->set.soft_connect_timeout_msecs = set->soft_connect_timeout_msecs;
+               if (set->max_auto_retry_delay > 0)
+                       client->set.max_auto_retry_delay = set->max_auto_retry_delay;
+               client->set.socket_send_buffer_size = set->socket_send_buffer_size;
+               client->set.socket_recv_buffer_size = set->socket_recv_buffer_size;
+               client->set.debug = client->set.debug || set->debug;
        }
 
-       client->set.max_idle_time_msecs = set->max_idle_time_msecs;
-       client->set.max_parallel_connections =
-               (set->max_parallel_connections > 0 ? set->max_parallel_connections : 1);
-       client->set.max_pipelined_requests =
-               (set->max_pipelined_requests > 0 ? set->max_pipelined_requests : 1);
-       client->set.max_attempts = set->max_attempts;
-       client->set.max_connect_attempts = set->max_connect_attempts;
-       client->set.connect_backoff_time_msecs =
-               set->connect_backoff_time_msecs == 0 ?
-                       HTTP_CLIENT_DEFAULT_BACKOFF_TIME_MSECS :
-                       set->connect_backoff_time_msecs;
-       client->set.connect_backoff_max_time_msecs =
-               set->connect_backoff_max_time_msecs == 0 ?
-                       HTTP_CLIENT_DEFAULT_BACKOFF_MAX_TIME_MSECS :
-                       set->connect_backoff_max_time_msecs;
-       client->set.no_auto_redirect = set->no_auto_redirect;
-       client->set.no_auto_retry = set->no_auto_retry;
-       client->set.no_ssl_tunnel = set->no_ssl_tunnel;
-       client->set.max_redirects = set->max_redirects;
-       client->set.response_hdr_limits = set->response_hdr_limits;
-       client->set.request_absolute_timeout_msecs =
-               set->request_absolute_timeout_msecs;
-       client->set.request_timeout_msecs =
-               set->request_timeout_msecs == 0 ?
-                       HTTP_CLIENT_DEFAULT_REQUEST_TIMEOUT_MSECS :
-                       set->request_timeout_msecs;
-       client->set.connect_timeout_msecs = set->connect_timeout_msecs;
-       client->set.soft_connect_timeout_msecs = set->soft_connect_timeout_msecs;
-       client->set.max_auto_retry_delay = set->max_auto_retry_delay;
-       client->set.socket_send_buffer_size = set->socket_send_buffer_size;
-       client->set.socket_recv_buffer_size = set->socket_recv_buffer_size;
-       client->set.debug = set->debug;
-
        i_array_init(&client->delayed_failing_requests, 1);
 
        client->conn_list = http_client_connection_list_init();
@@ -163,6 +197,12 @@ struct http_client *http_client_init(const struct http_client_settings *set)
        return client;
 }
 
+struct http_client *
+http_client_init(const struct http_client_settings *set)
+{
+       return http_client_init_shared(NULL, set);
+}
+
 void http_client_deinit(struct http_client **_client)
 {
        struct http_client *client = *_client;
@@ -202,6 +242,7 @@ void http_client_deinit(struct http_client **_client)
 
        if (client->ssl_ctx != NULL)
                ssl_iostream_context_unref(&client->ssl_ctx);
+       http_client_context_unref(&client->cctx);
        pool_unref(&client->pool);
 }
 
@@ -339,3 +380,98 @@ void http_client_remove_request_error(struct http_client *client,
                }
        }
 }
+
+/*
+ * Client shared context
+ */
+
+struct http_client_context *
+http_client_context_create(const struct http_client_settings *set)
+{
+       struct http_client_context *cctx;
+       pool_t pool;
+
+       pool = pool_alloconly_create("http client context", 1024);
+       cctx = p_new(pool, struct http_client_context, 1);
+       cctx->pool = pool;
+       cctx->refcount = 1;
+
+       cctx->set.dns_client = set->dns_client;
+       cctx->set.dns_client_socket_path =
+               p_strdup_empty(pool, set->dns_client_socket_path);
+       cctx->set.dns_ttl_msecs = (set->dns_ttl_msecs == 0 ?
+                       HTTP_CLIENT_DEFAULT_DNS_TTL_MSECS : set->dns_ttl_msecs);
+       cctx->set.user_agent = p_strdup_empty(pool, set->user_agent);
+       cctx->set.rawlog_dir = p_strdup_empty(pool, set->rawlog_dir);
+
+       if (set->ssl != NULL)
+               cctx->set.ssl = ssl_iostream_settings_dup(pool, set->ssl);
+
+       if (set->proxy_socket_path != NULL && *set->proxy_socket_path != '\0') {
+               cctx->set.proxy_socket_path = p_strdup(pool, set->proxy_socket_path);
+       } else if (set->proxy_url != NULL) {
+               cctx->set.proxy_url = http_url_clone(pool, set->proxy_url);
+       }
+       if (set->proxy_username != NULL && *set->proxy_username != '\0') {
+               cctx->set.proxy_username = p_strdup_empty(pool, set->proxy_username);
+               cctx->set.proxy_password = p_strdup(pool, set->proxy_password);
+       } else if (set->proxy_url != NULL) {
+               cctx->set.proxy_username =
+                       p_strdup_empty(pool, set->proxy_url->user);
+               cctx->set.proxy_password =
+                       p_strdup(pool, set->proxy_url->password);
+       }
+
+       cctx->set.max_idle_time_msecs = set->max_idle_time_msecs;
+       cctx->set.max_pipelined_requests =
+               (set->max_pipelined_requests > 0 ? set->max_pipelined_requests : 1);
+       cctx->set.max_parallel_connections =
+               (set->max_parallel_connections > 0 ? set->max_parallel_connections : 1);
+       cctx->set.max_attempts = set->max_attempts;
+       cctx->set.max_connect_attempts = set->max_connect_attempts;
+       cctx->set.connect_backoff_time_msecs =
+               set->connect_backoff_time_msecs == 0 ?
+                       HTTP_CLIENT_DEFAULT_BACKOFF_TIME_MSECS :
+                       set->connect_backoff_time_msecs;
+       cctx->set.connect_backoff_max_time_msecs =
+               set->connect_backoff_max_time_msecs == 0 ?
+                       HTTP_CLIENT_DEFAULT_BACKOFF_MAX_TIME_MSECS :
+                       set->connect_backoff_max_time_msecs;
+       cctx->set.no_auto_redirect = set->no_auto_redirect;
+       cctx->set.no_auto_retry = set->no_auto_retry;
+       cctx->set.no_ssl_tunnel = set->no_ssl_tunnel;
+       cctx->set.max_redirects = set->max_redirects;
+       cctx->set.response_hdr_limits = set->response_hdr_limits;
+       cctx->set.request_absolute_timeout_msecs =
+               set->request_absolute_timeout_msecs;
+       cctx->set.request_timeout_msecs =
+               set->request_timeout_msecs == 0 ?
+                       HTTP_CLIENT_DEFAULT_REQUEST_TIMEOUT_MSECS :
+                       set->request_timeout_msecs;
+       cctx->set.connect_timeout_msecs = set->connect_timeout_msecs;
+       cctx->set.soft_connect_timeout_msecs = set->soft_connect_timeout_msecs;
+       cctx->set.max_auto_retry_delay = set->max_auto_retry_delay;
+       cctx->set.socket_send_buffer_size = set->socket_send_buffer_size;
+       cctx->set.socket_recv_buffer_size = set->socket_recv_buffer_size;
+       cctx->set.debug = set->debug;
+
+       return cctx;
+}
+
+void http_client_context_ref(struct http_client_context *cctx)
+{
+       cctx->refcount++;
+}
+
+void http_client_context_unref(struct http_client_context **_cctx)
+{
+       struct http_client_context *cctx = *_cctx;
+
+       *_cctx = NULL;
+
+       i_assert(cctx->refcount > 0);
+       if (--cctx->refcount > 0)
+               return;
+
+       pool_unref(&cctx->pool);
+}
index c1a37602996cd1dbc37b8451499d26c9fed1edf1..93f1d95ff6bfe860a2a24337f5519d9f331f4d12 100644 (file)
@@ -8,8 +8,9 @@
 struct timeval;
 struct http_response;
 
-struct http_client;
 struct http_client_request;
+struct http_client;
+struct http_client_context;
 
 struct ssl_iostream_settings;
 
@@ -415,7 +416,11 @@ void http_client_request_start_tunnel(struct http_client_request *req,
  * Client
  */
 
-struct http_client *http_client_init(const struct http_client_settings *set);
+struct http_client *
+http_client_init(const struct http_client_settings *set);
+struct http_client *
+http_client_init_shared(struct http_client_context *cctx,
+       const struct http_client_settings *set) ATTR_NULL(1);
 void http_client_deinit(struct http_client **_client);
 
 /* switch this client to the current ioloop */
@@ -428,4 +433,13 @@ void http_client_wait(struct http_client *client);
 unsigned int
 http_client_get_pending_request_count(struct http_client *client);
 
+/*
+ * Client shared context
+ */
+
+struct http_client_context *
+http_client_context_create(const struct http_client_settings *set);
+void http_client_context_ref(struct http_client_context *cctx);
+void http_client_context_unref(struct http_client_context **_cctx);
+
 #endif