summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormichaelo <michaelo@13f79535-47bb-0310-9956-ffa450edef68>2021-05-26 19:57:29 +0000
committermichaelo <michaelo@13f79535-47bb-0310-9956-ffa450edef68>2021-05-26 19:57:29 +0000
commit70a3095969ad60891851c694b0765a85cc9b8d9a (patch)
treead4fe6eb7089bb383f18955975de295d50cc5b9c
parent5ff1edfb2db4134c2fc611f788965af0531f2192 (diff)
downloadlibapr-70a3095969ad60891851c694b0765a85cc9b8d9a.tar.gz
Backport r1861050, r1805309, r1861045, r1861046, r1861049, r1861053, r1861054, r1861061 from trunk:
* misc/win32/misc.c (apr_get_oslevel): Fix condition to actually return APR_EGENERAL on unsupported OS. === apr_socket_listen(): Allow larger backlog queue lengths on Windows 8+. Starting with Windows 8, the socket listen() function accepts a special SOMAXCONN_HINT(N) argument that allows making the backlog queue length larger than the otherwise predefined limit of around 200: https://msdn.microsoft.com/en-us/library/windows/desktop/ms739168 https://blogs.msdn.microsoft.com/winsdk/2015/06/01/winsocks-listen-backlog-offers-more-flexibility-in-windows-8/ Having a larger listen backlog can be used for certain high performance applications that need to handle lots of incoming connections. One example would be the httpd server with it's "ListenBacklog" directive where setting it to a larger value currently allows serving more concurrent connections on Windows with mpm_winnt. * include/arch/win32/apr_arch_misc.h (enum apr_oslevel_e): Add APR_WIN_8. * misc/win32/misc.c (apr_get_oslevel): Determine whether we are running on Windows 7 or on Windows 8+. * network_io/win32/sockets.c (SOMAXCONN_HINT): Define this macro in case we are building against an older version of Windows SDK. (apr_socket_listen): Use SOMAXCONN_HINT() for the backlog queue length if it's supported by the Windows version we are running on. Patch by: Evgeny Kotkov <evgeny.kotkov {at} visualsvn.com> === * misc/win32/misc.c (apr_get_oslevel): Check return code from GetVersionEx(). === * misc/win32/misc.c (apr_get_oslevel): Do not use static variables to protect from potential race condition. === * misc/win32/misc.c (apr_get_oslevel): Use GetVersionExW() with OSVERSIONINFOEXW to version information with service pack info. === * include/arch/win32/apr_arch_misc.h (enum apr_oslevel_e): Add APR_WIN_8_1. * misc/win32/misc.c (apr_get_oslevel): Determine whether we are running on Windows 8 or on Windows 8.1+. === Fix problem that apr_get_oslevel() was returning APR_WIN_XP on Windows 10. * include/arch/win32/apr_arch_misc.h (enum apr_oslevel_e): Add APR_WIN_10. * misc/win32/misc.c (apr_get_oslevel): Return APR_WIN_10 when dwMajorVersion is greater than 6. === * include/arch/win32/apr_arch_misc.h (enum apr_oslevel_e): Add APR_WIN_7_SP1. * misc/win32/misc.c (apr_get_oslevel): Determine whether we are running on Windows 7 or on Windows 7 SP1. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/branches/1.7.x@1890230 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--CHANGES5
-rw-r--r--include/arch/win32/apr_arch_misc.h6
-rw-r--r--misc/win32/misc.c36
-rw-r--r--network_io/win32/sockets.c23
4 files changed, 49 insertions, 21 deletions
diff --git a/CHANGES b/CHANGES
index 927c3ffd5..53df1a38c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -47,6 +47,11 @@ Changes for APR 1.7.1
events are emitted on pool clear/destroy for proper accounting.
[Brane Čibej]
+ *) apr_socket_listen: Allow larger listen backlog values on Windows 8+.
+ [Evgeny Kotkov <evgeny.kotkov visualsvn.com>]
+
+ *) Fixed: apr_get_oslevel() was returning APR_WIN_XP on Windows 10
+
Changes for APR 1.7.0
*) apr_dir_read: [Unix] Dropped the preference of the dirread_r() flavor
diff --git a/include/arch/win32/apr_arch_misc.h b/include/arch/win32/apr_arch_misc.h
index 15312adf4..3b80502bd 100644
--- a/include/arch/win32/apr_arch_misc.h
+++ b/include/arch/win32/apr_arch_misc.h
@@ -110,7 +110,11 @@ typedef enum {
APR_WIN_XP_SP2 = 62,
APR_WIN_2003 = 70,
APR_WIN_VISTA = 80,
- APR_WIN_7 = 90
+ APR_WIN_7 = 90,
+ APR_WIN_7_SP1 = 91,
+ APR_WIN_8 = 100,
+ APR_WIN_8_1 = 110,
+ APR_WIN_10 = 120
} apr_oslevel_e;
extern APR_DECLARE_DATA apr_oslevel_e apr_os_level;
diff --git a/misc/win32/misc.c b/misc/win32/misc.c
index fd276c209..bfb7efae5 100644
--- a/misc/win32/misc.c
+++ b/misc/win32/misc.c
@@ -27,25 +27,15 @@ apr_status_t apr_get_oslevel(apr_oslevel_e *level)
{
if (apr_os_level == APR_WIN_UNK)
{
- static OSVERSIONINFO oslev;
- oslev.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- GetVersionEx(&oslev);
+ OSVERSIONINFOEXW oslev;
+ oslev.dwOSVersionInfoSize = sizeof(oslev);
+ if (!GetVersionExW((OSVERSIONINFOW*) &oslev)) {
+ return apr_get_os_error();
+ }
if (oslev.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
- static unsigned int servpack = 0;
- TCHAR *pservpack;
- if ((pservpack = oslev.szCSDVersion)) {
- while (*pservpack && !apr_isdigit(*pservpack)) {
- pservpack++;
- }
- if (*pservpack)
-#ifdef _UNICODE
- servpack = _wtoi(pservpack);
-#else
- servpack = atoi(pservpack);
-#endif
- }
+ unsigned int servpack = oslev.wServicePackMajor;
if (oslev.dwMajorVersion < 3) {
apr_os_level = APR_WIN_UNSUP;
@@ -99,11 +89,19 @@ apr_status_t apr_get_oslevel(apr_oslevel_e *level)
else if (oslev.dwMajorVersion == 6) {
if (oslev.dwMinorVersion == 0)
apr_os_level = APR_WIN_VISTA;
+ else if (oslev.dwMinorVersion == 1) {
+ if (servpack < 1)
+ apr_os_level = APR_WIN_7;
+ else
+ apr_os_level = APR_WIN_7_SP1;
+ }
+ else if (oslev.dwMinorVersion == 2)
+ apr_os_level = APR_WIN_8;
else
- apr_os_level = APR_WIN_7;
+ apr_os_level = APR_WIN_8_1;
}
else {
- apr_os_level = APR_WIN_XP;
+ apr_os_level = APR_WIN_10;
}
}
#ifndef WINNT
@@ -151,7 +149,7 @@ apr_status_t apr_get_oslevel(apr_oslevel_e *level)
*level = apr_os_level;
- if (apr_os_level < APR_WIN_UNSUP) {
+ if (apr_os_level <= APR_WIN_UNSUP) {
return APR_EGENERAL;
}
diff --git a/network_io/win32/sockets.c b/network_io/win32/sockets.c
index 04f2d6268..5013bba88 100644
--- a/network_io/win32/sockets.c
+++ b/network_io/win32/sockets.c
@@ -24,6 +24,13 @@
#include "apr_arch_inherit.h"
#include "apr_arch_misc.h"
+/* Borrow the definition of SOMAXCONN_HINT() from Windows SDK 8,
+ * in case the SDK we are building against doesn't have it.
+ */
+#ifndef SOMAXCONN_HINT
+#define SOMAXCONN_HINT(b) (-(b))
+#endif
+
static char generic_inaddr_any[16] = {0}; /* big enough for IPv4 or IPv6 */
static apr_status_t socket_cleanup(void *sock)
@@ -223,7 +230,21 @@ APR_DECLARE(apr_status_t) apr_socket_bind(apr_socket_t *sock,
APR_DECLARE(apr_status_t) apr_socket_listen(apr_socket_t *sock,
apr_int32_t backlog)
{
- if (listen(sock->socketdes, backlog) == SOCKET_ERROR)
+ int backlog_val;
+
+ if (apr_os_level >= APR_WIN_8) {
+ /* Starting from Windows 8, listen() accepts a special SOMAXCONN_HINT()
+ * arg that allows setting the listen backlog value to a larger
+ * value than the predefined Winsock 2 limit (several hundred).
+ * https://blogs.msdn.microsoft.com/winsdk/2015/06/01/winsocks-listen-backlog-offers-more-flexibility-in-windows-8/
+ */
+ backlog_val = SOMAXCONN_HINT(backlog);
+ }
+ else {
+ backlog_val = backlog;
+ }
+
+ if (listen(sock->socketdes, backlog_val) == SOCKET_ERROR)
return apr_get_netos_error();
else
return APR_SUCCESS;