]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
connection API: Fixed connected() callback to actually allow detecting failed connects.
authorTimo Sirainen <tss@iki.fi>
Thu, 16 Aug 2012 03:09:22 +0000 (06:09 +0300)
committerTimo Sirainen <tss@iki.fi>
Thu, 16 Aug 2012 03:09:22 +0000 (06:09 +0300)
src/lib-dict/dict-memcached-ascii.c
src/lib-dict/dict-memcached.c
src/lib-dict/dict-redis.c
src/lib/connection.c
src/lib/connection.h

index fce96ee82f9f7971c774f309f3d8b5be74d94216..b73286f3b49a16f406167913187adc2cf3d3ecef 100644 (file)
@@ -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)
index 74dec6bc71729e89ede839a83c1d457d4a04562b..1cc6ee2608c46e8d5c52b997177d69536414e58d 100644 (file)
@@ -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 *
index d7733f6a44c68659092161475dcc45de7d62ca9f..d93de080d249a26edf58cc120cf75e432a5ebdf3 100644 (file)
@@ -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)
index 5cc8c39064394ecb213fbfb4e606267bfdcf178b..a55753e9d54b426dde0c889e635e2e2dd8b1de70 100644 (file)
@@ -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;
 }
index a495d0ffed0787cd76d63a0261d1ae84f122d136..d3361807c3831e9cdeb7ef93f13fc6188ebd98ed 100644 (file)
@@ -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 */