20
20
#define AUTH_WORKER_LOOKUP_TIMEOUT_SECS 60
21
21
#define AUTH_WORKER_MAX_IDLE_SECS (60*5)
22
#define AUTH_WORKER_ABORT_SECS 60
22
23
#define AUTH_WORKER_DELAY_WARN_SECS 3
23
24
#define AUTH_WORKER_DELAY_WARN_MIN_INTERVAL_SECS 300
25
26
struct auth_worker_request {
29
30
auth_worker_callback_t *callback;
46
47
unsigned int shutdown:1;
49
static ARRAY_DEFINE(connections, struct auth_worker_connection *) = ARRAY_INIT;
50
static ARRAY(struct auth_worker_connection *) connections = ARRAY_INIT;
50
51
static unsigned int idle_count = 0, auth_workers_with_errors = 0;
51
static ARRAY_DEFINE(worker_request_array, struct auth_worker_request *);
52
static ARRAY(struct auth_worker_request *) worker_request_array;
52
53
static struct aqueue *worker_request_queue;
53
54
static time_t auth_worker_last_warn;
54
55
static unsigned int auth_workers_throttle_count;
58
59
static void worker_input(struct auth_worker_connection *conn);
59
60
static void auth_worker_destroy(struct auth_worker_connection **conn,
60
const char *reason, bool restart);
61
const char *reason, bool restart) ATTR_NULL(2);
62
63
static void auth_worker_idle_timeout(struct auth_worker_connection *conn)
76
77
auth_worker_destroy(&conn, "Lookup timed out", TRUE);
79
static void auth_worker_request_send(struct auth_worker_connection *conn,
80
static bool auth_worker_request_send(struct auth_worker_connection *conn,
80
81
struct auth_worker_request *request)
82
83
struct const_iovec iov[3];
84
unsigned int age_secs = ioloop_time - request->created;
84
if (ioloop_time - request->created > AUTH_WORKER_DELAY_WARN_SECS &&
86
if (age_secs >= AUTH_WORKER_ABORT_SECS) {
87
i_error("Aborting auth request that was queued for %d secs, "
89
age_secs, aqueue_count(worker_request_queue));
90
request->callback(t_strdup_printf(
91
"FAIL\t%d", PASSDB_RESULT_INTERNAL_FAILURE),
95
if (age_secs >= AUTH_WORKER_DELAY_WARN_SECS &&
85
96
ioloop_time - auth_worker_last_warn >
86
97
AUTH_WORKER_DELAY_WARN_MIN_INTERVAL_SECS) {
87
98
auth_worker_last_warn = ioloop_time;
88
99
i_warning("auth workers: Auth request was queued for %d "
89
100
"seconds, %d left in queue "
90
101
"(see auth_worker_max_count)",
91
(int)(ioloop_time - request->created),
92
aqueue_count(worker_request_queue));
102
age_secs, aqueue_count(worker_request_queue));
95
105
request->id = ++conn->id_counter;
97
107
iov[0].iov_base = t_strdup_printf("%d\t", request->id);
98
108
iov[0].iov_len = strlen(iov[0].iov_base);
99
iov[1].iov_base = request->data_str;
100
iov[1].iov_len = strlen(request->data_str);
109
iov[1].iov_base = request->data;
110
iov[1].iov_len = strlen(request->data);
101
111
iov[2].iov_base = "\n";
102
112
iov[2].iov_len = 1;
104
o_stream_sendv(conn->output, iov, 3);
114
o_stream_nsendv(conn->output, iov, 3);
106
116
i_assert(conn->request == NULL);
107
117
conn->request = request;
110
120
conn->to = timeout_add(AUTH_WORKER_LOOKUP_TIMEOUT_SECS * 1000,
111
121
auth_worker_call_timeout, conn);
115
126
static void auth_worker_request_send_next(struct auth_worker_connection *conn)
117
128
struct auth_worker_request *request, *const *requestp;
119
if (aqueue_count(worker_request_queue) == 0)
131
if (aqueue_count(worker_request_queue) == 0)
122
requestp = array_idx(&worker_request_array,
123
aqueue_idx(worker_request_queue, 0));
125
aqueue_delete_tail(worker_request_queue);
126
auth_worker_request_send(conn, request);
134
requestp = array_idx(&worker_request_array,
135
aqueue_idx(worker_request_queue, 0));
137
aqueue_delete_tail(worker_request_queue);
138
} while (!auth_worker_request_send(conn, request));
129
141
static void auth_worker_send_handshake(struct auth_worker_connection *conn)
145
157
binary_to_hex_append(str, userdb_md5, sizeof(userdb_md5));
146
158
str_append_c(str, '\n');
148
o_stream_send(conn->output, str_data(str), str_len(str));
160
o_stream_nsend(conn->output, str_data(str), str_len(str));
151
163
static struct auth_worker_connection *auth_worker_create(void)
173
185
conn->input = i_stream_create_fd(fd, AUTH_WORKER_MAX_LINE_LENGTH,
175
187
conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE);
188
o_stream_set_no_error_handling(conn->output, TRUE);
176
189
conn->io = io_add(fd, IO_READ, worker_input, conn);
177
190
conn->to = timeout_add(AUTH_WORKER_MAX_IDLE_SECS * 1000,
178
191
auth_worker_idle_timeout, conn);
388
401
struct auth_worker_connection *
389
auth_worker_call(pool_t pool, struct auth_stream_reply *data,
402
auth_worker_call(pool_t pool, const char *data,
390
403
auth_worker_callback_t *callback, void *context)
392
405
struct auth_worker_connection *conn;
395
408
request = p_new(pool, struct auth_worker_request, 1);
396
409
request->created = ioloop_time;
397
request->data_str = p_strdup(pool, auth_stream_reply_export(data));
410
request->data = p_strdup(pool, data);
398
411
request->callback = callback;
399
412
request->context = context;
409
422
conn = auth_worker_create();
413
auth_worker_request_send(conn, request);
426
if (!auth_worker_request_send(conn, request))
415
429
/* reached the limit, queue the request */
416
430
aqueue_append(worker_request_queue, &request);