bpo-27456: Ensure TCP_NODELAY is set on linux (#4231) · python/cpython@e796b2f (original) (raw)

`@@ -82,18 +82,24 @@ def _set_reuseport(sock):

`

82

82

`'SO_REUSEPORT defined but not implemented.')

`

83

83

``

84

84

``

85

``

`-

def _is_stream_socket(sock):

`

86

``

`-

Linux's socket.type is a bitmask that can include extra info

`

87

``

`-

about socket, therefore we can't do simple

`

88

``

`` -

sock_type == socket.SOCK_STREAM.

``

89

``

`-

return (sock.type & socket.SOCK_STREAM) == socket.SOCK_STREAM

`

``

85

`+

def _is_stream_socket(sock_type):

`

``

86

`+

if hasattr(socket, 'SOCK_NONBLOCK'):

`

``

87

`+

Linux's socket.type is a bitmask that can include extra info

`

``

88

`+

about socket (like SOCK_NONBLOCK bit), therefore we can't do simple

`

``

89

`` +

sock_type == socket.SOCK_STREAM, see

``

``

90

`+

https://github.com/torvalds/linux/blob/v4.13/include/linux/net.h#L77

`

``

91

`+

for more details.

`

``

92

`+

return (sock_type & 0xF) == socket.SOCK_STREAM

`

``

93

`+

else:

`

``

94

`+

return sock_type == socket.SOCK_STREAM

`

90

95

``

91

96

``

92

``

`-

def _is_dgram_socket(sock):

`

93

``

`-

Linux's socket.type is a bitmask that can include extra info

`

94

``

`-

about socket, therefore we can't do simple

`

95

``

`` -

sock_type == socket.SOCK_DGRAM.

``

96

``

`-

return (sock.type & socket.SOCK_DGRAM) == socket.SOCK_DGRAM

`

``

97

`+

def _is_dgram_socket(sock_type):

`

``

98

`+

if hasattr(socket, 'SOCK_NONBLOCK'):

`

``

99

`` +

See the comment in _is_stream_socket.

``

``

100

`+

return (sock_type & 0xF) == socket.SOCK_DGRAM

`

``

101

`+

else:

`

``

102

`+

return sock_type == socket.SOCK_DGRAM

`

97

103

``

98

104

``

99

105

`def _ipaddr_info(host, port, family, type, proto):

`

`@@ -106,14 +112,9 @@ def _ipaddr_info(host, port, family, type, proto):

`

106

112

`host is None:

`

107

113

`return None

`

108

114

``

109

``

`-

if type == socket.SOCK_STREAM:

`

110

``

`-

Linux only:

`

111

``

`-

getaddrinfo() can raise when socket.type is a bit mask.

`

112

``

`-

So if socket.type is a bit mask of SOCK_STREAM, and say

`

113

``

`-

SOCK_NONBLOCK, we simply return None, which will trigger

`

114

``

`-

a call to getaddrinfo() letting it process this request.

`

``

115

`+

if _is_stream_socket(type):

`

115

116

`proto = socket.IPPROTO_TCP

`

116

``

`-

elif type == socket.SOCK_DGRAM:

`

``

117

`+

elif _is_dgram_socket(type):

`

117

118

`proto = socket.IPPROTO_UDP

`

118

119

`else:

`

119

120

`return None

`

`@@ -758,7 +759,7 @@ async def create_connection(self, protocol_factory, host=None, port=None,

`

758

759

`if sock is None:

`

759

760

`raise ValueError(

`

760

761

`'host and port was not specified and no sock specified')

`

761

``

`-

if not _is_stream_socket(sock):

`

``

762

`+

if not _is_stream_socket(sock.type):

`

762

763

`# We allow AF_INET, AF_INET6, AF_UNIX as long as they

`

763

764

`# are SOCK_STREAM.

`

764

765

`# We support passing AF_UNIX sockets even though we have

`

`@@ -808,7 +809,7 @@ async def create_datagram_endpoint(self, protocol_factory,

`

808

809

`allow_broadcast=None, sock=None):

`

809

810

`"""Create datagram connection."""

`

810

811

`if sock is not None:

`

811

``

`-

if not _is_dgram_socket(sock):

`

``

812

`+

if not _is_dgram_socket(sock.type):

`

812

813

`raise ValueError(

`

813

814

`f'A UDP Socket was expected, got {sock!r}')

`

814

815

`if (local_addr or remote_addr or

`

`@@ -1036,7 +1037,7 @@ async def create_server(self, protocol_factory, host=None, port=None,

`

1036

1037

`else:

`

1037

1038

`if sock is None:

`

1038

1039

`raise ValueError('Neither host/port nor sock were specified')

`

1039

``

`-

if not _is_stream_socket(sock):

`

``

1040

`+

if not _is_stream_socket(sock.type):

`

1040

1041

`raise ValueError(f'A Stream Socket was expected, got {sock!r}')

`

1041

1042

`sockets = [sock]

`

1042

1043

``

`@@ -1059,7 +1060,7 @@ async def connect_accepted_socket(self, protocol_factory, sock,

`

1059

1060

` This method is a coroutine. When completed, the coroutine

`

1060

1061

` returns a (transport, protocol) pair.

`

1061

1062

` """

`

1062

``

`-

if not _is_stream_socket(sock):

`

``

1063

`+

if not _is_stream_socket(sock.type):

`

1063

1064

`raise ValueError(f'A Stream Socket was expected, got {sock!r}')

`

1064

1065

``

1065

1066

`transport, protocol = await self._create_connection_transport(

`