dovecot-2.0: lib-master: Added timeout for auth master lookups.
dovecot at dovecot.org
dovecot at dovecot.org
Wed Apr 7 03:45:51 EEST 2010
details: http://hg.dovecot.org/dovecot-2.0/rev/0979e9e1e124
changeset: 11097:0979e9e1e124
user: Timo Sirainen <tss at iki.fi>
date: Wed Apr 07 03:43:02 2010 +0300
description:
lib-master: Added timeout for auth master lookups.
diffstat:
src/lib-master/master-login-auth.c | 75 ++++++++++++++++++++++++++++++++++---
src/lib-master/master-login-auth.h | 3 +
2 files changed, 72 insertions(+), 6 deletions(-)
diffs (165 lines):
diff -r 6aaa6fcba131 -r 0979e9e1e124 src/lib-master/master-login-auth.c
--- a/src/lib-master/master-login-auth.c Wed Apr 07 03:16:30 2010 +0300
+++ b/src/lib-master/master-login-auth.c Wed Apr 07 03:43:02 2010 +0300
@@ -5,6 +5,7 @@
#include "ioloop.h"
#include "istream.h"
#include "ostream.h"
+#include "llist.h"
#include "hex-binary.h"
#include "hash.h"
#include "str.h"
@@ -14,8 +15,12 @@
#include <stdlib.h>
#define AUTH_MAX_INBUF_SIZE 8192
+#define AUTH_REQUEST_TIMEOUT_SECS (2*60)
struct master_login_auth_request {
+ struct master_login_auth_request *prev, *next;
+
+ time_t create_stamp;
master_login_auth_request_callback_t *callback;
void *context;
};
@@ -29,13 +34,18 @@
struct io *io;
struct istream *input;
struct ostream *output;
+ struct timeout *to;
unsigned int id_counter;
struct hash_table *requests;
+ /* linked list of requests, ordered by create_stamp */
+ struct master_login_auth_request *request_head, *request_tail;
unsigned int version_received:1;
};
+static void master_login_auth_set_timeout(struct master_login_auth *auth);
+
struct master_login_auth *master_login_auth_init(const char *auth_socket_path)
{
struct master_login_auth *auth;
@@ -53,19 +63,21 @@
void master_login_auth_disconnect(struct master_login_auth *auth)
{
- struct hash_iterate_context *iter;
- void *key, *value;
+ struct master_login_auth_request *request;
- iter = hash_table_iterate_init(auth->requests);
- while (hash_table_iterate(iter, &key, &value)) {
- struct master_login_auth_request *request = value;
+ while (auth->request_head != NULL) {
+ request = auth->request_head;
+ DLLIST2_REMOVE(&auth->request_head,
+ &auth->request_tail, request);
+
request->callback(NULL, MASTER_AUTH_ERRMSG_INTERNAL_FAILURE,
request->context);
i_free(request);
}
- hash_table_iterate_deinit(&iter);
hash_table_clear(auth->requests, FALSE);
+ if (auth->to != NULL)
+ timeout_remove(&auth->to);
if (auth->io != NULL)
io_remove(&auth->io);
if (auth->fd != -1) {
@@ -102,19 +114,65 @@
master_login_auth_unref(&auth);
}
+static unsigned int auth_get_next_timeout_secs(struct master_login_auth *auth)
+{
+ time_t expires;
+
+ expires = auth->request_head->create_stamp + AUTH_REQUEST_TIMEOUT_SECS;
+ return expires <= ioloop_time ? 0 : expires - ioloop_time;
+}
+
+static void master_login_auth_timeout(struct master_login_auth *auth)
+{
+ struct master_login_auth_request *request;
+
+ while (auth->request_head != NULL &&
+ auth_get_next_timeout_secs(auth) == 0) {
+ request = auth->request_head;
+ DLLIST2_REMOVE(&auth->request_head,
+ &auth->request_tail, request);
+
+ i_error("Auth server request timed out after %u secs",
+ (unsigned int)(ioloop_time - request->create_stamp));
+ request->callback(NULL, MASTER_AUTH_ERRMSG_INTERNAL_FAILURE,
+ request->context);
+ i_free(request);
+ }
+ timeout_remove(&auth->to);
+ master_login_auth_set_timeout(auth);
+}
+
+static void master_login_auth_set_timeout(struct master_login_auth *auth)
+{
+ i_assert(auth->to == NULL);
+
+ if (auth->request_head != NULL) {
+ auth->to = timeout_add(auth_get_next_timeout_secs(auth) * 1000,
+ master_login_auth_timeout, auth);
+ }
+}
+
static struct master_login_auth_request *
master_login_auth_lookup_request(struct master_login_auth *auth,
unsigned int id)
{
struct master_login_auth_request *request;
+ bool update_timeout;
request = hash_table_lookup(auth->requests, POINTER_CAST(id));
if (request == NULL) {
i_error("Auth server sent reply with unknown ID %u", id);
return NULL;
}
+ update_timeout = request->prev == NULL;
hash_table_remove(auth->requests, POINTER_CAST(id));
+ DLLIST2_REMOVE(&auth->request_head, &auth->request_tail, request);
+
+ if (update_timeout) {
+ timeout_remove(&auth->to);
+ master_login_auth_set_timeout(auth);
+ }
return request;
}
@@ -301,9 +359,14 @@
o_stream_send(auth->output, str_data(str), str_len(str));
login_req = i_new(struct master_login_auth_request, 1);
+ login_req->create_stamp = ioloop_time;
login_req->callback = callback;
login_req->context = context;
hash_table_insert(auth->requests, POINTER_CAST(id), login_req);
+ DLLIST2_APPEND(&auth->request_head, &auth->request_tail, login_req);
+
+ if (auth->to == NULL)
+ master_login_auth_set_timeout(auth);
}
unsigned int master_login_auth_request_count(struct master_login_auth *auth)
diff -r 6aaa6fcba131 -r 0979e9e1e124 src/lib-master/master-login-auth.h
--- a/src/lib-master/master-login-auth.h Wed Apr 07 03:16:30 2010 +0300
+++ b/src/lib-master/master-login-auth.h Wed Apr 07 03:43:02 2010 +0300
@@ -11,6 +11,9 @@
void master_login_auth_deinit(struct master_login_auth **auth);
void master_login_auth_disconnect(struct master_login_auth *auth);
+/* req has been sent by login process. this function finishes authentication
+ by performing verifying from auth that req is valid and doing the userdb
+ lookup. */
void master_login_auth_request(struct master_login_auth *auth,
const struct master_auth_request *req,
master_login_auth_request_callback_t *callback,
More information about the dovecot-cvs
mailing list