diff --git a/src/event/modules/ngx_iocp_module.c b/src/event/modules/ngx_iocp_module.c index 0fc7a7153..7b89227a3 100644 --- a/src/event/modules/ngx_iocp_module.c +++ b/src/event/modules/ngx_iocp_module.c @@ -77,6 +77,15 @@ ngx_module_t ngx_iocp_module = { }; +ngx_os_io_t ngx_iocp_io = { + ngx_overlapped_wsarecv, + NULL, + NULL, + ngx_wsasend_chain, + 0 +}; + + static HANDLE iocp; @@ -225,6 +234,7 @@ ngx_log_debug(log, "iocp ev: %08x" _ ev); switch (key) { case NGX_IOCP_IO: + ev->complete = 1; ev->ready = 1; break; diff --git a/src/http/ngx_http_cache.c b/src/http/ngx_http_cache.c index 299455ba3..6e64af140 100644 --- a/src/http/ngx_http_cache.c +++ b/src/http/ngx_http_cache.c @@ -140,9 +140,7 @@ int ngx_http_cache_update_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx, retry = 0; for ( ;; ) { - if (ngx_rename_file(temp_file->data, ctx->file.name.data) - != NGX_FILE_ERROR) - { + if (ngx_rename_file(temp_file, (&ctx->file.name), r->pool) == NGX_OK) { return NGX_OK; } diff --git a/src/os/unix/ngx_aio_read.c b/src/os/unix/ngx_aio_read.c index 28deac6d2..c5fb4a55f 100644 --- a/src/os/unix/ngx_aio_read.c +++ b/src/os/unix/ngx_aio_read.c @@ -25,12 +25,12 @@ ssize_t ngx_aio_read(ngx_connection_t *c, char *buf, size_t size) rev = c->read; if (!rev->ready) { - ngx_log_error(NGX_LOG_ALERT, rev->log, 0, "SECOND AIO POST"); + ngx_log_error(NGX_LOG_ALERT, c->log, 0, "SECOND AIO POST"); return NGX_AGAIN; } - ngx_log_debug(rev->log, "rev->complete: %d" _ rev->complete); - ngx_log_debug(rev->log, "aio size: %d" _ size); + ngx_log_debug(c->log, "rev->complete: %d" _ rev->complete); + ngx_log_debug(c->log, "aio size: %d" _ size); if (!rev->complete) { ngx_memzero(&rev->aiocb, sizeof(struct aiocb)); @@ -52,7 +52,7 @@ ssize_t ngx_aio_read(ngx_connection_t *c, char *buf, size_t size) return NGX_ERROR; } - ngx_log_debug(rev->log, "aio_read: #%d OK" _ c->fd); + ngx_log_debug(c->log, "aio_read: #%d OK" _ c->fd); rev->active = 1; rev->ready = 0; @@ -62,7 +62,7 @@ ssize_t ngx_aio_read(ngx_connection_t *c, char *buf, size_t size) n = aio_error(&rev->aiocb); if (n == -1) { - ngx_log_error(NGX_LOG_ALERT, rev->log, ngx_errno, "aio_error() failed"); + ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, "aio_error() failed"); rev->error = 1; return NGX_ERROR; } @@ -70,14 +70,14 @@ ssize_t ngx_aio_read(ngx_connection_t *c, char *buf, size_t size) if (n != 0) { if (n == NGX_EINPROGRESS) { if (rev->ready) { - ngx_log_error(NGX_LOG_ALERT, rev->log, n, + ngx_log_error(NGX_LOG_ALERT, c->log, n, "aio_read() still in progress"); rev->ready = 0; } return NGX_AGAIN; } - ngx_log_error(NGX_LOG_CRIT, rev->log, n, "aio_read() failed"); + ngx_log_error(NGX_LOG_CRIT, c->log, n, "aio_read() failed"); rev->error = 1; rev->ready = 0; return NGX_ERROR; @@ -85,7 +85,7 @@ ssize_t ngx_aio_read(ngx_connection_t *c, char *buf, size_t size) n = aio_return(&rev->aiocb); if (n == -1) { - ngx_log_error(NGX_LOG_ALERT, rev->log, ngx_errno, + ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, "aio_return() failed"); rev->error = 1; diff --git a/src/os/unix/ngx_files.h b/src/os/unix/ngx_files.h index 9990ae8c3..369c3ad5d 100644 --- a/src/os/unix/ngx_files.h +++ b/src/os/unix/ngx_files.h @@ -45,7 +45,7 @@ ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *ce, off_t offset, ngx_pool_t *pool); -#define ngx_rename_file rename +#define ngx_rename_file(from, to, pool) rename(from->data, to->data) #define ngx_rename_file_n "rename" diff --git a/src/os/unix/ngx_os.h b/src/os/unix/ngx_os.h index 33e394319..658c0a400 100644 --- a/src/os/unix/ngx_os.h +++ b/src/os/unix/ngx_os.h @@ -35,6 +35,8 @@ typedef struct { int ngx_os_init(ngx_log_t *log); int ngx_daemon(ngx_log_t *log); int ngx_posix_init(ngx_log_t *log); +int ngx_posix_post_conf_init(ngx_log_t *log); + ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size); ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *entry); diff --git a/src/os/unix/ngx_recv.c b/src/os/unix/ngx_recv.c index 1a14fd963..e75937957 100644 --- a/src/os/unix/ngx_recv.c +++ b/src/os/unix/ngx_recv.c @@ -40,6 +40,8 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size) } do { + rev->ready = 1; + n = recv(c->fd, buf, size, 0); ngx_log_debug(c->log, "recv: %d:%d" _ n _ size); @@ -78,11 +80,14 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size) } rev->ready = 0; - rev->error = 1; n = ngx_unix_recv_error(rev, ngx_socket_errno); } while (n == NGX_EINTR); + if (n == NGX_ERROR){ + rev->error = 1; + } + return n; } @@ -96,6 +101,8 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size) rev = c->read; do { + rev->ready = 1; + n = recv(c->fd, buf, size, 0); ngx_log_debug(c->log, "recv: %d:%d" _ n _ size); @@ -113,11 +120,14 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size) } rev->ready = 0; - rev->error = 1; n = ngx_unix_recv_error(rev, ngx_socket_errno); } while (n == NGX_EINTR); + if (n == NGX_ERROR){ + rev->error = 1; + } + return n; } diff --git a/src/os/unix/ngx_unix_init.c b/src/os/unix/ngx_unix_init.c index 95741642b..ab33979ec 100644 --- a/src/os/unix/ngx_unix_init.c +++ b/src/os/unix/ngx_unix_init.c @@ -3,17 +3,19 @@ #include +#if 0 /* STUB */ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size); ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in); int ngx_posix_init(ngx_log_t *log); int ngx_posix_post_conf_init(ngx_log_t *log); /* */ +#endif ngx_os_io_t ngx_os_io = { ngx_unix_recv, - NULL, + ngx_readv_chain, NULL, ngx_writev_chain, NGX_HAVE_ZEROCOPY diff --git a/src/os/unix/ngx_writev_chain.c b/src/os/unix/ngx_writev_chain.c index 6ead65f3a..9b9e62939 100644 --- a/src/os/unix/ngx_writev_chain.c +++ b/src/os/unix/ngx_writev_chain.c @@ -24,6 +24,7 @@ ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in) iov = NULL; /* create the iovec and coalesce the neighbouring hunks */ + for (cl = in; cl; cl = cl->next) { if (prev == cl->hunk->pos) { @@ -57,7 +58,7 @@ ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in) sent = n > 0 ? n : 0; #if (NGX_DEBUG_WRITE_CHAIN) - ngx_log_debug(c->log, "writev: %qd" _ sent); + ngx_log_debug(c->log, "writev: " OFF_FMT _ sent); #endif c->sent += sent; @@ -75,12 +76,6 @@ ngx_log_debug(c->log, "SIZE: %d" _ size); cl->hunk->pos = cl->hunk->last; } -#if 0 - if (cl->hunk->type & NGX_HUNK_FILE) { - cl->hunk->file_pos = cl->hunk->file_last; - } -#endif - continue; } @@ -88,12 +83,6 @@ ngx_log_debug(c->log, "SIZE: %d" _ size); cl->hunk->pos += sent; } -#if 0 - if (cl->hunk->type & NGX_HUNK_FILE) { - cl->hunk->file_pos += sent; - } -#endif - break; } diff --git a/src/os/win32/ngx_files.c b/src/os/win32/ngx_files.c index 139d141cb..35e83bfd6 100644 --- a/src/os/win32/ngx_files.c +++ b/src/os/win32/ngx_files.c @@ -6,13 +6,11 @@ ssize_t ngx_read_file(ngx_file_t *file, char *buf, size_t size, off_t offset) { size_t n; + long high_offset; + ngx_err_t err; OVERLAPPED ovlp, *povlp; -#if (WIN9X) - if (ngx_win32_version < NGX_WIN_NT) { - long high_offset; - ngx_err_t err; /* * in Win9X the overlapped pointer must be NULL @@ -47,8 +45,6 @@ ssize_t ngx_read_file(ngx_file_t *file, char *buf, size_t size, off_t offset) povlp = NULL; } else { - -#endif ovlp.Internal = 0; ovlp.InternalHigh = 0; ovlp.Offset = (DWORD) offset; @@ -56,10 +52,7 @@ ssize_t ngx_read_file(ngx_file_t *file, char *buf, size_t size, off_t offset) ovlp.hEvent = NULL; povlp = &ovlp; - -#if (WIN9X) } -#endif if (ReadFile(file->fd, buf, size, &n, povlp) == 0) { ngx_log_error(NGX_LOG_ERR, file->log, ngx_errno, "ReadFile() failed"); @@ -75,13 +68,11 @@ ssize_t ngx_read_file(ngx_file_t *file, char *buf, size_t size, off_t offset) ssize_t ngx_write_file(ngx_file_t *file, char *buf, size_t size, off_t offset) { size_t n; + long high_offset; + ngx_err_t err; OVERLAPPED ovlp, *povlp; -#if (WIN9X) - if (ngx_win32_version < NGX_WIN_NT) { - long high_offset; - ngx_err_t err; /* * in Win9X the overlapped pointer must be NULL @@ -116,9 +107,6 @@ ssize_t ngx_write_file(ngx_file_t *file, char *buf, size_t size, off_t offset) povlp = NULL; } else { - -#endif - ovlp.Internal = 0; ovlp.InternalHigh = 0; ovlp.Offset = (DWORD) offset; @@ -126,10 +114,7 @@ ssize_t ngx_write_file(ngx_file_t *file, char *buf, size_t size, off_t offset) ovlp.hEvent = NULL; povlp = &ovlp; - -#if (WIN9X) } -#endif if (WriteFile(file->fd, buf, size, &n, povlp) == 0) { ngx_log_error(NGX_LOG_ERR, file->log, ngx_errno, "WriteFile() failed"); @@ -142,15 +127,103 @@ ssize_t ngx_write_file(ngx_file_t *file, char *buf, size_t size, off_t offset) } +ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, + off_t offset, ngx_pool_t *pool) +{ + char *buf, *prev; + size_t size; + ssize_t total, n; + + total = 0; + + while (cl) { + buf = cl->hunk->pos; + prev = buf; + size = 0; + + /* coalesce the neighbouring hunks */ + + while (cl && prev == cl->hunk->pos) { + size += cl->hunk->last - cl->hunk->pos; + prev = cl->hunk->last; + cl = cl->next; + } + + n = ngx_write_file(file, buf, size, offset); + + if (n == NGX_ERROR) { + return NGX_ERROR; + } + + total += n; + offset += n; + } + + return total; +} + + +int ngx_rename_file(ngx_str_t *from, ngx_str_t *to, ngx_pool_t *pool) +{ + int rc, collision; + u_int num; + char *name; + ngx_err_t err; + + name = ngx_palloc(pool, to->len + 1 + 10 + 1 + sizeof("DELETE")); + ngx_memcpy(name, to->data, to->len); + + collision = 0; + + /* mutex_lock() (per cache or single ?) */ + + do { + num = ngx_next_temp_number(collision); + + ngx_snprintf(name + to->len, 1 + 10 + 1 + sizeof("DELETE"), + ".%010u.DELETE", num); + + if (MoveFile(to->data, name) == 0) { + err = ngx_errno; + if (err == NGX_ENOENT || err == NGX_ENOTDIR) { + return NGX_ERROR; + } + + collision = 1; + ngx_log_error(NGX_LOG_ERR, pool->log, ngx_errno, + "MoveFile() failed"); + } + + } while (collision); + + if (ngx_win32_version >= NGX_WIN_NT) { + if (DeleteFile(name) == 0) { + ngx_log_error(NGX_LOG_ERR, pool->log, ngx_errno, + "DeleteFile() failed"); + } + } + + if (MoveFile(from->data, to->data) == 0) { + rc = NGX_ERROR; + + } else { + rc = NGX_OK; + } + + if (rc == NGX_ERROR) { + ngx_log_error(NGX_LOG_ERR, pool->log, ngx_errno, "MoveFile() failed"); + } + + /* mutex_unlock() */ + + return rc; +} + + int ngx_file_append_mode(ngx_fd_t fd) { - ngx_err_t err; - if (SetFilePointer(fd, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER) { - err = ngx_errno; - if (err != NO_ERROR) { - ngx_log_error(NGX_LOG_ERR, file->log, err, - "SeekFilePointer() failed"); + if (ngx_errno != NO_ERROR) { return NGX_ERROR; } } diff --git a/src/os/win32/ngx_files.h b/src/os/win32/ngx_files.h index 8e386e8ca..9885c5f78 100644 --- a/src/os/win32/ngx_files.h +++ b/src/os/win32/ngx_files.h @@ -58,8 +58,7 @@ int ngx_file_append_mode(ngx_fd_t fd); #define ngx_close_file CloseHandle #define ngx_close_file_n "CloseHandle()" -/* STUB */ -#define ngx_rename_file MoveFile +int ngx_rename_file(ngx_str_t *from, ngx_str_t *to, ngx_pool_t *pool); #define ngx_rename_file_n "MoveFile()" #define ngx_mkdir(name) CreateDirectory(name, NULL) diff --git a/src/os/win32/ngx_os.h b/src/os/win32/ngx_os.h index 96f1c2d1f..52a7c05a8 100644 --- a/src/os/win32/ngx_os.h +++ b/src/os/win32/ngx_os.h @@ -1,4 +1,4 @@ -ifndef _NGX_OS_H_INCLUDED_ +#ifndef _NGX_OS_H_INCLUDED_ #define _NGX_OS_H_INCLUDED_ @@ -33,6 +33,11 @@ typedef struct { int ngx_os_init(ngx_log_t *log); +ssize_t ngx_wsarecv(ngx_connection_t *c, char *buf, size_t size); +ssize_t ngx_overlapped_wsarecv(ngx_connection_t *c, char *buf, size_t size); +ngx_chain_t *ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in); +ngx_chain_t *ngx_overlapped_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in); + extern ngx_os_io_t ngx_os_io; extern int ngx_max_sockets; diff --git a/src/os/win32/ngx_os_init.h b/src/os/win32/ngx_os_init.h deleted file mode 100644 index 8ab820694..000000000 --- a/src/os/win32/ngx_os_init.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _NGX_OS_INIT_H_INCLUDED_ -#define _NGX_OS_INIT_H_INCLUDED_ - - -#include -#include - - -int ngx_os_init(ngx_log_t *log); - -ssize_t ngx_wsarecv(ngx_connection_t *c, char *buf, size_t size); - - -#endif /* _NGX_OS_INIT_H_INCLUDED_ */ diff --git a/src/os/win32/ngx_recv.c b/src/os/win32/ngx_recv.c deleted file mode 100644 index ad2232c21..000000000 --- a/src/os/win32/ngx_recv.c +++ /dev/null @@ -1,93 +0,0 @@ - -#include -#include -#include - - -ssize_t ngx_wsarecv(ngx_connection_t *c, char *buf, size_t size) -{ - int rc; - u_int flags; - size_t bytes; - ngx_err_t err; - WSABUF wsabuf[1]; - ngx_event_t *ev; - LPWSAOVERLAPPED_COMPLETION_ROUTINE handler; - - ev = c->read; - -/* DEBUG */ bytes = 0; - - if (ev->timedout) { - ngx_set_socket_errno(NGX_ETIMEDOUT); - ngx_log_error(NGX_LOG_ERR, ev->log, 0, "WSARecv() timed out"); - - return NGX_ERROR; - } - - if (ev->ready) { - ev->ready = 0; - -#if (HAVE_IOCP_EVENT) /* iocp */ - - if (ngx_event_flags & NGX_HAVE_IOCP_EVENT) { - if (ev->ovlp.error) { - ngx_log_error(NGX_LOG_ERR, c->log, ev->ovlp.error, - "WSARecv() failed"); - return NGX_ERROR; - } - - return ev->available; - } - -#endif - - if (WSAGetOverlappedResult(c->fd, (LPWSAOVERLAPPED) &ev->ovlp, - &bytes, 0, NULL) == 0) { - err = ngx_socket_errno; - ngx_log_error(NGX_LOG_CRIT, ev->log, err, - "WSARecv() or WSAGetOverlappedResult() failed"); - - return NGX_ERROR; - } - - return bytes; - } - - ngx_memzero(&ev->ovlp, sizeof(WSAOVERLAPPED)); - wsabuf[0].buf = buf; - wsabuf[0].len = size; - flags = 0; - -#if 0 - handler = ev->handler; -#else - handler = NULL; -#endif - - rc = WSARecv(c->fd, wsabuf, 1, &bytes, &flags, - (LPWSAOVERLAPPED) &ev->ovlp, handler); - - ngx_log_debug(ev->log, "WSARecv: %d:%d" _ rc _ bytes); - - if (rc == -1) { - err = ngx_socket_errno; - if (err == WSA_IO_PENDING) { - return NGX_AGAIN; - - } else { - ngx_log_error(NGX_LOG_CRIT, ev->log, err, "WSARecv() failed"); - return NGX_ERROR; - } - } - -#if (HAVE_IOCP_EVENT) /* iocp */ - - if (ngx_event_flags & NGX_HAVE_IOCP_EVENT) { - return NGX_AGAIN; - } - -#endif - - return bytes; -} diff --git a/src/os/win32/ngx_win32_init.c b/src/os/win32/ngx_win32_init.c index c522c9e95..77e4462d0 100644 --- a/src/os/win32/ngx_win32_init.c +++ b/src/os/win32/ngx_win32_init.c @@ -2,11 +2,6 @@ #include #include -/* STUB */ -ssize_t ngx_wsarecv(ngx_connection_t *c, char *buf, size_t size); -ngx_chain_t *ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in); -/* */ - int ngx_win32_version; int ngx_max_sockets; diff --git a/src/os/win32/ngx_wsarecv.c b/src/os/win32/ngx_wsarecv.c index 883bed805..2a43498ad 100644 --- a/src/os/win32/ngx_wsarecv.c +++ b/src/os/win32/ngx_wsarecv.c @@ -4,6 +4,149 @@ #include +ssize_t ngx_wsarecv(ngx_connection_t *c, char *buf, size_t size) +{ + int rc; + u_int flags; + size_t bytes; + WSABUF wsabuf[1]; + ngx_err_t err; + ngx_event_t *rev; + + wsabuf[0].buf = buf; + wsabuf[0].len = size; + flags = 0; + bytes = 0; + + rc = WSARecv(c->fd, wsabuf, 1, &bytes, &flags, NULL, NULL); + + ngx_log_debug(c->log, "WSARecv: %d:%d" _ rc _ bytes); + + rev = c->read; + + if (rc == -1) { + rev->ready = 0; + err = ngx_socket_errno; + + if (err == WSAEWOULDBLOCK) { + ngx_log_error(NGX_LOG_INFO, c->log, err, "WSARecv() EAGAIN"); + return NGX_AGAIN; + } + + rev->error = 1; + ngx_log_error(NGX_LOG_CRIT, c->log, err, "WSARecv() failed"); + return NGX_ERROR; + } + + if (bytes < size) { + rev->ready = 0; + } + + if (bytes == 0) { + rev->eof = 1; + } + + return bytes; +} + + +ssize_t ngx_overlapped_wsarecv(ngx_connection_t *c, char *buf, size_t size) +{ + int rc; + u_int flags; + size_t bytes; + WSABUF wsabuf[1]; + ngx_err_t err; + ngx_event_t *rev; + LPWSAOVERLAPPED ovlp; + + rev = c->read; + + if (!rev->ready) { + ngx_log_error(NGX_LOG_ALERT, rev->log, 0, "SECOND WSA POST"); + return NGX_AGAIN; + } + + ngx_log_debug(c->log, "rev->complete: %d" _ rev->complete); + + if (rev->complete) { + rev->complete = 0; + + if (ngx_event_flags & NGX_USE_IOCP_EVENT) { + if (rev->ovlp.error) { + ngx_log_error(NGX_LOG_ERR, c->log, rev->ovlp.error, + "WSARecv() failed"); + return NGX_ERROR; + } + + return rev->available; + } + + if (WSAGetOverlappedResult(c->fd, (LPWSAOVERLAPPED) &rev->ovlp, + &bytes, 0, NULL) == 0) { + ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno, + "WSARecv() or WSAGetOverlappedResult() failed"); + + return NGX_ERROR; + } + + return bytes; + } + + ovlp = (LPWSAOVERLAPPED) &rev->ovlp; + ngx_memzero(ovlp, sizeof(WSAOVERLAPPED)); + wsabuf[0].buf = buf; + wsabuf[0].len = size; + flags = 0; + bytes = 0; + + rc = WSARecv(c->fd, wsabuf, 1, &bytes, &flags, ovlp, NULL); + + rev->complete = 0; + + ngx_log_debug(c->log, "WSARecv: %d:%d" _ rc _ bytes); + + if (rc == -1) { + err = ngx_socket_errno; + if (err == WSA_IO_PENDING) { + rev->active = 1; + return NGX_AGAIN; + } + + rev->error = 1; + ngx_log_error(NGX_LOG_CRIT, c->log, err, "WSARecv() failed"); + return NGX_ERROR; + } + + if (ngx_event_flags & NGX_USE_IOCP_EVENT) { + + /* + * if a socket was bound with I/O completion port + * then GetQueuedCompletionStatus() would anyway return its status + * despite that WSARecv() was already complete + */ + + rev->active = 1; + return NGX_AGAIN; + } + + if (bytes == 0) { + rev->eof = 1; + rev->ready = 0; + + } else { + rev->ready = 1; + } + + rev->active = 0; + + return bytes; +} + +#if 0 + +/* DELELTE IT WHEN ABOVE FUNC WOULD BE TESTED */ + ssize_t ngx_wsarecv(ngx_connection_t *c, char *buf, size_t size) { int rc; @@ -88,3 +231,5 @@ ssize_t ngx_wsarecv(ngx_connection_t *c, char *buf, size_t size) return bytes; } + +#endif diff --git a/src/os/win32/ngx_wsasend_chain.c b/src/os/win32/ngx_wsasend_chain.c index 5bfd71542..f0b5fe24c 100644 --- a/src/os/win32/ngx_wsasend_chain.c +++ b/src/os/win32/ngx_wsasend_chain.c @@ -4,6 +4,249 @@ #include +ngx_chain_t *ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in) +{ + int rc; + char *prev; + size_t size, sent; + LPWSABUF wsabuf; + ngx_err_t err; + ngx_event_t *wev; + ngx_array_t wsabufs; + ngx_chain_t *cl; + + wev = c->write; + + if (!wev->ready) { + return in; + } + + /* + * WSABUFs must be 4-byte aligned otherwise + * WSASend() will return undocumented WSAEINVAL error. + */ + + ngx_init_array(wsabufs, c->pool, 10, sizeof(WSABUF), NGX_CHAIN_ERROR); + + prev = NULL; + wsabuf = NULL; + + /* create the WSABUF and coalesce the neighbouring bufs */ + + for (cl = in; cl; cl = cl->next) { + + if (prev == cl->hunk->pos) { + wsabuf->len += cl->hunk->last - cl->hunk->pos; + prev = cl->hunk->last; + + } else { + ngx_test_null(wsabuf, ngx_push_array(&wsabufs), NGX_CHAIN_ERROR); + wsabuf->buf = cl->hunk->pos; + wsabuf->len = cl->hunk->last - cl->hunk->pos; + prev = cl->hunk->last; + } + } + + rc = WSASend(c->fd, wsabufs.elts, wsabufs.nelts, &sent, 0, NULL, NULL); + + if (rc == -1) { + err = ngx_errno; + + if (err == WSAEWOULDBLOCK) { + ngx_log_error(NGX_LOG_INFO, c->log, err, "WSASend() EAGAIN"); + wev->ready = 0; + return in; + + } else { + wev->error = 1; + ngx_log_error(NGX_LOG_CRIT, c->log, err, "WSASend() failed"); + return NGX_CHAIN_ERROR; + } + } + +#if (NGX_DEBUG_WRITE_CHAIN) + ngx_log_debug(c->log, "WSASend(): %d" _ sent); +#endif + + c->sent += sent; + + for (cl = in; cl && sent > 0; cl = cl->next) { + + size = cl->hunk->last - cl->hunk->pos; + + if (sent >= size) { + sent -= size; + + if (cl->hunk->type & NGX_HUNK_IN_MEMORY) { + cl->hunk->pos = cl->hunk->last; + } + + continue; + } + + if (cl->hunk->type & NGX_HUNK_IN_MEMORY) { + cl->hunk->pos += sent; + } + + break; + } + + if (cl) { + wev->ready = 0; + } + + return cl; +} + + +ngx_chain_t *ngx_overlapped_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in) +{ + int rc; + char *prev; + size_t size, sent; + LPWSABUF wsabuf; + ngx_err_t err; + ngx_event_t *wev; + ngx_array_t wsabufs; + ngx_chain_t *cl; + LPWSAOVERLAPPED ovlp; + + wev = c->write; + + if (!wev->ready) { + return in; + } + + if (!wev->complete) { + + /* post the overlapped WSASend() */ + + /* + * WSABUFs must be 4-byte aligned otherwise + * WSASend() will return undocumented WSAEINVAL error. + */ + + ngx_init_array(wsabufs, c->pool, 10, sizeof(WSABUF), NGX_CHAIN_ERROR); + + prev = NULL; + wsabuf = NULL; + + /* create the WSABUF and coalesce the neighbouring bufs */ + + for (cl = in; cl; cl = cl->next) { + + if (prev == cl->hunk->pos) { + wsabuf->len += cl->hunk->last - cl->hunk->pos; + prev = cl->hunk->last; + + } else { + ngx_test_null(wsabuf, ngx_push_array(&wsabufs), + NGX_CHAIN_ERROR); + wsabuf->buf = cl->hunk->pos; + wsabuf->len = cl->hunk->last - cl->hunk->pos; + prev = cl->hunk->last; + } + } + + ovlp = (LPWSAOVERLAPPED) &c->write->ovlp; + ngx_memzero(ovlp, sizeof(WSAOVERLAPPED)); + + rc = WSASend(c->fd, wsabufs.elts, wsabufs.nelts, &sent, 0, ovlp, NULL); + + wev->complete = 0; + + if (rc == -1) { + err = ngx_errno; + + if (err == WSA_IO_PENDING) { + wev->active = 1; + return in; + + } else { + wev->error = 1; + ngx_log_error(NGX_LOG_CRIT, c->log, err, "WSASend() failed"); + return NGX_CHAIN_ERROR; + } + + } else if (ngx_event_flags & NGX_USE_IOCP_EVENT) { + + /* + * if a socket was bound with I/O completion port then + * GetQueuedCompletionStatus() would anyway return its status + * despite that WSASend() was already complete + */ + + wev->active = 1; + return in; + } + + } else { + + /* the overlapped WSASend() complete */ + + wev->complete = 0; + wev->active = 0; + + if (ngx_event_flags & NGX_USE_IOCP_EVENT) { + if (wev->ovlp.error) { + ngx_log_error(NGX_LOG_ERR, c->log, wev->ovlp.error, + "WSASend() failed"); + return NGX_CHAIN_ERROR; + } + + sent = wev->available; + + } else { + if (WSAGetOverlappedResult(c->fd, (LPWSAOVERLAPPED) &wev->ovlp, + &sent, 0, NULL) == 0) { + ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno, + "WSASend() or WSAGetOverlappedResult() failed"); + + return NGX_CHAIN_ERROR; + } + } + } + +#if (NGX_DEBUG_WRITE_CHAIN) + ngx_log_debug(c->log, "WSASend(): %d" _ sent); +#endif + + c->sent += sent; + + for (cl = in; cl && sent > 0; cl = cl->next) { + + size = cl->hunk->last - cl->hunk->pos; + + if (sent >= size) { + sent -= size; + + if (cl->hunk->type & NGX_HUNK_IN_MEMORY) { + cl->hunk->pos = cl->hunk->last; + } + + continue; + } + + if (cl->hunk->type & NGX_HUNK_IN_MEMORY) { + cl->hunk->pos += sent; + } + + break; + } + + if (cl) { + wev->ready = 0; + + } else { + wev->ready = 1; + } + + return cl; +} + + +#if 0 + ngx_chain_t *ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in) { int rc; @@ -175,7 +418,7 @@ non-block break; } - ngx_destroy_array(&wsabufs); - return ce; } + +#endif