dovecot: Use separate per-client timeouts instead of going throu...
dovecot at dovecot.org
dovecot at dovecot.org
Thu Jan 3 23:47:11 EET 2008
details: http://hg.dovecot.org/dovecot/rev/3f5b7bebfd82
changeset: 7099:3f5b7bebfd82
user: Timo Sirainen <tss at iki.fi>
date: Thu Jan 03 23:46:04 2008 +0200
description:
Use separate per-client timeouts instead of going through all clients in one
timeout.
diffstat:
5 files changed, 106 insertions(+), 126 deletions(-)
src/imap-login/client-authenticate.c | 65 ++++++++++----------
src/imap-login/client.c | 110 ++++++++++++++++------------------
src/imap-login/client.h | 5 -
src/pop3-login/client.c | 50 ++++-----------
src/pop3-login/client.h | 2
diffs (truncated from 478 to 300 lines):
diff -r becdf2eacdce -r 3f5b7bebfd82 src/imap-login/client-authenticate.c
--- a/src/imap-login/client-authenticate.c Thu Jan 03 23:19:33 2008 +0200
+++ b/src/imap-login/client-authenticate.c Thu Jan 03 23:46:04 2008 +0200
@@ -18,6 +18,8 @@
#include <stdlib.h>
#define IMAP_SERVICE_NAME "imap"
+
+static void client_auth_failed(struct imap_client *client);
const char *client_authenticate_get_capabilities(bool secured)
{
@@ -211,13 +213,8 @@ static void sasl_callback(struct client
NULL);
client_send_tagline(client, msg);
- if (!client->destroyed) {
- /* get back to normal client input. */
- if (client->io != NULL)
- io_remove(&client->io);
- client->io = io_add(client->common.fd, IO_READ,
- client_input, client);
- }
+ if (!client->destroyed)
+ client_auth_failed(client);
break;
case SASL_SERVER_REPLY_MASTER_FAILED:
if (data == NULL)
@@ -251,6 +248,33 @@ static void sasl_callback(struct client
client_unref(client);
}
+static int client_auth_begin(struct imap_client *client, const char *mech_name,
+ const char *init_resp)
+{
+ client_ref(client);
+ sasl_server_auth_begin(&client->common, IMAP_SERVICE_NAME, mech_name,
+ init_resp, sasl_callback);
+ if (!client->common.authenticating)
+ return 1;
+
+ /* don't handle input until we get the initial auth reply */
+ if (client->io != NULL)
+ io_remove(&client->io);
+ client_set_auth_waiting(client);
+ return 0;
+}
+
+static void client_auth_failed(struct imap_client *client)
+{
+ /* get back to normal client input. */
+ if (client->io != NULL)
+ io_remove(&client->io);
+ client->io = io_add(client->common.fd, IO_READ,
+ client_input, client);
+
+ timeout_remove(&client->to_auth_waiting);
+}
+
int cmd_authenticate(struct imap_client *client, const struct imap_arg *args)
{
const char *mech_name, *init_resp = NULL;
@@ -269,17 +293,7 @@ int cmd_authenticate(struct imap_client
mech_name = IMAP_ARG_STR(&args[0]);
if (*mech_name == '\0')
return -1;
-
- client_ref(client);
- sasl_server_auth_begin(&client->common, IMAP_SERVICE_NAME, mech_name,
- init_resp, sasl_callback);
- if (!client->common.authenticating)
- return 1;
-
- /* don't handle input until we get the initial auth reply */
- if (client->io != NULL)
- io_remove(&client->io);
- return 0;
+ return client_auth_begin(client, mech_name, init_resp);
}
int cmd_login(struct imap_client *client, const struct imap_arg *args)
@@ -322,16 +336,5 @@ int cmd_login(struct imap_client *client
base64 = buffer_create_dynamic(pool_datastack_create(),
MAX_BASE64_ENCODED_SIZE(plain_login->used));
base64_encode(plain_login->data, plain_login->used, base64);
-
- client_ref(client);
- sasl_server_auth_begin(&client->common, IMAP_SERVICE_NAME, "PLAIN",
- str_c(base64), sasl_callback);
- if (!client->common.authenticating)
- return 1;
-
- /* don't read any input from client until login is finished */
- if (client->io != NULL)
- io_remove(&client->io);
-
- return 0;
-}
+ return client_auth_begin(client, "PLAIN", str_c(base64));
+}
diff -r becdf2eacdce -r 3f5b7bebfd82 src/imap-login/client.c
--- a/src/imap-login/client.c Thu Jan 03 23:19:33 2008 +0200
+++ b/src/imap-login/client.c Thu Jan 03 23:46:04 2008 +0200
@@ -28,8 +28,8 @@
/* maximum length for IMAP command line. */
#define MAX_IMAP_LINE 8192
-/* Disconnect client after idling this many seconds */
-#define CLIENT_LOGIN_IDLE_TIMEOUT (3*60)
+/* Disconnect client after idling this many milliseconds */
+#define CLIENT_LOGIN_IDLE_TIMEOUT_MSECS (3*60*1000)
/* Disconnect client when it sends too many bad commands */
#define CLIENT_MAX_BAD_COMMANDS 10
@@ -39,21 +39,21 @@
client hash, it's faster if we disconnect multiple clients. */
#define CLIENT_DESTROY_OLDEST_COUNT 16
-/* If we've been waiting auth server to respond for over this many seconds,
+/* If we've been waiting auth server to respond for over this many milliseconds,
send a "waiting" message. */
-#define AUTH_WAITING_TIMEOUT 30
-
-#if CLIENT_LOGIN_IDLE_TIMEOUT >= AUTH_REQUEST_TIMEOUT
+#define AUTH_WAITING_TIMEOUT_MSECS 30
+
+#if CLIENT_LOGIN_IDLE_TIMEOUT_MSECS >= AUTH_REQUEST_TIMEOUT*1000
# error client idle timeout must be smaller than authentication timeout
#endif
+#define AUTH_WAITING_MSG \
+ "* OK Waiting for authentication process to respond.."
+
const char *login_protocol = "IMAP";
const char *capability_string = CAPABILITY_STRING;
static struct hash_table *clients;
-static struct timeout *to_idle;
-
-static void idle_timeout(void *context);
static void client_set_title(struct imap_client *client)
{
@@ -345,7 +345,7 @@ bool client_read(struct imap_client *cli
void client_input(struct imap_client *client)
{
- client->last_input = ioloop_time;
+ timeout_reset(client->to_idle_disconnect);
if (!client_read(client))
return;
@@ -355,12 +355,12 @@ void client_input(struct imap_client *cl
if (!auth_client_is_connected(auth_client)) {
/* we're not yet connected to auth process -
don't allow any commands */
- client->waiting_sent = TRUE;
- client_send_line(client,
- "* OK Waiting for authentication process to respond..");
+ client_send_line(client, AUTH_WAITING_MSG);
+ if (client->to_auth_waiting != NULL)
+ timeout_remove(&client->to_auth_waiting);
+
client->input_blocked = TRUE;
} else {
- client->waiting_sent = FALSE;
o_stream_cork(client->output);
while (client_handle_input(client)) ;
o_stream_uncork(client->output);
@@ -425,6 +425,26 @@ static void client_send_greeting(struct
client->greeting_sent = TRUE;
}
+static void client_idle_disconnect_timeout(struct imap_client *client)
+{
+ client_send_line(client, "* BYE Disconnected for inactivity.");
+ client_destroy(client, "Disconnected: Inactivity");
+}
+
+static void client_auth_waiting_timeout(struct imap_client *client)
+{
+ client_send_line(client, AUTH_WAITING_MSG);
+ timeout_remove(&client->to_auth_waiting);
+}
+
+void client_set_auth_waiting(struct imap_client *client)
+{
+ i_assert(client->to_auth_waiting == NULL);
+ client->to_auth_waiting =
+ timeout_add(AUTH_WAITING_TIMEOUT_MSECS,
+ client_auth_waiting_timeout, client);
+}
+
struct client *client_create(int fd, bool ssl, const struct ip_addr *local_ip,
const struct ip_addr *ip)
{
@@ -450,17 +470,19 @@ struct client *client_create(int fd, boo
client_open_streams(client, fd);
client->io = io_add(fd, IO_READ, client_input, client);
- client->last_input = ioloop_time;
hash_insert(clients, client, client);
main_ref();
if (!greeting_capability || auth_client_is_connected(auth_client))
- client_send_greeting(client);
+ client_send_greeting(client);
+ else
+ client_set_auth_waiting(client);
client_set_title(client);
- if (to_idle == NULL)
- to_idle = timeout_add(1000, idle_timeout, NULL);
+ client->to_idle_disconnect =
+ timeout_add(CLIENT_LOGIN_IDLE_TIMEOUT_MSECS,
+ client_idle_disconnect_timeout, client);
return &client->common;
}
@@ -474,8 +496,6 @@ void client_destroy(struct imap_client *
client_syslog(&client->common, reason);
hash_remove(clients, client);
- if (hash_count(clients) == 0)
- timeout_remove(&to_idle);
if (client->input != NULL)
i_stream_close(client->input);
@@ -494,6 +514,10 @@ void client_destroy(struct imap_client *
if (client->io != NULL)
io_remove(&client->io);
+ if (client->to_idle_disconnect != NULL)
+ timeout_remove(&client->to_idle_disconnect);
+ if (client->to_auth_waiting != NULL)
+ timeout_remove(&client->to_auth_waiting);
if (client->common.fd != -1) {
net_disconnect(client->common.fd);
@@ -584,21 +608,12 @@ void client_send_tagline(struct imap_cli
client_send_line(client, t_strconcat(client->cmd_tag, " ", line, NULL));
}
-static void client_check_idle(struct imap_client *client)
-{
- if (ioloop_time - client->last_input >= CLIENT_LOGIN_IDLE_TIMEOUT) {
- client_send_line(client, "* BYE Disconnected for inactivity.");
- client_destroy(client, "Disconnected: Inactivity");
- } else if (!client->waiting_sent &&
- ioloop_time - client->last_input > AUTH_WAITING_TIMEOUT &&
- (client->common.authenticating || !client->greeting_sent)) {
- client->waiting_sent = TRUE;
- client_send_line(client,
- "* OK Waiting for authentication process to respond..");
- }
-}
-
-static void idle_timeout(void *context ATTR_UNUSED)
+unsigned int clients_get_count(void)
+{
+ return hash_count(clients);
+}
+
+void clients_notify_auth_connected(void)
{
struct hash_iterate_context *iter;
void *key, *value;
@@ -607,25 +622,8 @@ static void idle_timeout(void *context A
while (hash_iterate(iter, &key, &value)) {
struct imap_client *client = key;
- client_check_idle(client);
- }
- hash_iterate_deinit(&iter);
-}
-
-unsigned int clients_get_count(void)
-{
- return hash_count(clients);
-}
-
-void clients_notify_auth_connected(void)
-{
- struct hash_iterate_context *iter;
- void *key, *value;
-
- iter = hash_iterate_init(clients);
- while (hash_iterate(iter, &key, &value)) {
- struct imap_client *client = key;
-
+ if (client->to_auth_waiting != NULL)
+ timeout_remove(&client->to_auth_waiting);
if (!client->greeting_sent)
client_send_greeting(client);
if (client->input_blocked) {
@@ -659,6 +657,4 @@ void clients_deinit(void)
{
clients_destroy_all();
hash_destroy(&clients);
More information about the dovecot-cvs
mailing list