Commit e076ffb0 authored by Yury Selivanov's avatar Yury Selivanov

asyncio: Remove duplicate bind addresses in create_server.

Patch by Sebastien Bourdeauducq (issue #26338)
parent f9e1f2bd
...@@ -880,7 +880,10 @@ class BaseEventLoop(events.AbstractEventLoop): ...@@ -880,7 +880,10 @@ class BaseEventLoop(events.AbstractEventLoop):
to host and port. to host and port.
The host parameter can also be a sequence of strings and in that case The host parameter can also be a sequence of strings and in that case
the TCP server is bound to all hosts of the sequence. the TCP server is bound to all hosts of the sequence. If a host
appears multiple times (possibly indirectly e.g. when hostnames
resolve to the same IP address), the server is only bound once to that
host.
Return a Server object which can be used to stop the service. Return a Server object which can be used to stop the service.
...@@ -909,7 +912,7 @@ class BaseEventLoop(events.AbstractEventLoop): ...@@ -909,7 +912,7 @@ class BaseEventLoop(events.AbstractEventLoop):
flags=flags) flags=flags)
for host in hosts] for host in hosts]
infos = yield from tasks.gather(*fs, loop=self) infos = yield from tasks.gather(*fs, loop=self)
infos = itertools.chain.from_iterable(infos) infos = set(itertools.chain.from_iterable(infos))
completed = False completed = False
try: try:
......
...@@ -749,34 +749,37 @@ class EventLoopTestsMixin: ...@@ -749,34 +749,37 @@ class EventLoopTestsMixin:
@asyncio.coroutine @asyncio.coroutine
def getaddrinfo(host, port, *args, **kw): def getaddrinfo(host, port, *args, **kw):
if family == socket.AF_INET: if family == socket.AF_INET:
return [[family, socket.SOCK_STREAM, 6, '', (host, port)]] return [(family, socket.SOCK_STREAM, 6, '', (host, port))]
else: else:
return [[family, socket.SOCK_STREAM, 6, '', (host, port, 0, 0)]] return [(family, socket.SOCK_STREAM, 6, '', (host, port, 0, 0))]
def getaddrinfo_task(*args, **kwds): def getaddrinfo_task(*args, **kwds):
return asyncio.Task(getaddrinfo(*args, **kwds), loop=self.loop) return asyncio.Task(getaddrinfo(*args, **kwds), loop=self.loop)
unique_hosts = set(hosts)
if family == socket.AF_INET: if family == socket.AF_INET:
mock_sock.socket().getsockbyname.side_effect = [(host, 80) mock_sock.socket().getsockbyname.side_effect = [
for host in hosts] (host, 80) for host in unique_hosts]
else: else:
mock_sock.socket().getsockbyname.side_effect = [(host, 80, 0, 0) mock_sock.socket().getsockbyname.side_effect = [
for host in hosts] (host, 80, 0, 0) for host in unique_hosts]
self.loop.getaddrinfo = getaddrinfo_task self.loop.getaddrinfo = getaddrinfo_task
self.loop._start_serving = mock.Mock() self.loop._start_serving = mock.Mock()
self.loop._stop_serving = mock.Mock() self.loop._stop_serving = mock.Mock()
f = self.loop.create_server(lambda: MyProto(self.loop), hosts, 80) f = self.loop.create_server(lambda: MyProto(self.loop), hosts, 80)
server = self.loop.run_until_complete(f) server = self.loop.run_until_complete(f)
self.addCleanup(server.close) self.addCleanup(server.close)
server_hosts = [sock.getsockbyname()[0] for sock in server.sockets] server_hosts = {sock.getsockbyname()[0] for sock in server.sockets}
self.assertEqual(server_hosts, hosts) self.assertEqual(server_hosts, unique_hosts)
def test_create_server_multiple_hosts_ipv4(self): def test_create_server_multiple_hosts_ipv4(self):
self.create_server_multiple_hosts(socket.AF_INET, self.create_server_multiple_hosts(socket.AF_INET,
['1.2.3.4', '5.6.7.8']) ['1.2.3.4', '5.6.7.8', '1.2.3.4'])
def test_create_server_multiple_hosts_ipv6(self): def test_create_server_multiple_hosts_ipv6(self):
self.create_server_multiple_hosts(socket.AF_INET6, ['::1', '::2']) self.create_server_multiple_hosts(socket.AF_INET6,
['::1', '::2', '::1'])
def test_create_server(self): def test_create_server(self):
proto = MyProto(self.loop) proto = MyProto(self.loop)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment