diff options
Diffstat (limited to 'src/os/win32')
| -rw-r--r-- | src/os/win32/ngx_errno.c | 44 | ||||
| -rw-r--r-- | src/os/win32/ngx_os_init.h | 2 | ||||
| -rw-r--r-- | src/os/win32/ngx_socket.h | 8 | ||||
| -rw-r--r-- | src/os/win32/ngx_types.h | 1 | ||||
| -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.c | 90 | ||||
| -rw-r--r-- | src/os/win32/ngx_wsasend_chain.c | 181 |
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; +} |
