summaryrefslogtreecommitdiffhomepage
path: root/src/os/win32
diff options
context:
space:
mode:
Diffstat (limited to 'src/os/win32')
-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
7 files changed, 357 insertions, 22 deletions
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;
+}