Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nginx/nginx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src/os
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2003-06-11 19:28:34 +0400
committerIgor Sysoev <igor@sysoev.ru>2003-06-11 19:28:34 +0400
commit239baac646073cab7bbaf537ba2d6ca844f2c992 (patch)
treec7c3f61213697a68dc95898d27a730c08abce049 /src/os
parente4a2526e5ccd4f3f5f160656c1a7b6f865ac44c8 (diff)
nginx-0.0.1-2003-06-11-19:28:34 import
Diffstat (limited to 'src/os')
-rw-r--r--src/os/unix/ngx_aio_read.c1
-rw-r--r--src/os/unix/ngx_aio_write.c3
-rw-r--r--src/os/unix/ngx_freebsd_config.h19
-rw-r--r--src/os/unix/ngx_freebsd_sendfile_chain.c5
-rw-r--r--src/os/unix/ngx_linux_config.h13
-rw-r--r--src/os/unix/ngx_readv_chain.c1
-rw-r--r--src/os/unix/ngx_recv.c1
-rw-r--r--src/os/unix/ngx_socket.c3
-rw-r--r--src/os/unix/ngx_solaris_config.h3
-rw-r--r--src/os/unix/ngx_writev_chain.c13
-rw-r--r--src/os/win32/ngx_errno.c44
-rw-r--r--src/os/win32/ngx_os_init.h2
-rw-r--r--src/os/win32/ngx_socket.h8
-rw-r--r--src/os/win32/ngx_types.h1
-rw-r--r--src/os/win32/ngx_win32_init.c (renamed from src/os/win32/ngx_init.c)53
-rw-r--r--src/os/win32/ngx_wsarecv.c90
-rw-r--r--src/os/win32/ngx_wsasend_chain.c181
17 files changed, 396 insertions, 45 deletions
diff --git a/src/os/unix/ngx_aio_read.c b/src/os/unix/ngx_aio_read.c
index 4896af9ce..bc5055860 100644
--- a/src/os/unix/ngx_aio_read.c
+++ b/src/os/unix/ngx_aio_read.c
@@ -1,6 +1,7 @@
#include <ngx_config.h>
#include <ngx_core.h>
+#include <ngx_event.h>
#include <ngx_aio.h>
#if (HAVE_KQUEUE)
diff --git a/src/os/unix/ngx_aio_write.c b/src/os/unix/ngx_aio_write.c
index 918535aa7..3a4d8e0b4 100644
--- a/src/os/unix/ngx_aio_write.c
+++ b/src/os/unix/ngx_aio_write.c
@@ -1,6 +1,7 @@
#include <ngx_config.h>
#include <ngx_core.h>
+#include <ngx_event.h>
#include <ngx_aio.h>
#if (HAVE_KQUEUE)
@@ -29,6 +30,7 @@ ssize_t ngx_aio_write(ngx_connection_t *c, char *buf, size_t size)
ngx_log_debug(ev->log, "aio: ev->ready: %d" _ ev->ready);
ngx_log_debug(ev->log, "aio: aiocb: %08x" _ &ev->aiocb);
+#if 0
if (ev->timedout) {
ngx_set_socket_errno(NGX_ETIMEDOUT);
ngx_log_error(NGX_LOG_ERR, ev->log, 0, "aio_write() timed out");
@@ -46,6 +48,7 @@ ngx_log_debug(ev->log, "aio: aiocb: %08x" _ &ev->aiocb);
ev->ready = 1;
}
+#endif
first = 0;
diff --git a/src/os/unix/ngx_freebsd_config.h b/src/os/unix/ngx_freebsd_config.h
index 0a7eedd10..6fd0a694e 100644
--- a/src/os/unix/ngx_freebsd_config.h
+++ b/src/os/unix/ngx_freebsd_config.h
@@ -22,9 +22,22 @@
#include <osreldate.h>
-#define QD_FMT "%qd"
-#define QX_FMT "%qx"
-#define OFF_FMT "%qd"
+/* STUB */
+#define QD_FMT "%lld"
+#define QX_FMT "%llx"
+/**/
+
+#if (i386)
+#define OFF_FMT "%lld"
+#define SIZE_FMT "%d"
+#define SIZEX_FMT "%x"
+#else
+#define OFF_FMT "%ld"
+#define SIZE_FMT "%ld"
+#define SIZEX_FMT "%lx"
+#endif
+
+#define PID_FMT "%d"
#ifndef HAVE_SELECT
diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c
index a888c3613..a3c813e38 100644
--- a/src/os/unix/ngx_freebsd_sendfile_chain.c
+++ b/src/os/unix/ngx_freebsd_sendfile_chain.c
@@ -15,7 +15,8 @@
Until FreeBSD 4.5 the turning TCP_NOPUSH off does not not flush
the pending data that less than MSS and the data sent with 5 second delay.
- So we use TCP_NOPUSH on FreeBSD 4.5+ only.
+ So we use TCP_NOPUSH on FreeBSD prior to 4.5 only if the connection
+ is not needed not keepalive.
*/
@@ -23,7 +24,7 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
{
int rc, eintr, tcp_nopush;
char *prev;
- size_t hsize, size;
+ ssize_t hsize, size;
off_t sent;
struct iovec *iov;
struct sf_hdtr hdtr;
diff --git a/src/os/unix/ngx_linux_config.h b/src/os/unix/ngx_linux_config.h
index 96e1d8856..27fa317bc 100644
--- a/src/os/unix/ngx_linux_config.h
+++ b/src/os/unix/ngx_linux_config.h
@@ -29,14 +29,11 @@
#include <netdb.h>
-typedef unsigned int u_int;
-typedef unsigned short u_short;
-typedef unsigned char u_char;
-
-#define QD_FMT "%qd"
-#define QX_FMT "%qx"
-#define OFF_FMT "%qd"
+#define QD_FMT "%qd"
+#define QX_FMT "%qx"
+#define OFF_FMT "%qd"
+#define PID_FMT "%d"
#ifndef HAVE_SELECT
@@ -63,7 +60,7 @@ typedef unsigned char u_char;
#ifndef HAVE_FIONBIO
-#define HAVE_FIONBIO 1
+#define HAVE_FIONBIO 1
#endif
diff --git a/src/os/unix/ngx_readv_chain.c b/src/os/unix/ngx_readv_chain.c
index 8432f0c8d..744bf99bc 100644
--- a/src/os/unix/ngx_readv_chain.c
+++ b/src/os/unix/ngx_readv_chain.c
@@ -1,6 +1,7 @@
#include <ngx_config.h>
#include <ngx_core.h>
+#include <ngx_event.h>
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 98607d0c7..154565413 100644
--- a/src/os/unix/ngx_recv.c
+++ b/src/os/unix/ngx_recv.c
@@ -1,6 +1,7 @@
#include <ngx_config.h>
#include <ngx_core.h>
+#include <ngx_event.h>
static int ngx_unix_recv_error(ngx_event_t *rev, ngx_err_t err);
diff --git a/src/os/unix/ngx_socket.c b/src/os/unix/ngx_socket.c
index 941fc8cd1..48016cb10 100644
--- a/src/os/unix/ngx_socket.c
+++ b/src/os/unix/ngx_socket.c
@@ -55,8 +55,7 @@ int ngx_tcp_push(ngx_socket_t s)
(const void *) &tcp_nopush, sizeof(int));
}
-#else
-
+#else
int ngx_tcp_nopush(ngx_socket_t s)
{
diff --git a/src/os/unix/ngx_solaris_config.h b/src/os/unix/ngx_solaris_config.h
index e7946449d..78eeb7213 100644
--- a/src/os/unix/ngx_solaris_config.h
+++ b/src/os/unix/ngx_solaris_config.h
@@ -30,6 +30,7 @@ typedef uint32_t u_int32_t;
#define QD_FMT "%lld"
#define QX_FMT "%llx"
#define OFF_FMT "%lld"
+#define PID_FMT "%ld"
#ifndef HAVE_SELECT
@@ -62,7 +63,7 @@ typedef uint32_t u_int32_t;
#ifndef HAVE_FIONBIO
-#define HAVE_FIONBIO 1
+#define HAVE_FIONBIO 1
#endif
diff --git a/src/os/unix/ngx_writev_chain.c b/src/os/unix/ngx_writev_chain.c
index b667bc507..32b2dd48d 100644
--- a/src/os/unix/ngx_writev_chain.c
+++ b/src/os/unix/ngx_writev_chain.c
@@ -6,15 +6,14 @@
ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in)
{
char *prev;
- size_t size;
- ssize_t n;
+ ssize_t n, size;
off_t sent;
struct iovec *iov;
ngx_err_t err;
- ngx_array_t io;
+ ngx_array_t iovecs;
ngx_chain_t *ce;
- ngx_init_array(io, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR);
+ ngx_init_array(iovecs, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR);
prev = NULL;
iov = NULL;
@@ -27,14 +26,14 @@ ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in)
prev = ce->hunk->last;
} else {
- ngx_test_null(iov, ngx_push_array(&io), NGX_CHAIN_ERROR);
+ ngx_test_null(iov, ngx_push_array(&iovecs), NGX_CHAIN_ERROR);
iov->iov_base = ce->hunk->pos;
iov->iov_len = ce->hunk->last - ce->hunk->pos;
prev = ce->hunk->last;
}
}
- n = writev(c->fd, (struct iovec *) io.elts, io.nelts);
+ n = writev(c->fd, iovecs.elts, iovecs.nelts);
if (n == -1) {
err = ngx_errno;
@@ -93,7 +92,7 @@ ngx_log_debug(c->log, "SIZE: %d" _ size);
break;
}
- ngx_destroy_array(&io);
+ ngx_destroy_array(&iovecs);
return ce;
}
diff --git a/src/os/win32/ngx_errno.c b/src/os/win32/ngx_errno.c
index d0cff7b73..30c1b9315 100644
--- a/src/os/win32/ngx_errno.c
+++ b/src/os/win32/ngx_errno.c
@@ -9,9 +9,29 @@
#include <ngx_core.h>
+ngx_str_t wsa_errors[] = {
+ ngx_string("Invalid argument"), /* 10022 */
+ ngx_null_string, /* 10023 */
+ ngx_null_string, /* 10024 */
+ ngx_null_string, /* 10025 */
+ ngx_null_string, /* 10026 */
+ ngx_null_string, /* 10027 */
+ ngx_null_string, /* 10028 */
+ ngx_null_string, /* 10029 */
+ ngx_null_string, /* 10030 */
+ ngx_null_string, /* 10031 */
+ ngx_null_string, /* 10032 */
+ ngx_null_string, /* 10033 */
+ ngx_null_string, /* 10034 */
+ ngx_string("Resource temporarily unavailable") /* 10035 */
+};
+
+
int ngx_strerror_r(ngx_err_t err, char *errstr, size_t size)
{
- int len;
+ int n;
+ u_int len;
+ ngx_err_t format_error;
len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS,
@@ -19,12 +39,28 @@ int ngx_strerror_r(ngx_err_t err, char *errstr, size_t size)
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
errstr, size, NULL);
- /* add WSA error messages */
-
if (len == 0) {
+ format_error = GetLastError();
+
+ if (format_error == ERROR_MR_MID_NOT_FOUND) {
+ n = err - WSABASEERR - 22;
+
+ if (n >= 0 && n < 14) {
+ len = wsa_errors[n].len;
+
+ if (len) {
+ if (len > size) {
+ len = size;
+ }
+
+ ngx_memcpy(errstr, wsa_errors[n].data, len);
+ return len;
+ }
+ }
+ }
len = ngx_snprintf(errstr, size,
- "FormatMessage error:(%d)", GetLastError());
+ "FormatMessage() error:(%d)", format_error);
return len;
}
diff --git a/src/os/win32/ngx_os_init.h b/src/os/win32/ngx_os_init.h
index 4a00a3a05..8ab820694 100644
--- a/src/os/win32/ngx_os_init.h
+++ b/src/os/win32/ngx_os_init.h
@@ -8,5 +8,7 @@
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_socket.h b/src/os/win32/ngx_socket.h
index f86a39aff..55629a1a9 100644
--- a/src/os/win32/ngx_socket.h
+++ b/src/os/win32/ngx_socket.h
@@ -16,6 +16,7 @@ typedef int socklen_t;
#define ngx_socket(af, type, proto, flags) \
WSASocket(af, type, proto, NULL, 0, flags)
+
#define ngx_socket_n "WSASocket()"
int ngx_nonblocking(ngx_socket_t s);
@@ -36,4 +37,11 @@ extern LPFN_GETACCEPTEXSOCKADDRS getacceptexsockaddrs;
extern LPFN_TRANSMITFILE transmitfile;
+ngx_inline int ngx_tcp_push(s) {
+ return 0;
+}
+
+#define ngx_tcp_push_n "tcp_push()"
+
+
#endif /* _NGX_SOCKET_H_INCLUDED_ */
diff --git a/src/os/win32/ngx_types.h b/src/os/win32/ngx_types.h
index 1c4ff0c02..b858faee9 100644
--- a/src/os/win32/ngx_types.h
+++ b/src/os/win32/ngx_types.h
@@ -19,6 +19,7 @@ typedef BY_HANDLE_FILE_INFORMATION ngx_file_info_t;
#define QD_FMT "%I64d"
#define QX_FMT "%I64x"
#define OFF_FMT "%I64d"
+#define PID_FMT "%d"
#endif /* _NGX_TYPES_H_INCLUDED_ */
diff --git a/src/os/win32/ngx_init.c b/src/os/win32/ngx_win32_init.c
index c57ce6c9d..6bc69e4c9 100644
--- a/src/os/win32/ngx_init.c
+++ b/src/os/win32/ngx_win32_init.c
@@ -2,15 +2,23 @@
#include <ngx_config.h>
#include <ngx_core.h>
+/* 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;
+int ngx_inherited_nonblocking = 1;
ngx_os_io_t ngx_os_io = {
ngx_wsarecv,
NULL,
NULL,
- NULL
+ ngx_wsasend_chain,
+ 0
};
@@ -26,7 +34,7 @@ static GUID tf_guid = WSAID_TRANSMITFILE;
int ngx_os_init(ngx_log_t *log)
{
- u_int sp;
+ u_int osviex;
DWORD bytes;
SOCKET s;
WSADATA wsd;
@@ -34,14 +42,14 @@ int ngx_os_init(ngx_log_t *log)
/* get Windows version */
- ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
+ ngx_memzero(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
osviex = GetVersionEx((OSVERSIONINFO *) &osvi);
if (osviex == 0) {
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
- if (GetVersionEx((OSVERSIONINFO *) &osvi) == 0)
+ if (GetVersionEx((OSVERSIONINFO *) &osvi) == 0) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
"GetVersionEx() failed");
return NGX_ERROR;
@@ -49,27 +57,36 @@ int ngx_os_init(ngx_log_t *log)
}
/*
- * Windows 95 1400
- * Windows 98 1410
- * Windows ME 1490
- * Windows NT 3.51 2351
- * Windows NT 4.0 2400
- * Windows 2000 2500
- * Windows XP 2501
- * Windows 2003 2502
+ * Windows 95 140000
+ * Windows 98 141000
+ * Windows ME 149000
+ * Windows NT 3.51 235100
+ * Windows NT 4.0 240000
+ * Windows NT 4.0 SP5 240050
+ * Windows 2000 250000
+ * Windows XP 250100
+ * Windows 2003 250200
*/
- ngx_win32_version = osvi.dwPlatformId * 1000
- + osvi.dwMajorVersion * 100
- + osvi.dwMinorVersion;
+ ngx_win32_version = osvi.dwPlatformId * 100000
+ + osvi.dwMajorVersion * 10000
+ + osvi.dwMinorVersion * 100;
if (osviex) {
- sp = osvi.wServicePackMajor * 100 + osvi.wServicePackMinor;
+ ngx_win32_version += osvi.wServicePackMajor * 10
+ + osvi.wServicePackMinor;
+
+ ngx_log_error(NGX_LOG_INFO, log, 0,
+ "OS: %u build:%u, %s, suite:%x, type:%u",
+ ngx_win32_version, osvi.dwBuildNumber, osvi.szCSDVersion,
+ osvi.wReserved[0], osvi.wReserved[1]);
+#if 0
ngx_log_error(NGX_LOG_INFO, log, 0,
- "OS: %u build:%u, %s, SP:%u, suite:%x, type:%u",
+ "OS: %u build:%u, %s, suite:%x, type:%u",
ngx_win32_version, osvi.dwBuildNumber, osvi.szCSDVersion,
- sp, osvi.wSuiteMask, osvi.wProductType);
+ osvi.wSuiteMask, osvi.wProductType);
+#endif
} else {
ngx_log_error(NGX_LOG_INFO, log, 0, "OS: %u build:%u, %s",
diff --git a/src/os/win32/ngx_wsarecv.c b/src/os/win32/ngx_wsarecv.c
new file mode 100644
index 000000000..038554a68
--- /dev/null
+++ b/src/os/win32/ngx_wsarecv.c
@@ -0,0 +1,90 @@
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_event.h>
+
+
+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;
+ LPWSAOVERLAPPED ovlp;
+
+ rev = c->read;
+ bytes = 0;
+
+ if ((ngx_event_flags & NGX_HAVE_AIO_EVENT) && rev->ready) {
+ rev->ready = 0;
+
+ /* the overlapped WSARecv() completed */
+
+ if (ngx_event_flags & NGX_HAVE_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) {
+ err = ngx_socket_errno;
+ ngx_log_error(NGX_LOG_CRIT, c->log, err,
+ "WSARecv() or WSAGetOverlappedResult() failed");
+
+ return NGX_ERROR;
+ }
+
+ return bytes;
+ }
+
+ if (ngx_event_flags & NGX_HAVE_AIO_EVENT) {
+ ovlp = (LPWSAOVERLAPPED) &c->read->ovlp;
+ ngx_memzero(ovlp, sizeof(WSAOVERLAPPED));
+
+ } else {
+ ovlp = NULL;
+ }
+
+ wsabuf[0].buf = buf;
+ wsabuf[0].len = size;
+ flags = 0;
+
+ rc = WSARecv(c->fd, wsabuf, 1, &bytes, &flags, ovlp, NULL);
+
+ ngx_log_debug(c->log, "WSARecv: %d:%d" _ rc _ bytes);
+
+ if (rc == -1) {
+ err = ngx_socket_errno;
+ if (err == WSA_IO_PENDING) {
+ return NGX_AGAIN;
+
+ } else if (err == WSAEWOULDBLOCK) {
+ ngx_log_error(NGX_LOG_INFO, c->log, err, "WSARecv() EAGAIN");
+ return NGX_AGAIN;
+
+ } else {
+ ngx_log_error(NGX_LOG_CRIT, c->log, err, "WSARecv() failed");
+ return NGX_ERROR;
+ }
+ }
+
+ if (ngx_event_flags & NGX_HAVE_IOCP_EVENT) {
+
+ /*
+ * If a socket was bound with I/O completion port
+ * then GetQueuedCompletionStatus() would anyway return its status
+ * despite that WSARecv() was already completed.
+ */
+
+ return NGX_AGAIN;
+ }
+
+ return bytes;
+}
diff --git a/src/os/win32/ngx_wsasend_chain.c b/src/os/win32/ngx_wsasend_chain.c
new file mode 100644
index 000000000..ebaa77e96
--- /dev/null
+++ b/src/os/win32/ngx_wsasend_chain.c
@@ -0,0 +1,181 @@
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_event.h>
+
+
+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 *ce;
+ LPWSAOVERLAPPED ovlp;
+
+#if 0
+
+iocp:
+ if ready
+ get result
+ update chain
+ return if done;
+ wsasend
+
+non-block
+ for ( ;; ) {
+ wsasend
+ if no again
+ update chain
+ return if done;
+ }
+
+
+ for ( ;; ) {
+
+ make buffers and limit data for both ovlp and nonblocked,
+ configured in events module
+
+ if (iocp && ready) {
+ get result
+
+ } else {
+ if (file)
+ transmitfile
+ else
+ wsasend
+
+ if (iocp)
+ return chain
+ return chain if again
+ here is result
+ }
+
+ if (result)
+ update chain;
+ return chain if done
+ }
+ }
+
+
+#endif
+
+ wev = c->write;
+
+ if (((ngx_event_flags & NGX_HAVE_AIO_EVENT) && !wev->ready)
+ || ((ngx_event_flags & NGX_HAVE_AIO_EVENT) == 0))
+ {
+ /*
+ * 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 chain entries */
+ for (ce = in; ce; ce = ce->next) {
+
+ if (prev == ce->hunk->pos) {
+ wsabuf->len += ce->hunk->last - ce->hunk->pos;
+ prev = ce->hunk->last;
+
+ } else {
+ ngx_test_null(wsabuf, ngx_push_array(&wsabufs),
+ NGX_CHAIN_ERROR);
+ wsabuf->buf = ce->hunk->pos;
+ wsabuf->len = ce->hunk->last - ce->hunk->pos;
+ prev = ce->hunk->last;
+ }
+ }
+
+ if (ngx_event_flags & NGX_HAVE_AIO_EVENT) {
+ ovlp = (LPWSAOVERLAPPED) &c->write->ovlp;
+ ngx_memzero(ovlp, sizeof(WSAOVERLAPPED));
+
+ } else {
+ ovlp = NULL;
+ }
+
+ rc = WSASend(c->fd, wsabufs.elts, wsabufs.nelts, &sent, 0, ovlp, NULL);
+
+ if (rc == -1) {
+ err = ngx_errno;
+ if (err == WSA_IO_PENDING) {
+ sent = 0;
+
+ } else if (err == WSAEWOULDBLOCK) {
+ sent = 0;
+ ngx_log_error(NGX_LOG_INFO, c->log, err, "WSASend() EAGAIN");
+
+ } else {
+ ngx_log_error(NGX_LOG_CRIT, c->log, err, "WSASend() failed");
+ return NGX_CHAIN_ERROR;
+ }
+
+ } else {
+
+ if (ngx_event_flags & NGX_HAVE_IOCP_EVENT) {
+
+ /*
+ * If a socket was bound with I/O completion port then
+ * GetQueuedCompletionStatus() would anyway return its status
+ * despite that WSASend() was already completed.
+ */
+
+ sent = 0;
+ }
+ }
+
+ } else {
+ if (ngx_event_flags & NGX_HAVE_IOCP_EVENT) {
+ wev->ready = 0;
+
+ /* the overlapped WSASend() completed */
+
+ if (wev->ovlp.error) {
+ ngx_log_error(NGX_LOG_ERR, c->log, wev->ovlp.error,
+ "WSASend() failed");
+ return NGX_CHAIN_ERROR;
+ }
+
+ sent = wev->available;
+ }
+ }
+
+#if (NGX_DEBUG_WRITE_CHAIN)
+ ngx_log_debug(c->log, "WSASend(): %d" _ sent);
+#endif
+
+ c->sent += sent;
+
+ for (ce = in; ce && sent > 0; ce = ce->next) {
+
+ size = ce->hunk->last - ce->hunk->pos;
+
+ if (sent >= size) {
+ sent -= size;
+
+ if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
+ ce->hunk->pos = ce->hunk->last;
+ }
+
+ continue;
+ }
+
+ if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
+ ce->hunk->pos += sent;
+ }
+
+ break;
+ }
+
+ ngx_destroy_array(&wsabufs);
+
+ return ce;
+}