dovecot-2.2: lib-http: Added initial HTTP client implementation.
dovecot at dovecot.org
dovecot at dovecot.org
Sat Nov 24 00:33:06 EET 2012
details: http://hg.dovecot.org/dovecot-2.2/rev/107c8b2c9594
changeset: 15394:107c8b2c9594
user: Stephan Bosch <stephan at rename-it.nl>
date: Sat Nov 24 00:30:14 2012 +0200
description:
lib-http: Added initial HTTP client implementation.
diffstat:
src/lib-http/Makefile.am | 92 +++-
src/lib-http/http-client-connection.c | 788 +++++++++++++++++++++++++++++++
src/lib-http/http-client-host.c | 388 +++++++++++++++
src/lib-http/http-client-peer.c | 358 ++++++++++++++
src/lib-http/http-client-private.h | 250 +++++++++
src/lib-http/http-client-request.c | 386 +++++++++++++++
src/lib-http/http-client.c | 182 +++++++
src/lib-http/http-client.h | 83 +++
src/lib-http/http-header-parser.c | 282 +++++++++++
src/lib-http/http-header-parser.h | 15 +
src/lib-http/http-parser.c | 132 +++++
src/lib-http/http-parser.h | 53 ++
src/lib-http/http-response-parser.c | 503 +++++++++++++++++++
src/lib-http/http-response-parser.h | 37 +
src/lib-http/http-transfer-chunked.c | 479 ++++++++++++++++++
src/lib-http/http-transfer.h | 8 +
src/lib-http/test-http-client.c | 226 ++++++++
src/lib-http/test-http-header-parser.c | 18 +-
src/lib-http/test-http-response-parser.c | 206 ++++++++
src/lib-http/test-http-responses.c | 39 +
src/lib-http/test-http-transfer.c | 126 ++++
21 files changed, 4640 insertions(+), 11 deletions(-)
diffs (truncated from 4806 to 300 lines):
diff -r b40bda50541c -r 107c8b2c9594 src/lib-http/Makefile.am
--- a/src/lib-http/Makefile.am Fri Nov 23 23:49:39 2012 +0200
+++ b/src/lib-http/Makefile.am Sat Nov 24 00:30:14 2012 +0200
@@ -8,26 +8,51 @@
libhttp_la_SOURCES = \
http-date.c \
- http-url.c
+ http-url.c \
+ http-parser.c \
+ http-header-parser.c \
+ http-transfer-chunked.c \
+ http-response-parser.c \
+ http-client-request.c \
+ http-client-connection.c \
+ http-client-peer.c \
+ http-client-host.c \
+ http-client.c
headers = \
http-date.h \
- http-url.h
+ http-url.h \
+ http-parser.h \
+ http-header-parser.h \
+ http-transfer.h \
+ http-response-parser.h \
+ http-client-private.h \
+ http-client.h
pkginc_libdir=$(pkgincludedir)
pkginc_lib_HEADERS = $(headers)
test_programs = \
test-http-date \
- test-http-url
+ test-http-url \
+ test-http-header-parser \
+ test-http-transfer \
+ test-http-response-parser \
+ test-http-client
-noinst_PROGRAMS = $(test_programs)
+noinst_PROGRAMS = $(test_programs) test-http-responses
test_libs = \
../lib-test/libtest.la \
- ../lib/liblib.la
+ ../lib/liblib.la \
+ ../lib/safe-memset.lo \
+ $(MODULE_LIBS)
-test_deps = $(noinst_LTLIBRARIES) $(test_libs)
+test_deps = \
+ $(noinst_LTLIBRARIES)
+ ../lib-test/libtest.la \
+ ../lib/liblib.la \
+ ../lib/safe-memset.lo
test_http_url_SOURCES = test-http-url.c
test_http_url_LDADD = http-url.lo $(test_libs)
@@ -37,6 +62,61 @@
test_http_date_LDADD = http-date.lo $(test_libs)
test_http_date_DEPENDENCIES = $(test_deps)
+test_http_header_parser_SOURCES = test-http-header-parser.c
+test_http_header_parser_LDADD = http-parser.lo http-header-parser.lo $(test_libs)
+test_http_header_parser_DEPENDENCIES = $(test_deps)
+
+test_http_transfer_SOURCES = test-http-transfer.c
+test_http_transfer_LDADD = \
+ http-parser.lo \
+ http-header-parser.lo \
+ http-transfer-chunked.lo \
+ $(test_libs)
+test_http_transfer_DEPENDENCIES = $(test_deps)
+
+test_http_response_parser_SOURCES = test-http-response-parser.c
+test_http_response_parser_LDADD = \
+ http-date.lo \
+ http-parser.lo \
+ http-header-parser.lo \
+ http-transfer-chunked.lo \
+ http-response-parser.lo \
+ $(test_libs)
+test_http_response_parser_DEPENDENCIES = $(test_deps)
+
+test_http_client_SOURCES = test-http-client.c
+test_http_client_LDFLAGS = -export-dynamic
+test_http_client_LDADD = \
+ libhttp.la \
+ ../lib-dns/libdns.la \
+ ../lib-ssl-iostream/libssl_iostream.la \
+ $(test_libs)
+test_http_client_DEPENDENCIES = \
+ libhttp.la \
+ ../lib-dns/libdns.la \
+ ../lib-ssl-iostream/libssl_iostream.la \
+ $(test_deps)
+
+test_http_responses_SOURCES = test-http-responses.c
+test_http_responses_LDADD = \
+ http-date.lo \
+ http-parser.lo \
+ http-header-parser.lo \
+ http-transfer-chunked.lo \
+ http-response-parser.lo \
+ ../lib/liblib.la \
+ ../lib/safe-memset.lo \
+ $(MODULE_LIBS)
+test_http_responses_DEPENDENCIES = \
+ http-date.lo \
+ http-parser.lo \
+ http-header-parser.lo \
+ http-transfer-chunked.lo \
+ http-response-parser.lo \
+ $(noinst_LTLIBRARIES) \
+ ../lib/liblib.la \
+ ../lib/safe-memset.lo
+
check: check-am check-test
check-test: all-am
for bin in $(test_programs); do \
diff -r b40bda50541c -r 107c8b2c9594 src/lib-http/http-client-connection.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-http/http-client-connection.c Sat Nov 24 00:30:14 2012 +0200
@@ -0,0 +1,788 @@
+/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "net.h"
+#include "str.h"
+#include "hash.h"
+#include "array.h"
+#include "ioloop.h"
+#include "istream.h"
+#include "ostream.h"
+#include "iostream-rawlog.h"
+#include "iostream-ssl.h"
+#include "http-response-parser.h"
+
+#include "http-client-private.h"
+
+/*
+ * Logging
+ */
+
+static inline void
+http_client_connection_debug(struct http_client_connection *conn,
+ const char *format, ...) ATTR_FORMAT(2, 3);
+static inline void
+http_client_connection_error(struct http_client_connection *conn,
+ const char *format, ...) ATTR_FORMAT(2, 3);
+
+static inline void
+http_client_connection_debug(struct http_client_connection *conn,
+ const char *format, ...)
+{
+ va_list args;
+
+ if (conn->client->set.debug) {
+
+ va_start(args, format);
+ i_debug("http-client: conn %s: %s",
+ http_client_connection_label(conn), t_strdup_vprintf(format, args));
+ va_end(args);
+ }
+}
+
+static inline void
+http_client_connection_error(struct http_client_connection *conn,
+ const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ i_error("http-client: conn %s: %s",
+ http_client_connection_label(conn), t_strdup_vprintf(format, args));
+ va_end(args);
+}
+
+
+/*
+ * Connection
+ */
+
+static void http_client_connection_input(struct connection *_conn);
+
+bool http_client_connection_is_ready(struct http_client_connection *conn)
+{
+ return (conn->connected && !conn->output_locked &&
+ array_count(&conn->request_wait_list) <
+ conn->client->set.max_pipelined_requests);
+}
+
+static void
+http_client_connection_retry_requests(struct http_client_connection *conn,
+ unsigned int status, const char *error)
+{
+ struct http_client_request **req;
+
+ array_foreach_modifiable(&conn->request_wait_list, req) {
+ http_client_request_retry(*req, status, error);
+ }
+ array_clear(&conn->request_wait_list);
+}
+
+static void
+http_client_connection_server_close(struct http_client_connection **_conn)
+{
+ struct http_client_connection *conn = *_conn;
+ struct http_client_request **req;
+
+ conn->connected = FALSE;
+ conn->closing = TRUE;
+
+ http_client_connection_debug(conn,
+ "Server explicitly closed connection");
+
+ array_foreach_modifiable(&conn->request_wait_list, req) {
+ http_client_request_resubmit(*req);
+ }
+ array_clear(&conn->request_wait_list);
+
+ if (conn->client->ioloop != NULL)
+ io_loop_stop(conn->client->ioloop);
+
+ http_client_connection_free(_conn);
+}
+
+static void
+http_client_connection_abort_temp_error(struct http_client_connection **_conn,
+ unsigned int status, const char *error)
+{
+ struct http_client_connection *conn = *_conn;
+
+ conn->connected = FALSE;
+ conn->closing = TRUE;
+
+ http_client_connection_retry_requests(conn, status, error);
+ http_client_connection_free(_conn);
+}
+
+static void
+http_client_connection_abort_error(struct http_client_connection **_conn,
+ unsigned int status, const char *error)
+{
+ struct http_client_connection *conn = *_conn;
+ struct http_client_request **req;
+
+ conn->connected = FALSE;
+ conn->closing = TRUE;
+
+ array_foreach_modifiable(&conn->request_wait_list, req) {
+ http_client_request_error(*req, status, error);
+ }
+ array_clear(&conn->request_wait_list);
+ http_client_connection_free(_conn);
+}
+
+static void
+http_client_connection_idle_timeout(struct http_client_connection *conn)
+{
+ http_client_connection_debug(conn, "Idle connection timed out");
+
+ http_client_connection_free(&conn);
+}
+
+static void
+http_client_connection_check_idle(struct http_client_connection *conn)
+{
+ unsigned int timeout, count;
+
+ if (array_count(&conn->request_wait_list) == 0 &&
+ conn->incoming_payload == NULL &&
+ conn->client->set.max_idle_time_msecs > 0) {
+
+ if (conn->to_idle != NULL) {
+ /* timeout already set */
+ return;
+ }
+
+ http_client_connection_debug(conn,
+ "No more requests queued; going idle");
+
+ if (conn->client->ioloop != NULL)
+ io_loop_stop(conn->client->ioloop);
+
+ count = array_count(&conn->peer->conns);
+ i_assert(count > 0);
+
+ /* set timeout for this connection */
+ if (count > conn->client->set.max_parallel_connections) {
+ /* instant death for (urgent) connections above limit */
+ timeout = 0;
+ } else {
+ /* kill duplicate connections quicker;
+ linearly based on the number of connections */
+ timeout = (conn->client->set.max_parallel_connections - count) *
+ (conn->client->set.max_idle_time_msecs /
More information about the dovecot-cvs
mailing list