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);
}
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)
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 {
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 *
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 {
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)
"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,
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)
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;
}
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 */