Skip to content

Commit

Permalink
Merge pull request tornadoweb#977 from schlamar/fix-port-allocation
Browse files Browse the repository at this point in the history
Fixed automatic port allocation in bind_sockets.
  • Loading branch information
bdarnell committed Feb 22, 2014
2 parents b9c6c33 + 151eef7 commit 2ad4a90
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 1 deletion.
9 changes: 9 additions & 0 deletions tornado/netutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ def bind_sockets(port, address=None, family=socket.AF_UNSPEC, backlog=128, flags
family = socket.AF_INET
if flags is None:
flags = socket.AI_PASSIVE
bound_port = None
for res in set(socket.getaddrinfo(address, port, family, socket.SOCK_STREAM,
0, flags)):
af, socktype, proto, canonname, sockaddr = res
Expand All @@ -100,8 +101,16 @@ def bind_sockets(port, address=None, family=socket.AF_UNSPEC, backlog=128, flags
# Python 2.x on windows doesn't have IPPROTO_IPV6.
if hasattr(socket, "IPPROTO_IPV6"):
sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)

# automatic port allocation with port=None
# should bind on the same port on IPv4 and IPv6
host, requested_port = sockaddr[:2]
if requested_port == 0 and bound_port is not None:
sockaddr = tuple([host, bound_port] + list(sockaddr[2:]))

sock.setblocking(0)
sock.bind(sockaddr)
bound_port = sock.getsockname()[1]
sock.listen(backlog)
sockets.append(sock)
return sockets
Expand Down
9 changes: 8 additions & 1 deletion tornado/test/netutil_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import sys
import time

from tornado.netutil import BlockingResolver, ThreadedResolver, is_valid_ip
from tornado.netutil import BlockingResolver, ThreadedResolver, is_valid_ip, bind_sockets
from tornado.stack_context import ExceptionStackContext
from tornado.testing import AsyncTestCase, gen_test
from tornado.test.util import unittest
Expand Down Expand Up @@ -144,3 +144,10 @@ def test_is_valid_ip(self):
self.assertTrue(not is_valid_ip(' '))
self.assertTrue(not is_valid_ip('\n'))
self.assertTrue(not is_valid_ip('\x00'))


class TestPortAllocation(unittest.TestCase):
def test_same_port_allocation(self):
sockets = bind_sockets(None, 'localhost')
port = sockets[0].getsockname()[1]
self.assertTrue(all(s.getsockname()[1] == port for s in sockets[1:]))

0 comments on commit 2ad4a90

Please sign in to comment.