http-client.c revision 56d1345c43bbd28c36b7faa85e4163bd9e874290
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
a0f8619bc2bbe3614578c21b5b50a88d2841e7aavboxsync/* FIXME: This implementation not yet finished. The essence works: it is
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync possible to submit requests through the client. Responses are dumped to
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync Structure so far:
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync Client - Acts much like a browser; it is not dedicated to a single host.
0c437bb10c61b229407a7517efde04dfe3b1e4a1vboxsync Client can accept requests to different hosts, which can be served
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync at different IPs. Redirects can be handled in the background by
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync making a new connection. Connections to new hosts are created once
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync needed for servicing a request.
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync Requests - Semantics are similar to imapc commands. Create a request,
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync optionally modify some aspects of it and finally submit it.
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync Hosts - We maintain a 'cache' of hosts for which we have looked up IPs.
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync Requests are first queued in the host struct on a per-port basis.
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync Peers - Group connections to the same ip/port (== peer_addr).
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync Connections - Actual connections to a server. Once a connection is ready to
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync handle requests, it claims a request from a host object. One
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync connection hand service multiple hosts and one host can have
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync multiple associated connections, possibly to different ips and
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync TODO: lots of cleanup, authentication, ssl, timeouts, rawlog etc.
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsyncstatic inline void
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsyncstatic inline void
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync const char *format, ...)
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync i_debug("http-client: %s", t_strdup_vprintf(format, args));
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsyncstruct http_client *http_client_init(const struct http_client_settings *set)
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync if (set->dns_client_socket_path != NULL && *set->dns_client_socket_path != '\0') {
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync if (set->rawlog_dir != NULL && *set->rawlog_dir != '\0')
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync client->set.rawlog_dir = p_strdup(pool, set->rawlog_dir);
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync client->set.ssl_ca_dir = p_strdup(pool, set->ssl_ca_dir);
a0f8619bc2bbe3614578c21b5b50a88d2841e7aavboxsync client->set.ssl_ca_file = p_strdup(pool, set->ssl_ca_file);
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync client->set.ssl_crypto_device = p_strdup(pool, set->ssl_crypto_device);
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync client->set.ssl_allow_invalid_cert = set->ssl_allow_invalid_cert;
cfb87b49d2b36055eb5aea681936cdc130b54267vboxsync client->set.max_idle_time_msecs = set->max_idle_time_msecs;
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync (set->max_parallel_connections > 0 ? set->max_parallel_connections : 1);
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync (set->max_pipelined_requests > 0 ? set->max_pipelined_requests : 1);
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync client->conn_list = http_client_connection_list_init();
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync hash_table_create(&client->hosts, default_pool, 0, str_hash, strcmp);
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync http_client_peer_addr_hash, http_client_peer_addr_cmp);
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsyncvoid http_client_deinit(struct http_client **_client)
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync /* free peers */
b4fc07ae3f394595370fc5ed6ab1c353a87259dbvboxsync /* free hosts */
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsyncvoid http_client_switch_ioloop(struct http_client *client)
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync struct connection *_conn = client->conn_list->connections;
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync /* move connections */
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync /* FIXME: we wouldn't necessarily need to switch all of them
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync immediately, only those that have requests now. but also connections
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync that get new requests before ioloop is switched again.. */
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync /* move dns lookups and delayed requests */
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync for (host = client->hosts_list; host != NULL; host = host->next)
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync /* either we're waiting for network I/O or we're getting out of a
a0f8619bc2bbe3614578c21b5b50a88d2841e7aavboxsync callback using timeout_add_short(0) */
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync "Waiting for %d requests to finish", client->pending_requests);
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync http_client_debug(client, "All requests finished");
a0f8619bc2bbe3614578c21b5b50a88d2841e7aavboxsyncint http_client_init_ssl_ctx(struct http_client *client, const char **error_r)
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync const char *error;
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync ssl_set.crypto_device = client->set.ssl_crypto_device;
a0f8619bc2bbe3614578c21b5b50a88d2841e7aavboxsync if (ssl_iostream_context_init_client(&ssl_set, &client->ssl_ctx, &error) < 0) {
632b4638bd18092c6b8edb4e1028c9be112f5076vboxsync *error_r = t_strdup_printf("Couldn't initialize SSL context: %s",