]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Fixed automatic port allocation in bind_sockets. 977/head
authorschlamar <marc.schlaich@gmail.com>
Thu, 23 Jan 2014 11:23:53 +0000 (12:23 +0100)
committerschlamar <marc.schlaich@gmail.com>
Fri, 21 Feb 2014 12:06:55 +0000 (13:06 +0100)
bind_sockets should use the same port on IPv4 and IPv6 if port=None.

tornado/netutil.py
tornado/test/netutil_test.py

index 7c89dc511fd5ddea4815e020264993d5396e4f9d..a4699138eeb6345d1e2a68bfc8a2235ba339b984 100644 (file)
@@ -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
@@ -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
index ea8d51a534b67d284e7276ce066985728bea1d04..9f707a8d2ceed7de327241da4a664ae12b3254e7 100644 (file)
@@ -6,7 +6,7 @@ from subprocess import Popen
 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
@@ -144,3 +144,10 @@ class IsValidIPTest(unittest.TestCase):
         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:]))