mirror of
https://github.com/nginx/nginx.git
synced 2025-06-07 17:52:38 +08:00
nginx-0.3.42-RELEASE import
*) Feature: the "bind" option of the "listen" directive in IMAP/POP3 proxy. *) Bugfix: if the same capture in the "rewrite" directive was used more then once. *) Bugfix: the $sent_http_content_type, $sent_http_content_length, $sent_http_last_modified, $sent_http_connection, $sent_http_keep_alive, and $sent_http_transfer_encoding variables were not written to access log. *) Bugfix: the $sent_http_cache_control returned value of the single "Cache-Control" response header line.
This commit is contained in:
parent
5026d3799b
commit
7f7846d820
@ -61,6 +61,12 @@ if [ $HTTP_SSI = YES ]; then
|
|||||||
HTTP_POSTPONE=YES
|
HTTP_POSTPONE=YES
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if [ $HTTP_ADDITION = YES ]; then
|
||||||
|
HTTP_POSTPONE=YES
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
# the module order is important
|
# the module order is important
|
||||||
# ngx_http_autoindex_module
|
# ngx_http_autoindex_module
|
||||||
# ngx_http_index_module
|
# ngx_http_index_module
|
||||||
|
@ -9,6 +9,54 @@
|
|||||||
<title lang="en">nginx changelog</title>
|
<title lang="en">nginx changelog</title>
|
||||||
|
|
||||||
|
|
||||||
|
<changes ver="0.3.42" date="26.04.2006">
|
||||||
|
|
||||||
|
<change type="feature">
|
||||||
|
<para lang="ru">
|
||||||
|
ÐÁÒÁÍÅÔÒ bind × ÄÉÒÅËÔÉ×Å listen × IMAP/POP3 ÐÒÏËÓÉ.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
the "bind" option of the "listen" directive in IMAP/POP3 proxy.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
ÏÛÉÂËÉ ÐÒÉ ÉÓÐÏÌØÚÏ×ÁÎÉÉ × ÄÉÒÅËÔÉ×Å rewrite ÏÄÎÏÇÏ É ÔÏÇÏ ÖÅ
|
||||||
|
×ÙÄÅÌÅÎÉÑ ÂÏÌÅÅ ÏÄÎÏÇÏ ÒÁÚÁ.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
if the same capture in the "rewrite" directive was used more then once.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
× ÌÏÇ ÎÅ ÚÁÐÉÓÙ×ÁÌÉÓØ ÐÅÒÅÍÅÎÎÙÅ
|
||||||
|
$sent_http_content_type, $sent_http_content_length, $sent_http_last_modified,
|
||||||
|
$sent_http_connection, $sent_http_keep_alive É $sent_http_transfer_encoding.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
the $sent_http_content_type, $sent_http_content_length,
|
||||||
|
$sent_http_last_modified, $sent_http_connection, $sent_http_keep_alive,
|
||||||
|
and $sent_http_transfer_encoding variables were not written to access log.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
ÐÅÒÅÍÅÎÎÁÑ $sent_http_cache_control ×ÏÚ×ÒÁÝÁÌÁ ÓÏÄÅÒÖÉÍÏÅ ÔÏÌØËÏ ÏÄÎÏÊ
|
||||||
|
ÓÔÒÏËÉ "Cache-Control" × ÚÁÇÏÌÏ×ËÅ ÏÔ×ÅÔÁ.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
the $sent_http_cache_control returned value of the single "Cache-Control"
|
||||||
|
response header line.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
</changes>
|
||||||
|
|
||||||
|
|
||||||
<changes ver="0.3.41" date="21.04.2006">
|
<changes ver="0.3.41" date="21.04.2006">
|
||||||
|
|
||||||
<change type="feature">
|
<change type="feature">
|
||||||
|
@ -239,8 +239,10 @@ main(int argc, char *const *argv)
|
|||||||
ngx_write_fd(ngx_stderr_fileno, "built by " NGX_COMPILER CRLF,
|
ngx_write_fd(ngx_stderr_fileno, "built by " NGX_COMPILER CRLF,
|
||||||
sizeof("built by " NGX_COMPILER CRLF) - 1);
|
sizeof("built by " NGX_COMPILER CRLF) - 1);
|
||||||
#endif
|
#endif
|
||||||
|
if (!ngx_test_config) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ngx_test_config) {
|
if (ngx_test_config) {
|
||||||
log->log_level = NGX_LOG_INFO;
|
log->log_level = NGX_LOG_INFO;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#define _NGINX_H_INCLUDED_
|
#define _NGINX_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
#define NGINX_VER "nginx/0.3.41"
|
#define NGINX_VER "nginx/0.3.42"
|
||||||
|
|
||||||
#define NGINX_VAR "NGINX"
|
#define NGINX_VAR "NGINX"
|
||||||
#define NGX_OLDPID_EXT ".oldbin"
|
#define NGX_OLDPID_EXT ".oldbin"
|
||||||
|
@ -33,7 +33,6 @@ struct ngx_listening_s {
|
|||||||
/* handler of accepted connection */
|
/* handler of accepted connection */
|
||||||
ngx_connection_handler_pt handler;
|
ngx_connection_handler_pt handler;
|
||||||
|
|
||||||
void *ctx; /* ngx_http_conf_ctx_t, for example */
|
|
||||||
void *servers; /* array of ngx_http_in_addr_t, for example */
|
void *servers; /* array of ngx_http_in_addr_t, for example */
|
||||||
|
|
||||||
ngx_log_t log;
|
ngx_log_t log;
|
||||||
@ -113,10 +112,6 @@ struct ngx_connection_s {
|
|||||||
|
|
||||||
off_t sent;
|
off_t sent;
|
||||||
|
|
||||||
void *ctx;
|
|
||||||
void *servers;
|
|
||||||
|
|
||||||
|
|
||||||
ngx_log_t *log;
|
ngx_log_t *log;
|
||||||
|
|
||||||
ngx_pool_t *pool;
|
ngx_pool_t *pool;
|
||||||
|
@ -432,8 +432,10 @@ ngx_event_module_init(ngx_cycle_t *cycle)
|
|||||||
|
|
||||||
ecf = (*cf)[ngx_event_core_module.ctx_index];
|
ecf = (*cf)[ngx_event_core_module.ctx_index];
|
||||||
|
|
||||||
|
if (!ngx_test_config) {
|
||||||
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
|
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
|
||||||
"using the \"%s\" event method", ecf->name);
|
"using the \"%s\" event method", ecf->name);
|
||||||
|
}
|
||||||
|
|
||||||
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
|
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
|
||||||
|
|
||||||
@ -738,9 +740,6 @@ ngx_event_process_init(ngx_cycle_t *cycle)
|
|||||||
c->listening = &ls[i];
|
c->listening = &ls[i];
|
||||||
ls[i].connection = c;
|
ls[i].connection = c;
|
||||||
|
|
||||||
c->ctx = ls[i].ctx;
|
|
||||||
c->servers = ls[i].servers;
|
|
||||||
|
|
||||||
rev = c->read;
|
rev = c->read;
|
||||||
|
|
||||||
rev->log = c->log;
|
rev->log = c->log;
|
||||||
|
@ -156,9 +156,6 @@ ngx_event_accept(ngx_event_t *ev)
|
|||||||
|
|
||||||
c->unexpected_eof = 1;
|
c->unexpected_eof = 1;
|
||||||
|
|
||||||
c->ctx = lc->ctx;
|
|
||||||
c->servers = lc->servers;
|
|
||||||
|
|
||||||
rev = c->read;
|
rev = c->read;
|
||||||
wev = c->write;
|
wev = c->write;
|
||||||
|
|
||||||
|
@ -158,9 +158,6 @@ ngx_event_post_acceptex(ngx_listening_t *ls, ngx_uint_t n)
|
|||||||
|
|
||||||
c->unexpected_eof = 1;
|
c->unexpected_eof = 1;
|
||||||
|
|
||||||
c->ctx = ls->ctx;
|
|
||||||
c->servers = ls->servers;
|
|
||||||
|
|
||||||
c->listening = ls;
|
c->listening = ls;
|
||||||
|
|
||||||
rev = c->read;
|
rev = c->read;
|
||||||
|
@ -395,7 +395,7 @@ ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
regex->size = sc.size;
|
regex->size = sc.size;
|
||||||
regex->args = sc.args;
|
regex->args = sc.args;
|
||||||
|
|
||||||
if (sc.variables == 0) {
|
if (sc.variables == 0 && !sc.dup_capture) {
|
||||||
regex->lengths = NULL;
|
regex->lengths = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -734,6 +734,19 @@ ngx_http_ssi_output(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx)
|
|||||||
ngx_buf_t *b;
|
ngx_buf_t *b;
|
||||||
ngx_chain_t *cl;
|
ngx_chain_t *cl;
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
b = NULL;
|
||||||
|
for (cl = ctx->out; cl; cl = cl->next) {
|
||||||
|
if (cl->buf == b) {
|
||||||
|
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
|
||||||
|
"the same buf was used in ssi");
|
||||||
|
ngx_debug_point();
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
b = cl->buf;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
rc = ngx_http_next_body_filter(r, ctx->out);
|
rc = ngx_http_next_body_filter(r, ctx->out);
|
||||||
|
|
||||||
if (ctx->busy == NULL) {
|
if (ctx->busy == NULL) {
|
||||||
|
@ -725,8 +725,6 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
ls->deferred_accept = in_addr[a].listen_conf->deferred_accept;
|
ls->deferred_accept = in_addr[a].listen_conf->deferred_accept;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ls->ctx = ctx;
|
|
||||||
|
|
||||||
hip = ngx_palloc(cf->pool, sizeof(ngx_http_in_port_t));
|
hip = ngx_palloc(cf->pool, sizeof(ngx_http_in_port_t));
|
||||||
if (hip == NULL) {
|
if (hip == NULL) {
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
|
@ -1328,6 +1328,7 @@ ngx_http_internal_redirect(ngx_http_request_t *r,
|
|||||||
ngx_http_update_location_config(r);
|
ngx_http_update_location_config(r);
|
||||||
|
|
||||||
r->internal = 1;
|
r->internal = 1;
|
||||||
|
r->method = NGX_HTTP_GET;
|
||||||
|
|
||||||
ngx_http_handler(r);
|
ngx_http_handler(r);
|
||||||
|
|
||||||
@ -2528,6 +2529,7 @@ ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
static ngx_http_method_name_t ngx_methods_names[] = {
|
static ngx_http_method_name_t ngx_methods_names[] = {
|
||||||
{ "GET", (uint32_t) ~NGX_HTTP_GET },
|
{ "GET", (uint32_t) ~NGX_HTTP_GET },
|
||||||
{ "HEAD", (uint32_t) ~NGX_HTTP_HEAD },
|
{ "HEAD", (uint32_t) ~NGX_HTTP_HEAD },
|
||||||
|
{ "POST", (uint32_t) ~NGX_HTTP_POST },
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -89,6 +89,22 @@ ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
{
|
||||||
|
ngx_chain_t *cl;
|
||||||
|
ngx_buf_t *b = NULL;
|
||||||
|
for (cl = pr->out; cl; cl = cl->next) {
|
||||||
|
if (cl->buf == b) {
|
||||||
|
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
|
||||||
|
"the same buf was used in postponed");
|
||||||
|
ngx_debug_point();
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
b = cl->buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (r != r->connection->data || r->postponed->request) {
|
if (r != r->connection->data || r->postponed->request) {
|
||||||
return NGX_AGAIN;
|
return NGX_AGAIN;
|
||||||
}
|
}
|
||||||
|
@ -201,11 +201,11 @@ ngx_http_init_connection(ngx_connection_t *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static
|
static void
|
||||||
void ngx_http_init_request(ngx_event_t *rev)
|
ngx_http_init_request(ngx_event_t *rev)
|
||||||
{
|
{
|
||||||
ngx_uint_t i;
|
|
||||||
socklen_t len;
|
socklen_t len;
|
||||||
|
ngx_uint_t i;
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
ngx_connection_t *c;
|
ngx_connection_t *c;
|
||||||
ngx_http_request_t *r;
|
ngx_http_request_t *r;
|
||||||
@ -274,7 +274,7 @@ void ngx_http_init_request(ngx_event_t *rev)
|
|||||||
|
|
||||||
/* AF_INET only */
|
/* AF_INET only */
|
||||||
|
|
||||||
hip = c->servers;
|
hip = c->listening->servers;
|
||||||
hia = hip->addrs;
|
hia = hip->addrs;
|
||||||
|
|
||||||
r->port = hip->port;
|
r->port = hip->port;
|
||||||
@ -311,7 +311,7 @@ void ngx_http_init_request(ngx_event_t *rev)
|
|||||||
r->in_addr = sin.sin_addr.s_addr;
|
r->in_addr = sin.sin_addr.s_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the last in_port->addrs address is "*" */
|
/* the last address is "*" */
|
||||||
|
|
||||||
for ( /* void */ ; i < hip->naddrs - 1; i++) {
|
for ( /* void */ ; i < hip->naddrs - 1; i++) {
|
||||||
if (hia[i].addr == r->in_addr) {
|
if (hia[i].addr == r->in_addr) {
|
||||||
@ -1405,6 +1405,12 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
|
|||||||
|| rc == NGX_HTTP_REQUEST_TIME_OUT
|
|| rc == NGX_HTTP_REQUEST_TIME_OUT
|
||||||
|| r->connection->error)
|
|| r->connection->error)
|
||||||
{
|
{
|
||||||
|
if (rc == NGX_HTTP_CLIENT_CLOSED_REQUEST
|
||||||
|
&& r->headers_out.status == 0)
|
||||||
|
{
|
||||||
|
r->headers_out.status = NGX_HTTP_CLIENT_CLOSED_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
if (ngx_http_post_action(r) == NGX_OK) {
|
if (ngx_http_post_action(r) == NGX_OK) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -91,6 +91,14 @@ ngx_http_script_compile(ngx_http_script_compile_t *sc)
|
|||||||
|
|
||||||
if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') {
|
if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') {
|
||||||
|
|
||||||
|
n = sc->source->data[i] - '0';
|
||||||
|
|
||||||
|
if (sc->captures_mask & (1 << n)) {
|
||||||
|
sc->dup_capture = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sc->captures_mask |= 1 << n;
|
||||||
|
|
||||||
copy_capture = ngx_http_script_add_code(*sc->lengths,
|
copy_capture = ngx_http_script_add_code(*sc->lengths,
|
||||||
sizeof(ngx_http_script_copy_capture_code_t),
|
sizeof(ngx_http_script_copy_capture_code_t),
|
||||||
NULL);
|
NULL);
|
||||||
@ -100,7 +108,8 @@ ngx_http_script_compile(ngx_http_script_compile_t *sc)
|
|||||||
|
|
||||||
copy_capture->code = (ngx_http_script_code_pt)
|
copy_capture->code = (ngx_http_script_code_pt)
|
||||||
ngx_http_script_copy_capture_len_code;
|
ngx_http_script_copy_capture_len_code;
|
||||||
copy_capture->n = 2 * (sc->source->data[i] - '0');
|
copy_capture->n = 2 * n;
|
||||||
|
|
||||||
|
|
||||||
copy_capture = ngx_http_script_add_code(*sc->values,
|
copy_capture = ngx_http_script_add_code(*sc->values,
|
||||||
sizeof(ngx_http_script_copy_capture_code_t),
|
sizeof(ngx_http_script_copy_capture_code_t),
|
||||||
@ -110,14 +119,12 @@ ngx_http_script_compile(ngx_http_script_compile_t *sc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
copy_capture->code = ngx_http_script_copy_capture_code;
|
copy_capture->code = ngx_http_script_copy_capture_code;
|
||||||
copy_capture->n = sc->source->data[i] - '0';
|
copy_capture->n = 2 * n;
|
||||||
|
|
||||||
if (sc->ncaptures < copy_capture->n) {
|
if (sc->ncaptures < n) {
|
||||||
sc->ncaptures = copy_capture->n;
|
sc->ncaptures = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
copy_capture->n *= 2;
|
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
@ -47,6 +47,7 @@ typedef struct {
|
|||||||
|
|
||||||
ngx_uint_t variables;
|
ngx_uint_t variables;
|
||||||
ngx_uint_t ncaptures;
|
ngx_uint_t ncaptures;
|
||||||
|
ngx_uint_t captures_mask;
|
||||||
ngx_uint_t size;
|
ngx_uint_t size;
|
||||||
|
|
||||||
void *main;
|
void *main;
|
||||||
@ -54,6 +55,7 @@ typedef struct {
|
|||||||
unsigned compile_args:1;
|
unsigned compile_args:1;
|
||||||
unsigned complete_lengths:1;
|
unsigned complete_lengths:1;
|
||||||
unsigned complete_values:1;
|
unsigned complete_values:1;
|
||||||
|
unsigned dup_capture:1;
|
||||||
|
|
||||||
unsigned args:1;
|
unsigned args:1;
|
||||||
} ngx_http_script_compile_t;
|
} ngx_http_script_compile_t;
|
||||||
|
@ -170,6 +170,10 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
|
|||||||
ngx_http_upstream_ignore_header_line, 0,
|
ngx_http_upstream_ignore_header_line, 0,
|
||||||
ngx_http_upstream_ignore_header_line, 0, 0 },
|
ngx_http_upstream_ignore_header_line, 0, 0 },
|
||||||
|
|
||||||
|
{ ngx_string("Keep-Alive"),
|
||||||
|
ngx_http_upstream_ignore_header_line, 0,
|
||||||
|
ngx_http_upstream_ignore_header_line, 0, 0 },
|
||||||
|
|
||||||
{ ngx_string("X-Pad"),
|
{ ngx_string("X-Pad"),
|
||||||
ngx_http_upstream_ignore_header_line, 0,
|
ngx_http_upstream_ignore_header_line, 0,
|
||||||
ngx_http_upstream_ignore_header_line, 0, 0 },
|
ngx_http_upstream_ignore_header_line, 0, 0 },
|
||||||
@ -626,6 +630,8 @@ ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r->connection->log->action = "SSL handshaking to upstream";
|
||||||
|
|
||||||
rc = ngx_ssl_handshake(c);
|
rc = ngx_ssl_handshake(c);
|
||||||
|
|
||||||
if (rc == NGX_AGAIN) {
|
if (rc == NGX_AGAIN) {
|
||||||
@ -852,7 +858,6 @@ ngx_http_upstream_send_request_handler(ngx_event_t *wev)
|
|||||||
"http upstream send request handler");
|
"http upstream send request handler");
|
||||||
|
|
||||||
if (wev->timedout) {
|
if (wev->timedout) {
|
||||||
c->log->action = "sending request to upstream";
|
|
||||||
ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT);
|
ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,19 @@ static ngx_int_t ngx_http_variable_body_bytes_sent(ngx_http_request_t *r,
|
|||||||
static ngx_int_t ngx_http_variable_request_completion(ngx_http_request_t *r,
|
static ngx_int_t ngx_http_variable_request_completion(ngx_http_request_t *r,
|
||||||
ngx_http_variable_value_t *v, uintptr_t data);
|
ngx_http_variable_value_t *v, uintptr_t data);
|
||||||
|
|
||||||
|
static ngx_int_t ngx_http_variable_sent_content_type(ngx_http_request_t *r,
|
||||||
|
ngx_http_variable_value_t *v, uintptr_t data);
|
||||||
|
static ngx_int_t ngx_http_variable_sent_content_length(ngx_http_request_t *r,
|
||||||
|
ngx_http_variable_value_t *v, uintptr_t data);
|
||||||
|
static ngx_int_t ngx_http_variable_sent_last_modified(ngx_http_request_t *r,
|
||||||
|
ngx_http_variable_value_t *v, uintptr_t data);
|
||||||
|
static ngx_int_t ngx_http_variable_sent_connection(ngx_http_request_t *r,
|
||||||
|
ngx_http_variable_value_t *v, uintptr_t data);
|
||||||
|
static ngx_int_t ngx_http_variable_sent_keep_alive(ngx_http_request_t *r,
|
||||||
|
ngx_http_variable_value_t *v, uintptr_t data);
|
||||||
|
static ngx_int_t ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r,
|
||||||
|
ngx_http_variable_value_t *v, uintptr_t data);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO:
|
* TODO:
|
||||||
@ -59,6 +72,13 @@ static ngx_int_t ngx_http_variable_request_completion(ngx_http_request_t *r,
|
|||||||
* Apache SSI: DOCUMENT_NAME, LAST_MODIFIED, USER_NAME (file owner)
|
* Apache SSI: DOCUMENT_NAME, LAST_MODIFIED, USER_NAME (file owner)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* the $http_host, $http_user_agent, $http_referer, $http_via,
|
||||||
|
* and $http_x_forwarded_for variables may be handled by generic
|
||||||
|
* ngx_http_variable_unknown_header_in(), but for perfomance reasons
|
||||||
|
* they are handled using dedicated entries
|
||||||
|
*/
|
||||||
|
|
||||||
static ngx_http_variable_t ngx_http_core_variables[] = {
|
static ngx_http_variable_t ngx_http_core_variables[] = {
|
||||||
|
|
||||||
{ ngx_string("http_host"), NULL, ngx_http_variable_header,
|
{ ngx_string("http_host"), NULL, ngx_http_variable_header,
|
||||||
@ -146,6 +166,27 @@ static ngx_http_variable_t ngx_http_core_variables[] = {
|
|||||||
ngx_http_variable_request_completion,
|
ngx_http_variable_request_completion,
|
||||||
0, 0, 0 },
|
0, 0, 0 },
|
||||||
|
|
||||||
|
{ ngx_string("sent_http_content_type"), NULL,
|
||||||
|
ngx_http_variable_sent_content_type, 0, 0, 0 },
|
||||||
|
|
||||||
|
{ ngx_string("sent_http_content_length"), NULL,
|
||||||
|
ngx_http_variable_sent_content_length, 0, 0, 0 },
|
||||||
|
|
||||||
|
{ ngx_string("sent_http_last_modified"), NULL,
|
||||||
|
ngx_http_variable_sent_last_modified, 0, 0, 0 },
|
||||||
|
|
||||||
|
{ ngx_string("sent_http_connection"), NULL,
|
||||||
|
ngx_http_variable_sent_connection, 0, 0, 0 },
|
||||||
|
|
||||||
|
{ ngx_string("sent_http_keep_alive"), NULL,
|
||||||
|
ngx_http_variable_sent_keep_alive, 0, 0, 0 },
|
||||||
|
|
||||||
|
{ ngx_string("sent_http_transfer_encoding"), NULL,
|
||||||
|
ngx_http_variable_sent_transfer_encoding, 0, 0, 0 },
|
||||||
|
|
||||||
|
{ ngx_string("sent_http_cache_control"), NULL, ngx_http_variable_headers,
|
||||||
|
offsetof(ngx_http_request_t, headers_out.cache_control), 0, 0 },
|
||||||
|
|
||||||
{ ngx_string("limit_rate"), ngx_http_variable_request_set_size,
|
{ ngx_string("limit_rate"), ngx_http_variable_request_set_size,
|
||||||
ngx_http_variable_request,
|
ngx_http_variable_request,
|
||||||
offsetof(ngx_http_request_t, limit_rate),
|
offsetof(ngx_http_request_t, limit_rate),
|
||||||
@ -846,6 +887,178 @@ ngx_http_variable_body_bytes_sent(ngx_http_request_t *r,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_variable_sent_content_type(ngx_http_request_t *r,
|
||||||
|
ngx_http_variable_value_t *v, uintptr_t data)
|
||||||
|
{
|
||||||
|
if (r->headers_out.content_type.len) {
|
||||||
|
v->len = r->headers_out.content_type.len;
|
||||||
|
v->valid = 1;
|
||||||
|
v->no_cachable = 0;
|
||||||
|
v->not_found = 0;
|
||||||
|
v->data = r->headers_out.content_type.data;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
v->not_found = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_variable_sent_content_length(ngx_http_request_t *r,
|
||||||
|
ngx_http_variable_value_t *v, uintptr_t data)
|
||||||
|
{
|
||||||
|
u_char *p;
|
||||||
|
|
||||||
|
if (r->headers_out.content_length) {
|
||||||
|
v->len = r->headers_out.content_length->value.len;
|
||||||
|
v->valid = 1;
|
||||||
|
v->no_cachable = 0;
|
||||||
|
v->not_found = 0;
|
||||||
|
v->data = r->headers_out.content_length->value.data;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r->headers_out.content_length_n >= 0) {
|
||||||
|
p = ngx_palloc(r->pool, NGX_OFF_T_LEN);
|
||||||
|
if (p == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
v->len = ngx_sprintf(p, "%O", r->headers_out.content_length_n) - p;
|
||||||
|
v->valid = 1;
|
||||||
|
v->no_cachable = 0;
|
||||||
|
v->not_found = 0;
|
||||||
|
v->data = p;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
v->not_found = 1;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_variable_sent_last_modified(ngx_http_request_t *r,
|
||||||
|
ngx_http_variable_value_t *v, uintptr_t data)
|
||||||
|
{
|
||||||
|
u_char *p;
|
||||||
|
|
||||||
|
if (r->headers_out.last_modified) {
|
||||||
|
v->len = r->headers_out.last_modified->value.len;
|
||||||
|
v->valid = 1;
|
||||||
|
v->no_cachable = 0;
|
||||||
|
v->not_found = 0;
|
||||||
|
v->data = r->headers_out.last_modified->value.data;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r->headers_out.last_modified_time >= 0) {
|
||||||
|
p = ngx_palloc(r->pool,
|
||||||
|
sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT") - 1);
|
||||||
|
if (p == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
v->len = ngx_http_time(p, r->headers_out.last_modified_time) - p;
|
||||||
|
v->valid = 1;
|
||||||
|
v->no_cachable = 0;
|
||||||
|
v->not_found = 0;
|
||||||
|
v->data = p;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
v->not_found = 1;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_variable_sent_connection(ngx_http_request_t *r,
|
||||||
|
ngx_http_variable_value_t *v, uintptr_t data)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (r->keepalive) {
|
||||||
|
len = sizeof("keep-alive") - 1;
|
||||||
|
p = "keep-alive";
|
||||||
|
|
||||||
|
} else {
|
||||||
|
len = sizeof("close") - 1;
|
||||||
|
p = "close";
|
||||||
|
}
|
||||||
|
|
||||||
|
v->len = len;
|
||||||
|
v->valid = 1;
|
||||||
|
v->no_cachable = 0;
|
||||||
|
v->not_found = 0;
|
||||||
|
v->data = (u_char *) p;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_variable_sent_keep_alive(ngx_http_request_t *r,
|
||||||
|
ngx_http_variable_value_t *v, uintptr_t data)
|
||||||
|
{
|
||||||
|
u_char *p;
|
||||||
|
ngx_http_core_loc_conf_t *clcf;
|
||||||
|
|
||||||
|
if (r->keepalive) {
|
||||||
|
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
||||||
|
|
||||||
|
if (clcf->keepalive_header) {
|
||||||
|
|
||||||
|
p = ngx_palloc(r->pool, sizeof("timeout=") - 1 + NGX_TIME_T_LEN);
|
||||||
|
if (p == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
v->len = ngx_sprintf(p, "timeout=%T", clcf->keepalive_header) - p;
|
||||||
|
v->valid = 1;
|
||||||
|
v->no_cachable = 0;
|
||||||
|
v->not_found = 0;
|
||||||
|
v->data = p;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v->not_found = 1;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r,
|
||||||
|
ngx_http_variable_value_t *v, uintptr_t data)
|
||||||
|
{
|
||||||
|
if (r->chunked) {
|
||||||
|
v->len = sizeof("chunked") - 1;
|
||||||
|
v->valid = 1;
|
||||||
|
v->no_cachable = 0;
|
||||||
|
v->not_found = 0;
|
||||||
|
v->data = (u_char *) "chunked";
|
||||||
|
|
||||||
|
} else {
|
||||||
|
v->not_found = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_http_variable_request_completion(ngx_http_request_t *r,
|
ngx_http_variable_request_completion(ngx_http_request_t *r,
|
||||||
ngx_http_variable_value_t *v, uintptr_t data)
|
ngx_http_variable_value_t *v, uintptr_t data)
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
|
|
||||||
static char *ngx_imap_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
static char *ngx_imap_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
||||||
|
static int ngx_libc_cdecl ngx_imap_cmp_conf_in_addrs(const void *one,
|
||||||
|
const void *two);
|
||||||
|
|
||||||
|
|
||||||
ngx_uint_t ngx_imap_max_module;
|
ngx_uint_t ngx_imap_max_module;
|
||||||
@ -56,10 +58,18 @@ static char *
|
|||||||
ngx_imap_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
ngx_imap_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
{
|
{
|
||||||
char *rv;
|
char *rv;
|
||||||
ngx_uint_t m, mi, s;
|
u_char *text;
|
||||||
|
size_t len;
|
||||||
|
ngx_uint_t i, a, l, m, mi, s, p, last, bind_all, done;
|
||||||
ngx_conf_t pcf;
|
ngx_conf_t pcf;
|
||||||
|
ngx_array_t in_ports;
|
||||||
|
ngx_listening_t *ls;
|
||||||
|
ngx_imap_listen_t *imls;
|
||||||
ngx_imap_module_t *module;
|
ngx_imap_module_t *module;
|
||||||
|
ngx_imap_in_port_t *imip;
|
||||||
ngx_imap_conf_ctx_t *ctx;
|
ngx_imap_conf_ctx_t *ctx;
|
||||||
|
ngx_imap_conf_in_port_t *in_port;
|
||||||
|
ngx_imap_conf_in_addr_t *in_addr;
|
||||||
ngx_imap_core_srv_conf_t **cscfp;
|
ngx_imap_core_srv_conf_t **cscfp;
|
||||||
ngx_imap_core_main_conf_t *cmcf;
|
ngx_imap_core_main_conf_t *cmcf;
|
||||||
|
|
||||||
@ -191,5 +201,203 @@ ngx_imap_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
|
|
||||||
*cf = pcf;
|
*cf = pcf;
|
||||||
|
|
||||||
|
|
||||||
|
if (ngx_array_init(&in_ports, cf->temp_pool, 4,
|
||||||
|
sizeof(ngx_imap_conf_in_port_t))
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
imls = cmcf->listen.elts;
|
||||||
|
|
||||||
|
for (l = 0; l < cmcf->listen.nelts; l++) {
|
||||||
|
|
||||||
|
/* AF_INET only */
|
||||||
|
|
||||||
|
in_port = in_ports.elts;
|
||||||
|
for (p = 0; p < in_ports.nelts; p++) {
|
||||||
|
if (in_port[p].port == imls[l].port) {
|
||||||
|
in_port = &in_port[p];
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
in_port = ngx_array_push(&in_ports);
|
||||||
|
if (in_port == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
in_port->port = imls[l].port;
|
||||||
|
|
||||||
|
if (ngx_array_init(&in_port->addrs, cf->temp_pool, 2,
|
||||||
|
sizeof(ngx_imap_conf_in_addr_t))
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
found:
|
||||||
|
|
||||||
|
in_addr = ngx_array_push(&in_port->addrs);
|
||||||
|
if (in_addr == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
in_addr->addr = imls[l].addr;
|
||||||
|
in_addr->ctx = imls[l].ctx;
|
||||||
|
in_addr->bind = imls[l].bind;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* optimize the lists of ports and addresses */
|
||||||
|
|
||||||
|
/* AF_INET only */
|
||||||
|
|
||||||
|
in_port = in_ports.elts;
|
||||||
|
for (p = 0; p < in_ports.nelts; p++) {
|
||||||
|
|
||||||
|
ngx_qsort(in_port[p].addrs.elts, (size_t) in_port[p].addrs.nelts,
|
||||||
|
sizeof(ngx_imap_conf_in_addr_t), ngx_imap_cmp_conf_in_addrs);
|
||||||
|
|
||||||
|
in_addr = in_port[p].addrs.elts;
|
||||||
|
last = in_port[p].addrs.nelts;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if there is the binding to the "*:port" then we need to bind()
|
||||||
|
* to the "*:port" only and ignore the other bindings
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (in_addr[last - 1].addr == INADDR_ANY) {
|
||||||
|
in_addr[last - 1].bind = 1;
|
||||||
|
bind_all = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
bind_all = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (a = 0; a < last; /* void */ ) {
|
||||||
|
|
||||||
|
if (!bind_all && !in_addr[a].bind) {
|
||||||
|
a++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ls = ngx_listening_inet_stream_socket(cf, in_addr[a].addr,
|
||||||
|
in_port[p].port);
|
||||||
|
if (ls == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ls->backlog = -1;
|
||||||
|
ls->rcvbuf = -1;
|
||||||
|
ls->sndbuf = -1;
|
||||||
|
|
||||||
|
ls->addr_ntop = 1;
|
||||||
|
ls->handler = ngx_imap_init_connection;
|
||||||
|
ls->pool_size = 256;
|
||||||
|
|
||||||
|
/* STUB */
|
||||||
|
ls->log = *cf->cycle->new_log;
|
||||||
|
ls->log.data = &ls->addr_text;
|
||||||
|
ls->log.handler = ngx_accept_log_error;
|
||||||
|
/**/
|
||||||
|
|
||||||
|
imip = ngx_palloc(cf->pool, sizeof(ngx_imap_in_port_t));
|
||||||
|
if (imip == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ls->servers = imip;
|
||||||
|
|
||||||
|
in_addr = in_port[p].addrs.elts;
|
||||||
|
|
||||||
|
if (in_addr[a].bind && in_addr[a].addr != INADDR_ANY) {
|
||||||
|
imip->naddrs = 1;
|
||||||
|
done = 0;
|
||||||
|
|
||||||
|
} else if (in_port[p].addrs.nelts > 1
|
||||||
|
&& in_addr[last - 1].addr == INADDR_ANY)
|
||||||
|
{
|
||||||
|
imip->naddrs = last;
|
||||||
|
done = 1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
imip->naddrs = 1;
|
||||||
|
done = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
ngx_log_error(NGX_LOG_ALERT, cf->log, 0,
|
||||||
|
"%ui: %V %d %ui %ui",
|
||||||
|
a, &ls->addr_text, in_addr[a].bind,
|
||||||
|
imip->naddrs, last);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
imip->addrs = ngx_pcalloc(cf->pool,
|
||||||
|
imip->naddrs * sizeof(ngx_imap_in_addr_t));
|
||||||
|
if (imip->addrs == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < imip->naddrs; i++) {
|
||||||
|
imip->addrs[i].addr = in_addr[i].addr;
|
||||||
|
imip->addrs[i].ctx = in_addr[i].ctx;
|
||||||
|
|
||||||
|
text = ngx_palloc(cf->pool,
|
||||||
|
INET_ADDRSTRLEN - 1 + sizeof(":65535") - 1);
|
||||||
|
if (text == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = ngx_inet_ntop(AF_INET, &in_addr[i].addr, text,
|
||||||
|
INET_ADDRSTRLEN);
|
||||||
|
|
||||||
|
len = ngx_sprintf(text + len, ":%d", in_port[p].port) - text;
|
||||||
|
|
||||||
|
imip->addrs[i].addr_text.len = len;
|
||||||
|
imip->addrs[i].addr_text.data = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (done) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
in_addr++;
|
||||||
|
in_port[p].addrs.elts = in_addr;
|
||||||
|
last--;
|
||||||
|
|
||||||
|
a = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int ngx_libc_cdecl
|
||||||
|
ngx_imap_cmp_conf_in_addrs(const void *one, const void *two)
|
||||||
|
{
|
||||||
|
ngx_imap_conf_in_addr_t *first, *second;
|
||||||
|
|
||||||
|
first = (ngx_imap_conf_in_addr_t *) one;
|
||||||
|
second = (ngx_imap_conf_in_addr_t *) two;
|
||||||
|
|
||||||
|
if (first->addr == INADDR_ANY) {
|
||||||
|
/* the INADDR_ANY must be the last resort, shift it to the end */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first->bind && !second->bind) {
|
||||||
|
/* shift explicit bind()ed addresses to the start */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!first->bind && second->bind) {
|
||||||
|
/* shift explicit bind()ed addresses to the start */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do not sort by default */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -25,8 +25,47 @@ typedef struct {
|
|||||||
} ngx_imap_conf_ctx_t;
|
} ngx_imap_conf_ctx_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
in_addr_t addr;
|
||||||
|
in_port_t port;
|
||||||
|
int family;
|
||||||
|
|
||||||
|
/* server ctx */
|
||||||
|
ngx_imap_conf_ctx_t *ctx;
|
||||||
|
|
||||||
|
unsigned bind:1;
|
||||||
|
} ngx_imap_listen_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
in_addr_t addr;
|
||||||
|
ngx_imap_conf_ctx_t *ctx;
|
||||||
|
ngx_str_t addr_text;
|
||||||
|
} ngx_imap_in_addr_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_imap_in_addr_t *addrs; /* array of ngx_imap_in_addr_t */
|
||||||
|
ngx_uint_t naddrs;
|
||||||
|
} ngx_imap_in_port_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
in_port_t port;
|
||||||
|
ngx_array_t addrs; /* array of ngx_imap_conf_in_addr_t */
|
||||||
|
} ngx_imap_conf_in_port_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
in_addr_t addr;
|
||||||
|
ngx_imap_conf_ctx_t *ctx;
|
||||||
|
unsigned bind:1;
|
||||||
|
} ngx_imap_conf_in_addr_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ngx_array_t servers; /* ngx_imap_core_srv_conf_t */
|
ngx_array_t servers; /* ngx_imap_core_srv_conf_t */
|
||||||
|
ngx_array_t listen; /* ngx_imap_listen_t */
|
||||||
} ngx_imap_core_main_conf_t;
|
} ngx_imap_core_main_conf_t;
|
||||||
|
|
||||||
|
|
||||||
@ -109,6 +148,7 @@ typedef struct {
|
|||||||
unsigned quoted:1;
|
unsigned quoted:1;
|
||||||
unsigned backslash:1;
|
unsigned backslash:1;
|
||||||
unsigned no_sync_literal:1;
|
unsigned no_sync_literal:1;
|
||||||
|
unsigned starttls:1;
|
||||||
|
|
||||||
ngx_str_t login;
|
ngx_str_t login;
|
||||||
ngx_str_t passwd;
|
ngx_str_t passwd;
|
||||||
@ -116,6 +156,8 @@ typedef struct {
|
|||||||
ngx_str_t tag;
|
ngx_str_t tag;
|
||||||
ngx_str_t tagged_line;
|
ngx_str_t tagged_line;
|
||||||
|
|
||||||
|
ngx_str_t *addr_text;
|
||||||
|
|
||||||
ngx_uint_t command;
|
ngx_uint_t command;
|
||||||
ngx_array_t args;
|
ngx_array_t args;
|
||||||
|
|
||||||
@ -184,6 +226,9 @@ typedef struct {
|
|||||||
(s)->main_conf[module.ctx_index]
|
(s)->main_conf[module.ctx_index]
|
||||||
#define ngx_imap_get_module_srv_conf(s, module) (s)->srv_conf[module.ctx_index]
|
#define ngx_imap_get_module_srv_conf(s, module) (s)->srv_conf[module.ctx_index]
|
||||||
|
|
||||||
|
#define ngx_imap_conf_get_module_main_conf(cf, module) \
|
||||||
|
((ngx_imap_conf_ctx_t *) cf->ctx)->main_conf[module.ctx_index]
|
||||||
|
|
||||||
|
|
||||||
void ngx_imap_init_connection(ngx_connection_t *c);
|
void ngx_imap_init_connection(ngx_connection_t *c);
|
||||||
void ngx_imap_send(ngx_event_t *wev);
|
void ngx_imap_send(ngx_event_t *wev);
|
||||||
|
@ -55,7 +55,7 @@ static ngx_command_t ngx_imap_core_commands[] = {
|
|||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("listen"),
|
{ ngx_string("listen"),
|
||||||
NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1,
|
NGX_IMAP_SRV_CONF|NGX_CONF_TAKE12,
|
||||||
ngx_imap_core_listen,
|
ngx_imap_core_listen,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@ -143,7 +143,14 @@ ngx_imap_core_create_main_conf(ngx_conf_t *cf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ngx_array_init(&cmcf->servers, cf->pool, 4,
|
if (ngx_array_init(&cmcf->servers, cf->pool, 4,
|
||||||
sizeof(ngx_imap_core_srv_conf_t *)) == NGX_ERROR)
|
sizeof(ngx_imap_core_srv_conf_t *))
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_array_init(&cmcf->listen, cf->pool, 4, sizeof(ngx_imap_listen_t))
|
||||||
|
!= NGX_OK)
|
||||||
{
|
{
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
@ -422,9 +429,11 @@ ngx_imap_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
char *err;
|
char *err;
|
||||||
ngx_str_t *value;
|
ngx_str_t *value;
|
||||||
in_addr_t in_addr;
|
in_addr_t in_addr;
|
||||||
|
ngx_uint_t i;
|
||||||
struct hostent *h;
|
struct hostent *h;
|
||||||
ngx_listening_t *ls;
|
ngx_imap_listen_t *imls;
|
||||||
ngx_inet_upstream_t inet_upstream;
|
ngx_inet_upstream_t inet_upstream;
|
||||||
|
ngx_imap_core_main_conf_t *cmcf;
|
||||||
|
|
||||||
value = cf->args->elts;
|
value = cf->args->elts;
|
||||||
|
|
||||||
@ -469,31 +478,48 @@ ngx_imap_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
in_addr = INADDR_ANY;
|
in_addr = INADDR_ANY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmcf = ngx_imap_conf_get_module_main_conf(cf, ngx_imap_core_module);
|
||||||
|
|
||||||
ls = ngx_listening_inet_stream_socket(cf, in_addr, inet_upstream.port);
|
imls = cmcf->listen.elts;
|
||||||
if (ls == NULL) {
|
|
||||||
|
for (i = 0; i < cmcf->listen.nelts; i++) {
|
||||||
|
|
||||||
|
if (imls[i].addr != in_addr || imls[i].port != inet_upstream.port) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"duplicate \"%V\" address and port pair",
|
||||||
|
&inet_upstream.url);
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ls->backlog = -1;
|
imls = ngx_array_push(&cmcf->listen);
|
||||||
ls->rcvbuf = -1;
|
if (imls == NULL) {
|
||||||
ls->sndbuf = -1;
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
ls->addr_ntop = 1;
|
ngx_memzero(imls, sizeof(ngx_imap_listen_t));
|
||||||
ls->handler = ngx_imap_init_connection;
|
|
||||||
ls->pool_size = 256;
|
|
||||||
|
|
||||||
ls->ctx = cf->ctx;
|
imls->addr = in_addr;
|
||||||
|
imls->port = inet_upstream.port;
|
||||||
/* STUB */
|
imls->family = AF_INET;
|
||||||
ls->log = *cf->cycle->new_log;
|
imls->ctx = cf->ctx;
|
||||||
ls->log.data = &ls->addr_text;
|
|
||||||
ls->log.handler = ngx_accept_log_error;
|
|
||||||
/**/
|
|
||||||
|
|
||||||
|
if (cf->args->nelts == 2) {
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ngx_strcmp(value[2].data, "bind") == 0) {
|
||||||
|
imls->bind = 1;
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"the invalid \"%V\" parameter", &value[2]);
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
ngx_imap_core_capability(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
ngx_imap_core_capability(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
|
@ -44,35 +44,103 @@ static u_char imap_invalid_command[] = "BAD invalid command" CRLF;
|
|||||||
void
|
void
|
||||||
ngx_imap_init_connection(ngx_connection_t *c)
|
ngx_imap_init_connection(ngx_connection_t *c)
|
||||||
{
|
{
|
||||||
ngx_imap_log_ctx_t *lctx;
|
in_addr_t in_addr;
|
||||||
|
socklen_t len;
|
||||||
|
ngx_uint_t i;
|
||||||
|
struct sockaddr_in sin;
|
||||||
|
ngx_imap_log_ctx_t *ctx;
|
||||||
|
ngx_imap_in_port_t *imip;
|
||||||
|
ngx_imap_in_addr_t *imia;
|
||||||
|
ngx_imap_session_t *s;
|
||||||
#if (NGX_IMAP_SSL)
|
#if (NGX_IMAP_SSL)
|
||||||
ngx_imap_conf_ctx_t *ctx;
|
|
||||||
ngx_imap_ssl_conf_t *sslcf;
|
ngx_imap_ssl_conf_t *sslcf;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%ui client %V connected to %V",
|
|
||||||
c->number, &c->addr_text, &c->listening->addr_text);
|
|
||||||
|
|
||||||
lctx = ngx_palloc(c->pool, sizeof(ngx_imap_log_ctx_t));
|
/* find the server configuration for the address:port */
|
||||||
if (lctx == NULL) {
|
|
||||||
|
/* AF_INET only */
|
||||||
|
|
||||||
|
imip = c->listening->servers;
|
||||||
|
imia = imip->addrs;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
if (imip->naddrs > 1) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There are several addresses on this port and one of them
|
||||||
|
* is the "*:port" wildcard so getsockname() is needed to determine
|
||||||
|
* the server address.
|
||||||
|
*
|
||||||
|
* AcceptEx() already gave this address.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if (NGX_WIN32)
|
||||||
|
if (c->local_sockaddr) {
|
||||||
|
in_addr =
|
||||||
|
((struct sockaddr_in *) c->local_sockaddr)->sin_addr.s_addr;
|
||||||
|
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
len = sizeof(struct sockaddr_in);
|
||||||
|
if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) {
|
||||||
|
ngx_connection_error(c, ngx_socket_errno,
|
||||||
|
"getsockname() failed");
|
||||||
ngx_imap_close_connection(c);
|
ngx_imap_close_connection(c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lctx->client = &c->addr_text;
|
in_addr = sin.sin_addr.s_addr;
|
||||||
lctx->session = NULL;
|
}
|
||||||
|
|
||||||
|
/* the last address is "*" */
|
||||||
|
|
||||||
|
for ( /* void */ ; i < imip->naddrs - 1; i++) {
|
||||||
|
if (in_addr == imia[i].addr) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
s = ngx_pcalloc(c->pool, sizeof(ngx_imap_session_t));
|
||||||
|
if (s == NULL) {
|
||||||
|
ngx_imap_close_connection(c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->main_conf = imia[i].ctx->main_conf;
|
||||||
|
s->srv_conf = imia[i].ctx->srv_conf;
|
||||||
|
|
||||||
|
s->addr_text = &imia[i].addr_text;
|
||||||
|
|
||||||
|
c->data = s;
|
||||||
|
s->connection = c;
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%ui client %V connected to %V",
|
||||||
|
c->number, &c->addr_text, s->addr_text);
|
||||||
|
|
||||||
|
ctx = ngx_palloc(c->pool, sizeof(ngx_imap_log_ctx_t));
|
||||||
|
if (ctx == NULL) {
|
||||||
|
ngx_imap_close_connection(c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->client = &c->addr_text;
|
||||||
|
ctx->session = s;
|
||||||
|
|
||||||
c->log->connection = c->number;
|
c->log->connection = c->number;
|
||||||
c->log->handler = ngx_imap_log_error;
|
c->log->handler = ngx_imap_log_error;
|
||||||
c->log->data = lctx;
|
c->log->data = ctx;
|
||||||
c->log->action = "sending client greeting line";
|
c->log->action = "sending client greeting line";
|
||||||
|
|
||||||
c->log_error = NGX_ERROR_INFO;
|
c->log_error = NGX_ERROR_INFO;
|
||||||
|
|
||||||
#if (NGX_IMAP_SSL)
|
#if (NGX_IMAP_SSL)
|
||||||
|
|
||||||
ctx = c->ctx;
|
sslcf = ngx_imap_get_module_srv_conf(s, ngx_imap_ssl_module);
|
||||||
sslcf = ngx_imap_get_module_srv_conf(ctx, ngx_imap_ssl_module);
|
|
||||||
|
|
||||||
if (sslcf->enable) {
|
if (sslcf->enable) {
|
||||||
ngx_imap_ssl_init_connection(&sslcf->ssl, c);
|
ngx_imap_ssl_init_connection(&sslcf->ssl, c);
|
||||||
@ -96,6 +164,7 @@ ngx_imap_starttls_handler(ngx_event_t *rev)
|
|||||||
|
|
||||||
c = rev->data;
|
c = rev->data;
|
||||||
s = c->data;
|
s = c->data;
|
||||||
|
s->starttls = 1;
|
||||||
|
|
||||||
c->log->action = "in starttls state";
|
c->log->action = "in starttls state";
|
||||||
|
|
||||||
@ -108,7 +177,7 @@ ngx_imap_starttls_handler(ngx_event_t *rev)
|
|||||||
static void
|
static void
|
||||||
ngx_imap_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c)
|
ngx_imap_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c)
|
||||||
{
|
{
|
||||||
ngx_imap_conf_ctx_t *ctx;
|
ngx_imap_session_t *s;
|
||||||
ngx_imap_core_srv_conf_t *cscf;
|
ngx_imap_core_srv_conf_t *cscf;
|
||||||
|
|
||||||
if (ngx_ssl_create_connection(ssl, c, 0) == NGX_ERROR) {
|
if (ngx_ssl_create_connection(ssl, c, 0) == NGX_ERROR) {
|
||||||
@ -118,8 +187,9 @@ ngx_imap_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c)
|
|||||||
|
|
||||||
if (ngx_ssl_handshake(c) == NGX_AGAIN) {
|
if (ngx_ssl_handshake(c) == NGX_AGAIN) {
|
||||||
|
|
||||||
ctx = c->ctx;
|
s = c->data;
|
||||||
cscf = ngx_imap_get_module_srv_conf(ctx, ngx_imap_core_module);
|
|
||||||
|
cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module);
|
||||||
|
|
||||||
ngx_add_timer(c->read, cscf->timeout);
|
ngx_add_timer(c->read, cscf->timeout);
|
||||||
|
|
||||||
@ -135,9 +205,13 @@ ngx_imap_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c)
|
|||||||
static void
|
static void
|
||||||
ngx_imap_ssl_handshake_handler(ngx_connection_t *c)
|
ngx_imap_ssl_handshake_handler(ngx_connection_t *c)
|
||||||
{
|
{
|
||||||
|
ngx_imap_session_t *s;
|
||||||
|
|
||||||
if (c->ssl->handshaked) {
|
if (c->ssl->handshaked) {
|
||||||
|
|
||||||
if (c->data) {
|
s = c->data;
|
||||||
|
|
||||||
|
if (s->starttls) {
|
||||||
c->read->handler = ngx_imap_init_protocol;
|
c->read->handler = ngx_imap_init_protocol;
|
||||||
c->write->handler = ngx_imap_send;
|
c->write->handler = ngx_imap_send;
|
||||||
|
|
||||||
@ -160,24 +234,14 @@ static void
|
|||||||
ngx_imap_init_session(ngx_connection_t *c)
|
ngx_imap_init_session(ngx_connection_t *c)
|
||||||
{
|
{
|
||||||
ngx_imap_session_t *s;
|
ngx_imap_session_t *s;
|
||||||
ngx_imap_log_ctx_t *lctx;
|
|
||||||
ngx_imap_conf_ctx_t *ctx;
|
|
||||||
ngx_imap_core_srv_conf_t *cscf;
|
ngx_imap_core_srv_conf_t *cscf;
|
||||||
|
|
||||||
c->read->handler = ngx_imap_init_protocol;
|
c->read->handler = ngx_imap_init_protocol;
|
||||||
c->write->handler = ngx_imap_send;
|
c->write->handler = ngx_imap_send;
|
||||||
|
|
||||||
s = ngx_pcalloc(c->pool, sizeof(ngx_imap_session_t));
|
s = c->data;
|
||||||
if (s == NULL) {
|
|
||||||
ngx_imap_close_connection(c);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = c->ctx;
|
cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module);
|
||||||
cscf = ngx_imap_get_module_srv_conf(ctx, ngx_imap_core_module);
|
|
||||||
|
|
||||||
c->data = s;
|
|
||||||
s->connection = c;
|
|
||||||
|
|
||||||
s->protocol = cscf->protocol;
|
s->protocol = cscf->protocol;
|
||||||
|
|
||||||
@ -187,14 +251,8 @@ ngx_imap_init_session(ngx_connection_t *c)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->main_conf = ctx->main_conf;
|
|
||||||
s->srv_conf = ctx->srv_conf;
|
|
||||||
|
|
||||||
s->out = greetings[s->protocol];
|
s->out = greetings[s->protocol];
|
||||||
|
|
||||||
lctx = c->log->data;
|
|
||||||
lctx->session = s;
|
|
||||||
|
|
||||||
ngx_add_timer(c->read, cscf->timeout);
|
ngx_add_timer(c->read, cscf->timeout);
|
||||||
|
|
||||||
if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
|
if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
|
||||||
@ -896,8 +954,7 @@ ngx_imap_log_error(ngx_log_t *log, u_char *buf, size_t len)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = ngx_snprintf(buf, len, ", server: %V",
|
p = ngx_snprintf(buf, len, ", server: %V", s->addr_text);
|
||||||
&s->connection->listening->addr_text);
|
|
||||||
len -= p - buf;
|
len -= p - buf;
|
||||||
buf = p;
|
buf = p;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user