Skip to content

Commit 76bb934

Browse files
committed
Fix create_server to bind correctly to ipv6 addresses on Linux
1 parent 073c55a commit 76bb934

File tree

5 files changed

+33
-4
lines changed

5 files changed

+33
-4
lines changed

tests/test_tcp.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,17 @@ def test_create_server_4(self):
177177
self.loop.run_until_complete(
178178
self.loop.create_server(object, *addr))
179179

180+
def test_create_server_5(self):
181+
port = tb.find_free_port()
182+
183+
async def runner():
184+
srv = await self.loop.create_server(
185+
asyncio.Protocol,
186+
None, port)
187+
srv.close()
188+
189+
self.loop.run_until_complete(runner())
190+
180191
def test_create_connection_1(self):
181192
CNT = 0
182193
TOTAL_CNT = 100

uvloop/_testbase.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,19 @@ def filter(self, record):
8585
logger.removeFilter(filter)
8686

8787

88+
def find_free_port(start_from=50000):
89+
for port in range(start_from, start_from + 500):
90+
sock = socket.socket()
91+
with sock:
92+
try:
93+
sock.bind(('', port))
94+
except socket.error:
95+
continue
96+
else:
97+
return port
98+
raise RuntimeError('could not find a free port')
99+
100+
88101
class SSLTestCase:
89102

90103
ONLYCERT = _cert_fullname('ssl_cert.pem')

uvloop/includes/stdlib.pxi

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,7 @@ cdef ft_partial = functools.partial
4242

4343
cdef iter_chain = itertools.chain
4444

45-
cdef int has_AF_INET6 = hasattr(socket, 'AF_INET6')
4645
cdef int has_SO_REUSEPORT = hasattr(socket, 'SO_REUSEPORT')
47-
cdef int has_IPPROTO_IPV6 = hasattr(socket, 'IPPROTO_IPV6')
4846
cdef int SO_REUSEPORT = getattr(socket, 'SO_REUSEPORT', 0)
4947

5048
cdef socket_gaierror = socket.gaierror

uvloop/includes/uv.pxd

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ cdef extern from "includes/compat.h":
1111

1212

1313
cdef extern from "uv.h" nogil:
14+
cdef int UV_TCP_IPV6ONLY
15+
1416
cdef int UV_EACCES
1517
cdef int UV_EAGAIN
1618
cdef int UV_EALREADY
@@ -57,7 +59,6 @@ cdef extern from "uv.h" nogil:
5759
cdef int AI_PASSIVE
5860
cdef int AI_NUMERICHOST
5961
cdef int INET6_ADDRSTRLEN
60-
cdef int IPV6_V6ONLY
6162
cdef int IPPROTO_IPV6
6263
cdef int SOCK_STREAM
6364
cdef int SOCK_DGRAM

uvloop/loop.pyx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,7 @@ cdef class Loop:
11211121
TCPServer tcp
11221122
system.addrinfo *addrinfo
11231123
Server server = Server(self)
1124+
int bind_flags
11241125

11251126
if ssl is not None and not isinstance(ssl, ssl_SSLContext):
11261127
raise TypeError('ssl argument must be an SSLContext or None')
@@ -1163,8 +1164,13 @@ cdef class Loop:
11631164
if reuse_port:
11641165
self._sock_set_reuseport(tcp._fileno())
11651166

1167+
if addrinfo.ai_family == uv.AF_INET6:
1168+
bind_flags = uv.UV_TCP_IPV6ONLY
1169+
else:
1170+
bind_flags = 0
1171+
11661172
try:
1167-
tcp.bind(addrinfo.ai_addr)
1173+
tcp.bind(addrinfo.ai_addr, bind_flags)
11681174
tcp.listen(backlog)
11691175
except OSError as err:
11701176
pyaddr = __convert_sockaddr_to_pyaddr(

0 commit comments

Comments
 (0)