[Jython-checkins] jython (merge 2.5 -> default): Merge w/2.5: Fix for http://bugs.jython.org/issue1844 (bad host returned by
alan.kennedy
jython-checkins at python.org
Sat Mar 17 23:03:30 CET 2012
http://hg.python.org/jython/rev/76287b6c2863
changeset: 6409:76287b6c2863
parent: 6406:5add107a20c8
parent: 6408:a33beb889a79
user: Alan Kennedy <alan at xhaus.com>
date: Sat Mar 17 22:02:42 2012 +0000
summary:
Merge w/2.5: Fix for http://bugs.jython.org/issue1844 (bad host returned by getsockname)
files:
Lib/socket.py | 58 ++++++++++++++-------------
Lib/test/test_socket.py | 62 +++++++++++++++++++++-------
NEWS | 4 +
3 files changed, 81 insertions(+), 43 deletions(-)
diff --git a/Lib/socket.py b/Lib/socket.py
--- a/Lib/socket.py
+++ b/Lib/socket.py
@@ -230,6 +230,8 @@
INADDR_ANY = "0.0.0.0"
INADDR_BROADCAST = "255.255.255.255"
+IN6ADDR_ANY_INIT = "::"
+
# Options with negative constants are not supported
# They are being added here so that code that refers to them
# will not break with an AttributeError
@@ -744,39 +746,36 @@
__repr__ = __str__
-def _get_jsockaddr(address_object, for_udp=False):
- if address_object is None:
- return java.net.InetSocketAddress(0) # Let the system pick an ephemeral port
+def _get_jsockaddr(address_object, family, sock_type, proto, flags):
+ # Is this an object that was returned from getaddrinfo? If so, it already contains an InetAddress
if isinstance(address_object, _ip_address_t):
return java.net.InetSocketAddress(address_object.jaddress, address_object[1])
+ # The user passed an address tuple, not an object returned from getaddrinfo
+ # So we must call getaddrinfo, after some translations and checking
+ if address_object is None:
+ address_object = ("", 0)
error_message = "Address must be a 2-tuple (ipv4: (host, port)) or a 4-tuple (ipv6: (host, port, flow, scope))"
if not isinstance(address_object, tuple) or \
- len(address_object) not in [2,4] or \
+ ((family == AF_INET and len(address_object) != 2) or (family == AF_INET6 and len(address_object) not in [2,4] )) or \
not isinstance(address_object[0], basestring) or \
not isinstance(address_object[1], (int, long)):
raise TypeError(error_message)
if len(address_object) == 4 and not isinstance(address_object[3], (int, long)):
raise TypeError(error_message)
hostname, port = address_object[0].strip(), address_object[1]
- if for_udp:
- if hostname == "":
- hostname = INADDR_ANY
- elif hostname == "<broadcast>":
- hostname = INADDR_BROADCAST
- else:
- if hostname == "":
- hostname = None
- if hostname is None:
- return java.net.InetSocketAddress(port)
+ if family == AF_INET and sock_type == SOCK_DGRAM and hostname == "<broadcast>":
+ hostname = INADDR_BROADCAST
+ if hostname == "":
+ if flags & AI_PASSIVE:
+ hostname = {AF_INET: INADDR_ANY, AF_INET6: IN6ADDR_ANY_INIT}[family]
+ else:
+ hostname = "localhost"
if isinstance(hostname, unicode):
hostname = _encode_idna(hostname)
- if len(address_object) == 4:
- # There is no way to get a Inet6Address: Inet6Address.getByName() simply calls
- # InetAddress.getByName,() which also returns Inet4Address objects
- # If users want to use IPv6 address, scoped or not,
- # they should use getaddrinfo(family=AF_INET6)
- pass
- return java.net.InetSocketAddress(java.net.InetAddress.getByName(hostname), port)
+ addresses = getaddrinfo(hostname, port, family, sock_type, proto, flags)
+ if len(addresses) == 0:
+ raise gaierror(errno.EGETADDRINFOFAILED, 'getaddrinfo failed')
+ return java.net.InetSocketAddress(addresses[0][4].jaddress, port)
# Workaround for this (predominantly windows) issue
# http://wiki.python.org/jython/NewSocketModule#IPV6_address_support
@@ -1072,7 +1071,7 @@
assert not self.sock_impl
assert not self.local_addr
# Do the address format check
- _get_jsockaddr(addr)
+ _get_jsockaddr(addr, self.family, self.type, self.proto, 0)
self.local_addr = addr
def listen(self, backlog):
@@ -1080,7 +1079,8 @@
try:
assert not self.sock_impl
self.server = 1
- self.sock_impl = _server_socket_impl(_get_jsockaddr(self.local_addr), backlog, self.pending_options[ (SOL_SOCKET, SO_REUSEADDR) ])
+ self.sock_impl = _server_socket_impl(_get_jsockaddr(self.local_addr, self.family, self.type, self.proto, AI_PASSIVE),
+ backlog, self.pending_options[ (SOL_SOCKET, SO_REUSEADDR) ])
self._config()
except java.lang.Exception, jlx:
raise _map_exception(jlx)
@@ -1107,9 +1107,10 @@
assert not self.sock_impl
self.sock_impl = _client_socket_impl()
if self.local_addr: # Has the socket been bound to a local address?
- self.sock_impl.bind(_get_jsockaddr(self.local_addr), self.pending_options[ (SOL_SOCKET, SO_REUSEADDR) ])
+ self.sock_impl.bind(_get_jsockaddr(self.local_addr, self.family, self.type, self.proto, 0),
+ self.pending_options[ (SOL_SOCKET, SO_REUSEADDR) ])
self._config() # Configure timeouts, etc, now that the socket exists
- self.sock_impl.connect(_get_jsockaddr(addr))
+ self.sock_impl.connect(_get_jsockaddr(addr, self.family, self.type, self.proto, 0))
except java.lang.Exception, jlx:
raise _map_exception(jlx)
@@ -1218,7 +1219,8 @@
def bind(self, addr):
try:
assert not self.sock_impl
- self.sock_impl = _datagram_socket_impl(_get_jsockaddr(addr, True), self.pending_options[ (SOL_SOCKET, SO_REUSEADDR) ])
+ self.sock_impl = _datagram_socket_impl(_get_jsockaddr(addr, self.family, self.type, self.proto, AI_PASSIVE),
+ self.pending_options[ (SOL_SOCKET, SO_REUSEADDR) ])
self._config()
except java.lang.Exception, jlx:
raise _map_exception(jlx)
@@ -1229,7 +1231,7 @@
if not self.sock_impl:
self.sock_impl = _datagram_socket_impl()
self._config()
- self.sock_impl.connect(_get_jsockaddr(addr))
+ self.sock_impl.connect(_get_jsockaddr(addr, self.family, self.type, self.proto, 0))
self.connected = True
except java.lang.Exception, jlx:
raise _map_exception(jlx)
@@ -1252,7 +1254,7 @@
self.sock_impl = _datagram_socket_impl()
self._config()
byte_array = java.lang.String(data).getBytes('iso-8859-1')
- result = self.sock_impl.sendto(byte_array, _get_jsockaddr(addr, True), flags)
+ result = self.sock_impl.sendto(byte_array, _get_jsockaddr(addr, self.family, self.type, self.proto, 0), flags)
return result
except java.lang.Exception, jlx:
raise _map_exception(jlx)
diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -1884,7 +1884,7 @@
def testIPV4AddressesFromGetAddrInfo(self):
local_addr = socket.getaddrinfo("localhost", 80, socket.AF_INET, socket.SOCK_STREAM, 0, 0)[0][4]
- sockaddr = socket._get_jsockaddr(local_addr)
+ sockaddr = socket._get_jsockaddr(local_addr, socket.AF_INET, None, 0, 0)
self.failUnless(isinstance(sockaddr, java.net.InetSocketAddress), "_get_jsockaddr returned wrong type: '%s'" % str(type(sockaddr)))
self.failUnlessEqual(sockaddr.address.hostAddress, "127.0.0.1")
self.failUnlessEqual(sockaddr.port, 80)
@@ -1895,27 +1895,28 @@
# older FreeBSDs may have spotty IPV6 Java support
return
local_addr = addrinfo[0][4]
- sockaddr = socket._get_jsockaddr(local_addr)
+ sockaddr = socket._get_jsockaddr(local_addr, socket.AF_INET6, None, 0, 0)
self.failUnless(isinstance(sockaddr, java.net.InetSocketAddress), "_get_jsockaddr returned wrong type: '%s'" % str(type(sockaddr)))
self.failUnless(sockaddr.address.hostAddress in ["::1", "0:0:0:0:0:0:0:1"])
self.failUnlessEqual(sockaddr.port, 80)
def testAddressesFrom2Tuple(self):
- for addr_tuple in [
- ("localhost", 80),
+ for family, addr_tuple, jaddress_type, expected in [
+ (socket.AF_INET, ("localhost", 80), java.net.Inet4Address, ["127.0.0.1"]),
+ (socket.AF_INET6, ("localhost", 80), java.net.Inet6Address, ["::1", "0:0:0:0:0:0:0:1"]),
]:
- sockaddr = socket._get_jsockaddr(addr_tuple)
+ sockaddr = socket._get_jsockaddr(addr_tuple, family, None, 0, 0)
self.failUnless(isinstance(sockaddr, java.net.InetSocketAddress), "_get_jsockaddr returned wrong type: '%s'" % str(type(sockaddr)))
- self.failUnless(sockaddr.address.hostAddress in ["127.0.0.1", "::1", "0:0:0:0:0:0:0:1"])
+ self.failUnless(isinstance(sockaddr.address, jaddress_type), "_get_jsockaddr returned wrong address type: '%s'(family=%d)" % (str(type(sockaddr.address)), family))
+ self.failUnless(sockaddr.address.hostAddress in expected)
self.failUnlessEqual(sockaddr.port, 80)
def testAddressesFrom4Tuple(self):
- # This test disabled: cannot construct IPV6 addresses from 4-tuple
- return
for addr_tuple in [
+ ("localhost", 80),
("localhost", 80, 0, 0),
]:
- sockaddr = socket._get_jsockaddr(addr_tuple)
+ sockaddr = socket._get_jsockaddr(addr_tuple, socket.AF_INET6, None, 0, 0)
self.failUnless(isinstance(sockaddr, java.net.InetSocketAddress), "_get_jsockaddr returned wrong type: '%s'" % str(type(sockaddr)))
self.failUnless(isinstance(sockaddr.address, java.net.Inet6Address), "_get_jsockaddr returned wrong address type: '%s'" % str(type(sockaddr.address)))
self.failUnless(sockaddr.address.hostAddress in ["::1", "0:0:0:0:0:0:0:1"])
@@ -1923,13 +1924,44 @@
self.failUnlessEqual(sockaddr.port, 80)
def testSpecialHostnames(self):
- for addr_tuple, for_udp, expected_hostname in [
- ( ("", 80), False, socket.INADDR_ANY),
- ( ("", 80), True, socket.INADDR_ANY),
- ( ("<broadcast>", 80), True, socket.INADDR_BROADCAST),
+ for family, sock_type, flags, addr_tuple, expected in [
+ ( socket.AF_INET, None, 0, ("", 80), ["localhost"]),
+ ( socket.AF_INET, None, socket.AI_PASSIVE, ("", 80), [socket.INADDR_ANY]),
+ ( socket.AF_INET6, None, 0, ("", 80), ["localhost"]),
+ ( socket.AF_INET6, None, socket.AI_PASSIVE, ("", 80), [socket.IN6ADDR_ANY_INIT, "0:0:0:0:0:0:0:0"]),
+ ( socket.AF_INET, socket.SOCK_DGRAM, 0, ("<broadcast>", 80), [socket.INADDR_BROADCAST]),
]:
- sockaddr = socket._get_jsockaddr(addr_tuple, for_udp)
- self.failUnlessEqual(sockaddr.hostName, expected_hostname, "_get_jsockaddr returned wrong hostname '%s' for special hostname '%s'" % (sockaddr.hostName, expected_hostname))
+ sockaddr = socket._get_jsockaddr(addr_tuple, family, sock_type, 0, flags)
+ self.failUnless(sockaddr.hostName in expected, "_get_jsockaddr returned wrong hostname '%s' for special hostname '%s'(family=%d)" % (sockaddr.hostName, addr_tuple[0], family))
+
+ def testNoneTo_get_jsockaddr(self):
+ for family, flags, expected in [
+ ( socket.AF_INET, 0, ["localhost"]),
+ ( socket.AF_INET, socket.AI_PASSIVE, [socket.INADDR_ANY]),
+ ( socket.AF_INET6, 0, ["localhost"]),
+ ( socket.AF_INET6, socket.AI_PASSIVE, [socket.IN6ADDR_ANY_INIT, "0:0:0:0:0:0:0:0"]),
+ ]:
+ sockaddr = socket._get_jsockaddr(None, family, None, 0, flags)
+ self.failUnless(sockaddr.hostName in expected, "_get_jsockaddr returned wrong hostname '%s' for sock tuple == None (family=%d)" % (sockaddr.hostName, family))
+
+ def testBadAddressTuples(self):
+ for family, address_tuple in [
+ ( socket.AF_INET, () ),
+ ( socket.AF_INET, ("") ),
+ ( socket.AF_INET, (80) ),
+ ( socket.AF_INET, ("localhost", 80, 0) ),
+ ( socket.AF_INET, ("localhost", 80, 0, 0) ),
+ ( socket.AF_INET6, () ),
+ ( socket.AF_INET6, ("") ),
+ ( socket.AF_INET6, (80) ),
+ ( socket.AF_INET6, ("localhost", 80, 0) ),
+ ]:
+ try:
+ sockaddr = socket._get_jsockaddr(address_tuple, family, None, 0, 0)
+ except TypeError:
+ pass
+ else:
+ self.fail("Bad tuple %s (family=%d) should have raised TypeError" % (str(address_tuple), family))
class TestExceptions(unittest.TestCase):
diff --git a/NEWS b/NEWS
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,9 @@
Jython NEWS
+Jython 2.5.3b2
+ Bugs Fixed
+ - [ 1844 ] bad host returned by getsockname
+
Jython 2.5.3b1
Bugs Fixed
- [ 1835 ] s/occured/occurred/ :)
--
Repository URL: http://hg.python.org/jython
More information about the Jython-checkins
mailing list