diff -r 06161ebf74ee Lib/_socket.py --- a/Lib/_socket.py Mon May 19 09:02:22 2014 +0100 +++ b/Lib/_socket.py Wed May 21 18:13:33 2014 -0700 @@ -605,6 +605,14 @@ } } +def _socktuple(addr): + port = addr.getPort() + inet_addr = addr.getAddress() + if isinstance(inet_addr, java.net.Inet6Address): + return str(inet_addr.getHostAddress()), port, 0, inet_addr.getScopeId() + else: + return str(inet_addr.getHostAddress()), port + # actual socket support ####################### @@ -826,7 +834,7 @@ self.child_handler = ChildSocketHandler(self) b.childHandler(self.child_handler) - future = b.bind(self.bind_addr) + future = b.bind(self.bind_addr.getAddress(), self.bind_addr.getPort()) self._handle_channel_future(future, "listen") self.bind_timestamp = time.time() self.channel = future.channel() @@ -1103,7 +1111,7 @@ if self.bind_addr == _EPHEMERAL_ADDRESS: raise error(errno.ENOTCONN, "Socket is not connected") else: - return self.bind_addr.getHostString(), self.bind_addr.getPort() + return _socktuple(self.bind_addr) # Netty 4 currently races between bind to ephemeral port and the availability # of the local address for the channel. Workaround for now is to poll. while True: @@ -1116,14 +1124,19 @@ raise error(errno.ENOTCONN, "Socket is not connected") log.debug("Poll for local address", extra={"sock": self}) time.sleep(0.1) # completely arbitrary - return local_addr.getHostString(), local_addr.getPort() + if local_addr.getAddress().isAnyLocalAddress(): + # Netty 4 will default to an IPv6 "any" address from a channel even if it was originally bound to an IPv4 "any" address + # so, as a workaround, let's construct a new "any" address using the port information gathered above + if type(self.bind_addr.getAddress()) != type(local_addr.getAddress()): + return _socktuple(java.net.InetSocketAddress(self.bind_addr.getAddress(), local_addr.getPort())) + return _socktuple(local_addr) def getpeername(self): self._verify_channel() remote_addr = self.channel.remoteAddress() if remote_addr is None: raise error(errno.ENOTCONN, "Socket is not connected") - return remote_addr.getHostString(), remote_addr.getPort() + return _socktuple(remote_addr) _socketmethods = ( diff -r 06161ebf74ee Lib/test/test_socket.py --- a/Lib/test/test_socket.py Mon May 19 09:02:22 2014 +0100 +++ b/Lib/test/test_socket.py Wed May 21 18:13:33 2014 -0700 @@ -577,6 +577,22 @@ name = sock.getsockname() self.assertEqual(name, ("0.0.0.0", PORT+1)) + def testSockNameEphemeralV4(self): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.bind(('', 0)) + sock.listen(1) + name = sock.getsockname() + self.assertEqual(len(name), 2) + self.assertNotEqual(name[1], 0) + + def testSockNameEphemeralV6(self): + sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) + sock.bind(('', 0, 0, 0)) + sock.listen(1) + name = sock.getsockname() + self.assertEqual(len(name), 4) + self.assertNotEqual(name[1], 0) + def testSockAttributes(self): # Testing required attributes for family in [socket.AF_INET, socket.AF_INET6]: