[nginx] Mail: added missing event handling in auth http code.
Maxim Dounin
mdounin at mdounin.ru
Thu Mar 26 04:02:24 UTC 2026
details: http://freenginx.org/hg/nginx/rev/87034744d6e1
branches:
changeset: 9488:87034744d6e1
user: Maxim Dounin <mdounin at mdounin.ru>
date: Thu Mar 26 06:51:27 2026 +0300
description:
Mail: added missing event handling in auth http code.
If we need to be notified about further events, ngx_handle_read_event()
(or ngx_handle_write_event()) needs to be called after an event is
processed. Without this, an event can be removed from the kernel and
won't be reported again, notably when using oneshot event methods, such
as eventport on Solaris.
While here, ngx_mail_auth_http_read_handler() was also modified to properly
detect and report premature connection close.
To do so, ngx_mail_auth_http_read_handler() is modified to use a loop
around ngx_recv(), ctx->handler() now reports if there was an error or
we are waiting for additional data, and ngx_handle_read_event() is called
when ngx_recv() reports NGX_AGAIN. The code is now similar to
ngx_ssl_ocsp_read_handler() (which in turn was originally based on the
auth http code).
Similarly, ngx_mail_auth_http_write_handler() is modified to call
ngx_handle_write_event() when the request is not fully sent to the
socket.
diffstat:
src/mail/ngx_mail_auth_http_module.c | 110 ++++++++++++++++++++++------------
1 files changed, 72 insertions(+), 38 deletions(-)
diffs (329 lines):
diff --git a/src/mail/ngx_mail_auth_http_module.c b/src/mail/ngx_mail_auth_http_module.c
--- a/src/mail/ngx_mail_auth_http_module.c
+++ b/src/mail/ngx_mail_auth_http_module.c
@@ -31,7 +31,7 @@ typedef struct {
typedef struct ngx_mail_auth_http_ctx_s ngx_mail_auth_http_ctx_t;
-typedef void (*ngx_mail_auth_http_handler_pt)(ngx_mail_session_t *s,
+typedef ngx_int_t (*ngx_mail_auth_http_handler_pt)(ngx_mail_session_t *s,
ngx_mail_auth_http_ctx_t *ctx);
struct ngx_mail_auth_http_ctx_s {
@@ -65,9 +65,9 @@ struct ngx_mail_auth_http_ctx_s {
static void ngx_mail_auth_http_write_handler(ngx_event_t *wev);
static void ngx_mail_auth_http_read_handler(ngx_event_t *rev);
-static void ngx_mail_auth_http_ignore_status_line(ngx_mail_session_t *s,
+static ngx_int_t ngx_mail_auth_http_ignore_status_line(ngx_mail_session_t *s,
ngx_mail_auth_http_ctx_t *ctx);
-static void ngx_mail_auth_http_process_headers(ngx_mail_session_t *s,
+static ngx_int_t ngx_mail_auth_http_process_headers(ngx_mail_session_t *s,
ngx_mail_auth_http_ctx_t *ctx);
static void ngx_mail_auth_sleep_handler(ngx_event_t *rev);
static void ngx_mail_auth_send_error(ngx_mail_session_t *s);
@@ -307,13 +307,20 @@ ngx_mail_auth_http_write_handler(ngx_eve
ahcf = ngx_mail_get_module_srv_conf(s, ngx_mail_auth_http_module);
ngx_add_timer(wev, ahcf->timeout);
}
+
+ if (ngx_handle_write_event(wev, 0) != NGX_OK) {
+ ngx_close_connection(c);
+ ngx_destroy_pool(ctx->pool);
+ ngx_mail_session_internal_server_error(s);
+ }
}
static void
ngx_mail_auth_http_read_handler(ngx_event_t *rev)
{
- ssize_t n, size;
+ ssize_t n, size;
+ ngx_int_t rc;
ngx_connection_t *c;
ngx_mail_session_t *s;
ngx_mail_auth_http_ctx_t *ctx;
@@ -345,19 +352,41 @@ ngx_mail_auth_http_read_handler(ngx_even
}
}
- size = ctx->response->end - ctx->response->last;
+ for ( ;; ) {
+
+ size = ctx->response->end - ctx->response->last;
+
+ n = ngx_recv(c, ctx->response->pos, size);
- n = ngx_recv(c, ctx->response->pos, size);
+ if (n > 0) {
+ ctx->response->last += n;
+
+ rc = ctx->handler(s, ctx);
+
+ if (rc == NGX_ERROR || rc == NGX_DONE) {
+ return;
+ }
- if (n > 0) {
- ctx->response->last += n;
+ continue;
+ }
- ctx->handler(s, ctx);
- return;
+ if (n == NGX_AGAIN) {
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
+ ngx_close_connection(c);
+ ngx_destroy_pool(ctx->pool);
+ ngx_mail_session_internal_server_error(s);
+ }
+
+ return;
+ }
+
+ break;
}
- if (n == NGX_AGAIN) {
- return;
+ if (n == 0) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
+ "auth http server %V prematurely closed connection",
+ ctx->peer.name);
}
ngx_close_connection(c);
@@ -366,7 +395,7 @@ ngx_mail_auth_http_read_handler(ngx_even
}
-static void
+static ngx_int_t
ngx_mail_auth_http_ignore_status_line(ngx_mail_session_t *s,
ngx_mail_auth_http_ctx_t *ctx)
{
@@ -448,17 +477,19 @@ ngx_mail_auth_http_ignore_status_line(ng
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
"auth http server %V sent invalid response",
ctx->peer.name);
+
ngx_close_connection(ctx->peer.connection);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+
+ return NGX_ERROR;
}
}
ctx->response->pos = p;
ctx->state = state;
- return;
+ return NGX_AGAIN;
next:
@@ -469,11 +500,11 @@ done:
ctx->response->pos = p + 1;
ctx->state = 0;
ctx->handler = ngx_mail_auth_http_process_headers;
- ctx->handler(s, ctx);
+ return ctx->handler(s, ctx);
}
-static void
+static ngx_int_t
ngx_mail_auth_http_process_headers(ngx_mail_session_t *s,
ngx_mail_auth_http_ctx_t *ctx)
{
@@ -499,7 +530,7 @@ ngx_mail_auth_http_process_headers(ngx_m
ngx_close_connection(ctx->peer.connection);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
h->key.len = ctx->header_name_end - ctx->header_name_start;
@@ -562,7 +593,7 @@ ngx_mail_auth_http_process_headers(ngx_m
ngx_close_connection(ctx->peer.connection);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
ctx->err.data = p;
@@ -627,7 +658,7 @@ ngx_mail_auth_http_process_headers(ngx_m
ngx_close_connection(ctx->peer.connection);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
ngx_memcpy(s->login.data, ctx->header_start, s->login.len);
@@ -649,7 +680,7 @@ ngx_mail_auth_http_process_headers(ngx_m
ngx_close_connection(ctx->peer.connection);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
ngx_memcpy(s->passwd.data, ctx->header_start, s->passwd.len);
@@ -687,7 +718,7 @@ ngx_mail_auth_http_process_headers(ngx_m
ngx_close_connection(ctx->peer.connection);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
ngx_memcpy(ctx->errcode.data, ctx->header_start,
@@ -722,7 +753,7 @@ ngx_mail_auth_http_process_headers(ngx_m
ngx_close_connection(ctx->peer.connection);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
ctx->errsasl.len = size;
@@ -770,7 +801,7 @@ ngx_mail_auth_http_process_headers(ngx_m
if (p == NULL) {
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
ctx->err.data = p;
@@ -790,14 +821,14 @@ ngx_mail_auth_http_process_headers(ngx_m
if (timer == 0) {
s->auth_quit = 1;
ngx_mail_auth_send_error(s);
- return;
+ return NGX_DONE;
}
ngx_add_timer(s->connection->read, (ngx_msec_t) (timer * 1000));
s->connection->read->handler = ngx_mail_auth_sleep_handler;
- return;
+ return NGX_DONE;
}
if (s->auth_wait) {
@@ -807,14 +838,14 @@ ngx_mail_auth_http_process_headers(ngx_m
if (timer == 0) {
ngx_mail_auth_http_init(s);
- return;
+ return NGX_DONE;
}
ngx_add_timer(s->connection->read, (ngx_msec_t) (timer * 1000));
s->connection->read->handler = ngx_mail_auth_sleep_handler;
- return;
+ return NGX_DONE;
}
if (ctx->addr.len == 0 || ctx->port.len == 0) {
@@ -823,7 +854,7 @@ ngx_mail_auth_http_process_headers(ngx_m
ctx->peer.name);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
if (s->passwd.data == NULL
@@ -834,14 +865,14 @@ ngx_mail_auth_http_process_headers(ngx_m
ctx->peer.name);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
peer = ngx_pcalloc(s->connection->pool, sizeof(ngx_addr_t));
if (peer == NULL) {
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
rc = ngx_parse_addr(s->connection->pool, peer,
@@ -861,7 +892,7 @@ ngx_mail_auth_http_process_headers(ngx_m
default:
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
port = ngx_atoi(ctx->port.data, ctx->port.len);
@@ -872,7 +903,7 @@ ngx_mail_auth_http_process_headers(ngx_m
ctx->peer.name, &ctx->port);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
ngx_inet_set_port(peer->sockaddr, (in_port_t) port);
@@ -885,7 +916,7 @@ ngx_mail_auth_http_process_headers(ngx_m
if (peer->name.data == NULL) {
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
len = ctx->addr.len;
@@ -900,17 +931,17 @@ ngx_mail_auth_http_process_headers(ngx_m
if (ngx_mail_limit_conn_handler(s) != NGX_OK) {
ngx_destroy_pool(ctx->pool);
- return;
+ return NGX_ERROR;
}
ngx_destroy_pool(ctx->pool);
ngx_mail_proxy_init(s, peer);
- return;
+ return NGX_DONE;
}
if (rc == NGX_AGAIN ) {
- return;
+ return NGX_AGAIN;
}
/* rc == NGX_ERROR */
@@ -918,12 +949,15 @@ ngx_mail_auth_http_process_headers(ngx_m
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
"auth http server %V sent invalid header in response",
ctx->peer.name);
+
ngx_close_connection(ctx->peer.connection);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
- return;
+ return NGX_ERROR;
}
+
+ /* not reached */
}
More information about the nginx-devel
mailing list