From: <am...@us...> - 2009-04-04 15:15:23
|
Revision: 6159 http://jython.svn.sourceforge.net/jython/?rev=6159&view=rev Author: amak Date: 2009-04-04 15:15:16 +0000 (Sat, 04 Apr 2009) Log Message: ----------- Re-arranging the way that options are handled: some options are at a level different to SOL_SOCKET, namely TCP_NODELAY, which is at level IPPROTO_TCP, which is now supported. Fixes 1191: socket.IPPROTO_TCP=6 missing constant for socket module http://bugs.jython.org/issue1191 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 2009-04-04 04:11:53 UTC (rev 6158) +++ trunk/jython/Lib/socket.py 2009-04-04 15:15:16 UTC (rev 6159) @@ -159,6 +159,8 @@ SOCK_SEQPACKET = 5 # not supported SOL_SOCKET = 0xFFFF +IPPROTO_TCP = 6 +IPPROTO_UDP = 17 SO_BROADCAST = 1 SO_KEEPALIVE = 2 @@ -195,7 +197,7 @@ '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', + 'INADDR_ANY', 'INADDR_BROADCAST', 'IPPROTO_TCP', 'IPPROTO_UDP', 'SocketType', 'error', 'herror', 'gaierror', 'timeout', 'getfqdn', 'gethostbyaddr', 'gethostbyname', 'gethostname', 'socket', 'getaddrinfo', 'getdefaulttimeout', 'setdefaulttimeout', @@ -222,9 +224,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 @@ -233,17 +235,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, "Level %d option not supported on socket(%s): %d" % (level, str(self.jsocket), option)) - 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, "Level %d option not supported on socket(%s): %d" % (level, str(self.jsocket), option)) def close(self): self.jsocket.close() @@ -256,15 +258,15 @@ 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', + options = { + (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): @@ -332,10 +334,10 @@ class _server_socket_impl(_nio_impl): - options = { - SO_RCVBUF: 'ReceiveBufferSize', - SO_REUSEADDR: 'ReuseAddress', - SO_TIMEOUT: 'SoTimeout', + options = { + (SOL_SOCKET, SO_RCVBUF): 'ReceiveBufferSize', + (SOL_SOCKET, SO_REUSEADDR): 'ReuseAddress', + (SOL_SOCKET, SO_TIMEOUT): 'SoTimeout', } def __init__(self, host, port, backlog, reuse_addr): @@ -370,12 +372,12 @@ class _datagram_socket_impl(_nio_impl): - options = { - SO_BROADCAST: 'Broadcast', - SO_RCVBUF: 'ReceiveBufferSize', - SO_REUSEADDR: 'ReuseAddress', - SO_SNDBUF: 'SendBufferSize', - SO_TIMEOUT: 'SoTimeout', + options = { + (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): @@ -542,13 +544,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): @@ -645,7 +650,7 @@ if self.timeout is not None: self.mode = MODE_TIMEOUT self.pending_options = { - SO_REUSEADDR: 0, + (SOL_SOCKET, SO_REUSEADDR): 0, } def gettimeout(self): @@ -674,22 +679,20 @@ 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) @@ -713,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: @@ -775,7 +778,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) @@ -790,7 +793,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() @@ -810,7 +813,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: @@ -925,7 +928,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) Modified: trunk/jython/Lib/test/test_socket.py =================================================================== --- trunk/jython/Lib/test/test_socket.py 2009-04-04 04:11:53 UTC (rev 6158) +++ trunk/jython/Lib/test/test_socket.py 2009-04-04 15:15:16 UTC (rev 6159) @@ -528,29 +528,29 @@ class TestSocketOptions(unittest.TestCase): - def setUp(self): + 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. @@ -559,7 +559,7 @@ 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) ) @@ -571,39 +571,39 @@ # 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(socket.SOL_SOCKET, option) >= values[-1], msg) + self.assert_(sock.getsockopt(level, option) >= values[-1], msg) else: - self.failUnlessEqual(sock.getsockopt(socket.SOL_SOCKET, option), values[-1], msg) - self._testSetAndGetOption(sock, option, values) + self.failUnlessEqual(sock.getsockopt(level, option), values[-1], msg) + self._testSetAndGetOption(sock, level, option, values) finally: server_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: @@ -613,50 +613,50 @@ class TestSupportedOptions(TestSocketOptions): - def testSO_BROADCAST(self): + 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): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |