http-client.c revision eb325a5a90c1d2655e74972bde0de6a699d2c864
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch/* FIXME: This implementation not yet finished. The essence works: it is
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch possible to submit requests through the client. Responses are dumped to
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch Structure so far:
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch Client - Acts much like a browser; it is not dedicated to a single host.
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch Client can accept requests to different hosts, which can be served
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch at different IPs. Redirects can be handled in the background by
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch making a new connection. Connections to new hosts are created once
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch needed for servicing a request.
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch Requests - Semantics are similar to imapc commands. Create a request,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch optionally modify some aspects of it and finally submit it.
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch Hosts - We maintain a 'cache' of hosts for which we have looked up IPs.
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch Requests are first queued in the host struct on a per-port basis.
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch Peers - Group connections to the same ip/port (== peer_addr).
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch Connections - Actual connections to a server. Once a connection is ready to
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch handle requests, it claims a request from a host object. One
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch connection hand service multiple hosts and one host can have
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch multiple associated connections, possibly to different ips and
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch TODO: lots of cleanup, authentication, ssl, timeouts, rawlog etc.
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic inline void
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic inline void
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch const char *format, ...)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch i_debug("http-client: %s", t_strdup_vprintf(format, args));
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstruct http_client *http_client_init(const struct http_client_settings *set)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch pool = pool_alloconly_create("http client", 1024);
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch if (set->dns_client_socket_path != NULL && *set->dns_client_socket_path != '\0') {
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch if (set->rawlog_dir != NULL && *set->rawlog_dir != '\0')
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch client->set.rawlog_dir = p_strdup(pool, set->rawlog_dir);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch client->set.ssl_ca_dir = p_strdup(pool, set->ssl_ca_dir);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch client->set.max_idle_time_msecs = set->max_idle_time_msecs;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch (set->max_parallel_connections > 0 ? set->max_parallel_connections : 1);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch (set->max_pipelined_requests > 0 ? set->max_pipelined_requests : 1);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch client->set.max_redirects = set->max_redirects;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch client->conn_list = http_client_connection_list_init();
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch hash_table_create(&client->hosts, default_pool, 0, str_hash, strcmp);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch hash_table_create(&client->peers, default_pool, 0,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch http_client_peer_addr_hash, http_client_peer_addr_cmp);
7384b4e78eaab44693c985192276e31322155e32Stephan Boschvoid http_client_deinit(struct http_client **_client)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch /* free peers */
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch iter = hash_table_iterate_init(client->peers);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch while (hash_table_iterate(iter, client->peers, &addr, &peer)) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch /* free hosts */
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch iter = hash_table_iterate_init(client->hosts);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch while (hash_table_iterate(iter, client->hosts, &hostname, &host)) {
7384b4e78eaab44693c985192276e31322155e32Stephan Boschvoid http_client_switch_ioloop(struct http_client *client)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct connection *_conn = client->conn_list->connections;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch /* move connections */
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch /* FIXME: we wouldn't necessarily need to switch all of them
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch immediately, only those that have requests now. but also connections
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch that get new requests before ioloop is switched again.. */
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch /* move dns lookups */
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (client->set.dns_client_socket_path != '\0') {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch iter = hash_table_iterate_init(client->hosts);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch while (hash_table_iterate(iter, client->hosts, &hostname, &host)) {
7384b4e78eaab44693c985192276e31322155e32Stephan Boschvoid http_client_wait(struct http_client *client)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch "Waiting for %d requests to finish", client->pending_requests);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch http_client_debug(client, "All requests finished");