bpo-32394: Remove some TCP options on old version Windows. (GH-5523)

This commit is contained in:
animalize 2018-02-27 02:10:36 +08:00 committed by Steve Dower
parent 3f2e6f15d6
commit 19e7d48ce8
4 changed files with 101 additions and 0 deletions

View File

@ -320,9 +320,16 @@ Constants
``SO_DOMAIN``, ``SO_PROTOCOL``, ``SO_PEERSEC``, ``SO_PASSSEC``,
``TCP_USER_TIMEOUT``, ``TCP_CONGESTION`` were added.
.. versionchanged:: 3.6.5
On Windows, ``TCP_FASTOPEN``, ``TCP_KEEPCNT`` appear if run-time Windows
supports.
.. versionchanged:: 3.7
``TCP_NOTSENT_LOWAT`` was added.
On Windows, ``TCP_KEEPIDLE``, ``TCP_KEEPINTVL`` appear if run-time Windows
supports.
.. data:: AF_CAN
PF_CAN
SOL_CAN_*

View File

@ -5945,6 +5945,27 @@ class LinuxKernelCryptoAPI(unittest.TestCase):
with self.assertRaises(TypeError):
sock.sendmsg_afalg(op=socket.ALG_OP_ENCRYPT, assoclen=-1)
@unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
class TestMSWindowsTCPFlags(unittest.TestCase):
knownTCPFlags = {
# avaliable since long time ago
'TCP_MAXSEG',
'TCP_NODELAY',
# available starting with Windows 10 1607
'TCP_FASTOPEN',
# available starting with Windows 10 1703
'TCP_KEEPCNT',
# available starting with Windows 10 1709
'TCP_KEEPIDLE',
'TCP_KEEPINTVL'
}
def test_new_tcp_flags(self):
provided = [s for s in dir(socket) if s.startswith('TCP')]
unknown = [s for s in provided if s not in self.knownTCPFlags]
self.assertEqual([], unknown,
"New TCP flags were discovered. See bpo-32394 for more information")
def test_main():
tests = [GeneralModuleTests, BasicTCPTest, TCPCloserTest, TCPTimeoutTest,
@ -6005,6 +6026,7 @@ def test_main():
SendfileUsingSendTest,
SendfileUsingSendfileTest,
])
tests.append(TestMSWindowsTCPFlags)
thread_info = support.threading_setup()
support.run_unittest(*tests)

View File

@ -0,0 +1,2 @@
socket: Remove TCP_FASTOPEN,TCP_KEEPCNT,TCP_KEEPIDLE,TCP_KEEPINTVL flags on
older version Windows during run-time.

View File

@ -305,6 +305,70 @@ http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/net/getaddrinfo.c.diff?r1=1.82&
/* Provides the IsWindows7SP1OrGreater() function */
#include <VersionHelpers.h>
/* remove some flags on older version Windows during run-time.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms738596.aspx */
typedef struct {
DWORD build_number; /* available starting with this Win10 BuildNumber */
const char flag_name[20];
} FlagRuntimeInfo;
/* IMPORTANT: make sure the list ordered by descending build_number */
static FlagRuntimeInfo win_runtime_flags[] = {
/* available starting with Windows 10 1709 */
{16299, "TCP_KEEPIDLE"},
{16299, "TCP_KEEPINTVL"},
/* available starting with Windows 10 1703 */
{15063, "TCP_KEEPCNT"},
/* available starting with Windows 10 1607 */
{14393, "TCP_FASTOPEN"}
};
static void
remove_unusable_flags(PyObject *m)
{
PyObject *dict;
OSVERSIONINFOEX info;
DWORDLONG dwlConditionMask;
dict = PyModule_GetDict(m);
if (dict == NULL) {
return;
}
/* set to Windows 10, except BuildNumber. */
memset(&info, 0, sizeof(info));
info.dwOSVersionInfoSize = sizeof(info);
info.dwMajorVersion = 10;
info.dwMinorVersion = 0;
/* set Condition Mask */
dwlConditionMask = 0;
VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
for (int i=0; i<sizeof(win_runtime_flags)/sizeof(FlagRuntimeInfo); i++) {
info.dwBuildNumber = win_runtime_flags[i].build_number;
/* greater than or equal to the specified version?
Compatibility Mode will not cheat VerifyVersionInfo(...) */
if (VerifyVersionInfo(
&info,
VER_MAJORVERSION|VER_MINORVERSION|VER_BUILDNUMBER,
dwlConditionMask)) {
break;
}
else {
if (PyDict_GetItemString(
dict,
win_runtime_flags[i].flag_name) != NULL) {
PyDict_DelItemString(
dict,
win_runtime_flags[i].flag_name);
}
}
}
}
#endif
#include <stddef.h>
@ -7890,5 +7954,11 @@ PyInit__socket(void)
#if defined(USE_GETHOSTBYNAME_LOCK) || defined(USE_GETADDRINFO_LOCK)
netdb_lock = PyThread_allocate_lock();
#endif
#ifdef MS_WINDOWS
/* remove some flags on older version Windows during run-time */
remove_unusable_flags(m);
#endif
return m;
}