summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/socket.rst12
-rw-r--r--Lib/test/test_socket.py26
-rw-r--r--Misc/NEWS.d/next/Windows/2024-08-29-16-13-45.gh-issue-123476.m2DFS4.rst1
-rw-r--r--Modules/socketmodule.c22
-rw-r--r--Modules/socketmodule.h3
5 files changed, 59 insertions, 5 deletions
diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst
index a81e115..8e3b020 100644
--- a/Doc/library/socket.rst
+++ b/Doc/library/socket.rst
@@ -413,14 +413,14 @@ Constants
``TCP_USER_TIMEOUT``, ``TCP_CONGESTION`` were added.
.. versionchanged:: 3.6.5
- On Windows, ``TCP_FASTOPEN``, ``TCP_KEEPCNT`` appear if run-time Windows
- supports.
+ Added support for ``TCP_FASTOPEN``, ``TCP_KEEPCNT`` on Windows platforms
+ when available.
.. versionchanged:: 3.7
``TCP_NOTSENT_LOWAT`` was added.
- On Windows, ``TCP_KEEPIDLE``, ``TCP_KEEPINTVL`` appear if run-time Windows
- supports.
+ Added support for ``TCP_KEEPIDLE``, ``TCP_KEEPINTVL`` on Windows platforms
+ when available.
.. versionchanged:: 3.10
``IP_RECVTOS`` was added.
@@ -454,6 +454,10 @@ Constants
Added missing ``IP_RECVERR``, ``IP_RECVTTL``, and ``IP_RECVORIGDSTADDR``
on Linux.
+ .. versionchanged:: 3.14
+ Added support for ``TCP_QUICKACK`` on Windows platforms when available.
+
+
.. data:: AF_CAN
PF_CAN
SOL_CAN_*
diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
index 7c607a8..628f806 100644
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -6826,6 +6826,28 @@ class TestMacOSTCPFlags(unittest.TestCase):
def test_tcp_keepalive(self):
self.assertTrue(socket.TCP_KEEPALIVE)
+@unittest.skipUnless(hasattr(socket, 'TCP_QUICKACK'), 'need socket.TCP_QUICKACK')
+class TestQuickackFlag(unittest.TestCase):
+ def check_set_quickack(self, sock):
+ # quickack already true by default on some OS distributions
+ opt = sock.getsockopt(socket.IPPROTO_TCP, socket.TCP_QUICKACK)
+ if opt:
+ sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_QUICKACK, 0)
+
+ opt = sock.getsockopt(socket.IPPROTO_TCP, socket.TCP_QUICKACK)
+ self.assertFalse(opt)
+
+ sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_QUICKACK, 1)
+
+ opt = sock.getsockopt(socket.IPPROTO_TCP, socket.TCP_QUICKACK)
+ self.assertTrue(opt)
+
+ def test_set_quickack(self):
+ sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM,
+ proto=socket.IPPROTO_TCP)
+ with sock:
+ self.check_set_quickack(sock)
+
@unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
class TestMSWindowsTCPFlags(unittest.TestCase):
@@ -6839,7 +6861,9 @@ class TestMSWindowsTCPFlags(unittest.TestCase):
'TCP_KEEPCNT',
# available starting with Windows 10 1709
'TCP_KEEPIDLE',
- 'TCP_KEEPINTVL'
+ 'TCP_KEEPINTVL',
+ # available starting with Windows 7 / Server 2008 R2
+ 'TCP_QUICKACK',
}
def test_new_tcp_flags(self):
diff --git a/Misc/NEWS.d/next/Windows/2024-08-29-16-13-45.gh-issue-123476.m2DFS4.rst b/Misc/NEWS.d/next/Windows/2024-08-29-16-13-45.gh-issue-123476.m2DFS4.rst
new file mode 100644
index 0000000..801214e
--- /dev/null
+++ b/Misc/NEWS.d/next/Windows/2024-08-29-16-13-45.gh-issue-123476.m2DFS4.rst
@@ -0,0 +1 @@
+Add support for ``socket.TCP_QUICKACK`` on Windows platforms.
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index 3ffdaa4..77e0965 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -3166,6 +3166,17 @@ sock_setsockopt(PySocketSockObject *s, PyObject *args)
/* setsockopt(level, opt, flag) */
if (PyArg_ParseTuple(args, "iii:setsockopt",
&level, &optname, &flag)) {
+#ifdef MS_WINDOWS
+ if (optname == SIO_TCP_SET_ACK_FREQUENCY) {
+ int dummy;
+ res = WSAIoctl(s->sock_fd, SIO_TCP_SET_ACK_FREQUENCY, &flag,
+ sizeof(flag), NULL, 0, &dummy, NULL, NULL);
+ if (res >= 0) {
+ s->quickack = flag;
+ }
+ goto done;
+ }
+#endif
res = setsockopt(s->sock_fd, level, optname,
(char*)&flag, sizeof flag);
goto done;
@@ -3252,6 +3263,11 @@ sock_getsockopt(PySocketSockObject *s, PyObject *args)
return PyLong_FromUnsignedLong(vflag);
}
#endif
+#ifdef MS_WINDOWS
+ if (optname == SIO_TCP_SET_ACK_FREQUENCY) {
+ return PyLong_FromLong(s->quickack);
+ }
+#endif
flagsize = sizeof flag;
res = getsockopt(s->sock_fd, level, optname,
(void *)&flag, &flagsize);
@@ -5316,6 +5332,9 @@ sock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
((PySocketSockObject *)new)->sock_fd = INVALID_SOCKET;
((PySocketSockObject *)new)->sock_timeout = _PyTime_FromSeconds(-1);
((PySocketSockObject *)new)->errorhandler = &set_error;
+#ifdef MS_WINDOWS
+ ((PySocketSockObject *)new)->quickack = 0;
+#endif
}
return new;
}
@@ -8616,6 +8635,9 @@ socket_exec(PyObject *m)
#ifdef TCP_CONNECTION_INFO
ADD_INT_MACRO(m, TCP_CONNECTION_INFO);
#endif
+#ifdef SIO_TCP_SET_ACK_FREQUENCY
+#define TCP_QUICKACK SIO_TCP_SET_ACK_FREQUENCY
+#endif
#ifdef TCP_QUICKACK
ADD_INT_MACRO(m, TCP_QUICKACK);
#endif
diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h
index 09fd70f..a77c620 100644
--- a/Modules/socketmodule.h
+++ b/Modules/socketmodule.h
@@ -325,6 +325,9 @@ typedef struct {
PyTime_t sock_timeout; /* Operation timeout in seconds;
0.0 means non-blocking */
struct _socket_state *state;
+#ifdef MS_WINDOWS
+ int quickack;
+#endif
} PySocketSockObject;
/* --- C API ----------------------------------------------------*/