From 239baac646073cab7bbaf537ba2d6ca844f2c992 Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Wed, 11 Jun 2003 15:28:34 +0000 Subject: nginx-0.0.1-2003-06-11-19:28:34 import --- src/os/win32/ngx_errno.c | 44 +++++++++- src/os/win32/ngx_init.c | 131 ---------------------------- src/os/win32/ngx_os_init.h | 2 + src/os/win32/ngx_socket.h | 8 ++ src/os/win32/ngx_types.h | 1 + src/os/win32/ngx_win32_init.c | 148 ++++++++++++++++++++++++++++++++ src/os/win32/ngx_wsarecv.c | 90 +++++++++++++++++++ src/os/win32/ngx_wsasend_chain.c | 181 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 470 insertions(+), 135 deletions(-) delete mode 100644 src/os/win32/ngx_init.c create mode 100644 src/os/win32/ngx_win32_init.c create mode 100644 src/os/win32/ngx_wsarecv.c create mode 100644 src/os/win32/ngx_wsasend_chain.c (limited to 'src/os/win32') 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_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_init.c b/src/os/win32/ngx_init.c deleted file mode 100644 index c57ce6c9d..000000000 --- a/src/os/win32/ngx_init.c +++ /dev/null @@ -1,131 +0,0 @@ - -#include -#include - - -int ngx_max_sockets; - - -ngx_os_io_t ngx_os_io = { - ngx_wsarecv, - NULL, - NULL, - NULL -}; - - -/* Should these pointers be per protocol ? */ -LPFN_ACCEPTEX acceptex; -LPFN_GETACCEPTEXSOCKADDRS getacceptexsockaddrs; -LPFN_TRANSMITFILE transmitfile; - -static GUID ae_guid = WSAID_ACCEPTEX; -static GUID as_guid = WSAID_GETACCEPTEXSOCKADDRS; -static GUID tf_guid = WSAID_TRANSMITFILE; - - -int ngx_os_init(ngx_log_t *log) -{ - u_int sp; - DWORD bytes; - SOCKET s; - WSADATA wsd; - OSVERSIONINFOEX osvi; - - /* get Windows version */ - - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - - osviex = GetVersionEx((OSVERSIONINFO *) &osvi); - - if (osviex == 0) { - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - if (GetVersionEx((OSVERSIONINFO *) &osvi) == 0) - ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, - "GetVersionEx() failed"); - return NGX_ERROR; - } - } - - /* - * 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 - */ - - ngx_win32_version = osvi.dwPlatformId * 1000 - + osvi.dwMajorVersion * 100 - + osvi.dwMinorVersion; - - if (osviex) { - sp = osvi.wServicePackMajor * 100 + osvi.wServicePackMinor; - - ngx_log_error(NGX_LOG_INFO, log, 0, - "OS: %u build:%u, %s, SP:%u, suite:%x, type:%u", - ngx_win32_version, osvi.dwBuildNumber, osvi.szCSDVersion, - sp, osvi.wSuiteMask, osvi.wProductType); - - } else { - ngx_log_error(NGX_LOG_INFO, log, 0, "OS: %u build:%u, %s", - ngx_win32_version, osvi.dwBuildNumber, osvi.szCSDVersion); - } - - - /* init Winsock */ - - if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - "WSAStartup() failed"); - return NGX_ERROR; - } - - /* get AcceptEx(), GetAcceptExSockAddrs() and TransmitFile() addresses */ - - s = ngx_socket(AF_INET, SOCK_STREAM, IPPROTO_IP, 0); - if (s == -1) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - ngx_socket_n " %s falied"); - return NGX_ERROR; - } - - if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &ae_guid, sizeof(GUID), - &acceptex, sizeof(LPFN_ACCEPTEX), &bytes, NULL, NULL) == -1) { - - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, " - "WSAID_ACCEPTEX) failed"); - return NGX_ERROR; - } - - if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &as_guid, sizeof(GUID), - &getacceptexsockaddrs, sizeof(LPFN_GETACCEPTEXSOCKADDRS), - &bytes, NULL, NULL) == -1) { - - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, " - "WSAID_ACCEPTEX) failed"); - return NGX_ERROR; - } - - if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &tf_guid, sizeof(GUID), - &transmitfile, sizeof(LPFN_TRANSMITFILE), &bytes, - NULL, NULL) == -1) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, " - "WSAID_TRANSMITFILE) failed"); - return NGX_ERROR; - } - - if (ngx_close_socket(s) == -1) { - ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno, - ngx_close_socket_n " failed"); - } - - return NGX_OK; -} 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_win32_init.c b/src/os/win32/ngx_win32_init.c new file mode 100644 index 000000000..6bc69e4c9 --- /dev/null +++ b/src/os/win32/ngx_win32_init.c @@ -0,0 +1,148 @@ + +#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; +int ngx_inherited_nonblocking = 1; + + +ngx_os_io_t ngx_os_io = { + ngx_wsarecv, + NULL, + NULL, + ngx_wsasend_chain, + 0 +}; + + +/* Should these pointers be per protocol ? */ +LPFN_ACCEPTEX acceptex; +LPFN_GETACCEPTEXSOCKADDRS getacceptexsockaddrs; +LPFN_TRANSMITFILE transmitfile; + +static GUID ae_guid = WSAID_ACCEPTEX; +static GUID as_guid = WSAID_GETACCEPTEXSOCKADDRS; +static GUID tf_guid = WSAID_TRANSMITFILE; + + +int ngx_os_init(ngx_log_t *log) +{ + u_int osviex; + DWORD bytes; + SOCKET s; + WSADATA wsd; + OSVERSIONINFOEX osvi; + + /* get Windows version */ + + 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) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, + "GetVersionEx() failed"); + return NGX_ERROR; + } + } + + /* + * 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 * 100000 + + osvi.dwMajorVersion * 10000 + + osvi.dwMinorVersion * 100; + + if (osviex) { + 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, suite:%x, type:%u", + ngx_win32_version, osvi.dwBuildNumber, osvi.szCSDVersion, + osvi.wSuiteMask, osvi.wProductType); +#endif + + } else { + ngx_log_error(NGX_LOG_INFO, log, 0, "OS: %u build:%u, %s", + ngx_win32_version, osvi.dwBuildNumber, osvi.szCSDVersion); + } + + + /* init Winsock */ + + if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + "WSAStartup() failed"); + return NGX_ERROR; + } + + /* get AcceptEx(), GetAcceptExSockAddrs() and TransmitFile() addresses */ + + s = ngx_socket(AF_INET, SOCK_STREAM, IPPROTO_IP, 0); + if (s == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + ngx_socket_n " %s falied"); + return NGX_ERROR; + } + + if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &ae_guid, sizeof(GUID), + &acceptex, sizeof(LPFN_ACCEPTEX), &bytes, NULL, NULL) == -1) { + + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, " + "WSAID_ACCEPTEX) failed"); + return NGX_ERROR; + } + + if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &as_guid, sizeof(GUID), + &getacceptexsockaddrs, sizeof(LPFN_GETACCEPTEXSOCKADDRS), + &bytes, NULL, NULL) == -1) { + + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, " + "WSAID_ACCEPTEX) failed"); + return NGX_ERROR; + } + + if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &tf_guid, sizeof(GUID), + &transmitfile, sizeof(LPFN_TRANSMITFILE), &bytes, + NULL, NULL) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, " + "WSAID_TRANSMITFILE) failed"); + return NGX_ERROR; + } + + if (ngx_close_socket(s) == -1) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno, + ngx_close_socket_n " failed"); + } + + return NGX_OK; +} 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 +#include +#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; + 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 +#include +#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 *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; +} -- cgit