Mercurial > dovecot > original-hg > dovecot-1.2
changeset 7099:3f5b7bebfd82 HEAD
Use separate per-client timeouts instead of going through all clients in one
timeout.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 03 Jan 2008 23:46:04 +0200 |
parents | becdf2eacdce |
children | 4c6364f99ff0 |
files | src/imap-login/client-authenticate.c src/imap-login/client.c src/imap-login/client.h src/pop3-login/client.c src/pop3-login/client.h |
diffstat | 5 files changed, 96 insertions(+), 116 deletions(-) [+] |
line wrap: on
line diff
--- 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 @@ -19,6 +19,8 @@ #define IMAP_SERVICE_NAME "imap" +static void client_auth_failed(struct imap_client *client); + const char *client_authenticate_get_capabilities(bool secured) { const struct auth_mech_desc *mech; @@ -211,13 +213,8 @@ 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 @@ 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 @@ 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 @@ 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)); }
--- 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 +#define AUTH_WAITING_TIMEOUT_MSECS 30 -#if CLIENT_LOGIN_IDLE_TIMEOUT >= AUTH_REQUEST_TIMEOUT +#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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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,34 +608,6 @@ 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) -{ - struct hash_iterate_context *iter; - void *key, *value; - - iter = hash_iterate_init(clients); - 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); @@ -626,6 +622,8 @@ 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 @@ { clients_destroy_all(); hash_destroy(&clients); - - i_assert(to_idle == NULL); }
--- a/src/imap-login/client.h Thu Jan 03 23:19:33 2008 +0200 +++ b/src/imap-login/client.h Thu Jan 03 23:46:04 2008 +0200 @@ -15,11 +15,11 @@ struct istream *input; struct ostream *output; struct imap_parser *parser; + struct timeout *to_idle_disconnect, *to_auth_waiting; struct login_proxy *proxy; char *proxy_user, *proxy_password; - time_t last_input; unsigned int bad_counter; const char *cmd_tag, *cmd_name; @@ -30,7 +30,6 @@ unsigned int input_blocked:1; unsigned int destroyed:1; unsigned int greeting_sent:1; - unsigned int waiting_sent:1; }; void client_destroy(struct imap_client *client, const char *reason); @@ -46,4 +45,6 @@ void client_ref(struct imap_client *client); bool client_unref(struct imap_client *client); +void client_set_auth_waiting(struct imap_client *client); + #endif
--- a/src/pop3-login/client.c Thu Jan 03 23:19:33 2008 +0200 +++ b/src/pop3-login/client.c Thu Jan 03 23:46:04 2008 +0200 @@ -26,8 +26,8 @@ SASL authentication gives the largest output. */ #define MAX_OUTBUF_SIZE 4096 -/* 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) /* Disconnect client when it sends too many bad commands */ #define CLIENT_MAX_BAD_COMMANDS 10 @@ -37,16 +37,13 @@ client hash, it's faster if we disconnect multiple clients. */ #define CLIENT_DESTROY_OLDEST_COUNT 16 -#if CLIENT_LOGIN_IDLE_TIMEOUT >= AUTH_REQUEST_TIMEOUT +#if CLIENT_LOGIN_IDLE_TIMEOUT_MSECS >= AUTH_REQUEST_TIMEOUT*1000 # error client idle timeout must be smaller than authentication timeout #endif const char *login_protocol = "POP3"; static struct hash_table *clients; -static struct timeout *to_idle; - -static void idle_timeout(void *context); static void client_set_title(struct pop3_client *client) { @@ -208,7 +205,7 @@ { char *line, *args; - client->last_input = ioloop_time; + timeout_reset(client->to_idle_disconnect); if (!client_read(client)) return; @@ -308,6 +305,11 @@ client->apop_challenge, NULL)); } +static void client_idle_disconnect_timeout(struct pop3_client *client) +{ + client_destroy(client, "Disconnected: Inactivity"); +} + struct client *client_create(int fd, bool ssl, const struct ip_addr *local_ip, const struct ip_addr *ip) { @@ -331,7 +333,6 @@ client->common.fd = fd; client_open_streams(client, fd); - client->last_input = ioloop_time; hash_insert(clients, client, client); main_ref(); @@ -341,8 +342,9 @@ client_auth_ready(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; } @@ -356,8 +358,6 @@ 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); @@ -376,6 +376,8 @@ if (client->io != NULL) io_remove(&client->io); + if (client->to_idle_disconnect != NULL) + timeout_remove(&client->to_idle_disconnect); if (client->common.fd != -1) { net_disconnect(client->common.fd); @@ -461,26 +463,6 @@ } } -static void client_check_idle(struct pop3_client *client) -{ - if (ioloop_time - client->last_input >= CLIENT_LOGIN_IDLE_TIMEOUT) - client_destroy(client, "Disconnected: Inactivity"); -} - -static void idle_timeout(void *context ATTR_UNUSED) -{ - struct hash_iterate_context *iter; - void *key, *value; - - iter = hash_iterate_init(clients); - while (hash_iterate(iter, &key, &value)) { - struct pop3_client *client = key; - - client_check_idle(client); - } - hash_iterate_deinit(&iter); -} - unsigned int clients_get_count(void) { return hash_count(clients); @@ -526,6 +508,4 @@ { clients_destroy_all(); hash_destroy(&clients); - - i_assert(to_idle == NULL); }
--- a/src/pop3-login/client.h Thu Jan 03 23:19:33 2008 +0200 +++ b/src/pop3-login/client.h Thu Jan 03 23:46:04 2008 +0200 @@ -15,12 +15,12 @@ struct io *io; struct istream *input; struct ostream *output; + struct timeout *to_idle_disconnect; struct login_proxy *proxy; char *proxy_user, *proxy_password; int proxy_state; - time_t last_input; unsigned int bad_counter; char *last_user;