summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2008-07-30 12:55:58 +0000
committerJonathan Kolb <jon@b0g.us>2008-07-30 12:55:58 +0000
commit49d825b7bd87fb50315138ac87135c1d85354d5a (patch)
tree59ea5a6da9821a11897f2c5d9f7ed3014bf104b8
parent886b713c0b9c3521e5bfae45c242c8b289771a5e (diff)
downloadnginx-0.7.7.tar.gz
Changes with nginx 0.7.7 30 Jul 2008v0.7.7
*) Change: now the EAGAIN error returned by connect() is not considered as temporary error. *) Change: now the $ssl_client_cert variable value is a certificate with TAB character intended before each line except first one; an unchanged certificate is available in the $ssl_client_raw_cert variable. *) Feature: the "ask" parameter in the "ssl_verify_client" directive. *) Feature: byte-range processing improvements. Thanks to Maxim Dounin. *) Feature: the "directio" directive. *) Feature: MacOSX 1.5 sendfile() support. *) Bugfix: now in MacOSX and Cygwin locations are tested in case insensitive mode; however, the compare is provided by single-byte locales only. *) Bugfix: mail proxy SSL connections hanged, if select, poll, or /dev/poll methods were used. *) Bugfix: UTF-8 encoding usage in the ngx_http_autoindex_module.
-rw-r--r--CHANGES29
-rw-r--r--CHANGES.ru30
-rw-r--r--auto/os/conf22
-rw-r--r--auto/os/darwin115
-rw-r--r--auto/os/features50
-rw-r--r--auto/sources5
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/core/ngx_config.h4
-rw-r--r--src/core/ngx_open_file_cache.c7
-rw-r--r--src/core/ngx_open_file_cache.h1
-rw-r--r--src/core/ngx_output_chain.c25
-rw-r--r--src/core/ngx_palloc.c28
-rw-r--r--src/core/ngx_palloc.h1
-rw-r--r--src/core/ngx_string.c62
-rw-r--r--src/core/ngx_string.h6
-rw-r--r--src/event/ngx_event_connect.c17
-rw-r--r--src/event/ngx_event_openssl.c49
-rw-r--r--src/event/ngx_event_openssl.h2
-rw-r--r--src/http/modules/ngx_http_autoindex_module.c13
-rw-r--r--src/http/modules/ngx_http_charset_filter_module.c8
-rw-r--r--src/http/modules/ngx_http_flv_module.c6
-rw-r--r--src/http/modules/ngx_http_gzip_static_module.c1
-rw-r--r--src/http/modules/ngx_http_index_module.c1
-rw-r--r--src/http/modules/ngx_http_range_filter_module.c391
-rw-r--r--src/http/modules/ngx_http_ssl_module.c41
-rw-r--r--src/http/modules/ngx_http_ssl_module.h4
-rw-r--r--src/http/modules/ngx_http_static_module.c1
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/modules/perl/nginx.xs1
-rw-r--r--src/http/ngx_http_core_module.c41
-rw-r--r--src/http/ngx_http_core_module.h1
-rw-r--r--src/http/ngx_http_request.c2
-rw-r--r--src/http/ngx_http_script.c1
-rw-r--r--src/mail/ngx_mail_ssl_module.c12
-rw-r--r--src/os/unix/ngx_alloc.h4
-rw-r--r--src/os/unix/ngx_darwin.h19
-rw-r--r--src/os/unix/ngx_darwin_config.h87
-rw-r--r--src/os/unix/ngx_darwin_init.c155
-rw-r--r--src/os/unix/ngx_darwin_sendfile_chain.c363
-rw-r--r--src/os/unix/ngx_files.c19
-rw-r--r--src/os/unix/ngx_files.h30
-rw-r--r--src/os/unix/ngx_os.h4
42 files changed, 1409 insertions, 253 deletions
diff --git a/CHANGES b/CHANGES
index 6623438ed..93d77163a 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,33 @@
+Changes with nginx 0.7.7 30 Jul 2008
+
+ *) Change: now the EAGAIN error returned by connect() is not considered
+ as temporary error.
+
+ *) Change: now the $ssl_client_cert variable value is a certificate
+ with TAB character intended before each line except first one; an
+ unchanged certificate is available in the $ssl_client_raw_cert
+ variable.
+
+ *) Feature: the "ask" parameter in the "ssl_verify_client" directive.
+
+ *) Feature: byte-range processing improvements.
+ Thanks to Maxim Dounin.
+
+ *) Feature: the "directio" directive.
+
+ *) Feature: MacOSX 1.5 sendfile() support.
+
+ *) Bugfix: now in MacOSX and Cygwin locations are tested in case
+ insensitive mode; however, the compare is provided by single-byte
+ locales only.
+
+ *) Bugfix: mail proxy SSL connections hanged, if select, poll, or
+ /dev/poll methods were used.
+
+ *) Bugfix: UTF-8 encoding usage in the ngx_http_autoindex_module.
+
+
Changes with nginx 0.7.6 07 Jul 2008
*) Bugfix: now if variables are used in the "access_log" directive a
diff --git a/CHANGES.ru b/CHANGES.ru
index 56abbc105..7eb6402b0 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,34 @@
+Изменения в nginx 0.7.7 30.07.2008
+
+ *) Изменение: теперь ошибка EAGAIN при вызове connect() не считается
+ временной.
+
+ *) Изменение: значением переменной $ssl_client_cert теперь является
+ сертификат, перед каждой строкой которого, кроме первой, вставляется
+ символ табуляции; неизменённый сертификат доступен через переменную
+ $ssl_client_raw_cert.
+
+ *) Добавление: параметр ask директивы ssl_verify_client.
+
+ *) Добавление: улучшения в обработке byte-range.
+ Спасибо Максиму Дунину.
+
+ *) Добавление: директива directio.
+
+ *) Добавление: поддержка sendfile() в MacOSX 1.5.
+
+ *) Исправление: в MacOSX и Cygwin при проверке location'ов теперь
+ делается сравнение без учёта регистра символов; однако, сравнение
+ ограничено только однобайтными locale'ями.
+
+ *) Исправление: соединения почтового прокси-сервера зависали в режиме
+ SSL, если использовались методы select, poll или /dev/poll.
+
+ *) Исправление: ошибки при использовании кодировки UTF-8 в
+ ngx_http_autoindex_module.
+
+
Изменения в nginx 0.7.6 07.07.2008
*) Исправление: теперь при использовании переменных в директиве
diff --git a/auto/os/conf b/auto/os/conf
index b34be7245..f4d08cb42 100644
--- a/auto/os/conf
+++ b/auto/os/conf
@@ -18,6 +18,10 @@ case "$NGX_PLATFORM" in
. auto/os/solaris
;;
+ Darwin:*)
+ . auto/os/darwin
+ ;;
+
win32)
. auto/os/win32
;;
@@ -36,24 +40,6 @@ case "$NGX_PLATFORM" in
'
;;
- Darwin:*)
- have=NGX_DARWIN . auto/have_headers
- have=NGX_HAVE_INHERITED_NONBLOCK . auto/have
- CORE_INCS="$UNIX_INCS"
- CORE_DEPS="$UNIX_DEPS $POSIX_DEPS"
- CORE_SRCS="$UNIX_SRCS"
-
- ngx_feature="atomic(3)"
- ngx_feature_name=NGX_DARWIN_ATOMIC
- ngx_feature_run=no
- ngx_feature_incs="#include <libkern/OSAtomic.h>"
- ngx_feature_path=
- ngx_feature_libs=
- ngx_feature_test="int32_t lock, n;
- n = OSAtomicCompareAndSwap32Barrier(0, 1, lock)"
- . auto/feature
- ;;
-
HP-UX:*)
# HP/UX
have=NGX_HPUX . auto/have_headers
diff --git a/auto/os/darwin b/auto/os/darwin
new file mode 100644
index 000000000..f9953b95c
--- /dev/null
+++ b/auto/os/darwin
@@ -0,0 +1,115 @@
+
+# Copyright (C) Igor Sysoev
+
+
+have=NGX_DARWIN . auto/have_headers
+
+CORE_INCS="$UNIX_INCS"
+CORE_DEPS="$UNIX_DEPS $DARWIN_DEPS"
+CORE_SRCS="$UNIX_SRCS $DARWIN_SRCS"
+
+
+
+ngx_spacer='
+'
+
+# kqueue
+
+echo " + kqueue found"
+have=NGX_HAVE_KQUEUE . auto/have
+have=NGX_HAVE_CLEAR_EVENT . auto/have
+EVENT_MODULES="$EVENT_MODULES $KQUEUE_MODULE"
+CORE_SRCS="$CORE_SRCS $KQUEUE_SRCS"
+EVENT_FOUND=YES
+NGX_KQUEUE_CHECKED=YES
+
+ngx_feature="kqueue's EVFILT_TIMER"
+ngx_feature_name="NGX_HAVE_TIMER_EVENT"
+ngx_feature_run=yes
+ngx_feature_incs="#include <sys/event.h>
+ #include <sys/time.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="int kq;
+ struct kevent kev;
+ struct timespec ts;
+
+ if ((kq = kqueue()) == -1) return 1;
+
+ kev.ident = 0;
+ kev.filter = EVFILT_TIMER;
+ kev.flags = EV_ADD|EV_ENABLE;
+ kev.fflags = 0;
+ kev.data = 1000;
+ kev.udata = 0;
+
+ ts.tv_sec = 0;
+ ts.tv_nsec = 0;
+
+ if (kevent(kq, &kev, 1, &kev, 1, &ts) == -1) return 1;
+
+ if (kev.flags & EV_ERROR) return 1;"
+
+. auto/feature
+
+
+ngx_feature="Darwin 64-bit kqueue millisecond timeout bug"
+ngx_feature_name=NGX_DARWIN_KEVENT_BUG
+ngx_feature_run=bug
+ngx_feature_incs="#include <sys/event.h>
+ #include <sys/time.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="int kq;
+ struct kevent kev;
+ struct timespec ts;
+ struct timeval tv, tv0;
+
+ kq = kqueue();
+
+ ts.tv_sec = 0;
+ ts.tv_nsec = 999000000;
+
+ gettimeofday(&tv, 0);
+ kevent(kq, NULL, 0, &kev, 1, &ts);
+ gettimeofday(&tv0, 0);
+ timersub(&tv0, &tv, &tv);
+
+ if (tv.tv_sec * 1000000 + tv.tv_usec < 900000) return 1;"
+
+. auto/feature
+
+
+# sendfile()
+
+CC_AUX_FLAGS="$CC_AUX_FLAGS"
+ngx_feature="sendfile()"
+ngx_feature_name="NGX_HAVE_SENDFILE"
+ngx_feature_run=yes
+ngx_feature_incs="#include <sys/types.h>
+ #include <sys/socket.h>
+ #include <sys/uio.h>
+ #include <sys/errno.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="int s = 0, fd = 1;
+ off_t n; off_t off = 0;
+ n = sendfile(s, fd, off, &n, NULL, 0);
+ if (n == -1 && errno == ENOSYS) return 1"
+. auto/feature
+
+if [ $ngx_found = yes ]; then
+ have=NGX_HAVE_SENDFILE . auto/have
+ CORE_SRCS="$CORE_SRCS $DARWIN_SENDFILE_SRCS"
+fi
+
+
+ngx_feature="atomic(3)"
+ngx_feature_name=NGX_DARWIN_ATOMIC
+ngx_feature_run=no
+ngx_feature_incs="#include <libkern/OSAtomic.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="int32_t lock, n;
+ n = OSAtomicCompareAndSwap32Barrier(0, 1, lock)"
+. auto/feature
diff --git a/auto/os/features b/auto/os/features
index 1e54f9d3d..ffb27a481 100644
--- a/auto/os/features
+++ b/auto/os/features
@@ -122,36 +122,6 @@ if test -z "$NGX_KQUEUE_CHECKED"; then
if (kev.flags & EV_ERROR) return 1;"
. auto/feature
-
-
- if [ "$NGX_SYSTEM" = "Darwin" ]; then
-
- ngx_feature="Darwin 64-bit kqueue millisecond timeout bug"
- ngx_feature_name=NGX_DARWIN_KEVENT_BUG
- ngx_feature_run=bug
- ngx_feature_incs="#include <sys/event.h>
-#include <sys/time.h>"
- ngx_feature_path=
- ngx_feature_libs=
- ngx_feature_test="int kq;
- struct kevent kev;
- struct timespec ts;
- struct timeval tv, tv0;
-
- kq = kqueue();
-
- ts.tv_sec = 0;
- ts.tv_nsec = 999000000;
-
- gettimeofday(&tv, 0);
- kevent(kq, NULL, 0, &kev, 1, &ts);
- gettimeofday(&tv0, 0);
- timersub(&tv0, &tv, &tv);
-
- if (tv.tv_sec * 1000000 + tv.tv_usec < 900000) return 1;"
-
- . auto/feature
- fi
fi
fi
@@ -200,3 +170,23 @@ if [ $ngx_found = no ]; then
CRYPT_LIB="-lcrypt"
fi
fi
+
+
+ngx_feature="O_DIRECT"
+ngx_feature_name="NGX_HAVE_O_DIRECT"
+ngx_feature_run=no
+ngx_feature_incs="#include <fcntl.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="fcntl(0, F_SETFL, O_DIRECT);"
+. auto/feature
+
+
+ngx_feature="F_NOCACHE"
+ngx_feature_name="NGX_HAVE_F_NOCACHE"
+ngx_feature_run=no
+ngx_feature_incs="#include <fcntl.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="fcntl(0, F_NOCACHE, 1);"
+. auto/feature
diff --git a/auto/sources b/auto/sources
index 62fb047cd..12ab1b79d 100644
--- a/auto/sources
+++ b/auto/sources
@@ -198,6 +198,11 @@ SOLARIS_SRCS=src/os/unix/ngx_solaris_init.c
SOLARIS_SENDFILEV_SRCS=src/os/unix/ngx_solaris_sendfilev_chain.c
+DARWIN_DEPS="src/os/unix/ngx_darwin_config.h src/os/unix/ngx_darwin.h"
+DARWIN_SRCS=src/os/unix/ngx_darwin_init.c
+DARWIN_SENDFILE_SRCS=src/os/unix/ngx_darwin_sendfile_chain.c
+
+
WIN32_INCS="$CORE_INCS $EVENT_INCS src/os/win32"
WIN32_DEPS="$CORE_DEPS $EVENT_DEPS \
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 50236196c..44b0099d2 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VERSION "0.7.6"
+#define NGINX_VERSION "0.7.7"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_config.h b/src/core/ngx_config.h
index 8b802aa9c..d2d4e043a 100644
--- a/src/core/ngx_config.h
+++ b/src/core/ngx_config.h
@@ -29,6 +29,10 @@
#include <ngx_solaris_config.h>
+#elif (NGX_DARWIN)
+#include <ngx_darwin_config.h>
+
+
#elif (NGX_WIN32)
#include <ngx_win32_config.h>
diff --git a/src/core/ngx_open_file_cache.c b/src/core/ngx_open_file_cache.c
index 704d0ab79..f2e8afc51 100644
--- a/src/core/ngx_open_file_cache.c
+++ b/src/core/ngx_open_file_cache.c
@@ -497,6 +497,13 @@ ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of, ngx_log_t *log)
} else {
of->fd = fd;
+
+ if (of->directio <= ngx_file_size(&fi)) {
+ if (ngx_directio(fd) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+ ngx_directio_n " \"%s\" failed", name);
+ }
+ }
}
done:
diff --git a/src/core/ngx_open_file_cache.h b/src/core/ngx_open_file_cache.h
index 4d8393b5d..1e1a27915 100644
--- a/src/core/ngx_open_file_cache.h
+++ b/src/core/ngx_open_file_cache.h
@@ -17,6 +17,7 @@ typedef struct {
ngx_file_uniq_t uniq;
time_t mtime;
off_t size;
+ off_t directio;
ngx_err_t err;
time_t valid;
diff --git a/src/core/ngx_output_chain.c b/src/core/ngx_output_chain.c
index 423a650d3..c4bd67851 100644
--- a/src/core/ngx_output_chain.c
+++ b/src/core/ngx_output_chain.c
@@ -32,6 +32,7 @@ ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in)
size_t size;
ngx_int_t rc, last;
ngx_uint_t recycled;
+ ngx_buf_t *b;
ngx_chain_t *cl, *out, **last_out;
if (ctx->in == NULL && ctx->busy == NULL) {
@@ -161,13 +162,29 @@ ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in)
}
}
- ctx->buf = ngx_create_temp_buf(ctx->pool, size);
- if (ctx->buf == NULL) {
+ b = ngx_calloc_buf(ctx->pool);
+ if (b == NULL) {
return NGX_ERROR;
}
- ctx->buf->tag = ctx->tag;
- ctx->buf->recycled = recycled;
+ /*
+ * allocate block aligned to a disk sector size
+ * to enable O_DIRECT
+ */
+
+ b->start = ngx_pmemalign(ctx->pool, size, 512);
+ if (b->start == NULL) {
+ return NGX_ERROR;
+ }
+
+ b->pos = b->start;
+ b->last = b->start;
+ b->end = b->last + size;
+ b->temporary = 1;
+ b->tag = ctx->tag;
+ b->recycled = recycled;
+
+ ctx->buf = b;
ctx->allocated++;
}
}
diff --git a/src/core/ngx_palloc.c b/src/core/ngx_palloc.c
index 5a0ea5121..0cadd4aed 100644
--- a/src/core/ngx_palloc.c
+++ b/src/core/ngx_palloc.c
@@ -195,17 +195,35 @@ ngx_palloc_large(ngx_pool_t *pool, size_t size)
void *p;
ngx_pool_large_t *large;
-#if 0
- p = ngx_memalign(ngx_pagesize, size, pool->log);
+ p = ngx_alloc(size, pool->log);
if (p == NULL) {
return NULL;
}
-#else
- p = ngx_alloc(size, pool->log);
+
+ large = ngx_palloc(pool, sizeof(ngx_pool_large_t));
+ if (large == NULL) {
+ ngx_free(p);
+ return NULL;
+ }
+
+ large->alloc = p;
+ large->next = pool->large;
+ pool->large = large;
+
+ return p;
+}
+
+
+void *
+ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment)
+{
+ void *p;
+ ngx_pool_large_t *large;
+
+ p = ngx_memalign(alignment, size, pool->log);
if (p == NULL) {
return NULL;
}
-#endif
large = ngx_palloc(pool, sizeof(ngx_pool_large_t));
if (large == NULL) {
diff --git a/src/core/ngx_palloc.h b/src/core/ngx_palloc.h
index 34878f5f2..2b3a30cbd 100644
--- a/src/core/ngx_palloc.h
+++ b/src/core/ngx_palloc.h
@@ -77,6 +77,7 @@ void ngx_destroy_pool(ngx_pool_t *pool);
void *ngx_palloc(ngx_pool_t *pool, size_t size);
void *ngx_pnalloc(ngx_pool_t *pool, size_t size);
void *ngx_pcalloc(ngx_pool_t *pool, size_t size);
+void *ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment);
ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p);
diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c
index c9193152c..2da6c8319 100644
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -952,16 +952,16 @@ ngx_decode_base64(ngx_str_t *dst, ngx_str_t *src)
/*
- * ngx_utf_decode() decodes two and more bytes UTF sequences only
+ * ngx_utf8_decode() decodes two and more bytes UTF sequences only
* the return values:
* 0x80 - 0x10ffff valid character
- * 0x10ffff - 0xfffffffd invalid sequence
+ * 0x110000 - 0xfffffffd invalid sequence
* 0xfffffffe incomplete sequence
* 0xffffffff error
*/
uint32_t
-ngx_utf_decode(u_char **p, size_t n)
+ngx_utf8_decode(u_char **p, size_t n)
{
size_t len;
uint32_t u, i, valid;
@@ -1018,31 +1018,26 @@ ngx_utf_decode(u_char **p, size_t n)
size_t
-ngx_utf_length(u_char *p, size_t n)
+ngx_utf8_length(u_char *p, size_t n)
{
- u_char c;
- size_t len;
- ngx_uint_t i;
+ u_char c, *last;
+ size_t len;
- for (len = 0, i = 0; i < n; len++, i++) {
+ last = p + n;
- c = p[i];
+ for (len = 0; p < last; len++) {
+
+ c = *p;
if (c < 0x80) {
+ p++;
continue;
}
- if (c >= 0xc0) {
- for (c <<= 1; c & 0x80; c <<= 1) {
- i++;
- }
-
- continue;
+ if (ngx_utf8_decode(&p, n) > 0x10ffff) {
+ /* invalid UTF-8 */
+ return n;
}
-
- /* invalid utf */
-
- return n;
}
return len;
@@ -1050,36 +1045,45 @@ ngx_utf_length(u_char *p, size_t n)
u_char *
-ngx_utf_cpystrn(u_char *dst, u_char *src, size_t n)
+ngx_utf8_cpystrn(u_char *dst, u_char *src, size_t n, size_t len)
{
- u_char c;
+ u_char c, *next;
if (n == 0) {
return dst;
}
- for ( /* void */ ; --n; dst++, src++) {
+ while (--n) {
c = *src;
*dst = c;
if (c < 0x80) {
- if (*dst != '\0') {
+
+ if (c != '\0') {
+ dst++;
+ src++;
+ len--;
+
continue;
}
return dst;
}
- if (c >= 0xc0) {
- for (c <<= 1; c & 0x80; c <<= 1) {
- *++dst = *++src;
- }
+ next = src;
- continue;
+ if (ngx_utf8_decode(&next, len) > 0x10ffff) {
+ /* invalid UTF-8 */
+ break;
}
- /* invalid utf */
+ len--;
+
+ while (src < next) {
+ *++dst = *++src;
+ len--;
+ }
}
*dst = '\0';
diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h
index 3514e52f3..dfb3bc4cc 100644
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -151,9 +151,9 @@ u_char *ngx_hex_dump(u_char *dst, u_char *src, size_t len);
void ngx_encode_base64(ngx_str_t *dst, ngx_str_t *src);
ngx_int_t ngx_decode_base64(ngx_str_t *dst, ngx_str_t *src);
-uint32_t ngx_utf_decode(u_char **p, size_t n);
-size_t ngx_utf_length(u_char *p, size_t n);
-u_char *ngx_utf_cpystrn(u_char *dst, u_char *src, size_t n);
+uint32_t ngx_utf8_decode(u_char **p, size_t n);
+size_t ngx_utf8_length(u_char *p, size_t n);
+u_char *ngx_utf8_cpystrn(u_char *dst, u_char *src, size_t n, size_t len);
#define NGX_ESCAPE_URI 0
diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c
index 5ae7b23bf..b5e1a870e 100644
--- a/src/event/ngx_event_connect.c
+++ b/src/event/ngx_event_connect.c
@@ -139,11 +139,22 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc)
if (rc == -1) {
err = ngx_socket_errno;
- /* Winsock returns WSAEWOULDBLOCK (NGX_EAGAIN) */
-
- if (err != NGX_EINPROGRESS && err != NGX_EAGAIN) {
+ if (err != NGX_EINPROGRESS
+#if (NGX_WIN32)
+ /* Winsock returns WSAEWOULDBLOCK (NGX_EAGAIN) */
+ && err != NGX_EAGAIN
+#endif
+ )
+ {
if (err == NGX_ECONNREFUSED
+#if (NGX_LINUX)
+ /*
+ * Linux returns EAGAIN instead of ECONNREFUSED
+ * for unix sockets if listen queue is full
+ */
+ || err == NGX_EAGAIN
+#endif
|| err == NGX_ENETDOWN
|| err == NGX_ENETUNREACH
|| err == NGX_EHOSTDOWN
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index 029d7dbfb..40e371280 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -505,6 +505,9 @@ ngx_ssl_handshake(ngx_connection_t *c)
if (n == 1) {
+ c->read->ready = 0;
+ c->write->ready = 1;
+
if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
return NGX_ERROR;
}
@@ -1884,7 +1887,7 @@ ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
ngx_int_t
-ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
+ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
{
size_t len;
BIO *bio;
@@ -1934,6 +1937,50 @@ failed:
ngx_int_t
+ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
+{
+ u_char *p;
+ size_t len;
+ ngx_uint_t i;
+ ngx_str_t cert;
+
+ if (ngx_ssl_get_raw_certificate(c, pool, &cert) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ if (cert.len == 0) {
+ s->len = 0;
+ return NGX_OK;
+ }
+
+ len = cert.len - 1;
+
+ for (i = 0; i < cert.len - 1; i++) {
+ if (cert.data[i] == LF) {
+ len++;
+ }
+ }
+
+ s->len = len;
+ s->data = ngx_pnalloc(pool, len);
+ if (s->data == NULL) {
+ return NGX_ERROR;
+ }
+
+ p = s->data;
+
+ for (i = 0; i < len; i++) {
+ *p++ = cert.data[i];
+ if (cert.data[i] == LF) {
+ *p++ = '\t';
+ }
+ }
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
{
char *p;
diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
index f5627701d..1e83606fd 100644
--- a/src/event/ngx_event_openssl.h
+++ b/src/event/ngx_event_openssl.h
@@ -121,6 +121,8 @@ ngx_int_t ngx_ssl_get_protocol(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *s);
ngx_int_t ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *s);
+ngx_int_t ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool,
+ ngx_str_t *s);
ngx_int_t ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *s);
ngx_int_t ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool,
diff --git a/src/http/modules/ngx_http_autoindex_module.c b/src/http/modules/ngx_http_autoindex_module.c
index b5b6ef7f3..86b7c0b30 100644
--- a/src/http/modules/ngx_http_autoindex_module.c
+++ b/src/http/modules/ngx_http_autoindex_module.c
@@ -135,7 +135,7 @@ ngx_http_autoindex_handler(ngx_http_request_t *r)
{
u_char *last, *filename, scale;
off_t length;
- size_t len, copy, allocated, root;
+ size_t len, utf_len, allocated, root;
ngx_tm_t tm;
ngx_err_t err;
ngx_buf_t *b;
@@ -329,7 +329,7 @@ ngx_http_autoindex_handler(ngx_http_request_t *r)
NGX_ESCAPE_HTML);
if (r->utf8) {
- entry->utf_len = ngx_utf_length(entry->name.data, entry->name.len);
+ entry->utf_len = ngx_utf8_length(entry->name.data, entry->name.len);
} else {
entry->utf_len = len;
}
@@ -412,15 +412,16 @@ ngx_http_autoindex_handler(ngx_http_request_t *r)
len = entry[i].utf_len;
- if (entry[i].name.len - len) {
+ if (entry[i].name.len != len) {
if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) {
- copy = NGX_HTTP_AUTOINDEX_NAME_LEN - 3 + 1;
+ utf_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3 + 1;
} else {
- copy = NGX_HTTP_AUTOINDEX_NAME_LEN + 1;
+ utf_len = NGX_HTTP_AUTOINDEX_NAME_LEN + 1;
}
- b->last = ngx_utf_cpystrn(b->last, entry[i].name.data, copy);
+ b->last = ngx_utf8_cpystrn(b->last, entry[i].name.data,
+ utf_len, entry[i].name.len + 1);
last = b->last;
} else {
diff --git a/src/http/modules/ngx_http_charset_filter_module.c b/src/http/modules/ngx_http_charset_filter_module.c
index a5db2d878..8ca859bd2 100644
--- a/src/http/modules/ngx_http_charset_filter_module.c
+++ b/src/http/modules/ngx_http_charset_filter_module.c
@@ -642,7 +642,7 @@ ngx_http_charset_recode_from_utf8(ngx_pool_t *pool, ngx_buf_t *buf,
size = buf->last - src;
saved = src;
- n = ngx_utf_decode(&saved, size);
+ n = ngx_utf8_decode(&saved, size);
if (n == 0xfffffffe) {
/* incomplete UTF-8 symbol */
@@ -710,7 +710,7 @@ ngx_http_charset_recode_from_utf8(ngx_pool_t *pool, ngx_buf_t *buf,
}
saved = ctx->saved;
- n = ngx_utf_decode(&saved, i);
+ n = ngx_utf8_decode(&saved, i);
c = '\0';
@@ -818,7 +818,7 @@ recode:
len = buf->last - src;
- n = ngx_utf_decode(&src, len);
+ n = ngx_utf8_decode(&src, len);
if (n < 0x10000) {
@@ -1270,7 +1270,7 @@ ngx_http_charset_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
p = &table->src2dst[src * NGX_UTF_LEN] + 1;
- n = ngx_utf_decode(&p, i);
+ n = ngx_utf8_decode(&p, i);
if (n > 0xffff) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
diff --git a/src/http/modules/ngx_http_flv_module.c b/src/http/modules/ngx_http_flv_module.c
index 235ccddea..dceb68abc 100644
--- a/src/http/modules/ngx_http_flv_module.c
+++ b/src/http/modules/ngx_http_flv_module.c
@@ -107,6 +107,7 @@ ngx_http_flv_handler(ngx_http_request_t *r)
ngx_memzero(&of, sizeof(ngx_open_file_info_t));
+ of.directio = clcf->directio;
of.valid = clcf->open_file_cache_valid;
of.min_uses = clcf->open_file_cache_min_uses;
of.errors = clcf->open_file_cache_errors;
@@ -212,9 +213,6 @@ ngx_http_flv_handler(ngx_http_request_t *r)
out[0].buf = b;
out[0].next = &out[1];
-
- } else {
- r->allow_ranges = 1;
}
@@ -228,6 +226,8 @@ ngx_http_flv_handler(ngx_http_request_t *r)
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
+ r->allow_ranges = 1;
+
rc = ngx_http_send_header(r);
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
diff --git a/src/http/modules/ngx_http_gzip_static_module.c b/src/http/modules/ngx_http_gzip_static_module.c
index 51fe0d56d..bc3a65f11 100644
--- a/src/http/modules/ngx_http_gzip_static_module.c
+++ b/src/http/modules/ngx_http_gzip_static_module.c
@@ -121,6 +121,7 @@ ngx_http_gzip_static_handler(ngx_http_request_t *r)
ngx_memzero(&of, sizeof(ngx_open_file_info_t));
+ of.directio = clcf->directio;
of.valid = clcf->open_file_cache_valid;
of.min_uses = clcf->open_file_cache_min_uses;
of.errors = clcf->open_file_cache_errors;
diff --git a/src/http/modules/ngx_http_index_module.c b/src/http/modules/ngx_http_index_module.c
index bc4cd5009..6d4cf34d3 100644
--- a/src/http/modules/ngx_http_index_module.c
+++ b/src/http/modules/ngx_http_index_module.c
@@ -210,6 +210,7 @@ ngx_http_index_handler(ngx_http_request_t *r)
ngx_memzero(&of, sizeof(ngx_open_file_info_t));
+ of.directio = clcf->directio;
of.valid = clcf->open_file_cache_valid;
of.min_uses = clcf->open_file_cache_min_uses;
of.errors = clcf->open_file_cache_errors;
diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c
index e2137f299..377ca9b28 100644
--- a/src/http/modules/ngx_http_range_filter_module.c
+++ b/src/http/modules/ngx_http_range_filter_module.c
@@ -58,6 +58,20 @@ typedef struct {
} ngx_http_range_filter_ctx_t;
+ngx_int_t ngx_http_range_parse(ngx_http_request_t *r,
+ ngx_http_range_filter_ctx_t *ctx);
+static ngx_int_t ngx_http_range_singlepart_header(ngx_http_request_t *r,
+ ngx_http_range_filter_ctx_t *ctx);
+static ngx_int_t ngx_http_range_multipart_header(ngx_http_request_t *r,
+ ngx_http_range_filter_ctx_t *ctx);
+static ngx_int_t ngx_http_range_not_satisfiable(ngx_http_request_t *r);
+static ngx_int_t ngx_http_range_test_overlapped(ngx_http_request_t *r,
+ ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in);
+static ngx_int_t ngx_http_range_singlepart_body(ngx_http_request_t *r,
+ ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in);
+static ngx_int_t ngx_http_range_multipart_body(ngx_http_request_t *r,
+ ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in);
+
static ngx_int_t ngx_http_range_header_filter_init(ngx_conf_t *cf);
static ngx_int_t ngx_http_range_body_filter_init(ngx_conf_t *cf);
@@ -131,15 +145,8 @@ static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
static ngx_int_t
ngx_http_range_header_filter(ngx_http_request_t *r)
{
- u_char *p;
- size_t len;
- off_t start, end;
time_t if_range;
ngx_int_t rc;
- ngx_uint_t suffix, i;
- ngx_atomic_uint_t boundary;
- ngx_table_elt_t *content_range;
- ngx_http_range_t *range;
ngx_http_range_filter_ctx_t *ctx;
if (r->http_version < NGX_HTTP_VERSION_10
@@ -185,8 +192,54 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
return NGX_ERROR;
}
- rc = 0;
- range = NULL;
+ rc = ngx_http_range_parse(r, ctx);
+
+ if (rc == NGX_OK) {
+
+ ngx_http_set_ctx(r, ctx, ngx_http_range_body_filter_module);
+
+ r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT;
+
+ if (ctx->ranges.nelts == 1) {
+ return ngx_http_range_singlepart_header(r, ctx);
+ }
+
+ return ngx_http_range_multipart_header(r, ctx);
+ }
+
+ if (rc == NGX_HTTP_RANGE_NOT_SATISFIABLE) {
+ return ngx_http_range_not_satisfiable(r);
+ }
+
+ /* rc == NGX_ERROR */
+
+ return rc;
+
+next_filter:
+
+ r->headers_out.accept_ranges = ngx_list_push(&r->headers_out.headers);
+ if (r->headers_out.accept_ranges == NULL) {
+ return NGX_ERROR;
+ }
+
+ r->headers_out.accept_ranges->hash = 1;
+ r->headers_out.accept_ranges->key.len = sizeof("Accept-Ranges") - 1;
+ r->headers_out.accept_ranges->key.data = (u_char *) "Accept-Ranges";
+ r->headers_out.accept_ranges->value.len = sizeof("bytes") - 1;
+ r->headers_out.accept_ranges->value.data = (u_char *) "bytes";
+
+ return ngx_http_next_header_filter(r);
+}
+
+
+ngx_int_t
+ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx)
+{
+ u_char *p;
+ off_t start, end;
+ ngx_uint_t suffix;
+ ngx_http_range_t *range;
+
p = r->headers_in.range->value.data + 6;
for ( ;; ) {
@@ -198,8 +251,7 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
if (*p != '-') {
if (*p < '0' || *p > '9') {
- rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
- break;
+ return NGX_HTTP_RANGE_NOT_SATISFIABLE;
}
while (*p >= '0' && *p <= '9') {
@@ -209,13 +261,11 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
while (*p == ' ') { p++; }
if (*p++ != '-') {
- rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
- break;
+ return NGX_HTTP_RANGE_NOT_SATISFIABLE;
}
if (start >= r->headers_out.content_length_n) {
- rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
- break;
+ return NGX_HTTP_RANGE_NOT_SATISFIABLE;
}
while (*p == ' ') { p++; }
@@ -230,7 +280,7 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
range->end = r->headers_out.content_length_n;
if (*p++ != ',') {
- break;
+ return NGX_OK;
}
continue;
@@ -242,8 +292,7 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
}
if (*p < '0' || *p > '9') {
- rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
- break;
+ return NGX_HTTP_RANGE_NOT_SATISFIABLE;
}
while (*p >= '0' && *p <= '9') {
@@ -253,8 +302,7 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
while (*p == ' ') { p++; }
if (*p != ',' && *p != '\0') {
- rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
- break;
+ return NGX_HTTP_RANGE_NOT_SATISFIABLE;
}
if (suffix) {
@@ -263,8 +311,7 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
}
if (start > end) {
- rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
- break;
+ return NGX_HTTP_RANGE_NOT_SATISFIABLE;
}
range = ngx_array_push(&ctx->ranges);
@@ -286,86 +333,65 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
}
if (*p++ != ',') {
- break;
+ return NGX_OK;
}
}
+}
- if (rc) {
-
- /* rc == NGX_HTTP_RANGE_NOT_SATISFIABLE */
-
- r->headers_out.status = rc;
-
- content_range = ngx_list_push(&r->headers_out.headers);
- if (content_range == NULL) {
- return NGX_ERROR;
- }
-
- r->headers_out.content_range = content_range;
-
- content_range->hash = 1;
- content_range->key.len = sizeof("Content-Range") - 1;
- content_range->key.data = (u_char *) "Content-Range";
-
- content_range->value.data = ngx_pnalloc(r->pool,
- sizeof("bytes */") - 1 + NGX_OFF_T_LEN);
- if (content_range->value.data == NULL) {
- return NGX_ERROR;
- }
-
- content_range->value.len = ngx_sprintf(content_range->value.data,
- "bytes */%O",
- r->headers_out.content_length_n)
- - content_range->value.data;
- ngx_http_clear_content_length(r);
+static ngx_int_t
+ngx_http_range_singlepart_header(ngx_http_request_t *r,
+ ngx_http_range_filter_ctx_t *ctx)
+{
+ ngx_table_elt_t *content_range;
+ ngx_http_range_t *range;
- return rc;
+ content_range = ngx_list_push(&r->headers_out.headers);
+ if (content_range == NULL) {
+ return NGX_ERROR;
}
- ngx_http_set_ctx(r, ctx, ngx_http_range_body_filter_module);
-
- r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT;
-
- if (ctx->ranges.nelts == 1) {
-
- content_range = ngx_list_push(&r->headers_out.headers);
- if (content_range == NULL) {
- return NGX_ERROR;
- }
+ r->headers_out.content_range = content_range;
- r->headers_out.content_range = content_range;
+ content_range->hash = 1;
+ content_range->key.len = sizeof("Content-Range") - 1;
+ content_range->key.data = (u_char *) "Content-Range";
- content_range->hash = 1;
- content_range->key.len = sizeof("Content-Range") - 1;
- content_range->key.data = (u_char *) "Content-Range";
-
- content_range->value.data =
- ngx_pnalloc(r->pool, sizeof("bytes -/") - 1 + 3 * NGX_OFF_T_LEN);
- if (content_range->value.data == NULL) {
- return NGX_ERROR;
- }
+ content_range->value.data = ngx_pnalloc(r->pool,
+ sizeof("bytes -/") - 1 + 3 * NGX_OFF_T_LEN);
+ if (content_range->value.data == NULL) {
+ return NGX_ERROR;
+ }
- /* "Content-Range: bytes SSSS-EEEE/TTTT" header */
+ /* "Content-Range: bytes SSSS-EEEE/TTTT" header */
- content_range->value.len = ngx_sprintf(content_range->value.data,
- "bytes %O-%O/%O",
- range->start, range->end - 1,
- r->headers_out.content_length_n)
- - content_range->value.data;
+ range = ctx->ranges.elts;
- r->headers_out.content_length_n = range->end - range->start;
+ content_range->value.len = ngx_sprintf(content_range->value.data,
+ "bytes %O-%O/%O",
+ range->start, range->end - 1,
+ r->headers_out.content_length_n)
+ - content_range->value.data;
- if (r->headers_out.content_length) {
- r->headers_out.content_length->hash = 0;
- r->headers_out.content_length = NULL;
- }
+ r->headers_out.content_length_n = range->end - range->start;
- return ngx_http_next_header_filter(r);
+ if (r->headers_out.content_length) {
+ r->headers_out.content_length->hash = 0;
+ r->headers_out.content_length = NULL;
}
+ return ngx_http_next_header_filter(r);
+}
+
- /* TODO: what if no content_type ?? */
+static ngx_int_t
+ngx_http_range_multipart_header(ngx_http_request_t *r,
+ ngx_http_range_filter_ctx_t *ctx)
+{
+ size_t len;
+ ngx_uint_t i;
+ ngx_http_range_t *range;
+ ngx_atomic_uint_t boundary;
len = sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN
+ sizeof(CRLF "Content-Type: ") - 1
@@ -403,7 +429,7 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
r->headers_out.charset.len = 0;
- } else {
+ } else if (r->headers_out.content_type.len) {
ctx->boundary_header.len = ngx_sprintf(ctx->boundary_header.data,
CRLF "--%0muA" CRLF
"Content-Type: %V" CRLF
@@ -411,6 +437,13 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
boundary,
&r->headers_out.content_type)
- ctx->boundary_header.data;
+
+ } else {
+ ctx->boundary_header.len = ngx_sprintf(ctx->boundary_header.data,
+ CRLF "--%0muA" CRLF
+ "Content-Range: bytes ",
+ boundary)
+ - ctx->boundary_header.data;
}
r->headers_out.content_type.data =
@@ -465,32 +498,47 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
}
return ngx_http_next_header_filter(r);
+}
-next_filter:
- r->headers_out.accept_ranges = ngx_list_push(&r->headers_out.headers);
- if (r->headers_out.accept_ranges == NULL) {
+static ngx_int_t
+ngx_http_range_not_satisfiable(ngx_http_request_t *r)
+{
+ ngx_table_elt_t *content_range;
+
+ r->headers_out.status = NGX_HTTP_RANGE_NOT_SATISFIABLE;
+
+ content_range = ngx_list_push(&r->headers_out.headers);
+ if (content_range == NULL) {
return NGX_ERROR;
}
- r->headers_out.accept_ranges->hash = 1;
- r->headers_out.accept_ranges->key.len = sizeof("Accept-Ranges") - 1;
- r->headers_out.accept_ranges->key.data = (u_char *) "Accept-Ranges";
- r->headers_out.accept_ranges->value.len = sizeof("bytes") - 1;
- r->headers_out.accept_ranges->value.data = (u_char *) "bytes";
+ r->headers_out.content_range = content_range;
- return ngx_http_next_header_filter(r);
+ content_range->hash = 1;
+ content_range->key.len = sizeof("Content-Range") - 1;
+ content_range->key.data = (u_char *) "Content-Range";
+
+ content_range->value.data = ngx_pnalloc(r->pool,
+ sizeof("bytes */") - 1 + NGX_OFF_T_LEN);
+ if (content_range->value.data == NULL) {
+ return NGX_ERROR;
+ }
+
+ content_range->value.len = ngx_sprintf(content_range->value.data,
+ "bytes */%O",
+ r->headers_out.content_length_n)
+ - content_range->value.data;
+
+ ngx_http_clear_content_length(r);
+
+ return NGX_HTTP_RANGE_NOT_SATISFIABLE;
}
static ngx_int_t
ngx_http_range_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
- off_t start, last;
- ngx_buf_t *b, *buf;
- ngx_uint_t i;
- ngx_chain_t *out, *hcl, *rcl, *dcl, **ll;
- ngx_http_range_t *range;
ngx_http_range_filter_ctx_t *ctx;
if (in == NULL) {
@@ -503,17 +551,40 @@ ngx_http_range_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
return ngx_http_next_body_filter(r, in);
}
- buf = in->buf;
+ if (ctx->ranges.nelts == 1) {
+ return ngx_http_range_singlepart_body(r, ctx, in);
+ }
+
+ /*
+ * multipart ranges are supported only if whole body is in a single buffer
+ */
if (ngx_buf_special(in->buf)) {
return ngx_http_next_body_filter(r, in);
}
+ if (ngx_http_range_test_overlapped(r, ctx, in) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ return ngx_http_range_multipart_body(r, ctx, in);
+}
+
+
+static ngx_int_t
+ngx_http_range_test_overlapped(ngx_http_request_t *r,
+ ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in)
+{
+ off_t start, last;
+ ngx_buf_t *buf;
+ ngx_uint_t i;
+ ngx_http_range_t *range;
+
if (ctx->offset) {
goto overlapped;
}
- range = ctx->ranges.elts;
+ buf = in->buf;
if (!buf->last_buf) {
@@ -526,6 +597,7 @@ ngx_http_range_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
last = buf->last - buf->start + ctx->offset;
}
+ range = ctx->ranges.elts;
for (i = 0; i < ctx->ranges.nelts; i++) {
if (start > range[i].start || last < range[i].end) {
goto overlapped;
@@ -533,29 +605,111 @@ ngx_http_range_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
}
}
- /*
- * the optimized version for the responses
- * that are passed in the single buffer
- */
-
ctx->offset = ngx_buf_size(buf);
- if (ctx->ranges.nelts == 1) {
+ return NGX_OK;
- if (buf->in_file) {
- buf->file_pos = range->start;
- buf->file_last = range->end;
+overlapped:
+
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+ "range in overlapped buffers");
+
+ return NGX_ERROR;
+}
+
+
+static ngx_int_t
+ngx_http_range_singlepart_body(ngx_http_request_t *r,
+ ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in)
+{
+ off_t start, last;
+ ngx_buf_t *buf;
+ ngx_chain_t *out, *cl, **ll;
+ ngx_http_range_t *range;
+
+ out = NULL;
+ ll = &out;
+ range = ctx->ranges.elts;
+
+ for (cl = in; cl; cl = cl->next) {
+
+ buf = cl->buf;
+
+ start = ctx->offset;
+ last = ctx->offset + ngx_buf_size(buf);
+
+ ctx->offset = last;
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http range body buf: %O-%O", start, last);
+
+ if (ngx_buf_special(buf)) {
+ *ll = cl;
+ ll = &cl->next;
+ continue;
}
- if (ngx_buf_in_memory(buf)) {
- buf->pos = buf->start + (size_t) range->start;
- buf->last = buf->start + (size_t) range->end;
+ if (range->end <= start || range->start >= last) {
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http range body skip");
+
+ buf->pos = buf->last;
+ continue;
}
- return ngx_http_next_body_filter(r, in);
+ if (range->start > start) {
+
+ if (buf->in_file) {
+ buf->file_pos += range->start - start;
+ }
+
+ if (ngx_buf_in_memory(buf)) {
+ buf->pos += (size_t) (range->start - start);
+ }
+ }
+
+ if (range->end <= last) {
+
+ if (buf->in_file) {
+ buf->file_last -= last - range->end;
+ }
+
+ if (ngx_buf_in_memory(buf)) {
+ buf->last -= (size_t) (last - range->end);
+ }
+
+ buf->last_buf = 1;
+ *ll = cl;
+ cl->next = NULL;
+
+ break;
+ }
+
+ *ll = cl;
+ ll = &cl->next;
+ }
+
+ if (out == NULL) {
+ return NGX_OK;
}
+ return ngx_http_next_body_filter(r, out);
+}
+
+
+static ngx_int_t
+ngx_http_range_multipart_body(ngx_http_request_t *r,
+ ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in)
+{
+ ngx_buf_t *b, *buf;
+ ngx_uint_t i;
+ ngx_chain_t *out, *hcl, *rcl, *dcl, **ll;
+ ngx_http_range_t *range;
+
ll = &out;
+ buf = in->buf;
+ range = ctx->ranges.elts;
for (i = 0; i < ctx->ranges.nelts; i++) {
@@ -671,13 +825,6 @@ ngx_http_range_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
*ll = hcl;
return ngx_http_next_body_filter(r, out);
-
-overlapped:
-
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- "range in overlapped buffers");
-
- return NGX_ERROR;
}
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
index c0f0fdadb..53e2a2157 100644
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -13,9 +13,9 @@ typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c,
ngx_pool_t *pool, ngx_str_t *s);
-#define NGX_DEFLAUT_CERTIFICATE "cert.pem"
-#define NGX_DEFLAUT_CERTIFICATE_KEY "cert.pem"
-#define NGX_DEFLAUT_CIPHERS "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP"
+#define NGX_DEFAULT_CERTIFICATE "cert.pem"
+#define NGX_DEFAULT_CERTIFICATE_KEY "cert.pem"
+#define NGX_DEFAULT_CIPHERS "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP"
static ngx_int_t ngx_http_ssl_static_variable(ngx_http_request_t *r,
@@ -49,6 +49,14 @@ static ngx_conf_bitmask_t ngx_http_ssl_protocols[] = {
};
+static ngx_conf_enum_t ngx_http_ssl_verify[] = {
+ { ngx_string("off"), 0 },
+ { ngx_string("on"), 1 },
+ { ngx_string("ask"), 2 },
+ { ngx_null_string, 0 }
+};
+
+
static ngx_command_t ngx_http_ssl_commands[] = {
{ ngx_string("ssl"),
@@ -95,10 +103,10 @@ static ngx_command_t ngx_http_ssl_commands[] = {
{ ngx_string("ssl_verify_client"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
+ ngx_conf_set_enum_slot,
NGX_HTTP_SRV_CONF_OFFSET,
offsetof(ngx_http_ssl_srv_conf_t, verify),
- NULL },
+ &ngx_http_ssl_verify },
{ ngx_string("ssl_verify_depth"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
@@ -185,6 +193,10 @@ static ngx_http_variable_t ngx_http_ssl_vars[] = {
{ ngx_string("ssl_client_cert"), NULL, ngx_http_ssl_variable,
(uintptr_t) ngx_ssl_get_certificate, NGX_HTTP_VAR_CHANGEABLE, 0 },
+ { ngx_string("ssl_client_raw_cert"), NULL, ngx_http_ssl_variable,
+ (uintptr_t) ngx_ssl_get_raw_certificate,
+ NGX_HTTP_VAR_CHANGEABLE, 0 },
+
{ ngx_string("ssl_client_s_dn"), NULL, ngx_http_ssl_variable,
(uintptr_t) ngx_ssl_get_subject_dn, NGX_HTTP_VAR_CHANGEABLE, 0 },
@@ -307,9 +319,9 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
*/
sscf->enable = NGX_CONF_UNSET;
+ sscf->prefer_server_ciphers = NGX_CONF_UNSET;
sscf->verify = NGX_CONF_UNSET;
sscf->verify_depth = NGX_CONF_UNSET;
- sscf->prefer_server_ciphers = NGX_CONF_UNSET;
sscf->builtin_session_cache = NGX_CONF_UNSET;
sscf->session_timeout = NGX_CONF_UNSET;
@@ -341,21 +353,21 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
(NGX_CONF_BITMASK_SET
|NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1));
- ngx_conf_merge_value(conf->verify, prev->verify, 0);
- ngx_conf_merge_value(conf->verify_depth, prev->verify_depth, 1);
+ ngx_conf_merge_uint_value(conf->verify, prev->verify, 0);
+ ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1);
ngx_conf_merge_str_value(conf->certificate, prev->certificate,
- NGX_DEFLAUT_CERTIFICATE);
+ NGX_DEFAULT_CERTIFICATE);
ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key,
- NGX_DEFLAUT_CERTIFICATE_KEY);
+ NGX_DEFAULT_CERTIFICATE_KEY);
ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, "");
ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate,
"");
- ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFLAUT_CIPHERS);
+ ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);
conf->ssl.log = cf->log;
@@ -402,6 +414,13 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
}
if (conf->verify) {
+
+ if (conf->client_certificate.len == 0) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "no ssl_client_certificate for ssl_client_verify");
+ return NGX_CONF_ERROR;
+ }
+
if (ngx_ssl_client_certificate(cf, &conf->ssl,
&conf->client_certificate,
conf->verify_depth)
diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h
index 74bf6e56e..2322d90c1 100644
--- a/src/http/modules/ngx_http_ssl_module.h
+++ b/src/http/modules/ngx_http_ssl_module.h
@@ -22,8 +22,8 @@ typedef struct {
ngx_uint_t protocols;
- ngx_int_t verify;
- ngx_int_t verify_depth;
+ ngx_uint_t verify;
+ ngx_uint_t verify_depth;
ssize_t builtin_session_cache;
diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c
index ce2f0fc65..8d399fccd 100644
--- a/src/http/modules/ngx_http_static_module.c
+++ b/src/http/modules/ngx_http_static_module.c
@@ -98,6 +98,7 @@ ngx_http_static_handler(ngx_http_request_t *r)
ngx_memzero(&of, sizeof(ngx_open_file_info_t));
+ of.directio = clcf->directio;
of.valid = clcf->open_file_cache_valid;
of.min_uses = clcf->open_file_cache_min_uses;
of.errors = clcf->open_file_cache_errors;
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index 54e98991f..58fc8a559 100644
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -47,7 +47,7 @@ our @EXPORT = qw(
HTTP_INSUFFICIENT_STORAGE
);
-our $VERSION = '0.7.6';
+our $VERSION = '0.7.7';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs
index f86b76f3e..6e7ad7760 100644
--- a/src/http/modules/perl/nginx.xs
+++ b/src/http/modules/perl/nginx.xs
@@ -652,6 +652,7 @@ sendfile(r, filename, offset = -1, bytes = 0)
ngx_memzero(&of, sizeof(ngx_open_file_info_t));
+ of.directio = clcf->directio;
of.valid = clcf->open_file_cache_valid;
of.min_uses = clcf->open_file_cache_min_uses;
of.errors = clcf->open_file_cache_errors;
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 20aba8653..468b3e151 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -54,6 +54,8 @@ static char *ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd,
static char *ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static char *ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
+static char *ngx_http_core_directio(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
static char *ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd,
@@ -353,6 +355,13 @@ static ngx_command_t ngx_http_core_commands[] = {
offsetof(ngx_http_core_loc_conf_t, sendfile_max_chunk),
NULL },
+ { ngx_string("directio"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_http_core_directio,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ 0,
+ NULL },
+
{ ngx_string("tcp_nopush"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
@@ -1204,7 +1213,7 @@ ngx_http_core_find_static_location(ngx_http_request_t *r,
n = (len <= (size_t) node->len) ? len : node->len;
- rc = ngx_memcmp(uri, node->name, n);
+ rc = ngx_filename_cmp(uri, node->name, n);
if (rc != 0) {
node = (rc < 0) ? node->left : node->right;
@@ -2586,6 +2595,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf)
lcf->client_body_in_file_only = NGX_CONF_UNSET;
lcf->sendfile = NGX_CONF_UNSET;
lcf->sendfile_max_chunk = NGX_CONF_UNSET_SIZE;
+ lcf->directio = NGX_CONF_UNSET;
lcf->tcp_nopush = NGX_CONF_UNSET;
lcf->tcp_nodelay = NGX_CONF_UNSET;
lcf->send_timeout = NGX_CONF_UNSET_MSEC;
@@ -2774,6 +2784,8 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0);
ngx_conf_merge_size_value(conf->sendfile_max_chunk,
prev->sendfile_max_chunk, 0);
+ ngx_conf_merge_off_value(conf->directio, prev->directio,
+ NGX_MAX_OFF_T_VALUE);
ngx_conf_merge_value(conf->tcp_nopush, prev->tcp_nopush, 0);
ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1);
@@ -3340,6 +3352,33 @@ ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
static char *
+ngx_http_core_directio(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_core_loc_conf_t *clcf = conf;
+
+ ngx_str_t *value;
+
+ if (clcf->directio != NGX_CONF_UNSET) {
+ return "is duplicate";
+ }
+
+ value = cf->args->elts;
+
+ if (ngx_strcmp(value[1].data, "off") == 0) {
+ clcf->directio = NGX_MAX_OFF_T_VALUE;
+ return NGX_CONF_OK;
+ }
+
+ clcf->directio = ngx_parse_offset(&value[1]);
+ if (clcf->directio == (off_t) NGX_ERROR) {
+ return "invalid value";
+ }
+
+ return NGX_CONF_OK;
+}
+
+
+static char *
ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_loc_conf_t *lcf = conf;
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index 85d96b079..57ee748e7 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -265,6 +265,7 @@ struct ngx_http_core_loc_conf_s {
ngx_str_t default_type;
off_t client_max_body_size; /* client_max_body_size */
+ off_t directio; /* directio */
size_t client_body_buffer_size; /* client_body_buffer_size */
size_t send_lowat; /* send_lowat */
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 8dc562f28..9aad1a487 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1446,7 +1446,7 @@ ngx_http_process_request(ngx_http_request_t *r)
sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
- if (sscf->verify) {
+ if (sscf->verify == 1) {
rc = SSL_get_verify_result(c->ssl->connection);
if (rc != X509_V_OK) {
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
index 7a47417e4..0ffa07cc8 100644
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -996,6 +996,7 @@ ngx_http_script_file_code(ngx_http_script_engine_t *e)
ngx_memzero(&of, sizeof(ngx_open_file_info_t));
+ of.directio = clcf->directio;
of.valid = clcf->open_file_cache_valid;
of.min_uses = clcf->open_file_cache_min_uses;
of.errors = clcf->open_file_cache_errors;
diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c
index c64d48cb4..11a0d1d80 100644
--- a/src/mail/ngx_mail_ssl_module.c
+++ b/src/mail/ngx_mail_ssl_module.c
@@ -9,9 +9,9 @@
#include <ngx_mail.h>
-#define NGX_DEFLAUT_CERTIFICATE "cert.pem"
-#define NGX_DEFLAUT_CERTIFICATE_KEY "cert.pem"
-#define NGX_DEFLAUT_CIPHERS "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP"
+#define NGX_DEFAULT_CERTIFICATE "cert.pem"
+#define NGX_DEFAULT_CERTIFICATE_KEY "cert.pem"
+#define NGX_DEFAULT_CIPHERS "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP"
static void *ngx_mail_ssl_create_conf(ngx_conf_t *cf);
@@ -214,14 +214,14 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1));
ngx_conf_merge_str_value(conf->certificate, prev->certificate,
- NGX_DEFLAUT_CERTIFICATE);
+ NGX_DEFAULT_CERTIFICATE);
ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key,
- NGX_DEFLAUT_CERTIFICATE_KEY);
+ NGX_DEFAULT_CERTIFICATE_KEY);
ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, "");
- ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFLAUT_CIPHERS);
+ ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);
conf->ssl.log = cf->log;
diff --git a/src/os/unix/ngx_alloc.h b/src/os/unix/ngx_alloc.h
index 8b7b766b2..c7a31aa54 100644
--- a/src/os/unix/ngx_alloc.h
+++ b/src/os/unix/ngx_alloc.h
@@ -21,8 +21,8 @@ void *ngx_calloc(size_t size, ngx_log_t *log);
/*
* Linux has memalign() or posix_memalign()
* Solaris has memalign()
- * FreeBSD has not memalign() or posix_memalign() but its malloc() alignes
- * allocations bigger than page size at the page boundary.
+ * FreeBSD 7.0 has posix_memalign(), besides, early version's malloc()
+ * aligns allocations bigger than page size at the page boundary
*/
#if (NGX_HAVE_POSIX_MEMALIGN || NGX_HAVE_MEMALIGN)
diff --git a/src/os/unix/ngx_darwin.h b/src/os/unix/ngx_darwin.h
new file mode 100644
index 000000000..7fa60ff0c
--- /dev/null
+++ b/src/os/unix/ngx_darwin.h
@@ -0,0 +1,19 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#ifndef _NGX_DARWIN_H_INCLUDED_
+#define _NGX_DARWIN_H_INCLUDED_
+
+
+ngx_chain_t *ngx_darwin_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in,
+ off_t limit);
+
+extern int ngx_darwin_kern_osreldate;
+extern int ngx_darwin_hw_ncpu;
+extern u_long ngx_darwin_net_inet_tcp_sendspace;
+
+
+#endif /* _NGX_DARWIN_H_INCLUDED_ */
diff --git a/src/os/unix/ngx_darwin_config.h b/src/os/unix/ngx_darwin_config.h
new file mode 100644
index 000000000..373ed14e3
--- /dev/null
+++ b/src/os/unix/ngx_darwin_config.h
@@ -0,0 +1,87 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#ifndef _NGX_DARWIN_CONFIG_H_INCLUDED_
+#define _NGX_DARWIN_CONFIG_H_INCLUDED_
+
+
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stddef.h> /* offsetof() */
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <pwd.h>
+#include <grp.h>
+#include <dirent.h>
+#include <glob.h>
+
+#include <sys/filio.h> /* FIONBIO */
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sched.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h> /* TCP_NODELAY */
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/un.h>
+
+#include <sys/sysctl.h>
+#include <xlocale.h>
+
+
+#ifndef IOV_MAX
+#define IOV_MAX 64
+#endif
+
+
+#include <ngx_auto_config.h>
+
+
+#if (NGX_HAVE_POLL)
+#include <poll.h>
+#endif
+
+
+#if (NGX_HAVE_KQUEUE)
+#include <sys/event.h>
+#endif
+
+
+#define NGX_LISTEN_BACKLOG -1
+
+
+#ifndef NGX_HAVE_INHERITED_NONBLOCK
+#define NGX_HAVE_INHERITED_NONBLOCK 1
+#endif
+
+
+#ifndef NGX_HAVE_CASELESS_FILESYSTEM
+#define NGX_HAVE_CASELESS_FILESYSTEM 1
+#endif
+
+
+#define NGX_HAVE_OS_SPECIFIC_INIT 1
+
+
+extern char **environ;
+
+
+#endif /* _NGX_DARWIN_CONFIG_H_INCLUDED_ */
diff --git a/src/os/unix/ngx_darwin_init.c b/src/os/unix/ngx_darwin_init.c
new file mode 100644
index 000000000..c10196c62
--- /dev/null
+++ b/src/os/unix/ngx_darwin_init.c
@@ -0,0 +1,155 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+char ngx_darwin_kern_ostype[16];
+char ngx_darwin_kern_osrelease[128];
+int ngx_darwin_hw_ncpu;
+int ngx_darwin_kern_ipc_somaxconn;
+u_long ngx_darwin_net_inet_tcp_sendspace;
+
+
+static ngx_os_io_t ngx_darwin_io = {
+ ngx_unix_recv,
+ ngx_readv_chain,
+ ngx_udp_unix_recv,
+ ngx_unix_send,
+#if (NGX_HAVE_SENDFILE)
+ ngx_darwin_sendfile_chain,
+ NGX_IO_SENDFILE
+#else
+ ngx_writev_chain,
+ 0
+#endif
+};
+
+
+typedef struct {
+ char *name;
+ void *value;
+ size_t size;
+ ngx_uint_t exists;
+} sysctl_t;
+
+
+sysctl_t sysctls[] = {
+ { "hw.ncpu",
+ &ngx_darwin_hw_ncpu,
+ sizeof(ngx_darwin_hw_ncpu), 0 },
+
+ { "net.inet.tcp.sendspace",
+ &ngx_darwin_net_inet_tcp_sendspace,
+ sizeof(ngx_darwin_net_inet_tcp_sendspace), 0 },
+
+ { "kern.ipc.somaxconn",
+ &ngx_darwin_kern_ipc_somaxconn,
+ sizeof(ngx_darwin_kern_ipc_somaxconn), 0 },
+
+ { NULL, NULL, 0, 0 }
+};
+
+
+ngx_int_t
+ngx_os_specific_init(ngx_log_t *log)
+{
+ int somaxconn;
+ size_t size;
+ ngx_err_t err;
+ ngx_uint_t i;
+
+ size = sizeof(ngx_darwin_kern_ostype);
+ if (sysctlbyname("kern.ostype",
+ ngx_darwin_kern_ostype, &size, NULL, 0) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+ "sysctlbyname(kern.ostype) failed");
+
+ if (ngx_errno != NGX_ENOMEM) {
+ return NGX_ERROR;
+ }
+
+ ngx_darwin_kern_ostype[size - 1] = '\0';
+ }
+
+ size = sizeof(ngx_darwin_kern_osrelease);
+ if (sysctlbyname("kern.osrelease",
+ ngx_darwin_kern_osrelease, &size, NULL, 0) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+ "sysctlbyname(kern.osrelease) failed");
+
+ if (ngx_errno != NGX_ENOMEM) {
+ return NGX_ERROR;
+ }
+
+ ngx_darwin_kern_osrelease[size - 1] = '\0';
+ }
+
+
+ for (i = 0; sysctls[i].name; i++) {
+ size = sysctls[i].size;
+
+ if (sysctlbyname(sysctls[i].name, sysctls[i].value, &size, NULL, 0)
+ == 0)
+ {
+ sysctls[i].exists = 1;
+ continue;
+ }
+
+ err = ngx_errno;
+
+ if (err == NGX_ENOENT) {
+ continue;
+ }
+
+ ngx_log_error(NGX_LOG_ALERT, log, err,
+ "sysctlbyname(%s) failed", sysctls[i].name);
+ return NGX_ERROR;
+ }
+
+ ngx_ncpu = ngx_darwin_hw_ncpu;
+
+ somaxconn = 32676;
+
+ if (ngx_darwin_kern_ipc_somaxconn > somaxconn) {
+ ngx_log_error(NGX_LOG_ALERT, log, 0,
+ "sysctl kern.ipc.somaxconn must be no more than %d",
+ somaxconn);
+ return NGX_ERROR;
+ }
+
+ ngx_tcp_nodelay_and_tcp_nopush = 1;
+
+ ngx_os_io = ngx_darwin_io;
+
+ return NGX_OK;
+}
+
+
+void
+ngx_os_specific_status(ngx_log_t *log)
+{
+ u_long value;
+ ngx_uint_t i;
+
+ ngx_log_error(NGX_LOG_NOTICE, log, 0, "OS: %s %s",
+ ngx_darwin_kern_ostype, ngx_darwin_kern_osrelease);
+
+ for (i = 0; sysctls[i].name; i++) {
+ if (sysctls[i].exists) {
+ if (sysctls[i].size == sizeof(long)) {
+ value = *(long *) sysctls[i].value;
+
+ } else {
+ value = *(int *) sysctls[i].value;
+ }
+
+ ngx_log_error(NGX_LOG_NOTICE, log, 0, "%s: %l",
+ sysctls[i].name, value);
+ }
+ }
+}
diff --git a/src/os/unix/ngx_darwin_sendfile_chain.c b/src/os/unix/ngx_darwin_sendfile_chain.c
new file mode 100644
index 000000000..e3ec7f704
--- /dev/null
+++ b/src/os/unix/ngx_darwin_sendfile_chain.c
@@ -0,0 +1,363 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_event.h>
+
+
+/*
+ * It seems that Darwin 9.4 (Mac OS X 1.5) sendfile() has the same
+ * old bug as early FreeBSD sendfile() syscall:
+ * http://www.freebsd.org/cgi/query-pr.cgi?pr=33771
+ *
+ * Besides sendfile() has another bug: if one calls sendfile()
+ * with both a header and a trailer, then sendfile() ignores a file part
+ * at all and sends only the header and the trailer together.
+ * For this reason we send a trailer only if there is no a header.
+ *
+ * Although sendfile() allows to pass a header or a trailer,
+ * it may send the header or the trailer and a part of the file
+ * in different packets. And FreeBSD workaround (TCP_NOPUSH option)
+ * does not help.
+ */
+
+
+#if (IOV_MAX > 64)
+#define NGX_HEADERS 64
+#define NGX_TRAILERS 64
+#else
+#define NGX_HEADERS IOV_MAX
+#define NGX_TRAILERS IOV_MAX
+#endif
+
+
+ngx_chain_t *
+ngx_darwin_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
+{
+ int rc;
+ u_char *prev;
+ off_t size, send, prev_send, aligned, sent, fprev;
+ off_t header_size, file_size;
+ ngx_uint_t eintr, eagain, complete;
+ ngx_err_t err;
+ ngx_buf_t *file;
+ ngx_array_t header, trailer;
+ ngx_event_t *wev;
+ ngx_chain_t *cl;
+ struct sf_hdtr hdtr;
+ struct iovec *iov, headers[NGX_HEADERS], trailers[NGX_TRAILERS];
+
+ wev = c->write;
+
+ if (!wev->ready) {
+ return in;
+ }
+
+#if (NGX_HAVE_KQUEUE)
+
+ if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) {
+ (void) ngx_connection_error(c, wev->kq_errno,
+ "kevent() reported about an closed connection");
+ wev->error = 1;
+ return NGX_CHAIN_ERROR;
+ }
+
+#endif
+
+ /* the maximum limit size is the maximum size_t value - the page size */
+
+ if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) {
+ limit = NGX_MAX_SIZE_T_VALUE - ngx_pagesize;
+ }
+
+ send = 0;
+ eagain = 0;
+
+ header.elts = headers;
+ header.size = sizeof(struct iovec);
+ header.nalloc = NGX_HEADERS;
+ header.pool = c->pool;
+
+ trailer.elts = trailers;
+ trailer.size = sizeof(struct iovec);
+ trailer.nalloc = NGX_TRAILERS;
+ trailer.pool = c->pool;
+
+ for ( ;; ) {
+ file = NULL;
+ file_size = 0;
+ header_size = 0;
+ eintr = 0;
+ complete = 0;
+ prev_send = send;
+
+ header.nelts = 0;
+ trailer.nelts = 0;
+
+ /* create the header iovec and coalesce the neighbouring bufs */
+
+ prev = NULL;
+ iov = NULL;
+
+ for (cl = in;
+ cl && header.nelts < IOV_MAX && send < limit;
+ cl = cl->next)
+ {
+ if (ngx_buf_special(cl->buf)) {
+ continue;
+ }
+
+ if (!ngx_buf_in_memory_only(cl->buf)) {
+ break;
+ }
+
+ size = cl->buf->last - cl->buf->pos;
+
+ if (send + size > limit) {
+ size = limit - send;
+ }
+
+ if (prev == cl->buf->pos) {
+ iov->iov_len += (size_t) size;
+
+ } else {
+ iov = ngx_array_push(&header);
+ if (iov == NULL) {
+ return NGX_CHAIN_ERROR;
+ }
+
+ iov->iov_base = (void *) cl->buf->pos;
+ iov->iov_len = (size_t) size;
+ }
+
+ prev = cl->buf->pos + (size_t) size;
+ header_size += size;
+ send += size;
+ }
+
+
+ if (cl && cl->buf->in_file && send < limit) {
+ file = cl->buf;
+
+ /* coalesce the neighbouring file bufs */
+
+ do {
+ size = cl->buf->file_last - cl->buf->file_pos;
+
+ if (send + size > limit) {
+ size = limit - send;
+
+ aligned = (cl->buf->file_pos + size + ngx_pagesize - 1)
+ & ~((off_t) ngx_pagesize - 1);
+
+ if (aligned <= cl->buf->file_last) {
+ size = aligned - cl->buf->file_pos;
+ }
+ }
+
+ file_size += size;
+ send += size;
+ fprev = cl->buf->file_pos + size;
+ cl = cl->next;
+
+ } while (cl
+ && cl->buf->in_file
+ && send < limit
+ && file->file->fd == cl->buf->file->fd
+ && fprev == cl->buf->file_pos);
+ }
+
+ if (file && header.nelts == 0) {
+
+ /* create the tailer iovec and coalesce the neighbouring bufs */
+
+ prev = NULL;
+ iov = NULL;
+
+ while (cl && header.nelts < IOV_MAX && send < limit) {
+
+ if (ngx_buf_special(cl->buf)) {
+ cl = cl->next;
+ continue;
+ }
+
+ if (!ngx_buf_in_memory_only(cl->buf)) {
+ break;
+ }
+
+ size = cl->buf->last - cl->buf->pos;
+
+ if (send + size > limit) {
+ size = limit - send;
+ }
+
+ if (prev == cl->buf->pos) {
+ iov->iov_len += (size_t) size;
+
+ } else {
+ iov = ngx_array_push(&trailer);
+ if (iov == NULL) {
+ return NGX_CHAIN_ERROR;
+ }
+
+ iov->iov_base = (void *) cl->buf->pos;
+ iov->iov_len = (size_t) size;
+ }
+
+ prev = cl->buf->pos + (size_t) size;
+ send += size;
+ cl = cl->next;
+ }
+ }
+
+ if (file) {
+
+ /*
+ * sendfile() returns EINVAL if sf_hdtr's count is 0,
+ * but corresponding pointer is not NULL
+ */
+
+ hdtr.headers = header.nelts ? (struct iovec *) header.elts: NULL;
+ hdtr.hdr_cnt = header.nelts;
+ hdtr.trailers = trailer.nelts ? (struct iovec *) trailer.elts: NULL;
+ hdtr.trl_cnt = trailer.nelts;
+
+ sent = header_size + file_size;
+
+ ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
+ "sendfile: @%O %O h:%O",
+ file->file_pos, sent, header_size);
+
+ rc = sendfile(file->file->fd, c->fd, file->file_pos,
+ &sent, &hdtr, 0);
+
+ if (rc == -1) {
+ err = ngx_errno;
+
+ if (err == NGX_EAGAIN || err == NGX_EINTR) {
+ if (err == NGX_EINTR) {
+ eintr = 1;
+
+ } else {
+ eagain = 1;
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err,
+ "sendfile() sent only %O bytes", sent);
+
+ } else {
+ wev->error = 1;
+ (void) ngx_connection_error(c, err, "sendfile() failed");
+ return NGX_CHAIN_ERROR;
+ }
+ }
+
+ if (rc == 0 && sent == 0) {
+
+ /*
+ * if rc and sent equal to zero, then someone
+ * has truncated the file, so the offset became beyond
+ * the end of the file
+ */
+
+ ngx_log_error(NGX_LOG_ALERT, c->log, 0,
+ "sendfile() reported that \"%s\" was truncated",
+ file->file->name.data);
+
+ return NGX_CHAIN_ERROR;
+ }
+
+ ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
+ "sendfile: %d, @%O %O:%O",
+ 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, send);
+
+ if (rc == -1) {
+ err = ngx_errno;
+
+ if (err == NGX_EAGAIN || err == NGX_EINTR) {
+ if (err == NGX_EINTR) {
+ eintr = 1;
+ }
+
+ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
+ "writev() not ready");
+
+ } else {
+ wev->error = 1;
+ ngx_connection_error(c, err, "writev() failed");
+ return NGX_CHAIN_ERROR;
+ }
+ }
+
+ sent = rc > 0 ? rc : 0;
+ }
+
+ if (send - prev_send == sent) {
+ complete = 1;
+ }
+
+ c->sent += sent;
+
+ for (cl = in; cl; cl = cl->next) {
+
+ if (ngx_buf_special(cl->buf)) {
+ continue;
+ }
+
+ if (sent == 0) {
+ break;
+ }
+
+ size = ngx_buf_size(cl->buf);
+
+ if (sent >= size) {
+ sent -= size;
+
+ if (ngx_buf_in_memory(cl->buf)) {
+ cl->buf->pos = cl->buf->last;
+ }
+
+ if (cl->buf->in_file) {
+ cl->buf->file_pos = cl->buf->file_last;
+ }
+
+ continue;
+ }
+
+ if (ngx_buf_in_memory(cl->buf)) {
+ cl->buf->pos += (size_t) sent;
+ }
+
+ if (cl->buf->in_file) {
+ cl->buf->file_pos += sent;
+ }
+
+ break;
+ }
+
+ if (eintr) {
+ continue;
+ }
+
+ if (!complete) {
+ wev->ready = 0;
+ return cl;
+ }
+
+ if (send >= limit || cl == NULL) {
+ return cl;
+ }
+
+ in = cl;
+ }
+}
diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c
index 7ee8cbd84..e2148d843 100644
--- a/src/os/unix/ngx_files.c
+++ b/src/os/unix/ngx_files.c
@@ -351,3 +351,22 @@ ngx_unlock_fd(ngx_fd_t fd)
return 0;
}
+
+
+#if (NGX_HAVE_O_DIRECT)
+
+ngx_int_t
+ngx_directio(ngx_fd_t fd)
+{
+ int flags;
+
+ flags = fcntl(fd, F_GETFL);
+
+ if (flags == -1) {
+ return -1;
+ }
+
+ return fcntl(fd, F_SETFL, flags | O_DIRECT);
+}
+
+#endif
diff --git a/src/os/unix/ngx_files.h b/src/os/unix/ngx_files.h
index a223b34e8..62af63bce 100644
--- a/src/os/unix/ngx_files.h
+++ b/src/os/unix/ngx_files.h
@@ -19,6 +19,8 @@
#ifdef __CYGWIN__
+#define NGX_HAVE_CASELESS_FILESYSTEM 1
+
#define ngx_open_file(name, mode, create, access) \
open((const char *) name, mode|create|O_BINARY, access)
@@ -103,6 +105,16 @@ ngx_int_t ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s);
#define ngx_file_uniq(sb) (sb)->st_ino
+#if (NGX_HAVE_CASELESS_FILESYSTEM)
+
+#define ngx_filename_cmp(s1, s2, n) strncasecmp((char *) s1, (char *) s2, n)
+
+#else
+
+#define ngx_filename_cmp ngx_memcmp
+
+#endif
+
#define ngx_getcwd(buf, size) (getcwd(buf, size) != NULL)
#define ngx_getcwd_n "getcwd()"
@@ -177,4 +189,22 @@ ngx_err_t ngx_unlock_fd(ngx_fd_t fd);
#define ngx_unlock_fd_n "fcntl(F_SETLK, F_UNLCK)"
+#if (NGX_HAVE_O_DIRECT)
+
+ngx_int_t ngx_directio(ngx_fd_t fd);
+#define ngx_directio_n "fcntl(O_DIRECT)"
+
+#elif (NGX_HAVE_F_NOCACHE)
+
+#define ngx_directio(fd) fcntl(fd, F_NOCACHE, 1)
+#define ngx_directio_n "fcntl(F_NOCACHE)"
+
+#else
+
+#define ngx_directio(fd) 0
+#define ngx_directio_n "ngx_directio_n"
+
+#endif
+
+
#endif /* _NGX_FILES_H_INCLUDED_ */
diff --git a/src/os/unix/ngx_os.h b/src/os/unix/ngx_os.h
index 54b1370bd..44ed6d0f1 100644
--- a/src/os/unix/ngx_os.h
+++ b/src/os/unix/ngx_os.h
@@ -66,6 +66,10 @@ extern ngx_uint_t ngx_tcp_nodelay_and_tcp_nopush;
#elif (NGX_SOLARIS)
#include <ngx_solaris.h>
+
+
+#elif (NGX_DARWIN)
+#include <ngx_darwin.h>
#endif