|
From: <am...@us...> - 2011-01-25 23:46:33
|
Revision: 7191
http://jython.svn.sourceforge.net/jython/?rev=7191&view=rev
Author: amak
Date: 2011-01-25 23:46:27 +0000 (Tue, 25 Jan 2011)
Log Message:
-----------
1. Re-enabling the use of IPV6/AF_INET6 addresses
2. Adding workarounds for systems that have problems with IPV6 on java
3. Test for #2
Modified Paths:
--------------
trunk/jython/Lib/socket.py
trunk/jython/Lib/test/test_socket.py
Modified: trunk/jython/Lib/socket.py
===================================================================
--- trunk/jython/Lib/socket.py 2011-01-23 15:58:55 UTC (rev 7190)
+++ trunk/jython/Lib/socket.py 2011-01-25 23:46:27 UTC (rev 7191)
@@ -94,29 +94,40 @@
class timeout(error): pass
class sslerror(error): pass
+def _unmapped_exception(exc):
+ return error(-1, 'Unmapped exception: %s' % exc)
+
+def java_net_socketexception_handler(exc):
+ if exc.message.startswith("Address family not supported by protocol family"):
+ return error(errno.EAFNOSUPPORT, 'Address family not supported by protocol family: See http://wiki.python.org/jython/NewSocketModule#IPV6addresssupport')
+ return _unmapped_exception(exc)
+
+def would_block_error(exc=None):
+ return error(errno.EWOULDBLOCK, 'The socket operation could not complete without blocking')
+
ALL = None
_exception_map = {
-# (<javaexception>, <circumstance>) : lambda: <code that raises the python equivalent>, or None to stub out as unmapped
+# (<javaexception>, <circumstance>) : callable that raises the python equivalent exception, or None to stub out as unmapped
-(java.io.IOException, ALL) : lambda: error(errno.ECONNRESET, 'Software caused connection abort'),
-(java.io.InterruptedIOException, ALL) : lambda: timeout('timed out'),
+(java.io.IOException, ALL) : lambda x: error(errno.ECONNRESET, 'Software caused connection abort'),
+(java.io.InterruptedIOException, ALL) : lambda x: timeout('timed out'),
-(java.net.BindException, ALL) : lambda: error(errno.EADDRINUSE, 'Address already in use'),
-(java.net.ConnectException, ALL) : lambda: error(errno.ECONNREFUSED, 'Connection refused'),
+(java.net.BindException, ALL) : lambda x: error(errno.EADDRINUSE, 'Address already in use'),
+(java.net.ConnectException, ALL) : lambda x: error(errno.ECONNREFUSED, 'Connection refused'),
(java.net.NoRouteToHostException, ALL) : None,
(java.net.PortUnreachableException, ALL) : None,
(java.net.ProtocolException, ALL) : None,
-(java.net.SocketException, ALL) : None,
-(java.net.SocketTimeoutException, ALL) : lambda: timeout('timed out'),
-(java.net.UnknownHostException, ALL) : lambda: gaierror(errno.EGETADDRINFOFAILED, 'getaddrinfo failed'),
+(java.net.SocketException, ALL) : java_net_socketexception_handler,
+(java.net.SocketTimeoutException, ALL) : lambda x: timeout('timed out'),
+(java.net.UnknownHostException, ALL) : lambda x: gaierror(errno.EGETADDRINFOFAILED, 'getaddrinfo failed'),
-(java.nio.channels.AlreadyConnectedException, ALL) : lambda: error(errno.EISCONN, 'Socket is already connected'),
+(java.nio.channels.AlreadyConnectedException, ALL) : lambda x: error(errno.EISCONN, 'Socket is already connected'),
(java.nio.channels.AsynchronousCloseException, ALL) : None,
(java.nio.channels.CancelledKeyException, ALL) : None,
(java.nio.channels.ClosedByInterruptException, ALL) : None,
-(java.nio.channels.ClosedChannelException, ALL) : lambda: error(errno.EPIPE, 'Socket closed'),
+(java.nio.channels.ClosedChannelException, ALL) : lambda x: error(errno.EPIPE, 'Socket closed'),
(java.nio.channels.ClosedSelectorException, ALL) : None,
(java.nio.channels.ConnectionPendingException, ALL) : None,
(java.nio.channels.IllegalBlockingModeException, ALL) : None,
@@ -126,28 +137,25 @@
(java.nio.channels.NonWritableChannelException, ALL) : None,
(java.nio.channels.NotYetBoundException, ALL) : None,
(java.nio.channels.NotYetConnectedException, ALL) : None,
-(java.nio.channels.UnresolvedAddressException, ALL) : lambda: gaierror(errno.EGETADDRINFOFAILED, 'getaddrinfo failed'),
+(java.nio.channels.UnresolvedAddressException, ALL) : lambda x: gaierror(errno.EGETADDRINFOFAILED, 'getaddrinfo failed'),
(java.nio.channels.UnsupportedAddressTypeException, ALL) : None,
# These error codes are currently wrong: getting them correct is going to require
# some investigation. Cpython 2.6 introduced extensive SSL support.
-(javax.net.ssl.SSLException, ALL) : lambda: sslerror(-1, 'SSL exception'),
-(javax.net.ssl.SSLHandshakeException, ALL) : lambda: sslerror(-1, 'SSL handshake exception'),
-(javax.net.ssl.SSLKeyException, ALL) : lambda: sslerror(-1, 'SSL key exception'),
-(javax.net.ssl.SSLPeerUnverifiedException, ALL) : lambda: sslerror(-1, 'SSL peer unverified exception'),
-(javax.net.ssl.SSLProtocolException, ALL) : lambda: sslerror(-1, 'SSL protocol exception'),
+(javax.net.ssl.SSLException, ALL) : lambda x: sslerror(-1, 'SSL exception'),
+(javax.net.ssl.SSLHandshakeException, ALL) : lambda x: sslerror(-1, 'SSL handshake exception'),
+(javax.net.ssl.SSLKeyException, ALL) : lambda x: sslerror(-1, 'SSL key exception'),
+(javax.net.ssl.SSLPeerUnverifiedException, ALL) : lambda x: sslerror(-1, 'SSL peer unverified exception'),
+(javax.net.ssl.SSLProtocolException, ALL) : lambda x: sslerror(-1, 'SSL protocol exception'),
}
-def would_block_error(exc=None):
- return error(errno.EWOULDBLOCK, 'The socket operation could not complete without blocking')
-
def _map_exception(exc, circumstance=ALL):
# print "Mapping exception: %s" % exc
mapped_exception = _exception_map.get((exc.__class__, circumstance))
if mapped_exception:
- exception = mapped_exception()
+ exception = mapped_exception(exc)
else:
exception = error(-1, 'Unmapped exception: %s' % exc)
exception.java_exception = exc
@@ -588,7 +596,7 @@
return Protocol.getProtocolByName(protocol_name).getProto()
def _realsocket(family = AF_INET, type = SOCK_STREAM, protocol=0):
- assert family == AF_INET, "Only AF_INET sockets are currently supported on jython"
+ assert family in (AF_INET, AF_INET6), "Only AF_INET and AF_INET6 sockets are currently supported on jython"
assert type in (SOCK_DGRAM, SOCK_STREAM), "Only SOCK_STREAM and SOCK_DGRAM sockets are currently supported on jython"
if type == SOCK_STREAM:
if protocol != 0:
@@ -599,16 +607,25 @@
assert protocol == IPPROTO_UDP, "Only IPPROTO_UDP supported on SOCK_DGRAM sockets"
return _udpsocket()
+_ipv4_addresses_only = False
+
+def _use_ipv4_addresses_only(value):
+ global _ipv4_addresses_only
+ _ipv4_addresses_only = value
+
def getaddrinfo(host, port, family=AF_INET, socktype=None, proto=0, flags=None):
try:
if not family in [AF_INET, AF_INET6, AF_UNSPEC]:
raise gaierror(errno.EIO, 'ai_family not supported')
filter_fns = []
- filter_fns.append({
- AF_INET: lambda x: isinstance(x, java.net.Inet4Address),
- AF_INET6: lambda x: isinstance(x, java.net.Inet6Address),
- AF_UNSPEC: lambda x: isinstance(x, java.net.InetAddress),
- }[family])
+ if _ipv4_addresses_only:
+ filter_fns.append( lambda x: isinstance(x, java.net.Inet4Address) )
+ else:
+ filter_fns.append({
+ AF_INET: lambda x: isinstance(x, java.net.Inet4Address),
+ AF_INET6: lambda x: isinstance(x, java.net.Inet6Address),
+ AF_UNSPEC: lambda x: isinstance(x, java.net.InetAddress),
+ }[family])
if host == "":
host = java.net.InetAddress.getLocalHost().getHostName()
passive_mode = flags is not None and flags & AI_PASSIVE
@@ -617,18 +634,16 @@
for a in java.net.InetAddress.getAllByName(host):
if len([f for f in filter_fns if f(a)]):
family = {java.net.Inet4Address: AF_INET, java.net.Inet6Address: AF_INET6}[a.getClass()]
- # bug 1697: exclude IPv6 addresses from being returned
- if family != AF_INET6:
- if passive_mode and not canonname_mode:
- canonname = ""
- else:
- canonname = asPyString(a.getCanonicalHostName())
- if host is None and passive_mode and not canonname_mode:
- sockname = INADDR_ANY
- else:
- sockname = asPyString(a.getHostAddress())
- # TODO: Include flowinfo and scopeid in a 4-tuple for IPv6 addresses
- results.append((family, socktype, proto, canonname, (sockname, port)))
+ if passive_mode and not canonname_mode:
+ canonname = ""
+ else:
+ canonname = asPyString(a.getCanonicalHostName())
+ if host is None and passive_mode and not canonname_mode:
+ sockname = INADDR_ANY
+ else:
+ sockname = asPyString(a.getHostAddress())
+ # TODO: Include flowinfo and scopeid in a 4-tuple for IPv6 addresses
+ results.append((family, socktype, proto, canonname, (sockname, port)))
return results
except java.lang.Exception, jlx:
raise _map_exception(jlx)
Modified: trunk/jython/Lib/test/test_socket.py
===================================================================
--- trunk/jython/Lib/test/test_socket.py 2011-01-23 15:58:55 UTC (rev 7190)
+++ trunk/jython/Lib/test/test_socket.py 2011-01-25 23:46:27 UTC (rev 7191)
@@ -1493,6 +1493,15 @@
self.failUnlessEqual(expected_canonname, canonname, "For hostname '%s' and flags %d, canonname '%s' != '%s'" % (host_param, flags, expected_canonname, canonname) )
self.failUnlessEqual(expected_sockaddr, sockaddr[0], "For hostname '%s' and flags %d, sockaddr '%s' != '%s'" % (host_param, flags, expected_sockaddr, sockaddr[0]) )
+ def testIPV4AddressesOnly(self):
+ socket._use_ipv4_addresses_only(True)
+ def doAddressTest(addrinfos):
+ for family, socktype, proto, canonname, sockaddr in addrinfos:
+ self.failIf(":" in sockaddr[0], "Incorrectly received IPv6 address '%s'" % (sockaddr[0]) )
+ doAddressTest(socket.getaddrinfo("localhost", 0, socket.AF_INET6, socket.SOCK_STREAM, 0, 0))
+ doAddressTest(socket.getaddrinfo("localhost", 0, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, 0))
+ socket._use_ipv4_addresses_only(False)
+
class TestExceptions(unittest.TestCase):
def testExceptionTree(self):
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|