From: <am...@us...> - 2008-09-13 14:10:15
|
Revision: 5322 http://jython.svn.sourceforge.net/jython/?rev=5322&view=rev Author: amak Date: 2008-09-13 14:10:12 +0000 (Sat, 13 Sep 2008) Log Message: ----------- Checking in fixes for 3 bugs http://bugs.jython.org/issue1119 - socket module has no attribute SO_ERROR http://bugs.jython.org/issue1120 - invalid socket shutdown gives AssertionError, should be "transport endpoint not connected" socket.error http://bugs.jython.org/issue1121 - listening socket shutdown expects the wrong kind of socket Will port fixes to trunk also. Modified Paths: -------------- branches/Release_2_2maint/jython/Lib/socket.py branches/Release_2_2maint/jython/Lib/test/test_socket.py Modified: branches/Release_2_2maint/jython/Lib/socket.py =================================================================== --- branches/Release_2_2maint/jython/Lib/socket.py 2008-09-11 20:18:43 UTC (rev 5321) +++ branches/Release_2_2maint/jython/Lib/socket.py 2008-09-13 14:10:12 UTC (rev 5322) @@ -145,7 +145,7 @@ __all__ = ['AF_UNSPEC', 'AF_INET', 'AF_INET6', 'AI_PASSIVE', 'SOCK_DGRAM', 'SOCK_RAW', 'SOCK_RDM', 'SOCK_SEQPACKET', 'SOCK_STREAM', 'SOL_SOCKET', - 'SO_BROADCAST', 'SO_KEEPALIVE', 'SO_LINGER', 'SO_OOBINLINE', + 'SO_BROADCAST', 'SO_ERROR', 'SO_KEEPALIVE', 'SO_LINGER', 'SO_OOBINLINE', 'SO_RCVBUF', 'SO_REUSEADDR', 'SO_SNDBUF', 'SO_TIMEOUT', 'TCP_NODELAY', 'SocketType', 'error', 'herror', 'gaierror', 'timeout', 'getfqdn', 'gethostbyaddr', 'gethostbyname', 'gethostname', @@ -179,6 +179,23 @@ TCP_NODELAY = 256 +# 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 + +SO_ACCEPTCONN = -1 +SO_DEBUG = -2 +SO_DONTROUTE = -4 +SO_ERROR = -8 +SO_EXCLUSIVEADDRUSE = -16 +SO_RCVLOWAT = -32 +SO_RCVTIMEO = -64 +SO_REUSEPORT = -128 +SO_SNDLOWAT = -256 +SO_SNDTIMEO = -512 +SO_TYPE = -1024 +SO_USELOOPBACK = -2048 + class _nio_impl: timeout = None @@ -236,12 +253,16 @@ def shutdownInput(self): try: self.jsocket.shutdownInput() + except AttributeError, ax: + raise error(errno.ENOTCONN, "Transport endpoint is not connected") except java.lang.Exception, jlx: raise _map_exception(jlx) def shutdownOutput(self): try: self.jsocket.shutdownOutput() + except AttributeError, ax: + raise error(errno.ENOTCONN, "Transport endpoint is not connected") except java.lang.Exception, jlx: raise _map_exception(jlx) @@ -786,8 +807,9 @@ raise _map_exception(jlx) def shutdown(self, how): + if not self.sock_impl: + raise error(errno.ENOTCONN, "Transport endpoint is not connected") assert how in (SHUT_RD, SHUT_WR, SHUT_RDWR) - assert self.sock_impl if how in (SHUT_RD, SHUT_RDWR): self.sock_impl.shutdownInput() if how in (SHUT_WR, SHUT_RDWR): Modified: branches/Release_2_2maint/jython/Lib/test/test_socket.py =================================================================== --- branches/Release_2_2maint/jython/Lib/test/test_socket.py 2008-09-11 20:18:43 UTC (rev 5321) +++ branches/Release_2_2maint/jython/Lib/test/test_socket.py 2008-09-13 14:10:12 UTC (rev 5322) @@ -1,5 +1,3 @@ -from __future__ import nested_scopes - """ AMAK: 20050515: This module is the test_socket.py from cpython 2.4, ported to jython. """ @@ -569,8 +567,10 @@ else: self.fail("Setting unsupported option should have raised an exception") +class TestSupportedOptions(TestSocketOptions): + def testSO_BROADCAST(self): - self.test_udp = 1 ; + self.test_udp = 1 self._testOption(socket.SO_BROADCAST, [0, 1]) def testSO_KEEPALIVE(self): @@ -614,28 +614,49 @@ self.test_tcp_client = 1 self._testOption(socket.TCP_NODELAY, [0, 1]) -class AsYetUnsupportedOptions: +class TestUnsupportedOptions(TestSocketOptions): - def testSO_ACCEPTCONN(self): pass - def testSO_DEBUG(self): pass - def testSO_DONTROUTE(self): pass - def testSO_ERROR(self): pass + def testSO_ACCEPTCONN(self): + self.failUnless(hasattr(socket, 'SO_ACCEPTCONN')) + + def testSO_DEBUG(self): + self.failUnless(hasattr(socket, 'SO_DEBUG')) + + def testSO_DONTROUTE(self): + self.failUnless(hasattr(socket, 'SO_DONTROUTE')) + + def testSO_ERROR(self): + self.failUnless(hasattr(socket, 'SO_ERROR')) + def testSO_EXCLUSIVEADDRUSE(self): # this is an MS specific option that will not be appearing on java # http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6421091 # http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6402335 - pass - def testSO_RCVLOWAT(self): pass - def testSO_RCVTIMEO(self): pass + self.failUnless(hasattr(socket, 'SO_EXCLUSIVEADDRUSE')) + + def testSO_RCVLOWAT(self): + self.failUnless(hasattr(socket, 'SO_RCVLOWAT')) + + def testSO_RCVTIMEO(self): + self.failUnless(hasattr(socket, 'SO_RCVTIMEO')) + def testSO_REUSEPORT(self): # not yet supported on java # http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6432031 - pass - def testSO_SNDLOWAT(self): pass - def testSO_SNDTIMEO(self): pass - def testSO_TYPE(self): pass - def testSO_USELOOPBACK(self): pass + self.failUnless(hasattr(socket, 'SO_REUSEPORT')) + def testSO_SNDLOWAT(self): + self.failUnless(hasattr(socket, 'SO_SNDLOWAT')) + + def testSO_SNDTIMEO(self): + self.failUnless(hasattr(socket, 'SO_SNDTIMEO')) + + def testSO_TYPE(self): + self.failUnless(hasattr(socket, 'SO_TYPE')) + + def testSO_USELOOPBACK(self): + self.failUnless(hasattr(socket, 'SO_USELOOPBACK')) + class BasicTCPTest(SocketConnectedTest): def __init__(self, methodName='runTest'): @@ -1436,14 +1457,42 @@ def setUp(self): self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +class TestInvalidUsage(unittest.TestCase): + + def setUp(self): + self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + + def testShutdownIOOnListener(self): + self.socket.listen() # socket is now a server socket + try: + self.socket.shutdown(socket.SHUT_RDWR) + except socket.error, se: + self.failUnlessEqual(se[0], errno.ENOTCONN, "Shutdown on listening socket should have raised errno.ENOTCONN, not %s" % str(se[0])) + except Exception, x: + self.fail("Shutdown on listening socket should have raised socket exception, not %s" % str(x)) + else: + self.fail("Shutdown on listening socket should have raised socket exception") + + def testShutdownOnUnconnectedSocket(self): + try: + self.socket.shutdown(socket.SHUT_RDWR) + except socket.error, se: + self.failUnlessEqual(se[0], errno.ENOTCONN, "Shutdown on unconnected socket should have raised errno.ENOTCONN, not %s" % str(se[0])) + except Exception, x: + self.fail("Shutdown on unconnected socket should have raised socket exception, not %s" % str(x)) + else: + self.fail("Shutdown on unconnected socket should have raised socket exception") + def test_main(): tests = [ GeneralModuleTests, - TestSocketOptions, + TestSupportedOptions, + TestUnsupportedOptions, BasicTCPTest, TCPTimeoutTest, TCPClientTimeoutTest, TestExceptions, + TestInvalidUsage, TestTCPAddressParameters, TestUDPAddressParameters, BasicUDPTest, @@ -1457,7 +1506,7 @@ PrivateFileObjectTestCase, UnbufferedFileObjectClassTestCase, LineBufferedFileObjectClassTestCase, - SmallBufferedFileObjectClassTestCase + SmallBufferedFileObjectClassTestCase, ] if hasattr(socket, "socketpair"): tests.append(BasicSocketPairTest) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <am...@us...> - 2008-09-13 18:37:33
|
Revision: 5326 http://jython.svn.sourceforge.net/jython/?rev=5326&view=rev Author: amak Date: 2008-09-13 18:37:31 +0000 (Sat, 13 Sep 2008) Log Message: ----------- Change of mind on behaviour when shutting down server sockets. Instead to raising an exception, best to let the failure pass silently, as cpython does. http://bugs.jython.org/issue1121 Modified Paths: -------------- branches/Release_2_2maint/jython/Lib/socket.py branches/Release_2_2maint/jython/Lib/test/test_socket.py Modified: branches/Release_2_2maint/jython/Lib/socket.py =================================================================== --- branches/Release_2_2maint/jython/Lib/socket.py 2008-09-13 18:31:07 UTC (rev 5325) +++ branches/Release_2_2maint/jython/Lib/socket.py 2008-09-13 18:37:31 UTC (rev 5326) @@ -254,7 +254,7 @@ try: self.jsocket.shutdownInput() except AttributeError, ax: - raise error(errno.ENOTCONN, "Transport endpoint is not connected") + pass # Fail silently server sockets except java.lang.Exception, jlx: raise _map_exception(jlx) @@ -262,7 +262,7 @@ try: self.jsocket.shutdownOutput() except AttributeError, ax: - raise error(errno.ENOTCONN, "Transport endpoint is not connected") + pass # Fail silently server sockets except java.lang.Exception, jlx: raise _map_exception(jlx) Modified: branches/Release_2_2maint/jython/Lib/test/test_socket.py =================================================================== --- branches/Release_2_2maint/jython/Lib/test/test_socket.py 2008-09-13 18:31:07 UTC (rev 5325) +++ branches/Release_2_2maint/jython/Lib/test/test_socket.py 2008-09-13 18:37:31 UTC (rev 5326) @@ -1466,12 +1466,10 @@ self.socket.listen() # socket is now a server socket try: self.socket.shutdown(socket.SHUT_RDWR) - except socket.error, se: - self.failUnlessEqual(se[0], errno.ENOTCONN, "Shutdown on listening socket should have raised errno.ENOTCONN, not %s" % str(se[0])) except Exception, x: - self.fail("Shutdown on listening socket should have raised socket exception, not %s" % str(x)) + self.fail("Shutdown on listening socket should not have raised socket exception, not %s" % str(x)) else: - self.fail("Shutdown on listening socket should have raised socket exception") + pass def testShutdownOnUnconnectedSocket(self): try: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <am...@us...> - 2008-10-18 19:03:47
|
Revision: 5461 http://jython.svn.sourceforge.net/jython/?rev=5461&view=rev Author: amak Date: 2008-10-18 19:03:40 +0000 (Sat, 18 Oct 2008) Log Message: ----------- 1. Fixed a bug whereby timeouts were not being honoured when recv()ing (http://bugs.jython.com/issue1154) 2. Fixed another (previously unreported) bug that resulted in an exception when switching from non-blocking to timeout mode. 3. Back-ported some of pjenvey's changes relating to getaddrinfo, non-blocking connects and file buffer sizes. Modified Paths: -------------- branches/Release_2_2maint/jython/Lib/socket.py branches/Release_2_2maint/jython/Lib/test/test_socket.py Modified: branches/Release_2_2maint/jython/Lib/socket.py =================================================================== --- branches/Release_2_2maint/jython/Lib/socket.py 2008-10-18 01:58:29 UTC (rev 5460) +++ branches/Release_2_2maint/jython/Lib/socket.py 2008-10-18 19:03:40 UTC (rev 5461) @@ -6,8 +6,6 @@ XXX Restrictions: - Only INET sockets -- No asynchronous behavior -- No socket options - Can't do a very good gethostbyaddr() right... AMAK: 20050527: added socket timeouts AMAK: 20070515: Added non-blocking (asynchronous) support @@ -201,16 +199,6 @@ timeout = None mode = MODE_BLOCKING - def read(self, buf): - bytebuf = java.nio.ByteBuffer.wrap(buf) - count = self.jchannel.read(bytebuf) - return count - - def write(self, buf): - bytebuf = java.nio.ByteBuffer.wrap(buf) - count = self.jchannel.write(bytebuf) - return count - def getpeername(self): return (self.jsocket.getInetAddress().getHostName(), self.jsocket.getPort() ) @@ -221,6 +209,7 @@ if self.mode == MODE_NONBLOCKING: self.jchannel.configureBlocking(0) if self.mode == MODE_TIMEOUT: + self.jchannel.configureBlocking(1) self._timeout_millis = int(timeout*1000) self.jsocket.setSoTimeout(self._timeout_millis) @@ -310,6 +299,36 @@ def finish_connect(self): return self.jchannel.finishConnect() + def _do_read_net(self, buf): + # Need two separate implementations because the java.nio APIs do not support timeouts + return self.jsocket.getInputStream().read(buf) + + def _do_read_nio(self, buf): + bytebuf = java.nio.ByteBuffer.wrap(buf) + count = self.jchannel.read(bytebuf) + return count + + def _do_write_net(self, buf): + self.jsocket.getOutputStream().write(buf) + return len(buf) + + def _do_write_nio(self, buf): + bytebuf = java.nio.ByteBuffer.wrap(buf) + count = self.jchannel.write(bytebuf) + return count + + def read(self, buf): + if self.mode == MODE_TIMEOUT: + return self._do_read_net(buf) + else: + return self._do_read_nio(buf) + + def write(self, buf): + if self.mode == MODE_TIMEOUT: + return self._do_write_net(buf) + else: + return self._do_write_nio(buf) + class _server_socket_impl(_nio_impl): options = { @@ -515,10 +534,10 @@ else: return _udpsocket() -def getaddrinfo(host, port, family=None, socktype=None, proto=0, flags=None): +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 NotSupportedError() + raise gaierror(errno.EIO, 'ai_family not supported') filter_fns = [] filter_fns.append({ AF_INET: lambda x: isinstance(x, java.net.Inet4Address), @@ -736,9 +755,12 @@ def connect_ex(self, addr): "This signifies a client socket" - self._do_connect(addr) + if not self.sock_impl: + self._do_connect(addr) if self.sock_impl.finish_connect(): self._setup() + if self.mode == MODE_NONBLOCKING: + return errno.EISCONN return 0 return errno.EINPROGRESS @@ -775,6 +797,8 @@ if self.sock_impl.jchannel.isConnectionPending(): self.sock_impl.jchannel.finishConnect() numwritten = self.sock_impl.write(s) + if numwritten == 0 and self.mode == MODE_NONBLOCKING: + raise would_block_error() return numwritten except java.lang.Exception, jlx: raise _map_exception(jlx) @@ -861,8 +885,11 @@ self._do_connect(addr) def connect_ex(self, addr): - self._do_connect(addr) + if not self.sock_impl: + self._do_connect(addr) if self.sock_impl.finish_connect(): + if self.mode == MODE_NONBLOCKING: + return errno.EISCONN return 0 return errno.EINPROGRESS @@ -1151,7 +1178,7 @@ self._rbuf = "" while True: left = size - buf_len - recv_size = max(self._rbufsize, left) + recv_size = min(self._rbufsize, left) data = self._sock.recv(recv_size) if not data: break Modified: branches/Release_2_2maint/jython/Lib/test/test_socket.py =================================================================== --- branches/Release_2_2maint/jython/Lib/test/test_socket.py 2008-10-18 01:58:29 UTC (rev 5460) +++ branches/Release_2_2maint/jython/Lib/test/test_socket.py 2008-10-18 19:03:40 UTC (rev 5461) @@ -292,6 +292,22 @@ if not fqhn in all_host_names: self.fail("Error testing host resolution mechanisms.") + def testGetAddrInfo(self): + try: + socket.getaddrinfo(HOST, PORT, 9999) + except socket.gaierror, gaix: + self.failUnlessEqual(gaix[0], errno.EIO) + except Exception, x: + self.fail("getaddrinfo with bad family raised wrong exception: %s" % x) + else: + self.fail("getaddrinfo with bad family should have raised exception") + + addrinfos = socket.getaddrinfo(HOST, PORT) + for addrinfo in addrinfos: + family, socktype, proto, canonname, sockaddr = addrinfo + self.assert_(isinstance(canonname, str)) + self.assert_(isinstance(sockaddr[0], str)) + def testRefCountGetNameInfo(self): # Testing reference count for getnameinfo import sys @@ -670,6 +686,16 @@ def _testRecv(self): self.serv_conn.send(MSG) + def testRecvTimeoutMode(self): + # Do this test in timeout mode, because the code path is different + self.cli_conn.settimeout(10) + msg = self.cli_conn.recv(1024) + self.assertEqual(msg, MSG) + + def _testRecvTimeoutMode(self): + self.serv_conn.settimeout(10) + self.serv_conn.send(MSG) + def testOverFlowRecv(self): # Testing receive in chunks over TCP seg1 = self.cli_conn.recv(len(MSG) - 3) @@ -1226,14 +1252,14 @@ bufsize = 2 # Exercise the buffering code -class TCPTimeoutTest(SocketTCPTest): +class TCPServerTimeoutTest(SocketTCPTest): - def testTCPTimeout(self): + def testAcceptTimeout(self): def raise_timeout(*args, **kwargs): self.serv.settimeout(1.0) self.serv.accept() self.failUnlessRaises(socket.timeout, raise_timeout, - "Error generating a timeout exception (TCP)") + "TCP socket accept failed to generate a timeout exception (TCP)") def testTimeoutZero(self): ok = False @@ -1249,9 +1275,9 @@ if not ok: self.fail("accept() returned success when we did not expect it") -class TCPClientTimeoutTest(unittest.TestCase): +class TCPClientTimeoutTest(SocketTCPTest): - def testClientTimeout(self): + def testConnectTimeout(self): cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM) cli.settimeout(0.1) host = '192.168.192.168' @@ -1266,8 +1292,45 @@ socket.timeout. This tries to connect to %s in the assumption that it isn't used, but if it is on your network this failure is bogus.''' % host) - + def testRecvTimeout(self): + def raise_timeout(*args, **kwargs): + cli_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + cli_sock.connect( (HOST, PORT) ) + cli_sock.settimeout(1) + cli_sock.recv(1024) + self.failUnlessRaises(socket.timeout, raise_timeout, + "TCP socket recv failed to generate a timeout exception (TCP)") + # Disable this test, but leave it present for documentation purposes + # socket timeouts only work for read and accept, not for write + # http://java.sun.com/j2se/1.4.2/docs/api/java/net/SocketTimeoutException.html + def estSendTimeout(self): + def raise_timeout(*args, **kwargs): + cli_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + cli_sock.connect( (HOST, PORT) ) + # First fill the socket + cli_sock.settimeout(1) + sent = 0 + while True: + bytes_sent = cli_sock.send(MSG) + sent += bytes_sent + self.failUnlessRaises(socket.timeout, raise_timeout, + "TCP socket send failed to generate a timeout exception (TCP)") + + def testSwitchModes(self): + cli_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + cli_sock.connect( (HOST, PORT) ) + # set non-blocking mode + cli_sock.setblocking(0) + # then set timeout mode + cli_sock.settimeout(1) + try: + cli_sock.send(MSG) + except Exception, x: + self.fail("Switching mode from non-blocking to timeout raised exception: %s" % x) + else: + pass + # # AMAK: 20070307 # Corrected the superclass of UDPTimeoutTest @@ -1487,7 +1550,7 @@ TestSupportedOptions, TestUnsupportedOptions, BasicTCPTest, - TCPTimeoutTest, + TCPServerTimeoutTest, TCPClientTimeoutTest, TestExceptions, TestInvalidUsage, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <am...@us...> - 2008-10-27 17:02:53
|
Revision: 5520 http://jython.svn.sourceforge.net/jython/?rev=5520&view=rev Author: amak Date: 2008-10-27 17:02:39 +0000 (Mon, 27 Oct 2008) Log Message: ----------- Adding support for address manipulation functions inet_pton, inet_ntop, inet_aton and inet_ntoa. Modified Paths: -------------- branches/Release_2_2maint/jython/Lib/socket.py branches/Release_2_2maint/jython/Lib/test/test_socket.py Modified: branches/Release_2_2maint/jython/Lib/socket.py =================================================================== --- branches/Release_2_2maint/jython/Lib/socket.py 2008-10-27 15:11:18 UTC (rev 5519) +++ branches/Release_2_2maint/jython/Lib/socket.py 2008-10-27 17:02:39 UTC (rev 5520) @@ -588,6 +588,33 @@ def ntohs(x): return x def ntohl(x): return x +def inet_pton(family, ip_string): + try: + ia = java.net.InetAddress.getByName(ip_string) + bytes = [] + for byte in ia.getAddress(): + if byte < 0: + bytes.append(byte+256) + else: + bytes.append(byte) + return "".join([chr(byte) for byte in bytes]) + except java.lang.Exception, jlx: + raise _map_exception(jlx) + +def inet_ntop(family, packed_ip): + try: + jByteArray = jarray.array(packed_ip, 'b') + ia = java.net.InetAddress.getByAddress(jByteArray) + return ia.getHostAddress() + except java.lang.Exception, jlx: + raise _map_exception(jlx) + +def inet_aton(ip_string): + return inet_pton(AF_INET, ip_string) + +def inet_ntoa(packed_ip): + return inet_ntop(AF_INET, packed_ip) + class _nonblocking_api_mixin: timeout = _defaulttimeout Modified: branches/Release_2_2maint/jython/Lib/test/test_socket.py =================================================================== --- branches/Release_2_2maint/jython/Lib/test/test_socket.py 2008-10-27 15:11:18 UTC (rev 5519) +++ branches/Release_2_2maint/jython/Lib/test/test_socket.py 2008-10-27 17:02:39 UTC (rev 5520) @@ -471,8 +471,11 @@ return f = lambda a: inet_ntop(AF_INET6, a) - self.assertEquals('::', f('\x00' * 16)) - self.assertEquals('::1', f('\x00' * 15 + '\x01')) +# self.assertEquals('::', f('\x00' * 16)) +# self.assertEquals('::1', f('\x00' * 15 + '\x01')) + # java.net.InetAddress always return the full unabbreviated form + self.assertEquals('0:0:0:0:0:0:0:0', f('\x00' * 16)) + self.assertEquals('0:0:0:0:0:0:0:1', f('\x00' * 15 + '\x01')) self.assertEquals( 'aef:b01:506:1001:ffff:9997:55:170', f('\x0a\xef\x0b\x01\x05\x06\x10\x01\xff\xff\x99\x97\x00\x55\x01\x70') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <am...@us...> - 2008-12-18 17:43:39
|
Revision: 5777 http://jython.svn.sourceforge.net/jython/?rev=5777&view=rev Author: amak Date: 2008-12-18 17:43:35 +0000 (Thu, 18 Dec 2008) Log Message: ----------- Restoring an important line that got lost back r3251, which checked if the object passed to _getselectable() was actually already a SelectableChannel. Added unit test to explicitly check for same. This was illustrated by a failure in the telnetlib module, as reported in http://bugs.jython.org/issue1211 Modified Paths: -------------- branches/Release_2_2maint/jython/Lib/select.py branches/Release_2_2maint/jython/Lib/test/test_select.py Modified: branches/Release_2_2maint/jython/Lib/select.py =================================================================== --- branches/Release_2_2maint/jython/Lib/select.py 2008-12-18 11:05:16 UTC (rev 5776) +++ branches/Release_2_2maint/jython/Lib/select.py 2008-12-18 17:43:35 UTC (rev 5777) @@ -43,6 +43,8 @@ POLLNVAL = 32 def _getselectable(selectable_object): + if isinstance(selectable_object, java.nio.channels.SelectableChannel): + return selectable_object for method in ['getchannel', 'fileno']: try: channel = getattr(selectable_object, method)() Modified: branches/Release_2_2maint/jython/Lib/test/test_select.py =================================================================== --- branches/Release_2_2maint/jython/Lib/test/test_select.py 2008-12-18 11:05:16 UTC (rev 5776) +++ branches/Release_2_2maint/jython/Lib/test/test_select.py 2008-12-18 17:43:35 UTC (rev 5777) @@ -181,6 +181,17 @@ else: self.fail("Registering blocking socket should have raised select.error") + def testSelectOnSocketFileno(self): + self.cli_conn = self.serv.accept() + + def _testSelectOnSocketFileno(self): + self.cli.connect( (test_socket.HOST, test_socket.PORT) ) + self.cli.setblocking(0) + try: + rfd, wfd, xfd = select.select([self.cli.fileno()], [], [], 1) + except Exception, x: + self.fail("Selecting on socket.fileno() should not have raised exception: %s" % str(x)) + class TestPipes(unittest.TestCase): verbose = 1 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <am...@us...> - 2009-01-05 19:58:55
|
Revision: 5855 http://jython.svn.sourceforge.net/jython/?rev=5855&view=rev Author: amak Date: 2009-01-05 19:58:51 +0000 (Mon, 05 Jan 2009) Log Message: ----------- Fixed a bug where connect timeouts were not being honoured when set through socket.setdefaulttimeout() http://bugs.jython.org/issue1218 Modified Paths: -------------- branches/Release_2_2maint/jython/Lib/socket.py branches/Release_2_2maint/jython/Lib/test/test_socket.py Modified: branches/Release_2_2maint/jython/Lib/socket.py =================================================================== --- branches/Release_2_2maint/jython/Lib/socket.py 2009-01-05 19:47:25 UTC (rev 5854) +++ branches/Release_2_2maint/jython/Lib/socket.py 2009-01-05 19:58:51 UTC (rev 5855) @@ -617,12 +617,14 @@ class _nonblocking_api_mixin: - timeout = _defaulttimeout mode = MODE_BLOCKING reference_count = 0 close_lock = threading.Lock() def __init__(self): + self.timeout = _defaulttimeout + if self.timeout is not None: + self.mode = MODE_TIMEOUT self.pending_options = { SO_REUSEADDR: 0, } Modified: branches/Release_2_2maint/jython/Lib/test/test_socket.py =================================================================== --- branches/Release_2_2maint/jython/Lib/test/test_socket.py 2009-01-05 19:47:25 UTC (rev 5854) +++ branches/Release_2_2maint/jython/Lib/test/test_socket.py 2009-01-05 19:58:51 UTC (rev 5855) @@ -1295,6 +1295,23 @@ socket.timeout. This tries to connect to %s in the assumption that it isn't used, but if it is on your network this failure is bogus.''' % host) + def testConnectDefaultTimeout(self): + _saved_timeout = socket.getdefaulttimeout() + socket.setdefaulttimeout(0.1) + cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + host = '192.168.192.168' + try: + cli.connect((host, 5000)) + except socket.timeout, st: + pass + except Exception, x: + self.fail("Client socket timeout should have raised socket.timeout, not %s" % str(x)) + else: + self.fail('''Client socket timeout should have raised +socket.timeout. This tries to connect to %s in the assumption that it isn't +used, but if it is on your network this failure is bogus.''' % host) + socket.setdefaulttimeout(_saved_timeout) + def testRecvTimeout(self): def raise_timeout(*args, **kwargs): cli_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <am...@us...> - 2009-01-28 16:26:20
|
Revision: 5993 http://jython.svn.sourceforge.net/jython/?rev=5993&view=rev Author: amak Date: 2009-01-28 16:26:16 +0000 (Wed, 28 Jan 2009) Log Message: ----------- Fix and unit test for bug 1244. Problem letting system choose the port for binding UDP socket http://bugs.jython.org/issue1244 Modified Paths: -------------- branches/Release_2_2maint/jython/Lib/socket.py branches/Release_2_2maint/jython/Lib/test/test_socket.py Modified: branches/Release_2_2maint/jython/Lib/socket.py =================================================================== --- branches/Release_2_2maint/jython/Lib/socket.py 2009-01-28 16:05:59 UTC (rev 5992) +++ branches/Release_2_2maint/jython/Lib/socket.py 2009-01-28 16:26:16 UTC (rev 5993) @@ -372,7 +372,7 @@ def __init__(self, port=None, address=None, reuse_addr=0): self.jchannel = java.nio.channels.DatagramChannel.open() self.jsocket = self.jchannel.socket() - if port: + if port is not None: if address is not None: local_address = java.net.InetSocketAddress(address, port) else: Modified: branches/Release_2_2maint/jython/Lib/test/test_socket.py =================================================================== --- branches/Release_2_2maint/jython/Lib/test/test_socket.py 2009-01-28 16:05:59 UTC (rev 5992) +++ branches/Release_2_2maint/jython/Lib/test/test_socket.py 2009-01-28 16:26:16 UTC (rev 5993) @@ -789,6 +789,21 @@ self.serv_conn.send(MSG) self.serv_conn.send('and ' + MSG) +class UDPBindTest(unittest.TestCase): + + HOST = HOST + PORT = PORT + + def setUp(self): + self.sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) + + def testBindEphemeral(self): + self.sock.bind( (self.HOST, 0) ) # let system choose a free port + self.failUnless(self.sock.getsockname()[1] != 0, "Binding to port zero should have allocated an ephemeral port number") + + def tearDown(self): + self.sock.close() + class BasicUDPTest(ThreadedUDPSocketTest): def __init__(self, methodName='runTest'): @@ -1576,6 +1591,7 @@ TestInvalidUsage, TestTCPAddressParameters, TestUDPAddressParameters, + UDPBindTest, BasicUDPTest, UDPTimeoutTest, NonBlockingTCPTests, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <am...@us...> - 2009-01-29 17:41:07
|
Revision: 6000 http://jython.svn.sourceforge.net/jython/?rev=6000&view=rev Author: amak Date: 2009-01-29 17:41:00 +0000 (Thu, 29 Jan 2009) Log Message: ----------- Re-arranging the socket shutdown methods. TCP client sockets can shutdown their input streams, but this is not appropriate for either TCP server sockets or UDP sockets, which don't have input and output streams. For these latter two types, the shutdown method should have the same effect as the close method, and thus the shutdown method is a no-op for these types. I have documented this difference between cpython and jython on the wiki. This should finally resolve bug 1121: listening socket shutdown expects the wrong kind of socket http://bugs.jython.org/issue1121 Modified Paths: -------------- branches/Release_2_2maint/jython/Lib/socket.py branches/Release_2_2maint/jython/Lib/test/test_socket.py Modified: branches/Release_2_2maint/jython/Lib/socket.py =================================================================== --- branches/Release_2_2maint/jython/Lib/socket.py 2009-01-29 14:24:33 UTC (rev 5999) +++ branches/Release_2_2maint/jython/Lib/socket.py 2009-01-29 17:41:00 UTC (rev 6000) @@ -239,22 +239,6 @@ def close(self): self.jsocket.close() - def shutdownInput(self): - try: - self.jsocket.shutdownInput() - except AttributeError, ax: - pass # Fail silently server sockets - except java.lang.Exception, jlx: - raise _map_exception(jlx) - - def shutdownOutput(self): - try: - self.jsocket.shutdownOutput() - except AttributeError, ax: - pass # Fail silently server sockets - except java.lang.Exception, jlx: - raise _map_exception(jlx) - def getchannel(self): return self.jchannel @@ -329,6 +313,12 @@ else: return self._do_write_nio(buf) + def shutdown(self, how): + if how in (SHUT_RD, SHUT_RDWR): + self.jsocket.shutdownInput() + if how in (SHUT_WR, SHUT_RDWR): + self.jsocket.shutdownOutput() + class _server_socket_impl(_nio_impl): options = { @@ -359,6 +349,13 @@ new_cli_sock = self.jsocket.accept() return _client_socket_impl(new_cli_sock) + def shutdown(self, how): + # This is no-op on java, for server sockets. + # What the user wants to achieve is achieved by calling close() on + # java/jython. But we can't call that here because that would then + # later cause the user explicit close() call to fail + pass + class _datagram_socket_impl(_nio_impl): options = { @@ -393,6 +390,13 @@ """ self.jchannel.disconnect() + def shutdown(self, how): + # This is no-op on java, for datagram sockets. + # What the user wants to achieve is achieved by calling close() on + # java/jython. But we can't call that here because that would then + # later cause the user explicit close() call to fail + pass + def _do_send_net(self, byte_array, socket_address, flags): # Need two separate implementations because the java.nio APIs do not support timeouts num_bytes = len(byte_array) @@ -674,6 +678,22 @@ except java.lang.Exception, jlx: raise _map_exception(jlx) + def shutdown(self, how): + assert how in (SHUT_RD, SHUT_WR, SHUT_RDWR) + if not self.sock_impl: + raise error(errno.ENOTCONN, "Transport endpoint is not connected") + try: + self.sock_impl.shutdown(how) + except java.lang.Exception, jlx: + raise _map_exception(jlx) + + def close(self): + try: + if self.sock_impl: + self.sock_impl.close() + except java.lang.Exception, jlx: + raise _map_exception(jlx) + def _config(self): assert self.mode in _permitted_modes if self.sock_impl: @@ -859,15 +879,6 @@ except java.lang.Exception, jlx: raise _map_exception(jlx) - def shutdown(self, how): - if not self.sock_impl: - raise error(errno.ENOTCONN, "Transport endpoint is not connected") - assert how in (SHUT_RD, SHUT_WR, SHUT_RDWR) - if how in (SHUT_RD, SHUT_RDWR): - self.sock_impl.shutdownInput() - if how in (SHUT_WR, SHUT_RDWR): - self.sock_impl.shutdownOutput() - def close(self): try: if self.istream: @@ -877,8 +888,7 @@ if self.sock_impl: self.sock_impl.close() except java.lang.Exception, jlx: - raise _map_exception(jlx) - + raise _map_exception(jlx) class _udpsocket(_nonblocking_api_mixin): @@ -991,14 +1001,7 @@ def __del__(self): self.close() - - def close(self): - try: - if self.sock_impl: - self.sock_impl.close() - except java.lang.Exception, jlx: - raise _map_exception(jlx) - + _socketmethods = ( 'bind', 'connect', 'connect_ex', 'fileno', 'listen', 'getpeername', 'getsockname', 'getsockopt', 'setsockopt', Modified: branches/Release_2_2maint/jython/Lib/test/test_socket.py =================================================================== --- branches/Release_2_2maint/jython/Lib/test/test_socket.py 2009-01-29 14:24:33 UTC (rev 5999) +++ branches/Release_2_2maint/jython/Lib/test/test_socket.py 2009-01-29 17:41:00 UTC (rev 6000) @@ -797,10 +797,20 @@ def setUp(self): self.sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) + def testBindSpecific(self): + self.sock.bind( (self.HOST, self.PORT) ) # Use a specific port + actual_port = self.sock.getsockname()[1] + self.failUnless(actual_port == self.PORT, + "Binding to specific port number should have returned same number: %d != %d" % (actual_port, self.PORT)) + def testBindEphemeral(self): self.sock.bind( (self.HOST, 0) ) # let system choose a free port self.failUnless(self.sock.getsockname()[1] != 0, "Binding to port zero should have allocated an ephemeral port number") + def testShutdown(self): + self.sock.bind( (self.HOST, self.PORT) ) + self.sock.shutdown(socket.SHUT_RDWR) + def tearDown(self): self.sock.close() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <am...@us...> - 2009-01-29 20:51:24
|
Revision: 6002 http://jython.svn.sourceforge.net/jython/?rev=6002&view=rev Author: amak Date: 2009-01-29 20:51:21 +0000 (Thu, 29 Jan 2009) Log Message: ----------- Back-porting changes relating to UDP broadcast. Also back-porting some variable scoping changes to the test_socket module. Modified Paths: -------------- branches/Release_2_2maint/jython/Lib/socket.py branches/Release_2_2maint/jython/Lib/test/test_socket.py Modified: branches/Release_2_2maint/jython/Lib/socket.py =================================================================== --- branches/Release_2_2maint/jython/Lib/socket.py 2009-01-29 17:59:04 UTC (rev 6001) +++ branches/Release_2_2maint/jython/Lib/socket.py 2009-01-29 20:51:21 UTC (rev 6002) @@ -177,6 +177,9 @@ TCP_NODELAY = 256 +INADDR_ANY = "0.0.0.0" +INADDR_BROADCAST = "255.255.255.255" + # 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 @@ -712,7 +715,7 @@ def _get_jsocket(self): return self.sock_impl.jsocket -def _unpack_address_tuple(address_tuple, for_tx=False): +def _unpack_address_tuple(address_tuple): # TODO: Upgrade to support the 4-tuples used for IPv6 addresses # which include flowinfo and scope_id. # To be upgraded in synch with getaddrinfo @@ -722,11 +725,6 @@ or type(address_tuple[1]) is not type(0): raise TypeError(error_message) hostname = address_tuple[0].strip() - if hostname == "<broadcast>": - if for_tx: - hostname = "255.255.255.255" - else: - hostname = "0.0.0.0" return hostname, address_tuple[1] class _tcpsocket(_nonblocking_api_mixin): @@ -902,6 +900,8 @@ try: assert not self.sock_impl host, port = _unpack_address_tuple(addr) + if host == "": + host = INADDR_ANY host_address = java.net.InetAddress.getByName(host) self.sock_impl = _datagram_socket_impl(port, host_address, self.pending_options[SO_REUSEADDR]) self._config() @@ -941,7 +941,9 @@ if not self.sock_impl: self.sock_impl = _datagram_socket_impl() self._config() - host, port = _unpack_address_tuple(addr, True) + host, port = _unpack_address_tuple(addr) + if host == "<broadcast>": + host = INADDR_BROADCAST byte_array = java.lang.String(data).getBytes('iso-8859-1') result = self.sock_impl.sendto(byte_array, host, port, flags) return result Modified: branches/Release_2_2maint/jython/Lib/test/test_socket.py =================================================================== --- branches/Release_2_2maint/jython/Lib/test/test_socket.py 2009-01-29 17:59:04 UTC (rev 6001) +++ branches/Release_2_2maint/jython/Lib/test/test_socket.py 2009-01-29 20:51:21 UTC (rev 6002) @@ -28,10 +28,13 @@ class SocketTCPTest(unittest.TestCase): + HOST = HOST + PORT = PORT + def setUp(self): self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - self.serv.bind((HOST, PORT)) + self.serv.bind((self.HOST, self.PORT)) self.serv.listen(1) def tearDown(self): @@ -40,10 +43,13 @@ class SocketUDPTest(unittest.TestCase): + HOST = HOST + PORT = PORT + def setUp(self): self.serv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - self.serv.bind((HOST, PORT)) + self.serv.bind((self.HOST, self.PORT)) def tearDown(self): self.serv.close() @@ -196,7 +202,7 @@ def clientSetUp(self): ThreadedTCPSocketTest.clientSetUp(self) - self.cli.connect((HOST, PORT)) + self.cli.connect((self.HOST, self.PORT)) self.serv_conn = self.cli def clientTearDown(self): @@ -540,7 +546,7 @@ # First listen on a server socket, so that the connection won't be refused. server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_sock.bind( (HOST, PORT) ) - server_sock.listen() + server_sock.listen(50) # Now do the tests sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._testSetAndGetOption(sock, option, values) @@ -561,7 +567,7 @@ self._testSetAndGetOption(sock, option, values) # now bind and listen on the socket i.e. cause the implementation socket to be created sock.bind( (HOST, PORT) ) - sock.listen() + sock.listen(50) self.failUnlessEqual(sock.getsockopt(socket.SOL_SOCKET, option), values[-1], \ "Option value '%s'='%s' did not propagate to implementation socket" % (option, values[-1])) self._testSetAndGetOption(sock, option, values) @@ -825,7 +831,7 @@ self.assertEqual(msg, MSG) def _testSendtoAndRecv(self): - self.cli.sendto(MSG, 0, (HOST, PORT)) + self.cli.sendto(MSG, 0, (self.HOST, self.PORT)) def testSendtoAndRecvTimeoutMode(self): # Need to test again in timeout mode, which follows @@ -836,7 +842,7 @@ def _testSendtoAndRecvTimeoutMode(self): self.cli.settimeout(10) - self.cli.sendto(MSG, 0, (HOST, PORT)) + self.cli.sendto(MSG, 0, (self.HOST, self.PORT)) def testRecvFrom(self): # Testing recvfrom() over UDP @@ -844,7 +850,7 @@ self.assertEqual(msg, MSG) def _testRecvFrom(self): - self.cli.sendto(MSG, 0, (HOST, PORT)) + self.cli.sendto(MSG, 0, (self.HOST, self.PORT)) def testRecvFromTimeoutMode(self): # Need to test again in timeout mode, which follows @@ -855,7 +861,7 @@ def _testRecvFromTimeoutMode(self): self.cli.settimeout(10) - self.cli.sendto(MSG, 0, (HOST, PORT)) + self.cli.sendto(MSG, 0, (self.HOST, self.PORT)) def testSendtoEightBitSafe(self): # This test is necessary because java only supports signed bytes @@ -863,7 +869,7 @@ self.assertEqual(msg, EIGHT_BIT_MSG) def _testSendtoEightBitSafe(self): - self.cli.sendto(EIGHT_BIT_MSG, 0, (HOST, PORT)) + self.cli.sendto(EIGHT_BIT_MSG, 0, (self.HOST, self.PORT)) def testSendtoEightBitSafeTimeoutMode(self): # Need to test again in timeout mode, which follows @@ -874,7 +880,7 @@ def _testSendtoEightBitSafeTimeoutMode(self): self.cli.settimeout(10) - self.cli.sendto(EIGHT_BIT_MSG, 0, (HOST, PORT)) + self.cli.sendto(EIGHT_BIT_MSG, 0, (self.HOST, self.PORT)) class UDPBroadcastTest(ThreadedUDPSocketTest): @@ -883,13 +889,13 @@ self.serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) def testBroadcast(self): - self.serv.bind( ("<broadcast>", PORT) ) + self.serv.bind( ("", self.PORT) ) msg = self.serv.recv(len(EIGHT_BIT_MSG)) self.assertEqual(msg, EIGHT_BIT_MSG) def _testBroadcast(self): self.cli.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) - self.cli.sendto(EIGHT_BIT_MSG, ("<broadcast>", PORT) ) + self.cli.sendto(EIGHT_BIT_MSG, ("<broadcast>", self.PORT) ) class BasicSocketPairTest(SocketPairTest): @@ -956,7 +962,7 @@ def _testAcceptConnection(self): # Make a connection to the server - self.cli.connect((HOST, PORT)) + self.cli.connect((self.HOST, self.PORT)) # # AMAK: 20070311 @@ -971,7 +977,7 @@ def _testBlockingConnect(self): # Testing blocking connect self.cli.settimeout(10) - self.cli.connect((HOST, PORT)) + self.cli.connect((self.HOST, self.PORT)) def testNonBlockingConnect(self): # Testing non-blocking connect @@ -980,7 +986,7 @@ def _testNonBlockingConnect(self): # Testing non-blocking connect self.cli.setblocking(0) - result = self.cli.connect_ex((HOST, PORT)) + result = self.cli.connect_ex((self.HOST, self.PORT)) rfds, wfds, xfds = select.select([], [self.cli], []) self.failUnless(self.cli in wfds) try: @@ -999,13 +1005,13 @@ def _testConnectWithLocalBind(self): # Testing blocking connect with local bind - cli_port = PORT - 1 + cli_port = self.PORT - 1 while True: # Keep trying until a local port is available self.cli.settimeout(1) - self.cli.bind( (HOST, cli_port) ) + self.cli.bind( (self.HOST, cli_port) ) try: - self.cli.connect((HOST, PORT)) + self.cli.connect((self.HOST, self.PORT)) break except socket.error, se: # cli_port is in use (maybe in TIME_WAIT state from a @@ -1033,7 +1039,7 @@ self.fail("Non-blocking socket with data should been in read list.") def _testRecvData(self): - self.cli.connect((HOST, PORT)) + self.cli.connect((self.HOST, self.PORT)) self.cli.send(MSG) def testRecvNoData(self): @@ -1048,7 +1054,7 @@ self.fail("Non-blocking recv of no data should have raised socket.error.") def _testRecvNoData(self): - self.cli.connect((HOST, PORT)) + self.cli.connect((self.HOST, self.PORT)) time.sleep(0.1) class NonBlockingUDPTests(ThreadedUDPSocketTest): pass @@ -1096,7 +1102,7 @@ self.cli_file = self.cli.makefile('wb') self.cli_file.close() try: - self.cli.sendto(MSG, 0, (HOST, PORT)) + self.cli.sendto(MSG, 0, (self.HOST, self.PORT)) except Exception, x: self.fail("Closing file wrapper appears to have closed underlying socket: %s" % str(x)) @@ -1108,7 +1114,7 @@ def _testCloseSocketDoesNotCloseFile(self): try: - self.cli.sendto(MSG, 0, (HOST, PORT)) + self.cli.sendto(MSG, 0, (self.HOST, self.PORT)) except Exception, x: self.fail("Closing file wrapper appears to have closed underlying socket: %s" % str(x)) @@ -1496,12 +1502,12 @@ def testBindException(self): # First bind to the target port self.s.bind( (HOST, PORT) ) - self.s.listen() + self.s.listen(50) try: # And then try to bind again t = socket.socket(socket.AF_INET, socket.SOCK_STREAM) t.bind( (HOST, PORT) ) - t.listen() + t.listen(50) except socket.error, se: self.failUnlessEqual(se[0], errno.EADDRINUSE) except Exception, x: @@ -1571,7 +1577,7 @@ self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) def testShutdownIOOnListener(self): - self.socket.listen() # socket is now a server socket + self.socket.listen(50) # socket is now a server socket try: self.socket.shutdown(socket.SHUT_RDWR) except Exception, x: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <am...@us...> - 2009-05-20 15:09:54
|
Revision: 6360 http://jython.svn.sourceforge.net/jython/?rev=6360&view=rev Author: amak Date: 2009-05-20 15:09:43 +0000 (Wed, 20 May 2009) Log Message: ----------- Backporting changes from trunk. 1. Socket options are now level specific 2. Explicit backlog parameter on listen 3. Setting has_ipv6 to False Modified Paths: -------------- branches/Release_2_2maint/jython/Lib/socket.py branches/Release_2_2maint/jython/Lib/test/test_socket.py Modified: branches/Release_2_2maint/jython/Lib/socket.py =================================================================== --- branches/Release_2_2maint/jython/Lib/socket.py 2009-05-20 06:09:43 UTC (rev 6359) +++ branches/Release_2_2maint/jython/Lib/socket.py 2009-05-20 15:09:43 UTC (rev 6360) @@ -141,17 +141,6 @@ SHUT_WR = 1 SHUT_RDWR = 2 -__all__ = ['AF_UNSPEC', 'AF_INET', 'AF_INET6', 'AI_PASSIVE', 'SOCK_DGRAM', - 'SOCK_RAW', 'SOCK_RDM', 'SOCK_SEQPACKET', 'SOCK_STREAM', 'SOL_SOCKET', - 'SO_BROADCAST', 'SO_ERROR', 'SO_KEEPALIVE', 'SO_LINGER', 'SO_OOBINLINE', - 'SO_RCVBUF', 'SO_REUSEADDR', 'SO_SNDBUF', 'SO_TIMEOUT', 'TCP_NODELAY', - 'SocketType', 'error', 'herror', 'gaierror', 'timeout', - 'getfqdn', 'gethostbyaddr', 'gethostbyname', 'gethostname', - 'socket', 'getaddrinfo', 'getdefaulttimeout', 'setdefaulttimeout', - 'has_ipv6', 'htons', 'htonl', 'ntohs', 'ntohl', - 'SHUT_RD', 'SHUT_WR', 'SHUT_RDWR', - ] - AF_UNSPEC = 0 AF_INET = 2 AF_INET6 = 23 @@ -165,6 +154,8 @@ SOCK_SEQPACKET = 5 # not supported SOL_SOCKET = 0xFFFF +IPPROTO_TCP = 6 +IPPROTO_UDP = 17 SO_BROADCAST = 1 SO_KEEPALIVE = 2 @@ -197,6 +188,28 @@ SO_TYPE = -1024 SO_USELOOPBACK = -2048 +__all__ = ['AF_UNSPEC', 'AF_INET', 'AF_INET6', 'AI_PASSIVE', 'SOCK_DGRAM', + 'SOCK_RAW', 'SOCK_RDM', 'SOCK_SEQPACKET', 'SOCK_STREAM', 'SOL_SOCKET', + 'SO_BROADCAST', 'SO_ERROR', 'SO_KEEPALIVE', 'SO_LINGER', 'SO_OOBINLINE', + 'SO_RCVBUF', 'SO_REUSEADDR', 'SO_SNDBUF', 'SO_TIMEOUT', 'TCP_NODELAY', + 'INADDR_ANY', 'INADDR_BROADCAST', 'IPPROTO_TCP', 'IPPROTO_UDP', + 'SocketType', 'error', 'herror', 'gaierror', 'timeout', + 'getfqdn', 'gethostbyaddr', 'gethostbyname', 'gethostname', + 'socket', 'getaddrinfo', 'getdefaulttimeout', 'setdefaulttimeout', + 'has_ipv6', 'htons', 'htonl', 'ntohs', 'ntohl', + 'SHUT_RD', 'SHUT_WR', 'SHUT_RDWR', + ] + +def _constant_to_name(const_value): + sock_module = sys.modules['socket'] + try: + for name in dir(sock_module): + if getattr(sock_module, name) is const_value: + return name + return "Unknown" + finally: + sock_module = None + class _nio_impl: timeout = None @@ -216,9 +229,9 @@ self._timeout_millis = int(timeout*1000) self.jsocket.setSoTimeout(self._timeout_millis) - def getsockopt(self, option): - if self.options.has_key(option): - result = getattr(self.jsocket, "get%s" % self.options[option])() + def getsockopt(self, level, option): + if self.options.has_key( (level, option) ): + result = getattr(self.jsocket, "get%s" % self.options[ (level, option) ])() if option == SO_LINGER: if result == -1: enabled, linger_time = 0, 0 @@ -227,17 +240,17 @@ return struct.pack('ii', enabled, linger_time) return result else: - raise error(errno.ENOPROTOOPT, "Option not supported on socket(%s): %d" % (str(self.jsocket), option)) + raise error(errno.ENOPROTOOPT, "Socket option '%s' (level '%s') not supported on socket(%s)" % (_constant_to_name(option), _constant_to_name(level), str(self.jsocket))) - def setsockopt(self, option, value): - if self.options.has_key(option): + def setsockopt(self, level, option, value): + if self.options.has_key( (level, option) ): if option == SO_LINGER: values = struct.unpack('ii', value) self.jsocket.setSoLinger(*values) else: - getattr(self.jsocket, "set%s" % self.options[option])(value) + getattr(self.jsocket, "set%s" % self.options[ (level, option) ])(value) else: - raise error(errno.ENOPROTOOPT, "Option not supported on socket(%s): %d" % (str(self.jsocket), option)) + raise error(errno.ENOPROTOOPT, "Socket option '%s' (level '%s') not supported on socket(%s)" % (_constant_to_name(option), _constant_to_name(level), str(self.jsocket))) def close(self): self.jsocket.close() @@ -250,14 +263,14 @@ class _client_socket_impl(_nio_impl): options = { - SO_KEEPALIVE: 'KeepAlive', - SO_LINGER: 'SoLinger', - SO_OOBINLINE: 'OOBInline', - SO_RCVBUF: 'ReceiveBufferSize', - SO_REUSEADDR: 'ReuseAddress', - SO_SNDBUF: 'SendBufferSize', - SO_TIMEOUT: 'SoTimeout', - TCP_NODELAY: 'TcpNoDelay', + (SOL_SOCKET, SO_KEEPALIVE): 'KeepAlive', + (SOL_SOCKET, SO_LINGER): 'SoLinger', + (SOL_SOCKET, SO_OOBINLINE): 'OOBInline', + (SOL_SOCKET, SO_RCVBUF): 'ReceiveBufferSize', + (SOL_SOCKET, SO_REUSEADDR): 'ReuseAddress', + (SOL_SOCKET, SO_SNDBUF): 'SendBufferSize', + (SOL_SOCKET, SO_TIMEOUT): 'SoTimeout', + (IPPROTO_TCP, TCP_NODELAY): 'TcpNoDelay', } def __init__(self, socket=None): @@ -325,9 +338,9 @@ class _server_socket_impl(_nio_impl): options = { - SO_RCVBUF: 'ReceiveBufferSize', - SO_REUSEADDR: 'ReuseAddress', - SO_TIMEOUT: 'SoTimeout', + (SOL_SOCKET, SO_RCVBUF): 'ReceiveBufferSize', + (SOL_SOCKET, SO_REUSEADDR): 'ReuseAddress', + (SOL_SOCKET, SO_TIMEOUT): 'SoTimeout', } def __init__(self, host, port, backlog, reuse_addr): @@ -353,20 +366,20 @@ return _client_socket_impl(new_cli_sock) def shutdown(self, how): - # This is no-op on java, for server sockets. - # What the user wants to achieve is achieved by calling close() on - # java/jython. But we can't call that here because that would then - # later cause the user explicit close() call to fail - pass - + # This is no-op on java, for server sockets. + # What the user wants to achieve is achieved by calling close() on + # java/jython. But we can't call that here because that would then + # later cause the user explicit close() call to fail + pass + class _datagram_socket_impl(_nio_impl): options = { - SO_BROADCAST: 'Broadcast', - SO_RCVBUF: 'ReceiveBufferSize', - SO_REUSEADDR: 'ReuseAddress', - SO_SNDBUF: 'SendBufferSize', - SO_TIMEOUT: 'SoTimeout', + (SOL_SOCKET, SO_BROADCAST): 'Broadcast', + (SOL_SOCKET, SO_RCVBUF): 'ReceiveBufferSize', + (SOL_SOCKET, SO_REUSEADDR): 'ReuseAddress', + (SOL_SOCKET, SO_SNDBUF): 'SendBufferSize', + (SOL_SOCKET, SO_TIMEOUT): 'SoTimeout', } def __init__(self, port=None, address=None, reuse_addr=0): @@ -394,12 +407,12 @@ self.jchannel.disconnect() def shutdown(self, how): - # This is no-op on java, for datagram sockets. - # What the user wants to achieve is achieved by calling close() on - # java/jython. But we can't call that here because that would then - # later cause the user explicit close() call to fail - pass - + # This is no-op on java, for datagram sockets. + # What the user wants to achieve is achieved by calling close() on + # java/jython. But we can't call that here because that would then + # later cause the user explicit close() call to fail + pass + def _do_send_net(self, byte_array, socket_address, flags): # Need two separate implementations because the java.nio APIs do not support timeouts num_bytes = len(byte_array) @@ -472,10 +485,11 @@ else: return self._do_receive_nio(0, num_bytes, flags) +# For now, we DO NOT have complete IPV6 support. +has_ipv6 = False + # Name and address functions -has_ipv6 = 1 - def _gethostbyaddr(name): # This is as close as I can get; at least the types are correct... addresses = java.net.InetAddress.getAllByName(gethostbyname(name)) @@ -532,13 +546,16 @@ # Same situation as above raise NotImplementedError("getprotobyname not yet supported on jython.") -def _realsocket(family = AF_INET, type = SOCK_STREAM, flags=0): - assert family == AF_INET - assert type in (SOCK_DGRAM, SOCK_STREAM) - assert flags == 0 +def _realsocket(family = AF_INET, type = SOCK_STREAM, protocol=0): + assert family == AF_INET, "Only AF_INET 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: + assert protocol == IPPROTO_TCP, "Only IPPROTO_TCP supported on SOCK_STREAM sockets" return _tcpsocket() else: + if protocol != 0: + assert protocol == IPPROTO_UDP, "Only IPPROTO_UDP supported on SOCK_DGRAM sockets" return _udpsocket() def getaddrinfo(host, port, family=AF_INET, socktype=None, proto=0, flags=None): @@ -629,11 +646,11 @@ close_lock = threading.Lock() def __init__(self): - self.timeout = _defaulttimeout - if self.timeout is not None: - self.mode = MODE_TIMEOUT + self.timeout = _defaulttimeout + if self.timeout is not None: + self.mode = MODE_TIMEOUT self.pending_options = { - SO_REUSEADDR: 0, + (SOL_SOCKET, SO_REUSEADDR): 0, } def gettimeout(self): @@ -662,34 +679,32 @@ return self.mode == MODE_BLOCKING def setsockopt(self, level, optname, value): - if level != SOL_SOCKET: return try: if self.sock_impl: - self.sock_impl.setsockopt(optname, value) + self.sock_impl.setsockopt(level, optname, value) else: - self.pending_options[optname] = value + self.pending_options[ (level, optname) ] = value except java.lang.Exception, jlx: raise _map_exception(jlx) def getsockopt(self, level, optname): - if level != SOL_SOCKET: return try: if self.sock_impl: - return self.sock_impl.getsockopt(optname) + return self.sock_impl.getsockopt(level, optname) else: - return self.pending_options.get(optname, None) + return self.pending_options.get( (level, optname), None) except java.lang.Exception, jlx: raise _map_exception(jlx) def shutdown(self, how): assert how in (SHUT_RD, SHUT_WR, SHUT_RDWR) if not self.sock_impl: - raise error(errno.ENOTCONN, "Transport endpoint is not connected") + raise error(errno.ENOTCONN, "Transport endpoint is not connected") try: self.sock_impl.shutdown(how) except java.lang.Exception, jlx: raise _map_exception(jlx) - + def close(self): try: if self.sock_impl: @@ -701,9 +716,9 @@ assert self.mode in _permitted_modes if self.sock_impl: self.sock_impl.config(self.mode, self.timeout) - for k in self.pending_options.keys(): - if k != SO_REUSEADDR: - self.sock_impl.setsockopt(k, self.pending_options[k]) + for level, optname in self.pending_options.keys(): + if optname != SO_REUSEADDR: + self.sock_impl.setsockopt(level, optname, self.pending_options[ (level, optname) ]) def getchannel(self): if not self.sock_impl: @@ -745,7 +760,7 @@ _unpack_address_tuple(addr) self.local_addr = addr - def listen(self, backlog=50): + def listen(self, backlog): "This signifies a server socket" try: assert not self.sock_impl @@ -754,7 +769,7 @@ host, port = _unpack_address_tuple(self.local_addr) else: host, port = "", 0 - self.sock_impl = _server_socket_impl(host, port, backlog, self.pending_options[SO_REUSEADDR]) + self.sock_impl = _server_socket_impl(host, port, backlog, self.pending_options[ (SOL_SOCKET, SO_REUSEADDR) ]) self._config() except java.lang.Exception, jlx: raise _map_exception(jlx) @@ -769,7 +784,7 @@ if not new_sock: raise would_block_error() cliconn = _tcpsocket() - cliconn.pending_options[SO_REUSEADDR] = new_sock.jsocket.getReuseAddress() + cliconn.pending_options[ (SOL_SOCKET, SO_REUSEADDR) ] = new_sock.jsocket.getReuseAddress() cliconn.sock_impl = new_sock cliconn._setup() return cliconn, new_sock.getpeername() @@ -789,7 +804,7 @@ self.sock_impl = _client_socket_impl() if self.local_addr: # Has the socket been bound to a local address? bind_host, bind_port = _unpack_address_tuple(self.local_addr) - self.sock_impl.bind(bind_host, bind_port, self.pending_options[SO_REUSEADDR]) + self.sock_impl.bind(bind_host, bind_port, self.pending_options[ (SOL_SOCKET, SO_REUSEADDR) ]) self._config() # Configure timeouts, etc, now that the socket exists self.sock_impl.connect(host, port) except java.lang.Exception, jlx: @@ -886,7 +901,7 @@ if self.sock_impl: self.sock_impl.close() except java.lang.Exception, jlx: - raise _map_exception(jlx) + raise _map_exception(jlx) class _udpsocket(_nonblocking_api_mixin): @@ -903,7 +918,7 @@ if host == "": host = INADDR_ANY host_address = java.net.InetAddress.getByName(host) - self.sock_impl = _datagram_socket_impl(port, host_address, self.pending_options[SO_REUSEADDR]) + self.sock_impl = _datagram_socket_impl(port, host_address, self.pending_options[ (SOL_SOCKET, SO_REUSEADDR) ]) self._config() except java.lang.Exception, jlx: raise _map_exception(jlx) @@ -1003,7 +1018,7 @@ def __del__(self): self.close() - + _socketmethods = ( 'bind', 'connect', 'connect_ex', 'fileno', 'listen', 'getpeername', 'getsockname', 'getsockopt', 'setsockopt', Modified: branches/Release_2_2maint/jython/Lib/test/test_socket.py =================================================================== --- branches/Release_2_2maint/jython/Lib/test/test_socket.py 2009-05-20 06:09:43 UTC (rev 6359) +++ branches/Release_2_2maint/jython/Lib/test/test_socket.py 2009-05-20 15:09:43 UTC (rev 6360) @@ -21,6 +21,10 @@ MSG = 'Michael Gilfix was here\n' EIGHT_BIT_MSG = 'Bh\xed Al\xe1in \xd3 Cinn\xe9ide anseo\n' +import java +os_name = java.lang.System.getProperty('os.name') +is_bsd = os_name == 'Mac OS X' or 'BSD' in os_name + try: True except NameError: @@ -522,26 +526,27 @@ def setUp(self): self.test_udp = self.test_tcp_client = self.test_tcp_server = 0 - def _testSetAndGetOption(self, sock, option, values): + def _testSetAndGetOption(self, sock, level, option, values): for expected_value in values: - sock.setsockopt(socket.SOL_SOCKET, option, expected_value) - retrieved_value = sock.getsockopt(socket.SOL_SOCKET, option) + sock.setsockopt(level, option, expected_value) + retrieved_value = sock.getsockopt(level, option) self.failUnlessEqual(retrieved_value, expected_value, \ - "Retrieved option(%s) value %s != %s(value set)" % (option, retrieved_value, expected_value)) + "Retrieved option(%s, %s) value %s != %s(value set)" % (level, option, retrieved_value, expected_value)) - def _testUDPOption(self, option, values): + def _testUDPOption(self, level, option, values): try: sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - self._testSetAndGetOption(sock, option, values) + self._testSetAndGetOption(sock, level, option, values) # now bind the socket i.e. cause the implementation socket to be created sock.bind( (HOST, PORT) ) - self.failUnlessEqual(sock.getsockopt(socket.SOL_SOCKET, option), values[-1], \ - "Option value '%s'='%s' did not propagate to implementation socket" % (option, values[-1]) ) - self._testSetAndGetOption(sock, option, values) + self.failUnlessEqual(sock.getsockopt(level, option), values[-1], \ + "Option value '(%s, %s)'='%s' did not propagate to implementation socket" % (level, option, values[-1]) ) + self._testSetAndGetOption(sock, level, option, values) finally: sock.close() - def _testTCPClientOption(self, option, values): + def _testTCPClientOption(self, level, option, values): + sock = None try: # First listen on a server socket, so that the connection won't be refused. server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) @@ -549,42 +554,51 @@ server_sock.listen(50) # Now do the tests sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self._testSetAndGetOption(sock, option, values) + self._testSetAndGetOption(sock, level, option, values) # now connect the socket i.e. cause the implementation socket to be created # First bind, so that the SO_REUSEADDR setting propagates sock.bind( (HOST, PORT+1) ) sock.connect( (HOST, PORT) ) - self.failUnlessEqual(sock.getsockopt(socket.SOL_SOCKET, option), values[-1], \ - "Option value '%s'='%s' did not propagate to implementation socket" % (option, values[-1])) - self._testSetAndGetOption(sock, option, values) + msg = "Option value '%s'='%s' did not propagate to implementation socket" % (option, values[-1]) + if is_bsd and option in (socket.SO_RCVBUF, socket.SO_SNDBUF): + # XXX: there's no guarantee that bufsize will be the + # exact setsockopt value, particularly after + # establishing a connection. seems it will be *at least* + # the values we test (which are rather small) on + # BSDs. may need to relax this on other platforms also + self.assert_(sock.getsockopt(level, option) >= values[-1], msg) + else: + self.failUnlessEqual(sock.getsockopt(level, option), values[-1], msg) + self._testSetAndGetOption(sock, level, option, values) finally: server_sock.close() - sock.close() + if sock: + sock.close() - def _testTCPServerOption(self, option, values): + def _testTCPServerOption(self, level, option, values): try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self._testSetAndGetOption(sock, option, values) + self._testSetAndGetOption(sock, level, option, values) # now bind and listen on the socket i.e. cause the implementation socket to be created sock.bind( (HOST, PORT) ) sock.listen(50) - self.failUnlessEqual(sock.getsockopt(socket.SOL_SOCKET, option), values[-1], \ - "Option value '%s'='%s' did not propagate to implementation socket" % (option, values[-1])) - self._testSetAndGetOption(sock, option, values) + self.failUnlessEqual(sock.getsockopt(level, option), values[-1], \ + "Option value '(%s,%s)'='%s' did not propagate to implementation socket" % (level, option, values[-1])) + self._testSetAndGetOption(sock, level, option, values) finally: sock.close() - def _testOption(self, option, values): + def _testOption(self, level, option, values): for flag, func in [ (self.test_udp, self._testUDPOption), (self.test_tcp_server, self._testTCPServerOption), (self.test_tcp_client, self._testTCPClientOption), ]: if flag: - func(option, values) + func(level, option, values) else: try: - func(option, values) + func(level, option, values) except socket.error, se: self.failUnlessEqual(se[0], errno.ENOPROTOOPT, "Wrong errno from unsupported option exception: %d" % se[0]) except Exception, x: @@ -596,48 +610,48 @@ def testSO_BROADCAST(self): self.test_udp = 1 - self._testOption(socket.SO_BROADCAST, [0, 1]) + self._testOption(socket.SOL_SOCKET, socket.SO_BROADCAST, [0, 1]) def testSO_KEEPALIVE(self): self.test_tcp_client = 1 - self._testOption(socket.SO_KEEPALIVE, [0, 1]) + self._testOption(socket.SOL_SOCKET, socket.SO_KEEPALIVE, [0, 1]) def testSO_LINGER(self): self.test_tcp_client = 1 off = struct.pack('ii', 0, 0) on_2_seconds = struct.pack('ii', 1, 2) - self._testOption(socket.SO_LINGER, [off, on_2_seconds]) + self._testOption(socket.SOL_SOCKET, socket.SO_LINGER, [off, on_2_seconds]) def testSO_OOBINLINE(self): self.test_tcp_client = 1 - self._testOption(socket.SO_OOBINLINE, [0, 1]) + self._testOption(socket.SOL_SOCKET, socket.SO_OOBINLINE, [0, 1]) def testSO_RCVBUF(self): self.test_udp = 1 self.test_tcp_client = 1 self.test_tcp_server = 1 - self._testOption(socket.SO_RCVBUF, [1024, 4096, 16384]) + self._testOption(socket.SOL_SOCKET, socket.SO_RCVBUF, [1024, 4096, 16384]) def testSO_REUSEADDR(self): self.test_udp = 1 self.test_tcp_client = 1 self.test_tcp_server = 1 - self._testOption(socket.SO_REUSEADDR, [0, 1]) + self._testOption(socket.SOL_SOCKET, socket.SO_REUSEADDR, [0, 1]) def testSO_SNDBUF(self): self.test_udp = 1 self.test_tcp_client = 1 - self._testOption(socket.SO_SNDBUF, [1024, 4096, 16384]) + self._testOption(socket.SOL_SOCKET, socket.SO_SNDBUF, [1024, 4096, 16384]) def testSO_TIMEOUT(self): self.test_udp = 1 self.test_tcp_client = 1 self.test_tcp_server = 1 - self._testOption(socket.SO_TIMEOUT, [0, 1, 1000]) + self._testOption(socket.SOL_SOCKET, socket.SO_TIMEOUT, [0, 1, 1000]) def testTCP_NODELAY(self): self.test_tcp_client = 1 - self._testOption(socket.TCP_NODELAY, [0, 1]) + self._testOption(socket.IPPROTO_TCP, socket.TCP_NODELAY, [0, 1]) class TestUnsupportedOptions(TestSocketOptions): @@ -795,31 +809,31 @@ self.serv_conn.send(MSG) self.serv_conn.send('and ' + MSG) -class UDPBindTest(unittest.TestCase): - +class UDPBindTest(unittest.TestCase): + HOST = HOST PORT = PORT - def setUp(self): + def setUp(self): self.sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) - - def testBindSpecific(self): + + def testBindSpecific(self): self.sock.bind( (self.HOST, self.PORT) ) # Use a specific port - actual_port = self.sock.getsockname()[1] - self.failUnless(actual_port == self.PORT, - "Binding to specific port number should have returned same number: %d != %d" % (actual_port, self.PORT)) + actual_port = self.sock.getsockname()[1] + self.failUnless(actual_port == self.PORT, + "Binding to specific port number should have returned same number: %d != %d" % (actual_port, self.PORT)) - def testBindEphemeral(self): + def testBindEphemeral(self): self.sock.bind( (self.HOST, 0) ) # let system choose a free port - self.failUnless(self.sock.getsockname()[1] != 0, "Binding to port zero should have allocated an ephemeral port number") + self.failUnless(self.sock.getsockname()[1] != 0, "Binding to port zero should have allocated an ephemeral port number") - def testShutdown(self): - self.sock.bind( (self.HOST, self.PORT) ) - self.sock.shutdown(socket.SHUT_RDWR) + def testShutdown(self): + self.sock.bind( (self.HOST, self.PORT) ) + self.sock.shutdown(socket.SHUT_RDWR) - def tearDown(self): - self.sock.close() - + def tearDown(self): + self.sock.close() + class BasicUDPTest(ThreadedUDPSocketTest): def __init__(self, methodName='runTest'): @@ -1327,7 +1341,7 @@ used, but if it is on your network this failure is bogus.''' % host) def testConnectDefaultTimeout(self): - _saved_timeout = socket.getdefaulttimeout() + _saved_timeout = socket.getdefaulttimeout() socket.setdefaulttimeout(0.1) cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM) host = '192.168.192.168' This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |