From: Timo Sirainen Date: Thu, 16 Aug 2012 03:09:22 +0000 (+0300) Subject: connection API: Fixed connected() callback to actually allow detecting failed connects. X-Git-Tag: 2.2.alpha1~320 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7db7fbea5d8a07463b625f93d69166d56018dadf;p=thirdparty%2Fdovecot%2Fcore.git connection API: Fixed connected() callback to actually allow detecting failed connects. --- diff --git a/src/lib-dict/dict-memcached-ascii.c b/src/lib-dict/dict-memcached-ascii.c index fce96ee82f..b73286f3b4 100644 --- a/src/lib-dict/dict-memcached-ascii.c +++ b/src/lib-dict/dict-memcached-ascii.c @@ -285,11 +285,12 @@ static int memcached_ascii_wait(struct memcached_ascii_dict *dict) return 0; } -static void memcached_ascii_conn_connected(struct connection *_conn) +static void +memcached_ascii_conn_connected(struct connection *_conn, bool success) { struct memcached_ascii_connection *conn = (struct memcached_ascii_connection *)_conn; - if ((errno = net_geterror(_conn->fd_in)) != 0) { + if (!success) { i_error("memcached_ascii: connect(%s, %u) failed: %m", net_ip2addr(&conn->dict->ip), conn->dict->port); } @@ -306,7 +307,7 @@ static const struct connection_settings memcached_ascii_conn_set = { static const struct connection_vfuncs memcached_ascii_conn_vfuncs = { .destroy = memcached_ascii_conn_destroy, .input = memcached_ascii_conn_input, - .connected = memcached_ascii_conn_connected + .client_connected = memcached_ascii_conn_connected }; static const char *memcached_ascii_escape_username(const char *username) diff --git a/src/lib-dict/dict-memcached.c b/src/lib-dict/dict-memcached.c index 74dec6bc71..1cc6ee2608 100644 --- a/src/lib-dict/dict-memcached.c +++ b/src/lib-dict/dict-memcached.c @@ -140,11 +140,12 @@ static void memcached_conn_input(struct connection *_conn) memcached_conn_destroy(_conn); } -static void memcached_conn_connected(struct connection *_conn) +static void memcached_conn_connected(struct connection *_conn, bool success) { - struct memcached_connection *conn = (struct memcached_connection *)_conn; + struct memcached_connection *conn = + (struct memcached_connection *)_conn; - if ((errno = net_geterror(_conn->fd_in)) != 0) { + if (!success) { i_error("memcached: connect(%s, %u) failed: %m", net_ip2addr(&conn->dict->ip), conn->dict->port); } else { @@ -163,7 +164,7 @@ static const struct connection_settings memcached_conn_set = { static const struct connection_vfuncs memcached_conn_vfuncs = { .destroy = memcached_conn_destroy, .input = memcached_conn_input, - .connected = memcached_conn_connected + .client_connected = memcached_conn_connected }; static struct dict * diff --git a/src/lib-dict/dict-redis.c b/src/lib-dict/dict-redis.c index d7733f6a44..d93de080d2 100644 --- a/src/lib-dict/dict-redis.c +++ b/src/lib-dict/dict-redis.c @@ -255,11 +255,11 @@ static void redis_conn_input(struct connection *_conn) redis_conn_destroy(_conn); } -static void redis_conn_connected(struct connection *_conn) +static void redis_conn_connected(struct connection *_conn, bool success) { struct redis_connection *conn = (struct redis_connection *)_conn; - if ((errno = net_geterror(_conn->fd_in)) != 0) { + if (!success) { i_error("redis: connect(%s, %u) failed: %m", net_ip2addr(&conn->dict->ip), conn->dict->port); } else { @@ -278,7 +278,7 @@ static const struct connection_settings redis_conn_set = { static const struct connection_vfuncs redis_conn_vfuncs = { .destroy = redis_conn_destroy, .input = redis_conn_input, - .connected = redis_conn_connected + .client_connected = redis_conn_connected }; static const char *redis_escape_username(const char *username) diff --git a/src/lib/connection.c b/src/lib/connection.c index 5cc8c39064..a55753e9d5 100644 --- a/src/lib/connection.c +++ b/src/lib/connection.c @@ -132,8 +132,21 @@ static void connection_init_streams(struct connection *conn) "VERSION\t%s\t%u\t%u\n", set->service_name_out, set->major_version, set->minor_version)); } - if (conn->list->v.connected != NULL) - conn->list->v.connected(conn); +} + +static void connection_client_connected(struct connection *conn, bool success) +{ + i_assert(conn->list->set.client); + + if (success) + connection_init_streams(conn); + if (conn->list->v.client_connected != NULL) + conn->list->v.client_connected(conn, success); + if (!success) { + conn->disconnect_reason = + CONNECTION_DISCONNECT_CONN_CLOSED; + conn->list->v.destroy(conn); + } } void connection_init_server(struct connection_list *list, @@ -180,13 +193,14 @@ void connection_init_client_unix(struct connection_list *list, DLLIST_PREPEND(&list->connections, conn); } -static void connection_connected(struct connection *conn) +static void connection_ip_connected(struct connection *conn) { io_remove(&conn->io); if (conn->to != NULL) timeout_remove(&conn->to); - connection_init_streams(conn); + errno = net_geterror(conn->fd_in); + connection_client_connected(conn, errno == 0); } int connection_client_connect(struct connection *conn) @@ -207,13 +221,13 @@ int connection_client_connect(struct connection *conn) if (conn->port != 0) { conn->io = io_add(conn->fd_out, IO_WRITE, - connection_connected, conn); + connection_ip_connected, conn); if (set->client_connect_timeout_msecs != 0) { conn->to = timeout_add(set->client_connect_timeout_msecs, connection_connect_timeout, conn); } } else { - connection_init_streams(conn); + connection_client_connected(conn, TRUE); } return 0; } diff --git a/src/lib/connection.h b/src/lib/connection.h index a495d0ffed..d3361807c3 100644 --- a/src/lib/connection.h +++ b/src/lib/connection.h @@ -27,7 +27,13 @@ enum connection_disconnect_reason { struct connection_vfuncs { void (*destroy)(struct connection *conn); - void (*connected)(struct connection *conn); + /* For UNIX socket clients this gets called immediately with + success=TRUE, for IP connections it gets called later: + + If connect() fails, sets success=FALSE and errno. Streams aren't + initialized in that situation either. destroy() is called after + the callback. */ + void (*client_connected)(struct connection *conn, bool success); /* implement one of the input*() methods. They return 0 = ok, -1 = error, disconnect the client */