diff options
author | Igor Sysoev <igor@sysoev.ru> | 2004-12-02 21:40:46 +0300 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2004-12-02 21:40:46 +0300 |
commit | 42b12b34fa74c15cfb1746d71cde949f3d5807ef (patch) | |
tree | c44cd3f35d794e6e2be01d516e72737464f76fff /src | |
parent | 4e7b11b02bd42ed284a5f006a13b0635fc33d556 (diff) |
nginx-0.1.11-RELEASE importrelease-0.1.11
*) Feature: the worker_priority directive.
*) Change: both tcp_nopush and tcp_nodelay directives affect the
transferred response.
*) Bugfix: nginx did not call initgroups().
Thanks to Andrew Sitnikov and Andrei Nigmatulin.
*) Change: now the ngx_http_autoindex_module shows the file size in the
bytes.
*) Bugfix: the ngx_http_autoindex_module returned the 500 error if the
broken symlink was in a directory.
*) Bugfix: the files bigger than 4G could not be transferred using
sendfile.
*) Bugfix: if the backend was resolved to several backends and there
was an error while the response waiting then process may got caught
in an endless loop.
*) Bugfix: the worker process may exit with the "unknown cycle" message
when the /dev/poll method was used.
*) Bugfix: "close() channel failed" errors.
*) Bugfix: the autodetection of the "nobody" and "nogroup" groups.
*) Bugfix: the send_lowat directive did not work on Linux.
*) Bugfix: the segmentation fault occurred if there was no events
section in configuration.
*) Bugfix: nginx could not be built on OpenBSD.
*) Bugfix: the double slashes in "://" in the URI were converted to
":/".
Diffstat (limited to 'src')
42 files changed, 795 insertions, 307 deletions
diff --git a/src/core/nginx.c b/src/core/nginx.c index 887fc7997..26406b3e7 100644 --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -16,6 +16,7 @@ static ngx_int_t ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv); static void *ngx_core_module_create_conf(ngx_cycle_t *cycle); static char *ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf); static char *ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static ngx_conf_enum_t ngx_debug_points[] = { @@ -80,6 +81,13 @@ static ngx_command_t ngx_core_commands[] = { 0, NULL }, + { ngx_string("worker_priority"), + NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, + ngx_set_priority, + 0, + 0, + NULL }, + { ngx_string("pid"), NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_slot, @@ -447,6 +455,7 @@ static void *ngx_core_module_create_conf(ngx_cycle_t *cycle) * * ccf->pid = NULL; * ccf->newpid = NULL; + * ccf->priority = 0; */ ccf->daemon = NGX_CONF_UNSET; ccf->master = NGX_CONF_UNSET; @@ -494,6 +503,7 @@ static char *ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf) return NGX_CONF_ERROR; } + ccf->username = NGX_USER; ccf->user = pwd->pw_uid; grp = getgrnam(NGX_GROUP); @@ -562,6 +572,8 @@ static char *ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) value = (ngx_str_t *) cf->args->elts; + ccf->username = (char *) value[1].data; + pwd = getpwnam((const char *) value[1].data); if (pwd == NULL) { ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, @@ -586,3 +598,42 @@ static char *ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) #endif } + + +static char *ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_core_conf_t *ccf = conf; + + ngx_str_t *value; + ngx_uint_t n, minus; + + if (ccf->priority != 0) { + return "is duplicate"; + } + + value = cf->args->elts; + + if (value[1].data[0] == '-') { + n = 1; + minus = 1; + + } else if (value[1].data[0] == '+') { + n = 1; + minus = 0; + + } else { + n = 0; + minus = 0; + } + + ccf->priority = ngx_atoi(&value[1].data[n], value[1].len - n); + if (ccf->priority == NGX_ERROR) { + return "invalid number"; + } + + if (minus) { + ccf->priority = -ccf->priority; + } + + return NGX_CONF_OK; +} diff --git a/src/core/nginx.h b/src/core/nginx.h index 9b61fc959..3ac28f155 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,7 +8,7 @@ #define _NGINX_H_INCLUDED_ -#define NGINX_VER "nginx/0.1.10" +#define NGINX_VER "nginx/0.1.11" #define NGINX_VAR "NGINX" #define NGX_NEWPID_EXT ".newbin" diff --git a/src/core/ngx_buf.h b/src/core/ngx_buf.h index e2d07190a..768400d25 100644 --- a/src/core/ngx_buf.h +++ b/src/core/ngx_buf.h @@ -109,8 +109,8 @@ typedef struct { ((b->flush || b->last_buf) && !ngx_buf_in_memory(b) && !b->in_file) #define ngx_buf_size(b) \ - (ngx_buf_in_memory(b) ? (size_t) (b->last - b->pos): \ - (size_t) (b->file_last - b->file_pos)) + (ngx_buf_in_memory(b) ? (off_t) (b->last - b->pos): \ + (b->file_last - b->file_pos)) ngx_buf_t *ngx_create_temp_buf(ngx_pool_t *pool, size_t size); ngx_chain_t *ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs); diff --git a/src/core/ngx_config.h b/src/core/ngx_config.h index 7d4463b09..b72add7f7 100644 --- a/src/core/ngx_config.h +++ b/src/core/ngx_config.h @@ -39,6 +39,11 @@ #endif +#ifndef NGX_HAVE_SO_SNDLOWAT +#define NGX_HAVE_SO_SNDLOWAT 1 +#endif + + #if !(NGX_WIN32) #define ngx_signal_helper(n) SIG##n diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c index d91ba8567..9592a81e6 100644 --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -50,7 +50,6 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle) ngx_open_file_t *file; ngx_listening_t *ls, *nls; ngx_core_conf_t *ccf; - ngx_event_conf_t *ecf; ngx_core_module_t *module; log = old_cycle->log; @@ -434,12 +433,6 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle) } - ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module); - - ngx_log_error(NGX_LOG_INFO, cycle->log, 0, - "using the \"%s\" event method", ecf->name); - - /* close and delete stuff that lefts from an old cycle */ /* close the unneeded listening sockets */ diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h index 2baf82904..face67fe8 100644 --- a/src/core/ngx_cycle.h +++ b/src/core/ngx_cycle.h @@ -17,51 +17,54 @@ struct ngx_cycle_s { - void ****conf_ctx; - ngx_pool_t *pool; + void ****conf_ctx; + ngx_pool_t *pool; - ngx_log_t *log; - ngx_log_t *new_log; + ngx_log_t *log; + ngx_log_t *new_log; - ngx_array_t listening; - ngx_array_t pathes; - ngx_list_t open_files; + ngx_array_t listening; + ngx_array_t pathes; + ngx_list_t open_files; - ngx_uint_t connection_n; - ngx_connection_t *connections; - ngx_event_t *read_events; - ngx_event_t *write_events; + ngx_uint_t connection_n; + ngx_connection_t *connections; + ngx_event_t *read_events; + ngx_event_t *write_events; - ngx_cycle_t *old_cycle; + ngx_cycle_t *old_cycle; - ngx_str_t conf_file; - ngx_str_t root; + ngx_str_t conf_file; + ngx_str_t root; }; typedef struct { - ngx_flag_t daemon; - ngx_flag_t master; + ngx_flag_t daemon; + ngx_flag_t master; - ngx_int_t worker_processes; - ngx_int_t debug_points; + ngx_int_t worker_processes; + ngx_int_t debug_points; - ngx_uid_t user; - ngx_gid_t group; + int priority; - ngx_str_t pid; - ngx_str_t newpid; + char *username; + ngx_uid_t user; + ngx_gid_t group; + + ngx_str_t pid; + ngx_str_t newpid; #if (NGX_THREADS) - ngx_int_t worker_threads; - size_t thread_stack_size; + ngx_int_t worker_threads; + size_t thread_stack_size; #endif } ngx_core_conf_t; typedef struct { - ngx_pool_t *pool; /* pcre's malloc() pool */ + ngx_pool_t *pool; /* pcre's malloc() pool */ } ngx_core_tls_t; diff --git a/src/core/ngx_output_chain.c b/src/core/ngx_output_chain.c index 1c367ccad..b925e4867 100644 --- a/src/core/ngx_output_chain.c +++ b/src/core/ngx_output_chain.c @@ -28,7 +28,8 @@ static ngx_int_t ngx_output_chain_copy_buf(ngx_buf_t *dst, ngx_buf_t *src, ngx_int_t ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in) { int rc, last; - size_t size, bsize; + off_t bsize; + size_t size; ngx_chain_t *cl, *out, **last_out; if (ctx->in == NULL && ctx->busy == NULL) { @@ -81,6 +82,8 @@ ngx_int_t ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in) ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0, "zero size buf"); + ngx_debug_point(); + ctx->in = ctx->in->next; continue; @@ -118,18 +121,18 @@ ngx_int_t ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in) if (ctx->in->buf->last_buf) { - if (bsize < ctx->bufs.size) { + if (bsize < (off_t) ctx->bufs.size) { /* * allocate small temp buf for the small last buf * or its small last part */ - size = bsize; + size = (size_t) bsize; } else if (ctx->bufs.num == 1 - && (bsize < ctx->bufs.size - + (ctx->bufs.size >> 2))) + && (bsize < (off_t) (ctx->bufs.size + + (ctx->bufs.size >> 2)))) { /* * allocate a temp buf that equals @@ -137,7 +140,7 @@ ngx_int_t ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in) * than 1.25 of bufs.size and a temp buf is single */ - size = bsize; + size = (size_t) bsize; } } @@ -306,12 +309,12 @@ static ngx_int_t ngx_output_chain_add_copy(ngx_pool_t *pool, static ngx_int_t ngx_output_chain_copy_buf(ngx_buf_t *dst, ngx_buf_t *src, ngx_uint_t sendfile) { - size_t size; + off_t size; ssize_t n; size = ngx_buf_size(src); - if (size > (size_t) (dst->end - dst->pos)) { + if (size > dst->end - dst->pos) { size = dst->end - dst->pos; } @@ -324,9 +327,9 @@ static ngx_int_t ngx_output_chain_copy_buf(ngx_buf_t *dst, ngx_buf_t *src, #endif if (ngx_buf_in_memory(src)) { - ngx_memcpy(dst->pos, src->pos, size); - src->pos += size; - dst->last += size; + ngx_memcpy(dst->pos, src->pos, (size_t) size); + src->pos += (size_t) size; + dst->last += (size_t) size; if (src->in_file) { @@ -351,7 +354,7 @@ static ngx_int_t ngx_output_chain_copy_buf(ngx_buf_t *dst, ngx_buf_t *src, } } else { - n = ngx_read_file(src->file, dst->pos, size, src->file_pos); + n = ngx_read_file(src->file, dst->pos, (size_t) size, src->file_pos); if (n == NGX_ERROR) { return n; @@ -363,9 +366,9 @@ static ngx_int_t ngx_output_chain_copy_buf(ngx_buf_t *dst, ngx_buf_t *src, } #endif - if ((size_t) n != size) { + if (n != size) { ngx_log_error(NGX_LOG_ALERT, src->file->log, 0, - ngx_read_file_n " reads only %z of %uz from file", + ngx_read_file_n " reads only %z of %O from file", n, size); if (n == 0) { return NGX_ERROR; @@ -399,10 +402,19 @@ ngx_int_t ngx_chain_writer(void *data, ngx_chain_t *in) { ngx_chain_writer_ctx_t *ctx = data; + off_t size; ngx_chain_t *cl; - for (/* void */; in; in = in->next) { + for (size = 0; in; in = in->next) { + +#if 1 + if (ngx_buf_size(in->buf) == 0 && !ngx_buf_special(in->buf)) { + ngx_debug_point(); + } +#endif + + size += ngx_buf_size(in->buf); ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->connection->log, 0, "chain writer buf size: %uz", ngx_buf_size(in->buf)); @@ -419,6 +431,23 @@ ngx_int_t ngx_chain_writer(void *data, ngx_chain_t *in) ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->connection->log, 0, "chain writer in: %p", ctx->out); + for (cl = ctx->out; cl; cl = cl->next) { + +#if 1 + + if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) { + ngx_debug_point(); + } + +#endif + + size += ngx_buf_size(cl->buf); + } + + if (size == 0) { + return NGX_OK; + } + ctx->out = ngx_send_chain(ctx->connection, ctx->out, ctx->limit); ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->connection->log, 0, diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c index 4e5d273c3..4c21fa61c 100644 --- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c @@ -30,7 +30,7 @@ u_char *ngx_cpystrn(u_char *dst, u_char *src, size_t n) /* * supported formats: - * %[0][width]O off_t + * %[0][width][x][X]O off_t * %[0][width]T time_t * %[0][width][u][x|X]z ssize_t/size_t * %[0][width][u][x|X]d int/u_int diff --git a/src/event/modules/ngx_devpoll_module.c b/src/event/modules/ngx_devpoll_module.c index 1a48ceccf..34775f2b1 100644 --- a/src/event/modules/ngx_devpoll_module.c +++ b/src/event/modules/ngx_devpoll_module.c @@ -435,6 +435,16 @@ int ngx_devpoll_process_events(ngx_cycle_t *cycle) c = &ngx_cycle->connections[event_list[i].fd]; if (c->fd == -1) { + if (ngx_cycle->read_events[event_list[i].fd].closed) { + continue; + } + + ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "unexpected event"); + continue; + } + +#if 0 + if (c->fd == -1) { old_cycle = ngx_old_cycles.elts; for (j = 0; j < ngx_old_cycles.nelts; j++) { if (old_cycle[j] == NULL) { @@ -451,6 +461,7 @@ int ngx_devpoll_process_events(ngx_cycle_t *cycle) ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "unknown cycle"); exit(1); } +#endif ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "devpoll: fd:%d, ev:%04Xd, rev:%04Xd", diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c index bd451bc65..ef25ffc51 100644 --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -174,10 +174,25 @@ static ngx_int_t ngx_event_module_init(ngx_cycle_t *cycle) { #if !(NGX_WIN32) - size_t size; - char *shared; - ngx_core_conf_t *ccf; - ngx_event_conf_t *ecf; + size_t size; + void ***cf; + char *shared; + ngx_core_conf_t *ccf; + ngx_event_conf_t *ecf; + + cf = ngx_get_conf(cycle->conf_ctx, ngx_events_module); + + if (cf == NULL) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, + "no \"events\" section in configuration"); + return NGX_ERROR; + } + + ecf = (*cf)[ngx_event_core_module.ctx_index]; + + ngx_log_error(NGX_LOG_INFO, cycle->log, 0, + "using the \"%s\" event method", ecf->name); + ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); @@ -185,8 +200,6 @@ static ngx_int_t ngx_event_module_init(ngx_cycle_t *cycle) return NGX_OK; } - ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module); - /* TODO: 128 is cache line size */ diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c index c06896895..6f0d94f86 100644 --- a/src/event/ngx_event_connect.c +++ b/src/event/ngx_event_connect.c @@ -81,9 +81,12 @@ ngx_int_t ngx_event_connect_peer(ngx_peer_connection_t *pc) for ( ;; ) { peer = &pc->peers->peers[pc->cur_peer]; - if (peer->fails <= pc->peers->max_fails - || (now - peer->accessed > pc->peers->fail_timeout)) - { + if (peer->fails <= pc->peers->max_fails) { + break; + } + + if (now - peer->accessed > pc->peers->fail_timeout) { + peer->fails = 0; break; } diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index 294f3b4ce..c0ec6adfe 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -9,7 +9,9 @@ #include <ngx_event.h> +static void ngx_ssl_write_handler(ngx_event_t *wev); static ssize_t ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size); +static void ngx_ssl_read_handler(ngx_event_t *rev); ngx_int_t ngx_ssl_init(ngx_log_t *log) @@ -69,6 +71,25 @@ ssize_t ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size) ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_read: %d", n); if (n > 0) { + if (c->ssl->saved_write_handler) { + + c->write->event_handler = c->ssl->saved_write_handler; + c->ssl->saved_write_handler = NULL; + c->write->ready = 1; + + if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { + return NGX_ERROR; + } + + if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { + return NGX_ERROR; + } + + ngx_post_event(c->write); + + ngx_mutex_unlock(ngx_posted_events_mutex); + } + return n; } @@ -93,13 +114,27 @@ ssize_t ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size) if (sslerr == SSL_ERROR_WANT_WRITE) { ngx_log_error(NGX_LOG_ALERT, c->log, err, "SSL wants to write%s", handshake); - return NGX_ERROR; -#if 0 + + c->write->ready = 0; + + if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { + return NGX_ERROR; + } + + /* + * we do not set the timer because there is already the read event timer + */ + + if (c->ssl->saved_write_handler == NULL) { + c->ssl->saved_write_handler = c->write->event_handler; + c->write->event_handler = ngx_ssl_write_handler; + } + return NGX_AGAIN; -#endif } c->ssl->no_rcv_shut = 1; + c->ssl->no_send_shut = 1; if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) { ngx_log_error(NGX_LOG_INFO, c->log, err, @@ -115,9 +150,18 @@ ssize_t ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size) } +static void ngx_ssl_write_handler(ngx_event_t *wev) +{ + ngx_connection_t *c; + + c = wev->data; + c->read->event_handler(c->read); +} + + /* * OpenSSL has no SSL_writev() so we copy several bufs into our 16K buffer - * before SSL_write() call to decrease a SSL overhead. + * before the SSL_write() call to decrease a SSL overhead. * * Besides for protocols such as HTTP it is possible to always buffer * the output to decrease a SSL overhead some more. @@ -155,6 +199,14 @@ ngx_chain_t *ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, return in; } + + /* the maximum limit size is the maximum uint32_t value - the page size */ + + if (limit == 0 || limit > NGX_MAX_UINT32_VALUE - ngx_pagesize) { + limit = NGX_MAX_UINT32_VALUE - ngx_pagesize; + } + + send = 0; flush = (in == NULL) ? 1 : 0; @@ -252,6 +304,25 @@ static ssize_t ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size) ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_write: %d", n); if (n > 0) { + if (c->ssl->saved_read_handler) { + + c->read->event_handler = c->ssl->saved_read_handler; + c->ssl->saved_read_handler = NULL; + c->read->ready = 1; + + if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { + return NGX_ERROR; + } + + if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { + return NGX_ERROR; + } + + ngx_post_event(c->read); + + ngx_mutex_unlock(ngx_posted_events_mutex); + } + return n; } @@ -277,13 +348,28 @@ static ssize_t ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size) ngx_log_error(NGX_LOG_ALERT, c->log, err, "SSL wants to read%s", handshake); - return NGX_ERROR; -#if 0 + + c->read->ready = 0; + + if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { + return NGX_ERROR; + } + + /* + * we do not set the timer because there is already + * the write event timer + */ + + if (c->ssl->saved_read_handler == NULL) { + c->ssl->saved_read_handler = c->read->event_handler; + c->read->event_handler = ngx_ssl_read_handler; + } + return NGX_AGAIN; -#endif } c->ssl->no_rcv_shut = 1; + c->ssl->no_send_shut = 1; ngx_ssl_error(NGX_LOG_ALERT, c->log, err, "SSL_write() failed"); @@ -291,21 +377,42 @@ static ssize_t ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size) } +static void ngx_ssl_read_handler(ngx_event_t *rev) +{ + ngx_connection_t *c; + + c = rev->data; + c->write->event_handler(c->write); +} + + ngx_int_t ngx_ssl_shutdown(ngx_connection_t *c) { - int n, sslerr; + int n, sslerr, mode; ngx_uint_t again; - if (c->timedout) { - SSL_set_shutdown(c->ssl->ssl, SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN); + if (!c->ssl->shutdown_set) { - } else { - if (c->ssl->no_rcv_shut) { - SSL_set_shutdown(c->ssl->ssl, SSL_RECEIVED_SHUTDOWN); + /* it seems that SSL_set_shutdown() could be called once only */ + + if (c->read->timedout) { + mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN; + + } else { + mode = 0; + + if (c->ssl->no_rcv_shut) { + mode = SSL_RECEIVED_SHUTDOWN; + } + + if (c->ssl->no_send_shut) { + mode |= SSL_SENT_SHUTDOWN; + } } - if (c->ssl->no_send_shut) { - SSL_set_shutdown(c->ssl->ssl, SSL_SENT_SHUTDOWN); + if (mode) { + SSL_set_shutdown(c->ssl->ssl, mode); + c->ssl->shutdown_set = 1; } } @@ -319,17 +426,17 @@ ngx_int_t ngx_ssl_shutdown(ngx_connection_t *c) ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n); - if (n == 0) { - again = 1; - break; - } - - if (n == 1) { + if (n == 1 || (n == 0 && c->read->timedout)) { SSL_free(c->ssl->ssl); c->ssl = NULL; return NGX_OK; } + if (n == 0) { + again = 1; + break; + } + break; } @@ -342,7 +449,7 @@ ngx_int_t ngx_ssl_shutdown(ngx_connection_t *c) if (again || sslerr == SSL_ERROR_WANT_READ) { - ngx_add_timer(c->read, 10000); + ngx_add_timer(c->read, 30000); if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { return NGX_ERROR; diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h index dbdb5f7b3..6e7b705b1 100644 --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -18,11 +18,13 @@ typedef struct { SSL *ssl; ngx_buf_t *buf; - ngx_event_handler_pt saved_handler; + ngx_event_handler_pt saved_read_handler; + ngx_event_handler_pt saved_write_handler; unsigned buffer:1; unsigned no_rcv_shut:1; unsigned no_send_shut:1; + unsigned shutdown_set:1; } ngx_ssl_t; @@ -48,10 +50,5 @@ ngx_int_t ngx_ssl_shutdown(ngx_connection_t *c); void ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...); -#define ngx_ssl_set_nosendshut(ssl) \ - if (ssl) { \ - ssl->no_send_shut = 1; \ - } - #endif /* _NGX_EVENT_OPENSSL_H_INCLUDED_ */ diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c index 3ca8a0cf3..310f0ce43 100644 --- a/src/event/ngx_event_pipe.c +++ b/src/event/ngx_event_pipe.c @@ -379,7 +379,7 @@ ngx_int_t ngx_event_pipe_read_upstream(ngx_event_pipe_t *p) ngx_int_t ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p) { - size_t bsize; + off_t bsize; ngx_uint_t flush; ngx_buf_t *b; ngx_chain_t *out, **ll, *cl, *tl; @@ -442,7 +442,7 @@ ngx_int_t ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p) } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, - "pipe write busy: %uz", bsize); + "pipe write busy: %O", bsize); out = NULL; ll = NULL; diff --git a/src/event/ngx_event_pipe.h b/src/event/ngx_event_pipe.h index 961f0666b..9781820d9 100644 --- a/src/event/ngx_event_pipe.h +++ b/src/event/ngx_event_pipe.h @@ -62,7 +62,7 @@ struct ngx_event_pipe_s { ngx_bufs_t bufs; ngx_buf_tag_t tag; - size_t busy_size; + ssize_t busy_size; off_t read_length; diff --git a/src/http/modules/ngx_http_autoindex_handler.c b/src/http/modules/ngx_http_autoindex_handler.c index f5ec9704f..ac2438e7f 100644 --- a/src/http/modules/ngx_http_autoindex_handler.c +++ b/src/http/modules/ngx_http_autoindex_handler.c @@ -105,11 +105,10 @@ static u_char tail[] = static ngx_int_t ngx_http_autoindex_handler(ngx_http_request_t *r) { - u_char *last, scale; + u_char *last; size_t len; - off_t length; ngx_tm_t tm; - ngx_int_t rc, size; + ngx_int_t rc; ngx_uint_t i, level; ngx_err_t err; ngx_buf_t *b; @@ -307,7 +306,7 @@ static ngx_int_t ngx_http_autoindex_handler(ngx_http_request_t *r) + NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof(">") - 2 + sizeof("</a>") - 1 + sizeof(" 28-Sep-1970 12:00 ") - 1 - + sizeof("1023G") - 1 + + 19 + 2; } @@ -383,44 +382,11 @@ static ngx_int_t ngx_http_autoindex_handler(ngx_http_request_t *r) tm.ngx_tm_min); if (entry[i].dir) { - b->last = ngx_cpymem(b->last, " -", sizeof(" -") - 1); + b->last = ngx_cpymem(b->last, " -", + sizeof(" -") - 1); } else { - length = entry[i].size; - - if (length > 1024 * 1024 * 1024 - 1) { - size = (ngx_int_t) (length / (1024 * 1024 * 1024)); - if ((length % (1024 * 1024 * 1024)) - > (1024 * 1024 * 1024 / 2 - 1)) - { - size++; - } - scale = 'G'; - - } else if (length > 1024 * 1024 - 1) { - size = (ngx_int_t) (length / (1024 * 1024)); - if ((length % (1024 * 1024)) > (1024 * 1024 / 2 - 1)) { - size++; - } - scale = 'M'; - - } else if (length > 9999) { - size = (ngx_int_t) (length / 1024); - if (length % 1024 > 511) { - size++; - } - scale = 'K'; - - } else { - size = (ngx_int_t) length; - scale = ' '; - } - - b->last = ngx_sprintf(b->last, "%4i", size); - - if (scale != ' ') { - *b->last++ = scale; - } + b->last = ngx_sprintf(b->last, "%19O", entry[i].size); } *b->last++ = CR; diff --git a/src/http/modules/ngx_http_chunked_filter.c b/src/http/modules/ngx_http_chunked_filter.c index 929a7ed2c..5134151ed 100644 --- a/src/http/modules/ngx_http_chunked_filter.c +++ b/src/http/modules/ngx_http_chunked_filter.c @@ -63,7 +63,7 @@ static ngx_int_t ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { u_char *chunk; - size_t size; + off_t size; ngx_buf_t *b; ngx_chain_t out, tail, *cl, *tl, **ll; @@ -106,13 +106,14 @@ static ngx_int_t ngx_http_chunked_body_filter(ngx_http_request_t *r, return NGX_ERROR; } - if (!(chunk = ngx_palloc(r->pool, sizeof("00000000" CRLF) - 1))) { + chunk = ngx_palloc(r->pool, sizeof("0000000000000000" CRLF) - 1); + if (chunk == NULL) { return NGX_ERROR; } b->temporary = 1; b->pos = chunk; - b->last = ngx_sprintf(chunk, "%xz" CRLF, size); + b->last = ngx_sprintf(chunk, "%xO" CRLF, size); out.buf = b; } diff --git a/src/http/modules/ngx_http_index_handler.c b/src/http/modules/ngx_http_index_handler.c index 3386953bd..74ccf0ae1 100644 --- a/src/http/modules/ngx_http_index_handler.c +++ b/src/http/modules/ngx_http_index_handler.c @@ -448,8 +448,7 @@ static char *ngx_http_index_merge_loc_conf(ngx_conf_t *cf, ngx_http_index_loc_conf_t *prev = parent; ngx_http_index_loc_conf_t *conf = child; - ngx_uint_t i; - ngx_str_t *index, *prev_index; + ngx_str_t *index; if (conf->max_index_len == 0) { if (prev->max_index_len != 0) { @@ -465,6 +464,8 @@ static char *ngx_http_index_merge_loc_conf(ngx_conf_t *cf, return NGX_CONF_OK; } +#if 0 + if (prev->max_index_len != 0) { prev_index = prev->indices.elts; @@ -476,6 +477,8 @@ static char *ngx_http_index_merge_loc_conf(ngx_conf_t *cf, } } +#endif + if (conf->max_index_len < prev->max_index_len) { conf->max_index_len = prev->max_index_len; } diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c index 425a1a6af..651dfa67b 100644 --- a/src/http/modules/proxy/ngx_http_proxy_handler.c +++ b/src/http/modules/proxy/ngx_http_proxy_handler.c @@ -275,12 +275,9 @@ ngx_module_t ngx_http_proxy_module = { static ngx_http_log_op_name_t ngx_http_proxy_log_fmt_ops[] = { - { ngx_string("proxy"), /* STUB */ 100, - ngx_http_proxy_log_proxy_state }, - { ngx_string("proxy_cache_state"), sizeof("BYPASS") - 1, - ngx_http_proxy_log_cache_state }, - { ngx_string("proxy_reason"), sizeof("BPS") - 1, - ngx_http_proxy_log_reason }, + { ngx_string("proxy"), 0, ngx_http_proxy_log_proxy_state }, + { ngx_string("proxy_cache_state"), 0, ngx_http_proxy_log_cache_state }, + { ngx_string("proxy_reason"), 0, ngx_http_proxy_log_reason }, { ngx_null_string, 0, NULL } }; @@ -792,111 +789,180 @@ u_char *ngx_http_proxy_log_error(void *data, u_char *buf, size_t len) static u_char *ngx_http_proxy_log_proxy_state(ngx_http_request_t *r, u_char *buf, uintptr_t data) { - ngx_http_proxy_ctx_t *p; + ngx_uint_t i; + ngx_http_proxy_ctx_t *p; + ngx_http_proxy_state_t *state; p = ngx_http_get_module_err_ctx(r, ngx_http_proxy_module); if (p == NULL) { + if (buf == NULL) { + return (u_char *) 1; + } + *buf = '-'; return buf + 1; } - if (p->state->cache_state == 0) { - *buf++ = '-'; - } else { - buf = ngx_cpymem(buf, cache_states[p->state->cache_state - 1].data, - cache_states[p->state->cache_state - 1].len); + if (buf == NULL) { + /* find the request line length */ + return (u_char *) (uintptr_t) (p->states.nelts * /* STUB */ 100); } - *buf++ = '/'; - if (p->state->expired == 0) { - *buf++ = '-'; + i = 0; + state = p->states.elts; - } else { - buf = ngx_sprintf(buf, "%T", p->state->expired); - } + for ( ;; ) { + if (state[i].cache_state == 0) { + *buf++ = '-'; - *buf++ = '/'; + } else { + buf = ngx_cpymem(buf, cache_states[state[i].cache_state - 1].data, + cache_states[state[i].cache_state - 1].len); + } - if (p->state->bl_time == 0) { - *buf++ = '-'; + *buf++ = '/'; - } else { - buf = ngx_sprintf(buf, "%T", p->state->bl_time); - } + if (state[i].expired == 0) { + *buf++ = '-'; - *buf++ = '/'; + } else { + buf = ngx_sprintf(buf, "%T", state[i].expired); + } - *buf++ = '*'; + *buf++ = '/'; - *buf++ = ' '; + if (state[i].bl_time == 0) { + *buf++ = '-'; - if (p->state->status == 0) { - *buf++ = '-'; + } else { + buf = ngx_sprintf(buf, "%T", state[i].bl_time); + } - } else { - buf = ngx_sprintf(buf, "%ui", p->state->status); - } + *buf++ = '/'; - *buf++ = '/'; + *buf++ = '*'; - if (p->state->reason == 0) { - *buf++ = '-'; + *buf++ = ' '; - } else { - buf = ngx_cpymem(buf, cache_reasons[p->state->reason - 1].data, - cache_reasons[p->state->reason - 1].len); - } + if (state[i].status == 0) { + *buf++ = '-'; + + } else { + buf = ngx_sprintf(buf, "%ui", state[i].status); + } - *buf++ = '/'; + *buf++ = '/'; - if (p->state->reason < NGX_HTTP_PROXY_CACHE_XAE) { - *buf++ = '-'; + if (state[i].reason == 0) { + *buf++ = '-'; - } else { - buf = ngx_sprintf(buf, "%T", p->state->expires); - } + } else { + buf = ngx_cpymem(buf, cache_reasons[state[i].reason - 1].data, + cache_reasons[state[i].reason - 1].len); + } + + *buf++ = '/'; + + if (state[i].reason < NGX_HTTP_PROXY_CACHE_XAE) { + *buf++ = '-'; + + } else { + buf = ngx_sprintf(buf, "%T", state[i].expires); + } - *buf++ = ' '; - *buf++ = '*'; + *buf++ = ' '; + *buf++ = '*'; - return buf; + if (++i == p->states.nelts) { + return buf; + } + + *buf++ = ','; + *buf++ = ' '; + } } static u_char *ngx_http_proxy_log_cache_state(ngx_http_request_t *r, u_char *buf, uintptr_t data) { - ngx_http_proxy_ctx_t *p; + ngx_uint_t i; + ngx_http_proxy_ctx_t *p; + ngx_http_proxy_state_t *state; p = ngx_http_get_module_err_ctx(r, ngx_http_proxy_module); if (p == NULL || p->state->cache_state == 0) { + if (buf == NULL) { + return (u_char *) 1; + } + *buf = '-'; return buf + 1; } - return ngx_cpymem(buf, cache_states[p->state->cache_state - 1].data, - cache_states[p->state->cache_state - 1].len); + if (buf == NULL) { + /* find the request line length */ + return (u_char *) (p->states.nelts * sizeof("BYPASS") - 1); + } + + i = 0; + state = p->states.elts; + + for ( ;; ) { + buf = ngx_cpymem(buf, cache_states[state[i].cache_state - 1].data, + cache_states[state[i].cache_state - 1].len); + + if (++i == p->states.nelts) { + return buf; + } + + *buf++ = ','; + *buf++ = ' '; + } } static u_char *ngx_http_proxy_log_reason(ngx_http_request_t *r, u_char *buf, uintptr_t data) { - ngx_http_proxy_ctx_t *p; + ngx_uint_t i; + ngx_http_proxy_ctx_t *p; + ngx_http_proxy_state_t *state; p = ngx_http_get_module_err_ctx(r, ngx_http_proxy_module); if (p == NULL || p->state->reason == 0) { + if (buf == NULL) { + return (u_char *) 1; + } + *buf = '-'; return buf + 1; } - return ngx_cpymem(buf, cache_reasons[p->state->reason - 1].data, - cache_reasons[p->state->reason - 1].len); + if (buf == NULL) { + /* find the request line length */ + return (u_char *) (p->states.nelts * sizeof("BPS") - 1); + } + + i = 0; + state = p->states.elts; + + for ( ;; ) { + buf = ngx_cpymem(buf, cache_reasons[state[i].reason - 1].data, + cache_reasons[state[i].reason - 1].len); + + if (++i == p->states.nelts) { + return buf; + } + + *buf++ = ','; + *buf++ = ' '; + } } @@ -1387,9 +1453,8 @@ static char *ngx_http_proxy_parse_upstream(ngx_str_t *url, static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data) { - ssize_t *np = data; - #if (NGX_FREEBSD) + ssize_t *np = data; if (*np >= ngx_freebsd_net_inet_tcp_sendspace) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, @@ -1401,6 +1466,7 @@ static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data) } #elif !(NGX_HAVE_SO_SNDLOWAT) + ssize_t *np = data; ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "\"proxy_send_lowat\" is not supported, ignored"); diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c index 23d40c493..47d2b17df 100644 --- a/src/http/modules/proxy/ngx_http_proxy_upstream.c +++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c @@ -528,6 +528,7 @@ static void ngx_http_proxy_reinit_upstream(ngx_http_proxy_ctx_t *p) { ngx_chain_t *cl; ngx_output_chain_ctx_t *output; + ngx_http_proxy_state_e state; /* reinit the request chain */ @@ -560,11 +561,17 @@ static void ngx_http_proxy_reinit_upstream(ngx_http_proxy_ctx_t *p) /* add one more state */ + state = p->state->cache_state; + if (!(p->state = ngx_push_array(&p->states))) { ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } + ngx_memzero(p->state, sizeof(ngx_http_proxy_state_t)); + + p->state->cache_state = state; + p->status = 0; p->status_count = 0; } @@ -719,9 +726,9 @@ static void ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p) writer->out = NULL; writer->last = &writer->out; writer->connection = c; - writer->limit = OFF_T_MAX_VALUE; + writer->limit = 0; - if (p->upstream->peer.tries > 1 && p->request_sent) { + if (p->request_sent) { ngx_http_proxy_reinit_upstream(p); } @@ -803,13 +810,13 @@ static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p) p->request_sent ? NULL: p->request->request_body->bufs); + p->request_sent = 1; + if (rc == NGX_ERROR) { ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR); return; } - p->request_sent = 1; - if (c->write->timer_set) { ngx_del_timer(c->write); } diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h index aa6690265..c882b3006 100644 --- a/src/http/ngx_http_cache.h +++ b/src/http/ngx_http_cache.h @@ -97,6 +97,11 @@ typedef struct { } ngx_http_cache_t; +typedef struct { + ngx_path_t path; + ngx_str_t key; +} ngx_http_cache_ctx_t; + #define NGX_HTTP_CACHE_STALE 1 #define NGX_HTTP_CACHE_AGED 2 diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index c4cb8b9f0..e3ccd8ff6 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -1815,9 +1815,8 @@ static char *ngx_set_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) static char *ngx_http_lowat_check(ngx_conf_t *cf, void *post, void *data) { - ssize_t *np = data; - #if (NGX_FREEBSD) + ssize_t *np = data; if (*np >= ngx_freebsd_net_inet_tcp_sendspace) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, @@ -1829,6 +1828,7 @@ static char *ngx_http_lowat_check(ngx_conf_t *cf, void *post, void *data) } #elif !(NGX_HAVE_SO_SNDLOWAT) + ssize_t *np = data; ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "\"send_lowat\" is not supported, ignored"); diff --git a/src/http/ngx_http_header_filter.c b/src/http/ngx_http_header_filter.c index 3fa11086d..31fa82635 100644 --- a/src/http/ngx_http_header_filter.c +++ b/src/http/ngx_http_header_filter.c @@ -252,9 +252,7 @@ static ngx_int_t ngx_http_header_filter(ngx_http_request_t *r) * Konqueror keeps the connection alive for about N seconds. */ - if (clcf->keepalive_header - && (r->headers_in.gecko || r->headers_in.konqueror)) - { + if (clcf->keepalive_header) { len += sizeof("Keep-Alive: timeout=") - 1 + TIME_T_LEN + 2; } @@ -384,9 +382,7 @@ static ngx_int_t ngx_http_header_filter(ngx_http_request_t *r) b->last = ngx_cpymem(b->last, "Connection: keep-alive" CRLF, sizeof("Connection: keep-alive" CRLF) - 1); - if (clcf->keepalive_header - && (r->headers_in.gecko || r->headers_in.konqueror)) - { + if (clcf->keepalive_header) { b->last = ngx_sprintf(b->last, "Keep-Alive: timeout=%T" CRLF, clcf->keepalive_header); } diff --git a/src/http/ngx_http_log_handler.c b/src/http/ngx_http_log_handler.c index 581a1ce65..fd373444e 100644 --- a/src/http/ngx_http_log_handler.c +++ b/src/http/ngx_http_log_handler.c @@ -166,7 +166,10 @@ ngx_int_t ngx_http_log_handler(ngx_http_request_t *r) len++; #endif - ngx_test_null(line, ngx_palloc(r->pool, len), NGX_ERROR); + if (!(line = ngx_palloc(r->pool, len))) { + return NGX_ERROR; + } + p = line; for (i = 0; i < log[l].ops->nelts; i++) { diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c index 96ed49c74..77db813ae 100644 --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -665,6 +665,8 @@ ngx_int_t ngx_http_parse_complex_uri(ngx_http_request_t *r) u_char c, ch, decoded, *p, *u; enum { sw_usual = 0, + sw_colon, + sw_colon_slash, sw_slash, sw_dot, sw_dot_dot, @@ -730,9 +732,70 @@ ngx_int_t ngx_http_parse_complex_uri(ngx_http_request_t *r) case '?': r->args_start = p; break; + case ':': + state = sw_colon; + *u++ = ch; + break; case '.': r->uri_ext = u + 1; + *u++ = ch; + break; + default: + *u++ = ch; + break; + } + ch = *p++; + break; + + case sw_colon: + switch(ch) { +#if (NGX_WIN32) + case '\\': + state = sw_colon_slash; + *u++ = '/'; + break; +#endif + case '/': + state = sw_colon_slash; + *u++ = ch; + break; + case ':': + *u++ = ch; + break; + case '%': + quoted_state = state; + state = sw_quoted; + break; default: + state = sw_usual; + *u++ = ch; + break; + } + ch = *p++; + break; + + case sw_colon_slash: + switch(ch) { +#if (NGX_WIN32) + case '\\': + state = sw_slash; + *u++ = '/'; + break; +#endif + case '/': + state = sw_slash; + *u++ = ch; + break; + case '.': + state = sw_dot; + *u++ = ch; + break; + case '%': + quoted_state = state; + state = sw_quoted; + break; + default: + state = sw_usual; *u++ = ch; break; } diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index b6013fcea..fe3d516cf 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -1190,8 +1190,9 @@ static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r) #if 0 /* MSIE ignores the SSL "close notify" alert */ - - ngx_ssl_set_nosendshut(r->connection->ssl); + if (c->ssl) { + r->connection->ssl->no_send_shut = 1; + } #endif } @@ -1269,7 +1270,7 @@ void ngx_http_finalize_request(ngx_http_request_t *r, int rc) } if (r->connection->read->pending_eof) { -#if (NGX_KQUEUE) +#if (NGX_HAVE_KQUEUE) ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, r->connection->read->kq_errno, "kevent() reported about an closed connection"); @@ -1702,24 +1703,26 @@ static void ngx_http_set_keepalive(ngx_http_request_t *r) } c->tcp_nopush = NGX_TCP_NOPUSH_UNSET; + tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0; } else { - if (clcf->tcp_nodelay && !c->tcp_nodelay) { - tcp_nodelay = 1; + tcp_nodelay = 1; + } - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); + if (tcp_nodelay && clcf->tcp_nodelay && !c->tcp_nodelay) { - if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, - (const void *) &tcp_nodelay, sizeof(int)) == -1) - { - ngx_connection_error(c, ngx_socket_errno, - "setsockopt(TCP_NODELAY) failed"); - ngx_http_close_connection(c); - return; - } + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); - c->tcp_nodelay = 1; + if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, + (const void *) &tcp_nodelay, sizeof(int)) == -1) + { + ngx_connection_error(c, ngx_socket_errno, + "setsockopt(TCP_NODELAY) failed"); + ngx_http_close_connection(c); + return; } + + c->tcp_nodelay = 1; } #if 0 @@ -1761,6 +1764,11 @@ static void ngx_http_keepalive_handler(ngx_event_t *rev) ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno, "kevent() reported that client %V closed " "keepalive connection", ctx->client); +#if (NGX_HTTP_SSL) + if (c->ssl) { + c->ssl->no_send_shut = 1; + } +#endif ngx_http_close_connection(c); return; } diff --git a/src/http/ngx_http_write_filter.c b/src/http/ngx_http_write_filter.c index 67f686267..50e8bc249 100644 --- a/src/http/ngx_http_write_filter.c +++ b/src/http/ngx_http_write_filter.c @@ -152,8 +152,7 @@ ngx_int_t ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in) sent = c->sent; - chain = c->send_chain(c, ctx->out, - clcf->limit_rate ? clcf->limit_rate: OFF_T_MAX_VALUE); + chain = c->send_chain(c, ctx->out, clcf->limit_rate); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http write filter %p", chain); diff --git a/src/os/unix/ngx_aio_write_chain.c b/src/os/unix/ngx_aio_write_chain.c index 4d45f079a..c1109dc12 100644 --- a/src/os/unix/ngx_aio_write_chain.c +++ b/src/os/unix/ngx_aio_write_chain.c @@ -20,6 +20,12 @@ ngx_chain_t *ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in, ngx_err_t err; ngx_chain_t *cl; + /* the maximum limit size is the maximum size_t value - the page size */ + + if (limit == 0 || limit > MAX_SIZE_T_VALUE - ngx_pagesize) { + limit = MAX_SIZE_T_VALUE - ngx_pagesize; + } + send = 0; sent = 0; cl = in; diff --git a/src/os/unix/ngx_files.h b/src/os/unix/ngx_files.h index 03de946a3..be9cebe6f 100644 --- a/src/os/unix/ngx_files.h +++ b/src/os/unix/ngx_files.h @@ -104,7 +104,7 @@ ngx_int_t ngx_open_dir(ngx_str_t *name, ngx_dir_t *dir); #else #define ngx_de_namelen(dir) ngx_strlen((dir)->de->d_name) #endif -#define ngx_de_info(name, dir) stat((const char *) name, &(dir)->info) +#define ngx_de_info(name, dir) lstat((const char *) name, &(dir)->info) #define ngx_de_info_n "stat()" #define ngx_de_is_dir(dir) (S_ISDIR((dir)->info.st_mode)) #define ngx_de_is_file(dir) (S_ISREG((dir)->info.st_mode)) diff --git a/src/os/unix/ngx_freebsd_init.c b/src/os/unix/ngx_freebsd_init.c index b76dc0cb9..044d9d5c9 100644 --- a/src/os/unix/ngx_freebsd_init.c +++ b/src/os/unix/ngx_freebsd_init.c @@ -204,6 +204,9 @@ ngx_int_t ngx_os_init(ngx_log_t *log) } + ngx_tcp_nodelay_and_tcp_nopush = 1; + + return ngx_posix_init(log); } diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c index f86e1c0d7..187365cb2 100644 --- a/src/os/unix/ngx_freebsd_sendfile_chain.c +++ b/src/os/unix/ngx_freebsd_sendfile_chain.c @@ -37,9 +37,8 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, { int rc; u_char *prev; - off_t fprev, sent, send, sprev, aligned; - size_t hsize, fsize; - ssize_t size; + off_t size, send, prev_send, aligned, sent, fprev; + size_t header_size, file_size; ngx_uint_t eintr, eagain, complete; ngx_err_t err; ngx_buf_t *file; @@ -67,6 +66,12 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, #endif + /* the maximum limit size is the maximum size_t value - the page size */ + + if (limit == 0 || limit > MAX_SIZE_T_VALUE - ngx_pagesize) { + limit = MAX_SIZE_T_VALUE - ngx_pagesize; + } + send = 0; eagain = 0; @@ -82,11 +87,11 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, for ( ;; ) { file = NULL; - fsize = 0; - hsize = 0; + file_size = 0; + header_size = 0; eintr = 0; complete = 0; - sprev = send; + prev_send = send; header.nelts = 0; trailer.nelts = 0; @@ -115,7 +120,7 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, } if (prev == cl->buf->pos) { - iov->iov_len += size; + iov->iov_len += (size_t) size; } else { if (!(iov = ngx_array_push(&header))) { @@ -123,11 +128,11 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, } iov->iov_base = (void *) cl->buf->pos; - iov->iov_len = size; + iov->iov_len = (size_t) size; } - prev = cl->buf->pos + size; - hsize += size; + prev = cl->buf->pos + (size_t) size; + header_size += (size_t) size; send += size; } @@ -138,7 +143,7 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, /* coalesce the neighbouring file bufs */ do { - size = (size_t) (cl->buf->file_last - cl->buf->file_pos); + size = cl->buf->file_last - cl->buf->file_pos; if (send + size > limit) { size = limit - send; @@ -151,7 +156,7 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, } } - fsize += size; + file_size += (size_t) size; send += size; fprev = cl->buf->file_pos + size; cl = cl->next; @@ -189,7 +194,7 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, } if (prev == cl->buf->pos) { - iov->iov_len += size; + iov->iov_len += (size_t) size; } else { if (!(iov = ngx_array_push(&trailer))) { @@ -197,10 +202,10 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, } iov->iov_base = (void *) cl->buf->pos; - iov->iov_len = size; + iov->iov_len = (size_t) size; } - prev = cl->buf->pos + size; + prev = cl->buf->pos + (size_t) size; send += size; cl = cl->next; } @@ -245,13 +250,13 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, */ if (ngx_freebsd_sendfile_nbytes_bug == 0) { - hsize = 0; + header_size = 0; } sent = 0; rc = sendfile(file->file->fd, c->fd, file->file_pos, - fsize + hsize, &hdtr, &sent, 0); + file_size + header_size, &hdtr, &sent, 0); if (rc == -1) { err = ngx_errno; @@ -265,8 +270,7 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err, - "sendfile() sent only %O bytes", - sent); + "sendfile() sent only %O bytes", sent); } else { wev->error = 1; @@ -291,13 +295,13 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, "sendfile: %d, @%O %O:%uz", - rc, file->file_pos, sent, fsize + hsize); + rc, file->file_pos, sent, file_size + header_size); } else { rc = writev(c->fd, header.elts, header.nelts); ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, - "writev: %d of %uz", rc, hsize); + "writev: %d of %uz", rc, header_size); if (rc == -1) { err = ngx_errno; @@ -320,7 +324,7 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, sent = rc > 0 ? rc : 0; } - if (send - sprev == sent) { + if (send - prev_send == sent) { complete = 1; } @@ -353,7 +357,7 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, } if (ngx_buf_in_memory(cl->buf)) { - cl->buf->pos += sent; + cl->buf->pos += (size_t) sent; } if (cl->buf->in_file) { diff --git a/src/os/unix/ngx_linux_sendfile_chain.c b/src/os/unix/ngx_linux_sendfile_chain.c index bcf9d4c76..c09d03675 100644 --- a/src/os/unix/ngx_linux_sendfile_chain.c +++ b/src/os/unix/ngx_linux_sendfile_chain.c @@ -25,11 +25,10 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) { - int rc; + int rc, tcp_nodelay; u_char *prev; - off_t fprev, send, sprev, aligned; - size_t fsize; - ssize_t size, sent; + off_t size, send, prev_send, aligned, sent, fprev; + size_t file_size; ngx_uint_t eintr, complete; ngx_err_t err; ngx_buf_t *file; @@ -49,6 +48,14 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, return in; } + + /* the maximum limit size is the maximum size_t value - the page size */ + + if (limit == 0 || limit > MAX_SIZE_T_VALUE - ngx_pagesize) { + limit = MAX_SIZE_T_VALUE - ngx_pagesize; + } + + send = 0; header.elts = headers; @@ -58,10 +65,10 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, for ( ;; ) { file = NULL; - fsize = 0; + file_size = 0; eintr = 0; complete = 0; - sprev = send; + prev_send = send; header.nelts = 0; @@ -89,7 +96,7 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, } if (prev == cl->buf->pos) { - iov->iov_len += size; + iov->iov_len += (size_t) size; } else { if (!(iov = ngx_array_push(&header))) { @@ -97,10 +104,10 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, } iov->iov_base = (void *) cl->buf->pos; - iov->iov_len = size; + iov->iov_len = (size_t) size; } - prev = cl->buf->pos + size; + prev = cl->buf->pos + (size_t) size; send += size; } @@ -111,25 +118,62 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, && cl && cl->buf->in_file) { - if (ngx_tcp_nopush(c->fd) == NGX_ERROR) { - err = ngx_errno; - /* - * there is a tiny chance to be interrupted, however - * we continue a processing without the TCP_CORK - */ + /* the TCP_CORK and TCP_NODELAY are mutually exclusive */ - if (err != NGX_EINTR) { - wev->error = 1; - ngx_connection_error(c, err, ngx_tcp_nopush_n " failed"); - return NGX_CHAIN_ERROR; + if (c->tcp_nodelay) { + + tcp_nodelay = 0; + + if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, + (const void *) &tcp_nodelay, sizeof(int)) == -1) + { + err = ngx_errno; + + /* + * there is a tiny chance to be interrupted, however + * we continue a processing with the TCP_NODELAY + * and without the TCP_CORK + */ + + if (err != NGX_EINTR) { + wev->error = 1; + ngx_connection_error(c, ngx_socket_errno, + "setsockopt(TCP_NODELAY) failed"); + return NGX_CHAIN_ERROR; + } + + } else { + c->tcp_nodelay = 0; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, + "no tcp_nodelay"); } + } - } else { - c->tcp_nopush = NGX_TCP_NOPUSH_SET; + if (!c->tcp_nodelay) { - ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, - "tcp_nopush"); + if (ngx_tcp_nopush(c->fd) == NGX_ERROR) { + err = ngx_errno; + + /* + * there is a tiny chance to be interrupted, however + * we continue a processing without the TCP_CORK + */ + + if (err != NGX_EINTR) { + wev->error = 1; + ngx_connection_error(c, err, + ngx_tcp_nopush_n " failed"); + return NGX_CHAIN_ERROR; + } + + } else { + c->tcp_nopush = NGX_TCP_NOPUSH_SET; + + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, + "tcp_nopush"); + } } } @@ -141,7 +185,7 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, /* coalesce the neighbouring file bufs */ do { - size = (size_t) (cl->buf->file_last - cl->buf->file_pos); + size = cl->buf->file_last - cl->buf->file_pos; if (send + size > limit) { size = limit - send; @@ -154,7 +198,7 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, } } - fsize += size; + file_size += (size_t) size; send += size; fprev = cl->buf->file_pos + size; cl = cl->next; @@ -172,7 +216,7 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, #else offset = (int32_t) file->file_pos; #endif - rc = sendfile(c->fd, file->file->fd, &offset, fsize); + rc = sendfile(c->fd, file->file->fd, &offset, file_size); if (rc == -1) { err = ngx_errno; @@ -195,8 +239,8 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, sent = rc > 0 ? rc : 0; ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, - "sendfile: %d, @%O %z:%uz", - rc, file->file_pos, sent, fsize); + "sendfile: %d, @%O %O:%uz", + rc, file->file_pos, sent, file_size); } else { rc = writev(c->fd, header.elts, header.nelts); @@ -221,10 +265,10 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, sent = rc > 0 ? rc : 0; - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %z", sent); + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %O", sent); } - if (send - sprev == sent) { + if (send - prev_send == sent) { complete = 1; } @@ -257,7 +301,7 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, } if (ngx_buf_in_memory(cl->buf)) { - cl->buf->pos += sent; + cl->buf->pos += (size_t) sent; } if (cl->buf->in_file) { diff --git a/src/os/unix/ngx_os.h b/src/os/unix/ngx_os.h index ee91df336..42fc88629 100644 --- a/src/os/unix/ngx_os.h +++ b/src/os/unix/ngx_os.h @@ -50,7 +50,8 @@ ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, extern ngx_os_io_t ngx_os_io; extern ngx_int_t ngx_ncpu; extern ngx_int_t ngx_max_sockets; -extern ngx_int_t ngx_inherited_nonblocking; +extern ngx_uint_t ngx_inherited_nonblocking; +extern ngx_uint_t ngx_tcp_nodelay_and_tcp_nopush; #define ngx_stderr_fileno STDERR_FILENO diff --git a/src/os/unix/ngx_posix_init.c b/src/os/unix/ngx_posix_init.c index 56be0cefb..626d821e9 100644 --- a/src/os/unix/ngx_posix_init.c +++ b/src/os/unix/ngx_posix_init.c @@ -8,9 +8,10 @@ #include <ngx_core.h> -ngx_int_t ngx_ncpu; -ngx_int_t ngx_max_sockets; -ngx_int_t ngx_inherited_nonblocking; +ngx_int_t ngx_ncpu; +ngx_int_t ngx_max_sockets; +ngx_uint_t ngx_inherited_nonblocking; +ngx_uint_t ngx_tcp_nodelay_and_tcp_nopush; struct rlimit rlmt; diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c index 3d1c51bc0..c3b9905b0 100644 --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -17,7 +17,7 @@ static void ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo); static ngx_uint_t ngx_reap_childs(ngx_cycle_t *cycle); static void ngx_master_exit(ngx_cycle_t *cycle); static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data); -static void ngx_worker_process_init(ngx_cycle_t *cycle); +static void ngx_worker_process_init(ngx_cycle_t *cycle, ngx_uint_t priority); static void ngx_channel_handler(ngx_event_t *ev); #if (NGX_THREADS) static void ngx_wakeup_worker_threads(ngx_cycle_t *cycle); @@ -564,6 +564,33 @@ static ngx_uint_t ngx_reap_childs(ngx_cycle_t *cycle) continue; } + + ch.command = NGX_CMD_OPEN_CHANNEL; + ch.pid = ngx_processes[ngx_process_slot].pid; + ch.slot = ngx_process_slot; + ch.fd = ngx_processes[ngx_process_slot].channel[0]; + + for (n = 0; n < ngx_last_process; n++) { + + if (n == ngx_process_slot + || ngx_processes[n].pid == -1 + || ngx_processes[n].channel[0] == -1) + { + continue; + } + + ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0, + "pass channel s:%d pid:%P fd:%d to s:%i pid:%P fd:%d", + ch.slot, ch.pid, ch.fd, + n, ngx_processes[n].pid, + ngx_processes[n].channel[0]); + + /* TODO: NGX_AGAIN */ + + ngx_write_channel(ngx_processes[n].channel[0], + &ch, sizeof(ngx_channel_t), cycle->log); + } + live = 1; continue; @@ -611,7 +638,7 @@ static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) ngx_err_t err; ngx_core_conf_t *ccf; - ngx_worker_process_init(cycle); + ngx_worker_process_init(cycle, 1); ngx_setproctitle("worker process"); @@ -718,7 +745,7 @@ static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) } -static void ngx_worker_process_init(ngx_cycle_t *cycle) +static void ngx_worker_process_init(ngx_cycle_t *cycle, ngx_uint_t priority) { sigset_t set; ngx_int_t n; @@ -739,6 +766,13 @@ static void ngx_worker_process_init(ngx_cycle_t *cycle) ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (geteuid() == 0) { + if (priority && ccf->priority != 0) { + if (setpriority(PRIO_PROCESS, 0, ccf->priority) == -1) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, + "setpriority(%d) failed", ccf->priority); + } + } + if (setgid(ccf->group) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "setgid(%d) failed", ccf->group); @@ -746,6 +780,12 @@ static void ngx_worker_process_init(ngx_cycle_t *cycle) exit(2); } + if (initgroups(ccf->username, ccf->group) == -1) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, + "initgroups(%s, %d) failed", + ccf->username, ccf->group); + } + if (setuid(ccf->user) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "setuid(%d) failed", ccf->user); @@ -1041,7 +1081,7 @@ static void ngx_garbage_collector_cycle(ngx_cycle_t *cycle, void *data) ngx_path_t **path; ngx_event_t *ev; - ngx_worker_process_init(cycle); + ngx_worker_process_init(cycle, 0); ev = &cycle->read_events[ngx_channel]; diff --git a/src/os/unix/ngx_solaris_sendfilev_chain.c b/src/os/unix/ngx_solaris_sendfilev_chain.c index 21f8b8f7c..4c873aa11 100644 --- a/src/os/unix/ngx_solaris_sendfilev_chain.c +++ b/src/os/unix/ngx_solaris_sendfilev_chain.c @@ -9,6 +9,28 @@ #include <ngx_event.h> +#if (NGX_TEST_BUILD_SOLARIS_SENDFILEV) + +/* Solaris declarations */ + +typedef struct sendfilevec { + int sfv_fd; + u_int sfv_flag; + off_t sfv_off; + size_t sfv_len; +} sendfilevec_t; + +#define SFV_FD_SELF -2 + +static ssize_t sendfilev(int fd, const struct sendfilevec *vec, + int sfvcnt, size_t *xferred) +{ + return -1; +} + +#endif + + #define NGX_SENDFILEVECS 16 @@ -17,8 +39,9 @@ ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, { int fd; u_char *prev; - off_t fprev, sprev, send, aligned; - ssize_t size, sent, n; + off_t size, send, prev_send, aligned, fprev; + size_t sent; + ssize_t n; ngx_int_t eintr, complete; ngx_err_t err; sendfilevec_t *sfv, sfvs[NGX_SENDFILEVECS]; @@ -36,6 +59,14 @@ ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, return ngx_writev_chain(c, in, limit); } + + /* the maximum limit size is the maximum size_t value - the page size */ + + if (limit == 0 || limit > MAX_SIZE_T_VALUE - ngx_pagesize) { + limit = MAX_SIZE_T_VALUE - ngx_pagesize; + } + + send = 0; complete = 0; @@ -51,7 +82,7 @@ ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, sfv = NULL; eintr = 0; sent = 0; - sprev = send; + prev_send = send; vec.nelts = 0; @@ -73,7 +104,7 @@ ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, } if (prev == cl->buf->pos) { - sfv->sfv_len += size; + sfv->sfv_len += (size_t) size; } else { if (!(sfv = ngx_array_push(&vec))) { @@ -83,16 +114,16 @@ ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, sfv->sfv_fd = SFV_FD_SELF; sfv->sfv_flag = 0; sfv->sfv_off = (off_t) (uintptr_t) cl->buf->pos; - sfv->sfv_len = size; + sfv->sfv_len = (size_t) size; } - prev = cl->buf->pos + size; + prev = cl->buf->pos + (size_t) size; send += size; } else { prev = NULL; - size = (size_t) (cl->buf->file_last - cl->buf->file_pos); + size = cl->buf->file_last - cl->buf->file_pos; if (send + size > limit) { size = limit - send; @@ -106,7 +137,7 @@ ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, } if (fd == cl->buf->file->fd && fprev == cl->buf->file_pos) { - sfv->sfv_len += size; + sfv->sfv_len += (size_t) size; } else { if (!(sfv = ngx_array_push(&vec))) { @@ -117,7 +148,7 @@ ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, sfv->sfv_fd = fd; sfv->sfv_flag = 0; sfv->sfv_off = cl->buf->file_pos; - sfv->sfv_len = size; + sfv->sfv_len = (size_t) size; } fprev = cl->buf->file_pos + size; @@ -136,7 +167,7 @@ ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err, - "sendfilev() sent only %z bytes", sent); + "sendfilev() sent only %uz bytes", sent); } else { wev->error = 1; @@ -148,7 +179,7 @@ ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "sendfilev: %z %z", n, sent); - if (send - sprev == sent) { + if (send - prev_send == (off_t) sent) { complete = 1; } @@ -166,8 +197,8 @@ ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in, size = ngx_buf_size(cl->buf); - if (sent >= size) { - sent -= size; + if ((off_t) sent >= size) { + sent = (size_t) ((off_t) sent - size); if (ngx_buf_in_memory(cl->buf)) { cl->buf->pos = cl->buf->last; diff --git a/src/os/unix/ngx_writev_chain.c b/src/os/unix/ngx_writev_chain.c index 2af64699b..8f1087b26 100644 --- a/src/os/unix/ngx_writev_chain.c +++ b/src/os/unix/ngx_writev_chain.c @@ -16,7 +16,7 @@ ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) { u_char *prev; ssize_t n, size, sent; - off_t send, sprev; + off_t send, prev_send; ngx_uint_t eintr, complete; ngx_err_t err; ngx_array_t vec; @@ -42,6 +42,12 @@ ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) #endif + /* the maximum limit size is the maximum size_t value - the page size */ + + if (limit == 0 || limit > MAX_SIZE_T_VALUE - ngx_pagesize) { + limit = MAX_SIZE_T_VALUE - ngx_pagesize; + } + send = 0; complete = 0; @@ -54,7 +60,7 @@ ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) prev = NULL; iov = NULL; eintr = 0; - sprev = send; + prev_send = send; vec.nelts = 0; @@ -118,7 +124,7 @@ ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %z", sent); - if (send - sprev == sent) { + if (send - prev_send == sent) { complete = 1; } diff --git a/src/os/win32/ngx_errno.c b/src/os/win32/ngx_errno.c index 8e9280d92..268ed5261 100644 --- a/src/os/win32/ngx_errno.c +++ b/src/os/win32/ngx_errno.c @@ -43,7 +43,11 @@ static ngx_str_t wsa_errors[] = { ngx_null_string, /* 10039 */ ngx_null_string, /* 10040 */ ngx_null_string, /* 10041 */ - ngx_null_string, /* 10042 */ + + /* WSAENOPROTOOPT 10042 */ + ngx_string("An unknown, invalid, or unsupported option or level was " + "specified in a getsockopt or setsockopt call"), + ngx_null_string, /* 10043 */ ngx_null_string, /* 10044 */ ngx_null_string, /* 10045 */ diff --git a/src/os/win32/ngx_os.h b/src/os/win32/ngx_os.h index 6d720fa58..611f7ef5c 100644 --- a/src/os/win32/ngx_os.h +++ b/src/os/win32/ngx_os.h @@ -48,6 +48,7 @@ extern ngx_uint_t ngx_ncpu; extern ngx_uint_t ngx_max_wsabufs; extern ngx_int_t ngx_max_sockets; extern ngx_uint_t ngx_inherited_nonblocking; +extern ngx_uint_t ngx_tcp_nodelay_and_tcp_nopush; extern ngx_uint_t ngx_win32_version; extern ngx_fd_t ngx_stderr_fileno; diff --git a/src/os/win32/ngx_win32_config.h b/src/os/win32/ngx_win32_config.h index c7703c29e..79cea3f4f 100644 --- a/src/os/win32/ngx_win32_config.h +++ b/src/os/win32/ngx_win32_config.h @@ -141,5 +141,10 @@ typedef uint32_t ngx_atomic_t; #define NGX_HAVE_SENDFILE 1 #endif +#ifndef NGX_HAVE_SO_SNDLOWAT +/* setsockopt(SO_SNDLOWAT) returns error WSAENOPROTOOPT */ +#define NGX_HAVE_SO_SNDLOWAT 0 +#endif + #endif /* _NGX_WIN32_CONFIG_H_INCLUDED_ */ diff --git a/src/os/win32/ngx_win32_init.c b/src/os/win32/ngx_win32_init.c index cb8c93128..2b8891321 100644 --- a/src/os/win32/ngx_win32_init.c +++ b/src/os/win32/ngx_win32_init.c @@ -13,6 +13,8 @@ ngx_uint_t ngx_ncpu; ngx_uint_t ngx_max_wsabufs; ngx_int_t ngx_max_sockets; ngx_uint_t ngx_inherited_nonblocking = 1; +ngx_uint_t ngx_tcp_nodelay_and_tcp_nopush; + ngx_fd_t ngx_stderr_fileno; diff --git a/src/os/win32/ngx_wsasend_chain.c b/src/os/win32/ngx_wsasend_chain.c index 1d75e0969..d5b1334a1 100644 --- a/src/os/win32/ngx_wsasend_chain.c +++ b/src/os/win32/ngx_wsasend_chain.c @@ -17,7 +17,7 @@ ngx_chain_t *ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in, { int rc; u_char *prev; - u_long size, sent, send, sprev; + u_long size, sent, send, prev_send; ngx_uint_t complete; ngx_err_t err; ngx_event_t *wev; @@ -32,6 +32,12 @@ ngx_chain_t *ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in, return in; } + /* the maximum limit size is the maximum u_long value - the page size */ + + if (limit == 0 || limit > NGX_MAX_UINT32_VALUE - ngx_pagesize) { + limit = NGX_MAX_UINT32_VALUE - ngx_pagesize; + } + send = 0; complete = 0; @@ -48,7 +54,7 @@ ngx_chain_t *ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in, for ( ;; ) { prev = NULL; wsabuf = NULL; - sprev = send; + prev_send = send; vec.nelts = 0; @@ -105,7 +111,7 @@ ngx_chain_t *ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in, ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "WSASend: fd:%d, s:%ul", c->fd, sent); - if (send - sprev == sent) { + if (send - prev_send == sent) { complete = 1; } @@ -153,8 +159,7 @@ ngx_chain_t *ngx_overlapped_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in, { int rc; u_char *prev; - size_t size; - u_long send, sent; + u_long size, send, sent; LPWSABUF wsabuf; ngx_err_t err; ngx_event_t *wev; @@ -175,6 +180,12 @@ ngx_chain_t *ngx_overlapped_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in, if (!wev->complete) { /* post the overlapped WSASend() */ + + /* the maximum limit size is the maximum u_long value - the page size */ + + if (limit == 0 || limit > NGX_MAX_UINT32_VALUE - ngx_pagesize) { + limit = NGX_MAX_UINT32_VALUE - ngx_pagesize; + } /* * WSABUFs must be 4-byte aligned otherwise |