Skip to content

Commit

Permalink
imapc: Support retrying after connect() failure.
Browse files Browse the repository at this point in the history
  • Loading branch information
sirainen authored and GitLab committed Apr 12, 2016
1 parent 1e85b60 commit e4020d1
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 12 deletions.
33 changes: 21 additions & 12 deletions src/lib-imap-client/imapc-connection.c
Expand Up @@ -372,6 +372,11 @@ imapc_connection_literal_reset(struct imapc_connection_literal *literal)
static void imapc_connection_disconnect_full(struct imapc_connection *conn,
bool reconnecting)
{
/* timeout may be set also in disconnected state */
if (conn->to != NULL)
timeout_remove(&conn->to);
conn->reconnecting = reconnecting;

if (conn->state == IMAPC_CONNECTION_STATE_DISCONNECTED)
return;

Expand All @@ -382,8 +387,6 @@ static void imapc_connection_disconnect_full(struct imapc_connection *conn,
dns_lookup_abort(&conn->dns_lookup);
imapc_connection_lfiles_free(conn);
imapc_connection_literal_reset(&conn->literal);
if (conn->to != NULL)
timeout_remove(&conn->to);
if (conn->to_output != NULL)
timeout_remove(&conn->to_output);
if (conn->to_throttle != NULL)
Expand Down Expand Up @@ -445,15 +448,21 @@ static void imapc_connection_reconnect(struct imapc_connection *conn)
}
}

static void imapc_connection_try_reconnect(struct imapc_connection *conn,
const char *errstr)
static void
imapc_connection_try_reconnect(struct imapc_connection *conn,
const char *errstr, unsigned int delay_msecs)
{
if (!imapc_connection_can_reconnect(conn)) {
i_error("imapc(%s): %s - disconnecting", conn->name, errstr);
imapc_connection_disconnect(conn);
} else {
i_warning("imapc(%s): %s - reconnecting", conn->name, errstr);
imapc_connection_reconnect(conn);
if (delay_msecs == 0)
imapc_connection_reconnect(conn);
else {
imapc_connection_disconnect_full(conn, TRUE);
conn->to = timeout_add(delay_msecs, imapc_connection_reconnect, conn);
}
}
}

Expand Down Expand Up @@ -1448,7 +1457,7 @@ static void imapc_connection_input(struct imapc_connection *conn)
str_printfa(str, "Server disconnected unexpectedly: %s",
errstr);
}
imapc_connection_try_reconnect(conn, str_c(str));
imapc_connection_try_reconnect(conn, str_c(str), 0);
}
imapc_connection_unref(&conn);
}
Expand Down Expand Up @@ -1541,10 +1550,10 @@ static void imapc_connection_connected(struct imapc_connection *conn)

err = net_geterror(conn->fd);
if (err != 0) {
i_error("imapc(%s): connect(%s, %u) failed: %s",
conn->name, net_ip2addr(ip), conn->client->set.port,
strerror(err));
imapc_connection_disconnect(conn);
imapc_connection_try_reconnect(conn, t_strdup_printf(
"connect(%s, %u) failed: %s",
net_ip2addr(ip), conn->client->set.port,
strerror(err)), IMAPC_CONNECT_RETRY_WAIT_MSECS);
return;
}
io_remove(&conn->io);
Expand Down Expand Up @@ -1574,7 +1583,7 @@ static void imapc_connection_timeout(struct imapc_connection *conn)
default:
i_unreached();
}
imapc_connection_try_reconnect(conn, errstr);
imapc_connection_try_reconnect(conn, errstr, 0);
}

static void
Expand Down Expand Up @@ -1816,7 +1825,7 @@ static void imapc_command_timeout(struct imapc_connection *conn)
i_assert(count > 0);

imapc_connection_try_reconnect(conn, t_strdup_printf(
"Command '%s' timed out", imapc_command_get_readable(cmds[0])));
"Command '%s' timed out", imapc_command_get_readable(cmds[0])), 0);
}

static bool
Expand Down
3 changes: 3 additions & 0 deletions src/lib-imap-client/imapc-connection.h
Expand Up @@ -8,6 +8,9 @@
#define IMAPC_THROTTLE_DEFAULT_MAX_MSECS (16*1000)
#define IMAPC_THROTTLE_DEFAULT_SHRINK_MIN_MSECS 500

/* If connect() fails, how long should we wait before reconnection */
#define IMAPC_CONNECT_RETRY_WAIT_MSECS 1000

struct imapc_client;
struct imapc_connection;

Expand Down

0 comments on commit e4020d1

Please sign in to comment.