mirror of
https://github.com/nginx/nginx.git
synced 2024-12-19 13:43:28 -06:00
Mail: smtp pipelining support.
Basically, this does the following two changes (and corresponding modifications of related code): 1. Does not reset session buffer unless it's reached it's end, and always wait for LF to terminate command (even if we detected invalid command). 2. Record command name to make it available for handlers (since now we can't assume that command starts from s->buffer->start).
This commit is contained in:
parent
f86169ae7b
commit
4f6f653f48
@ -234,6 +234,8 @@ typedef struct {
|
||||
ngx_str_t smtp_from;
|
||||
ngx_str_t smtp_to;
|
||||
|
||||
ngx_str_t cmd;
|
||||
|
||||
ngx_uint_t command;
|
||||
ngx_array_t args;
|
||||
|
||||
|
@ -620,7 +620,9 @@ ngx_mail_read_command(ngx_mail_session_t *s, ngx_connection_t *c)
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_AGAIN;
|
||||
if (s->buffer->pos == s->buffer->last) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
|
||||
@ -661,8 +663,12 @@ void
|
||||
ngx_mail_auth(ngx_mail_session_t *s, ngx_connection_t *c)
|
||||
{
|
||||
s->args.nelts = 0;
|
||||
s->buffer->pos = s->buffer->start;
|
||||
s->buffer->last = s->buffer->start;
|
||||
|
||||
if (s->buffer->pos == s->buffer->last) {
|
||||
s->buffer->pos = s->buffer->start;
|
||||
s->buffer->last = s->buffer->start;
|
||||
}
|
||||
|
||||
s->state = 0;
|
||||
|
||||
if (c->read->timer_set) {
|
||||
|
@ -626,6 +626,8 @@ ngx_mail_smtp_parse_command(ngx_mail_session_t *s)
|
||||
ngx_str_t *arg;
|
||||
enum {
|
||||
sw_start = 0,
|
||||
sw_command,
|
||||
sw_invalid,
|
||||
sw_spaces_before_argument,
|
||||
sw_argument,
|
||||
sw_almost_done
|
||||
@ -640,8 +642,14 @@ ngx_mail_smtp_parse_command(ngx_mail_session_t *s)
|
||||
|
||||
/* SMTP command */
|
||||
case sw_start:
|
||||
s->cmd_start = p;
|
||||
state = sw_command;
|
||||
|
||||
/* fall through */
|
||||
|
||||
case sw_command:
|
||||
if (ch == ' ' || ch == CR || ch == LF) {
|
||||
c = s->buffer->start;
|
||||
c = s->cmd_start;
|
||||
|
||||
if (p - c == 4) {
|
||||
|
||||
@ -719,6 +727,9 @@ ngx_mail_smtp_parse_command(ngx_mail_session_t *s)
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
s->cmd.data = s->cmd_start;
|
||||
s->cmd.len = p - s->cmd_start;
|
||||
|
||||
switch (ch) {
|
||||
case ' ':
|
||||
state = sw_spaces_before_argument;
|
||||
@ -738,6 +749,9 @@ ngx_mail_smtp_parse_command(ngx_mail_session_t *s)
|
||||
|
||||
break;
|
||||
|
||||
case sw_invalid:
|
||||
goto invalid;
|
||||
|
||||
case sw_spaces_before_argument:
|
||||
switch (ch) {
|
||||
case ' ':
|
||||
@ -824,9 +838,21 @@ done:
|
||||
|
||||
invalid:
|
||||
|
||||
s->state = sw_start;
|
||||
s->state = sw_invalid;
|
||||
s->arg_start = NULL;
|
||||
|
||||
/* skip invalid command till LF */
|
||||
|
||||
for (p = s->buffer->pos; p < s->buffer->last; p++) {
|
||||
if (*p == LF) {
|
||||
s->state = sw_start;
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
s->buffer->pos = p;
|
||||
|
||||
return NGX_MAIL_PARSE_INVALID_COMMAND;
|
||||
}
|
||||
|
||||
|
@ -657,7 +657,12 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
|
||||
c->log->action = NULL;
|
||||
ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in");
|
||||
|
||||
ngx_mail_proxy_handler(s->connection->write);
|
||||
if (s->buffer->pos == s->buffer->last) {
|
||||
ngx_mail_proxy_handler(s->connection->write);
|
||||
|
||||
} else {
|
||||
ngx_mail_proxy_handler(c->write);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
|
@ -486,6 +486,10 @@ ngx_mail_smtp_auth_state(ngx_event_t *rev)
|
||||
}
|
||||
}
|
||||
|
||||
if (s->buffer->pos < s->buffer->last) {
|
||||
s->blocked = 1;
|
||||
}
|
||||
|
||||
switch (rc) {
|
||||
|
||||
case NGX_DONE:
|
||||
@ -505,11 +509,14 @@ ngx_mail_smtp_auth_state(ngx_event_t *rev)
|
||||
|
||||
case NGX_OK:
|
||||
s->args.nelts = 0;
|
||||
s->buffer->pos = s->buffer->start;
|
||||
s->buffer->last = s->buffer->start;
|
||||
|
||||
if (s->buffer->pos == s->buffer->last) {
|
||||
s->buffer->pos = s->buffer->start;
|
||||
s->buffer->last = s->buffer->start;
|
||||
}
|
||||
|
||||
if (s->state) {
|
||||
s->arg_start = s->buffer->start;
|
||||
s->arg_start = s->buffer->pos;
|
||||
}
|
||||
|
||||
ngx_mail_send(c->write);
|
||||
@ -652,9 +659,7 @@ ngx_mail_smtp_auth(ngx_mail_session_t *s, ngx_connection_t *c)
|
||||
static ngx_int_t
|
||||
ngx_mail_smtp_mail(ngx_mail_session_t *s, ngx_connection_t *c)
|
||||
{
|
||||
u_char ch;
|
||||
ngx_str_t l;
|
||||
ngx_uint_t i;
|
||||
ngx_str_t *arg, cmd;
|
||||
ngx_mail_smtp_srv_conf_t *sscf;
|
||||
|
||||
sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);
|
||||
@ -672,37 +677,20 @@ ngx_mail_smtp_mail(ngx_mail_session_t *s, ngx_connection_t *c)
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
l.len = s->buffer->last - s->buffer->start;
|
||||
l.data = s->buffer->start;
|
||||
arg = s->args.elts;
|
||||
arg += s->args.nelts - 1;
|
||||
|
||||
for (i = 0; i < l.len; i++) {
|
||||
ch = l.data[i];
|
||||
cmd.len = arg->data + arg->len - s->cmd.data;
|
||||
cmd.data = s->cmd.data;
|
||||
|
||||
if (ch != CR && ch != LF) {
|
||||
continue;
|
||||
}
|
||||
s->smtp_from.len = cmd.len;
|
||||
|
||||
l.data[i] = ' ';
|
||||
}
|
||||
|
||||
while (i) {
|
||||
if (l.data[i - 1] != ' ') {
|
||||
break;
|
||||
}
|
||||
|
||||
i--;
|
||||
}
|
||||
|
||||
l.len = i;
|
||||
|
||||
s->smtp_from.len = l.len;
|
||||
|
||||
s->smtp_from.data = ngx_pnalloc(c->pool, l.len);
|
||||
s->smtp_from.data = ngx_pnalloc(c->pool, cmd.len);
|
||||
if (s->smtp_from.data == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_memcpy(s->smtp_from.data, l.data, l.len);
|
||||
ngx_memcpy(s->smtp_from.data, cmd.data, cmd.len);
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
|
||||
"smtp mail from:\"%V\"", &s->smtp_from);
|
||||
@ -716,46 +704,27 @@ ngx_mail_smtp_mail(ngx_mail_session_t *s, ngx_connection_t *c)
|
||||
static ngx_int_t
|
||||
ngx_mail_smtp_rcpt(ngx_mail_session_t *s, ngx_connection_t *c)
|
||||
{
|
||||
u_char ch;
|
||||
ngx_str_t l;
|
||||
ngx_uint_t i;
|
||||
ngx_str_t *arg, cmd;
|
||||
|
||||
if (s->smtp_from.len == 0) {
|
||||
ngx_str_set(&s->out, smtp_bad_sequence);
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
l.len = s->buffer->last - s->buffer->start;
|
||||
l.data = s->buffer->start;
|
||||
arg = s->args.elts;
|
||||
arg += s->args.nelts - 1;
|
||||
|
||||
for (i = 0; i < l.len; i++) {
|
||||
ch = l.data[i];
|
||||
cmd.len = arg->data + arg->len - s->cmd.data;
|
||||
cmd.data = s->cmd.data;
|
||||
|
||||
if (ch != CR && ch != LF) {
|
||||
continue;
|
||||
}
|
||||
s->smtp_to.len = cmd.len;
|
||||
|
||||
l.data[i] = ' ';
|
||||
}
|
||||
|
||||
while (i) {
|
||||
if (l.data[i - 1] != ' ') {
|
||||
break;
|
||||
}
|
||||
|
||||
i--;
|
||||
}
|
||||
|
||||
l.len = i;
|
||||
|
||||
s->smtp_to.len = l.len;
|
||||
|
||||
s->smtp_to.data = ngx_pnalloc(c->pool, l.len);
|
||||
s->smtp_to.data = ngx_pnalloc(c->pool, cmd.len);
|
||||
if (s->smtp_to.data == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_memcpy(s->smtp_to.data, l.data, l.len);
|
||||
ngx_memcpy(s->smtp_to.data, cmd.data, cmd.len);
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
|
||||
"smtp rcpt to:\"%V\"", &s->smtp_to);
|
||||
|
Loading…
Reference in New Issue
Block a user