1"""
2This is an updated socket module for use on JVMs >= 1.5; it is derived from the old jython socket module.
3It is documented, along with known issues and workarounds, on the jython wiki.
4http://wiki.python.org/jython/NewSocketModule
5"""
6
7_defaulttimeout = None
8
9import errno
10import jarray
11import string
12import struct
13import sys
14import threading
15import time
16import types
17
18# Java.io classes
19import java.io.BufferedInputStream
20import java.io.BufferedOutputStream
21# Java.io exceptions
22import java.io.InterruptedIOException
23import java.io.IOException
24
25# Java.lang classes
26import java.lang.String
27# Java.lang exceptions
28import java.lang.Exception
29
30# Java.net classes
31import java.net.DatagramPacket
32import java.net.InetAddress
33import java.net.InetSocketAddress
34import java.net.Socket
35# Java.net exceptions
36import java.net.BindException
37import java.net.ConnectException
38import java.net.NoRouteToHostException
39import java.net.PortUnreachableException
40import java.net.ProtocolException
41import java.net.SocketException
42import java.net.SocketTimeoutException
43import java.net.UnknownHostException
44
45# Java.nio classes
46import java.nio.ByteBuffer
47import java.nio.channels.DatagramChannel
48import java.nio.channels.ServerSocketChannel
49import java.nio.channels.SocketChannel
50# Java.nio exceptions
51import java.nio.channels.AlreadyConnectedException
52import java.nio.channels.AsynchronousCloseException
53import java.nio.channels.CancelledKeyException
54import java.nio.channels.ClosedByInterruptException
55import java.nio.channels.ClosedChannelException
56import java.nio.channels.ClosedSelectorException
57import java.nio.channels.ConnectionPendingException
58import java.nio.channels.IllegalBlockingModeException
59import java.nio.channels.IllegalSelectorException
60import java.nio.channels.NoConnectionPendingException
61import java.nio.channels.NonReadableChannelException
62import java.nio.channels.NonWritableChannelException
63import java.nio.channels.NotYetBoundException
64import java.nio.channels.NotYetConnectedException
65import java.nio.channels.UnresolvedAddressException
66import java.nio.channels.UnsupportedAddressTypeException
67
68# Javax.net.ssl classes
69import javax.net.ssl.SSLSocketFactory
70# Javax.net.ssl exceptions
71javax.net.ssl.SSLException
72javax.net.ssl.SSLHandshakeException
73javax.net.ssl.SSLKeyException
74javax.net.ssl.SSLPeerUnverifiedException
75javax.net.ssl.SSLProtocolException
76
77import org.python.core.io.DatagramSocketIO
78import org.python.core.io.ServerSocketIO
79import org.python.core.io.SocketIO
80from org.python.core.Py import newString as asPyString
81
82class error(IOError): pass
83class herror(error): pass
84class gaierror(error): pass
85class timeout(error): pass
86class sslerror(error): pass
87
88def _add_exception_attrs(exc):
89    setattr(exc, 'errno', exc[0])
90    setattr(exc, 'strerror', exc[1])
91    return exc
92
93def _unmapped_exception(exc):
94    return _add_exception_attrs(error(-1, 'Unmapped exception: %s' % exc))
95
96def java_net_socketexception_handler(exc):
97    if exc.message.startswith("Address family not supported by protocol family"):
98        return _add_exception_attrs(error(errno.EAFNOSUPPORT,
99                'Address family not supported by protocol family: See http://wiki.python.org/jython/NewSocketModule#IPV6_address_support'))
100    return _unmapped_exception(exc)
101
102def would_block_error(exc=None):
103    return _add_exception_attrs(error(errno.EWOULDBLOCK, 'The socket operation could not complete without blocking'))
104
105ALL = None
106
107_ssl_message = ": Differences between the SSL socket behaviour of cpython vs. jython are explained on the wiki:  http://wiki.python.org/jython/NewSocketModule#SSL_Support"
108
109_exception_map = {
110
111# (<javaexception>, <circumstance>) : callable that raises the python equivalent exception, or None to stub out as unmapped
112
113(java.io.IOException, ALL)            : lambda x: error(errno.ECONNRESET, 'Software caused connection abort'),
114(java.io.InterruptedIOException, ALL) : lambda x: timeout(None, 'timed out'),
115
116(java.net.BindException, ALL)            : lambda x: error(errno.EADDRINUSE, 'Address already in use'),
117(java.net.ConnectException, ALL)         : lambda x: error(errno.ECONNREFUSED, 'Connection refused'),
118(java.net.NoRouteToHostException, ALL)   : lambda x: error(errno.EHOSTUNREACH, 'No route to host'),
119(java.net.PortUnreachableException, ALL) : None,
120(java.net.ProtocolException, ALL)        : None,
121(java.net.SocketException, ALL)          : java_net_socketexception_handler,
122(java.net.SocketTimeoutException, ALL)   : lambda x: timeout(None, 'timed out'),
123(java.net.UnknownHostException, ALL)     : lambda x: gaierror(errno.EGETADDRINFOFAILED, 'getaddrinfo failed'),
124
125(java.nio.channels.AlreadyConnectedException, ALL)       : lambda x: error(errno.EISCONN, 'Socket is already connected'),
126(java.nio.channels.AsynchronousCloseException, ALL)      : None,
127(java.nio.channels.CancelledKeyException, ALL)           : None,
128(java.nio.channels.ClosedByInterruptException, ALL)      : None,
129(java.nio.channels.ClosedChannelException, ALL)          : lambda x: error(errno.EPIPE, 'Socket closed'),
130(java.nio.channels.ClosedSelectorException, ALL)         : None,
131(java.nio.channels.ConnectionPendingException, ALL)      : None,
132(java.nio.channels.IllegalBlockingModeException, ALL)    : None,
133(java.nio.channels.IllegalSelectorException, ALL)        : None,
134(java.nio.channels.NoConnectionPendingException, ALL)    : None,
135(java.nio.channels.NonReadableChannelException, ALL)     : None,
136(java.nio.channels.NonWritableChannelException, ALL)     : None,
137(java.nio.channels.NotYetBoundException, ALL)            : None,
138(java.nio.channels.NotYetConnectedException, ALL)        : None,
139(java.nio.channels.UnresolvedAddressException, ALL)      : lambda x: gaierror(errno.EGETADDRINFOFAILED, 'getaddrinfo failed'),
140(java.nio.channels.UnsupportedAddressTypeException, ALL) : None,
141
142# These error codes are currently wrong: getting them correct is going to require
143# some investigation. Cpython 2.6 introduced extensive SSL support.
144
145(javax.net.ssl.SSLException, ALL)                        : lambda x: sslerror(-1, 'SSL exception'+_ssl_message),
146(javax.net.ssl.SSLHandshakeException, ALL)               : lambda x: sslerror(-1, 'SSL handshake exception'+_ssl_message),
147(javax.net.ssl.SSLKeyException, ALL)                     : lambda x: sslerror(-1, 'SSL key exception'+_ssl_message),
148(javax.net.ssl.SSLPeerUnverifiedException, ALL)          : lambda x: sslerror(-1, 'SSL peer unverified exception'+_ssl_message),
149(javax.net.ssl.SSLProtocolException, ALL)                : lambda x: sslerror(-1, 'SSL protocol exception'+_ssl_message),
150
151}
152
153def _map_exception(java_exception, circumstance=ALL):
154    mapped_exception = _exception_map.get((java_exception.__class__, circumstance))
155    if mapped_exception:
156        py_exception = mapped_exception(java_exception)
157    else:
158        py_exception = error(-1, 'Unmapped exception: %s' % java_exception)
159    setattr(py_exception, 'java_exception', java_exception)
160    return _add_exception_attrs(py_exception)
161
162from functools import wraps
163
164# Used to map java exceptions to the equivalent python exception
165# And to set the _last_error attribute on socket objects, to support SO_ERROR
166def raises_java_exception(method_or_function):
167    @wraps(method_or_function)
168    def handle_exception(*args, **kwargs):
169        is_socket = (len(args) > 0 and isinstance(args[0], _nonblocking_api_mixin))
170        try:
171            try:
172                return method_or_function(*args, **kwargs)
173            except java.lang.Exception, jlx:
174                raise _map_exception(jlx)
175        except error, e:
176            if is_socket:
177                setattr(args[0], '_last_error', e[0])
178            raise
179        else:
180            if is_socket:
181                setattr(args[0], '_last_error', 0)
182    return handle_exception
183
184_feature_support_map = {
185    'ipv6': True,
186    'idna': False,
187    'tipc': False,
188}
189
190def supports(feature, *args):
191    if len(args) == 1:
192        _feature_support_map[feature] = args[0]
193    return _feature_support_map.get(feature, False)
194
195MODE_BLOCKING    = 'block'
196MODE_NONBLOCKING = 'nonblock'
197MODE_TIMEOUT     = 'timeout'
198
199_permitted_modes = (MODE_BLOCKING, MODE_NONBLOCKING, MODE_TIMEOUT)
200
201SHUT_RD   = 0
202SHUT_WR   = 1
203SHUT_RDWR = 2
204
205AF_UNSPEC = 0
206AF_INET   = 2
207AF_INET6  = 23
208
209AI_PASSIVE     = 1
210AI_CANONNAME   = 2
211AI_NUMERICHOST = 4
212AI_V4MAPPED    = 8
213AI_ALL         = 16
214AI_ADDRCONFIG  = 32
215AI_NUMERICSERV = 1024
216
217EAI_NONAME     = -2
218EAI_SERVICE    = -8
219EAI_ADDRFAMILY = -9
220
221NI_NUMERICHOST              = 1
222NI_NUMERICSERV              = 2
223NI_NOFQDN                   = 4
224NI_NAMEREQD                 = 8
225NI_DGRAM                    = 16
226NI_MAXSERV                  = 32
227NI_IDN                      = 64
228NI_IDN_ALLOW_UNASSIGNED     = 128
229NI_IDN_USE_STD3_ASCII_RULES = 256
230NI_MAXHOST                  = 1025
231
232# For some reason, probably historical, SOCK_DGRAM and SOCK_STREAM are opposite values of what they are on cpython.
233# I.E. The following is the way they are on cpython
234# SOCK_STREAM    = 1
235# SOCK_DGRAM     = 2
236# At some point, we should probably switch them around, which *should* not affect anybody
237
238SOCK_DGRAM     = 1
239SOCK_STREAM    = 2
240SOCK_RAW       = 3 # not supported
241SOCK_RDM       = 4 # not supported
242SOCK_SEQPACKET = 5 # not supported
243
244SOL_SOCKET = 0xFFFF
245
246IPPROTO_AH       =  51 # not supported
247IPPROTO_DSTOPTS  =  60 # not supported
248IPPROTO_ESP      =  50 # not supported
249IPPROTO_FRAGMENT =  44 # not supported
250IPPROTO_GGP      =   3 # not supported
251IPPROTO_HOPOPTS  =   0 # not supported
252IPPROTO_ICMP     =   1 # not supported
253IPPROTO_ICMPV6   =  58 # not supported
254IPPROTO_IDP      =  22 # not supported
255IPPROTO_IGMP     =   2 # not supported
256IPPROTO_IP       =   0
257IPPROTO_IPV4     =   4 # not supported
258IPPROTO_IPV6     =  41 # not supported
259IPPROTO_MAX      = 256 # not supported
260IPPROTO_ND       =  77 # not supported
261IPPROTO_NONE     =  59 # not supported
262IPPROTO_PUP      =  12 # not supported
263IPPROTO_RAW      = 255 # not supported
264IPPROTO_ROUTING  =  43 # not supported
265IPPROTO_TCP      =   6
266IPPROTO_UDP      =  17
267
268SO_ACCEPTCONN  = 1
269SO_BROADCAST   = 2
270SO_ERROR       = 4
271SO_KEEPALIVE   = 8
272SO_LINGER      = 16
273SO_OOBINLINE   = 32
274SO_RCVBUF      = 64
275SO_REUSEADDR   = 128
276SO_SNDBUF      = 256
277SO_TIMEOUT     = 512
278SO_TYPE        = 1024
279
280TCP_NODELAY    = 2048
281
282INADDR_ANY = "0.0.0.0"
283INADDR_BROADCAST = "255.255.255.255"
284
285IN6ADDR_ANY_INIT = "::"
286
287# Options with negative constants are not supported
288# They are being added here so that code that refers to them
289# will not break with an AttributeError
290
291SO_DEBUG            = -1
292SO_DONTROUTE        = -1
293SO_EXCLUSIVEADDRUSE = -8
294SO_RCVLOWAT         = -16
295SO_RCVTIMEO         = -32
296SO_REUSEPORT        = -64
297SO_SNDLOWAT         = -128
298SO_SNDTIMEO         = -256
299SO_USELOOPBACK      = -512
300
301__all__ = [
302    # Families
303    'AF_UNSPEC', 'AF_INET', 'AF_INET6',
304    # getaddrinfo and getnameinfo flags
305    'AI_PASSIVE', 'AI_CANONNAME', 'AI_NUMERICHOST', 'AI_V4MAPPED',
306    'AI_ALL', 'AI_ADDRCONFIG', 'AI_NUMERICSERV', 'EAI_NONAME',
307    'EAI_SERVICE', 'EAI_ADDRFAMILY',
308    'NI_NUMERICHOST', 'NI_NUMERICSERV', 'NI_NOFQDN', 'NI_NAMEREQD',
309    'NI_DGRAM', 'NI_MAXSERV', 'NI_IDN', 'NI_IDN_ALLOW_UNASSIGNED',
310    'NI_IDN_USE_STD3_ASCII_RULES', 'NI_MAXHOST',
311    # socket types
312    'SOCK_DGRAM', 'SOCK_STREAM', 'SOCK_RAW', 'SOCK_RDM', 'SOCK_SEQPACKET',
313    # levels
314    'SOL_SOCKET',
315    # protocols
316    'IPPROTO_AH', 'IPPROTO_DSTOPTS', 'IPPROTO_ESP', 'IPPROTO_FRAGMENT',
317    'IPPROTO_GGP', 'IPPROTO_HOPOPTS', 'IPPROTO_ICMP', 'IPPROTO_ICMPV6',
318    'IPPROTO_IDP', 'IPPROTO_IGMP', 'IPPROTO_IP', 'IPPROTO_IPV4',
319    'IPPROTO_IPV6', 'IPPROTO_MAX', 'IPPROTO_ND', 'IPPROTO_NONE',
320    'IPPROTO_PUP', 'IPPROTO_RAW', 'IPPROTO_ROUTING', 'IPPROTO_TCP',
321    'IPPROTO_UDP',
322    # Special hostnames
323    'INADDR_ANY', 'INADDR_BROADCAST', 'IN6ADDR_ANY_INIT',
324    # support socket options
325    'SO_BROADCAST', 'SO_KEEPALIVE', 'SO_LINGER', 'SO_OOBINLINE',
326    'SO_RCVBUF', 'SO_REUSEADDR', 'SO_SNDBUF', 'SO_TIMEOUT', 'TCP_NODELAY',
327    # unsupported socket options
328    'SO_ACCEPTCONN', 'SO_DEBUG', 'SO_DONTROUTE', 'SO_ERROR',
329    'SO_EXCLUSIVEADDRUSE', 'SO_RCVLOWAT', 'SO_RCVTIMEO', 'SO_REUSEPORT',
330    'SO_SNDLOWAT', 'SO_SNDTIMEO', 'SO_TYPE', 'SO_USELOOPBACK',
331    # functions
332    'getfqdn', 'gethostname', 'gethostbyname', 'gethostbyaddr',
333    'getservbyname', 'getservbyport', 'getprotobyname', 'getaddrinfo',
334    'getnameinfo', 'getdefaulttimeout', 'setdefaulttimeout', 'htons',
335    'htonl', 'ntohs', 'ntohl', 'inet_pton', 'inet_ntop', 'inet_aton',
336    'inet_ntoa', 'create_connection', 'socket', 'ssl',
337    # exceptions
338    'error', 'herror', 'gaierror', 'timeout', 'sslerror',
339    # classes
340    'SocketType',
341    # Misc flags
342    'has_ipv6', 'SHUT_RD', 'SHUT_WR', 'SHUT_RDWR',
343]
344
345def _constant_to_name(const_value, expected_name_starts):
346    sock_module = sys.modules['socket']
347    try:
348        for name in dir(sock_module):
349            if getattr(sock_module, name) is const_value:
350                for name_start in expected_name_starts:
351                    if name.startswith(name_start):
352                        return name
353        return "Unknown"
354    finally:
355        sock_module = None
356
357import _google_ipaddr_r234
358
359def _is_ip_address(addr, version=None):
360    try:
361        _google_ipaddr_r234.IPAddress(addr, version)
362        return True
363    except ValueError:
364        return False
365
366def is_ipv4_address(addr):
367    return _is_ip_address(addr, 4)
368
369def is_ipv6_address(addr):
370    return _is_ip_address(addr, 6)
371
372def is_ip_address(addr):
373    return _is_ip_address(addr)
374
375class _nio_impl:
376
377    timeout = None
378    mode = MODE_BLOCKING
379
380    def config(self, mode, timeout):
381        self.mode = mode
382        if self.mode == MODE_BLOCKING:
383            self.jchannel.configureBlocking(1)
384        if self.mode == MODE_NONBLOCKING:
385            self.jchannel.configureBlocking(0)
386        if self.mode == MODE_TIMEOUT:
387            self.jchannel.configureBlocking(1)
388            self._timeout_millis = int(timeout*1000)
389            self.jsocket.setSoTimeout(self._timeout_millis)
390
391    def getsockopt(self, level, option):
392        if (level, option) in self.options:
393            result = getattr(self.jsocket, "get%s" % self.options[ (level, option) ])()
394            if option == SO_LINGER:
395                if result == -1:
396                    enabled, linger_time = 0, 0
397                else:
398                    enabled, linger_time = 1, result
399                return struct.pack('ii', enabled, linger_time)
400            return result
401        else:
402            raise error(errno.ENOPROTOOPT, "Socket option '%s' (level '%s') not supported on socket(%s)" % \
403                (_constant_to_name(option, ['SO_', 'TCP_']), _constant_to_name(level, ['SOL_', 'IPPROTO_']), str(self.jsocket)))
404
405    def setsockopt(self, level, option, value):
406        if (level, option) in self.options:
407            if option == SO_LINGER:
408                values = struct.unpack('ii', value)
409                self.jsocket.setSoLinger(*values)
410            else:
411                getattr(self.jsocket, "set%s" % self.options[ (level, option) ])(value)
412        else:
413            raise error(errno.ENOPROTOOPT, "Socket option '%s' (level '%s') not supported on socket(%s)" % \
414                (_constant_to_name(option, ['SO_', 'TCP_']), _constant_to_name(level,  ['SOL_', 'IPPROTO_']), str(self.jsocket)))
415
416    def close(self):
417        self.jsocket.close()
418
419    def getchannel(self):
420        return self.jchannel
421
422    def fileno(self):
423        return self.socketio
424
425class _client_socket_impl(_nio_impl):
426
427    options = {
428        (SOL_SOCKET,  SO_KEEPALIVE):   'KeepAlive',
429        (SOL_SOCKET,  SO_LINGER):      'SoLinger',
430        (SOL_SOCKET,  SO_OOBINLINE):   'OOBInline',
431        (SOL_SOCKET,  SO_RCVBUF):      'ReceiveBufferSize',
432        (SOL_SOCKET,  SO_REUSEADDR):   'ReuseAddress',
433        (SOL_SOCKET,  SO_SNDBUF):      'SendBufferSize',
434        (SOL_SOCKET,  SO_TIMEOUT):     'SoTimeout',
435        (IPPROTO_TCP, TCP_NODELAY):    'TcpNoDelay',
436    }
437
438    def __init__(self, socket=None, pending_options=None):
439        if socket:
440            self.jchannel = socket.getChannel()
441        else:
442            self.jchannel = java.nio.channels.SocketChannel.open()
443        self.jsocket = self.jchannel.socket()
444        self.socketio = org.python.core.io.SocketIO(self.jchannel, 'rw')
445        if pending_options:
446            for level, optname in pending_options.keys():
447                self.setsockopt(level, optname, pending_options[ (level, optname) ])
448
449    def bind(self, jsockaddr, reuse_addr):
450        self.jsocket.setReuseAddress(reuse_addr)
451        self.jsocket.bind(jsockaddr)
452
453    def connect(self, jsockaddr):
454        if self.mode == MODE_TIMEOUT:
455            self.jsocket.connect (jsockaddr, self._timeout_millis)
456        else:
457            self.jchannel.connect(jsockaddr)
458
459    def finish_connect(self):
460        return self.jchannel.finishConnect()
461
462    def _do_read_net(self, buf):
463        # Need two separate implementations because the java.nio APIs do not support timeouts
464        return self.jsocket.getInputStream().read(buf)
465
466    def _do_read_nio(self, buf):
467        bytebuf = java.nio.ByteBuffer.wrap(buf)
468        count = self.jchannel.read(bytebuf)
469        return count
470
471    def _do_write_net(self, buf):
472        self.jsocket.getOutputStream().write(buf)
473        return len(buf)
474
475    def _do_write_nio(self, buf):
476        bytebuf = java.nio.ByteBuffer.wrap(buf)
477        count = self.jchannel.write(bytebuf)
478        return count
479
480    def read(self, buf):
481        if self.mode == MODE_TIMEOUT:
482            return self._do_read_net(buf)
483        else:
484            return self._do_read_nio(buf)
485
486    def write(self, buf):
487        if self.mode == MODE_TIMEOUT:
488            return self._do_write_net(buf)
489        else:
490            return self._do_write_nio(buf)
491
492    def shutdown(self, how):
493        if how in (SHUT_RD, SHUT_RDWR):
494            self.jsocket.shutdownInput()
495        if how in (SHUT_WR, SHUT_RDWR):
496            self.jsocket.shutdownOutput()
497
498    def getsockname(self):
499        return (self.jsocket.getLocalAddress().getHostAddress(), self.jsocket.getLocalPort())
500
501    def getpeername(self):
502        return (self.jsocket.getInetAddress().getHostAddress(), self.jsocket.getPort() )
503
504class _server_socket_impl(_nio_impl):
505
506    options = {
507        (SOL_SOCKET, SO_RCVBUF):      'ReceiveBufferSize',
508        (SOL_SOCKET, SO_REUSEADDR):   'ReuseAddress',
509        (SOL_SOCKET, SO_TIMEOUT):     'SoTimeout',
510    }
511
512    def __init__(self, jsockaddr, backlog, reuse_addr):
513        self.pending_client_options = {}
514        self.jchannel = java.nio.channels.ServerSocketChannel.open()
515        self.jsocket = self.jchannel.socket()
516        self.jsocket.setReuseAddress(reuse_addr)
517        self.jsocket.bind(jsockaddr, backlog)
518        self.socketio = org.python.core.io.ServerSocketIO(self.jchannel, 'rw')
519
520    def accept(self):
521        if self.mode in (MODE_BLOCKING, MODE_NONBLOCKING):
522            new_cli_chan = self.jchannel.accept()
523            if new_cli_chan is not None:
524                return _client_socket_impl(new_cli_chan.socket(), self.pending_client_options)
525            else:
526                return None
527        else:
528            # In timeout mode now
529            new_cli_sock = self.jsocket.accept()
530            return _client_socket_impl(new_cli_sock, self.pending_client_options)
531
532    def shutdown(self, how):
533        # This is no-op on java, for server sockets.
534        # What the user wants to achieve is achieved by calling close() on
535        # java/jython. But we can't call that here because that would then
536        # later cause the user explicit close() call to fail
537        pass
538
539    def getsockopt(self, level, option):
540        if self.options.has_key( (level, option) ):
541            return _nio_impl.getsockopt(self, level, option)
542        elif _client_socket_impl.options.has_key( (level, option) ):
543            return self.pending_client_options.get( (level, option), None)
544        else:
545            raise error(errno.ENOPROTOOPT, "Socket option '%s' (level '%s') not supported on socket(%s)" % \
546                (_constant_to_name(option, ['SO_', 'TCP_']), _constant_to_name(level,  ['SOL_', 'IPPROTO_']), str(self.jsocket)))
547
548    def setsockopt(self, level, option, value):
549        if self.options.has_key( (level, option) ):
550            _nio_impl.setsockopt(self, level, option, value)
551        elif _client_socket_impl.options.has_key( (level, option) ):
552            self.pending_client_options[ (level, option) ] = value
553        else:
554            raise error(errno.ENOPROTOOPT, "Socket option '%s' (level '%s') not supported on socket(%s)" % \
555                (_constant_to_name(option, ['SO_', 'TCP_']), _constant_to_name(level,  ['SOL_', 'IPPROTO_']), str(self.jsocket)))
556
557    def getsockname(self):
558        return (self.jsocket.getInetAddress().getHostAddress(), self.jsocket.getLocalPort())
559
560    def getpeername(self):
561        # Not a meaningful operation for server sockets.
562        raise error(errno.ENOTCONN, "Socket is not connected")
563
564class _datagram_socket_impl(_nio_impl):
565
566    options = {
567        (SOL_SOCKET, SO_BROADCAST):   'Broadcast',
568        (SOL_SOCKET, SO_RCVBUF):      'ReceiveBufferSize',
569        (SOL_SOCKET, SO_REUSEADDR):   'ReuseAddress',
570        (SOL_SOCKET, SO_SNDBUF):      'SendBufferSize',
571        (SOL_SOCKET, SO_TIMEOUT):     'SoTimeout',
572    }
573
574    def __init__(self, jsockaddr=None, reuse_addr=0):
575        self.jchannel = java.nio.channels.DatagramChannel.open()
576        self.jsocket = self.jchannel.socket()
577        if jsockaddr is not None:
578            self.jsocket.setReuseAddress(reuse_addr)
579            self.jsocket.bind(jsockaddr)
580        self.socketio = org.python.core.io.DatagramSocketIO(self.jchannel, 'rw')
581
582    def connect(self, jsockaddr):
583        self.jchannel.connect(jsockaddr)
584
585    def disconnect(self):
586        """
587            Disconnect the datagram socket.
588            cpython appears not to have this operation
589        """
590        self.jchannel.disconnect()
591
592    def shutdown(self, how):
593        # This is no-op on java, for datagram sockets.
594        # What the user wants to achieve is achieved by calling close() on
595        # java/jython. But we can't call that here because that would then
596        # later cause the user explicit close() call to fail
597        pass
598
599    def _do_send_net(self, byte_array, socket_address, flags):
600        # Need two separate implementations because the java.nio APIs do not support timeouts
601        num_bytes = len(byte_array)
602        if self.jsocket.isConnected() and socket_address is None:
603            packet = java.net.DatagramPacket(byte_array, num_bytes)
604        else:
605            packet = java.net.DatagramPacket(byte_array, num_bytes, socket_address)
606        self.jsocket.send(packet)
607        return num_bytes
608
609    def _do_send_nio(self, byte_array, socket_address, flags):
610        byte_buf = java.nio.ByteBuffer.wrap(byte_array)
611        if self.jchannel.isConnected() and socket_address is None:
612            bytes_sent = self.jchannel.write(byte_buf)
613        else:
614            bytes_sent = self.jchannel.send(byte_buf, socket_address)
615        return bytes_sent
616
617    def sendto(self, byte_array, jsockaddr, flags):
618        if self.mode == MODE_TIMEOUT:
619            return self._do_send_net(byte_array, jsockaddr, flags)
620        else:
621            return self._do_send_nio(byte_array, jsockaddr, flags)
622
623    def send(self, byte_array, flags):
624        if self.mode == MODE_TIMEOUT:
625            return self._do_send_net(byte_array, None, flags)
626        else:
627            return self._do_send_nio(byte_array, None, flags)
628
629    def _do_receive_net(self, return_source_address, num_bytes, flags):
630        byte_array = jarray.zeros(num_bytes, 'b')
631        packet = java.net.DatagramPacket(byte_array, num_bytes)
632        self.jsocket.receive(packet)
633        bytes_rcvd = packet.getLength()
634        if bytes_rcvd < num_bytes:
635            byte_array = byte_array[:bytes_rcvd]
636        return_data = byte_array.tostring()
637        if return_source_address:
638            host = None
639            if packet.getAddress():
640                host = packet.getAddress().getHostAddress()
641            port = packet.getPort()
642            return return_data, (host, port)
643        else:
644            return return_data
645
646    def _do_receive_nio(self, return_source_address, num_bytes, flags):
647        byte_array = jarray.zeros(num_bytes, 'b')
648        byte_buf = java.nio.ByteBuffer.wrap(byte_array)
649        source_address = self.jchannel.receive(byte_buf)
650        if source_address is None and not self.jchannel.isBlocking():
651            raise would_block_error()
652        byte_buf.flip() ; bytes_read = byte_buf.remaining()
653        if bytes_read < num_bytes:
654            byte_array = byte_array[:bytes_read]
655        return_data = byte_array.tostring()
656        if return_source_address:
657            return return_data, (source_address.getAddress().getHostAddress(), source_address.getPort())
658        else:
659            return return_data
660
661    def recvfrom(self, num_bytes, flags):
662        if self.mode == MODE_TIMEOUT:
663            return self._do_receive_net(1, num_bytes, flags)
664        else:
665            return self._do_receive_nio(1, num_bytes, flags)
666
667    def recv(self, num_bytes, flags):
668        if self.mode == MODE_TIMEOUT:
669            return self._do_receive_net(0, num_bytes, flags)
670        else:
671            return self._do_receive_nio(0, num_bytes, flags)
672
673    def getsockname(self):
674        return (self.jsocket.getLocalAddress().getHostAddress(), self.jsocket.getLocalPort())
675
676    def getpeername(self):
677        peer_address = self.jsocket.getInetAddress()
678        if peer_address is None:
679            raise error(errno.ENOTCONN, "Socket is not connected")
680        return (peer_address.getHostAddress(), self.jsocket.getPort() )
681
682has_ipv6 = True # IPV6 FTW!
683
684# Name and address functions
685
686def _gethostbyaddr(name):
687    # This is as close as I can get; at least the types are correct...
688    addresses = java.net.InetAddress.getAllByName(gethostbyname(name))
689    names = []
690    addrs = []
691    for addr in addresses:
692        names.append(asPyString(addr.getHostName()))
693        addrs.append(asPyString(addr.getHostAddress()))
694    return (names, addrs)
695
696@raises_java_exception
697def getfqdn(name=None):
698    """
699    Return a fully qualified domain name for name. If name is omitted or empty
700    it is interpreted as the local host.  To find the fully qualified name,
701    the hostname returned by gethostbyaddr() is checked, then aliases for the
702    host, if available. The first name which includes a period is selected.
703    In case no fully qualified domain name is available, the hostname is retur
704    New in version 2.0.
705    """
706    if not name:
707        name = gethostname()
708    names, addrs = _gethostbyaddr(name)
709    for a in names:
710        if a.find(".") >= 0:
711            return a
712    return name
713
714@raises_java_exception
715def gethostname():
716    return asPyString(java.net.InetAddress.getLocalHost().getHostName())
717
718@raises_java_exception
719def gethostbyname(name):
720    return asPyString(java.net.InetAddress.getByName(name).getHostAddress())
721
722#
723# Skeleton implementation of gethostbyname_ex
724# Needed because urllib2 refers to it
725#
726
727@raises_java_exception
728def gethostbyname_ex(name):
729    return (name, [], gethostbyname(name))
730
731@raises_java_exception
732def gethostbyaddr(name):
733    names, addrs = _gethostbyaddr(name)
734    return (names[0], names, addrs)
735
736def getservbyname(service_name, protocol_name=None):
737    try:
738        from jnr.netdb import Service
739    except ImportError:
740        return None
741    service = Service.getServiceByName(service_name, protocol_name)
742    if service is None:
743        raise error('service/proto not found')
744    return service.getPort()
745
746def getservbyport(port, protocol_name=None):
747    try:
748        from jnr.netdb import Service
749    except ImportError:
750        return None
751    service = Service.getServiceByPort(port, protocol_name)
752    if service is None:
753        raise error('port/proto not found')
754    return service.getName()
755
756def getprotobyname(protocol_name=None):
757    try:
758        from jnr.netdb import Protocol
759    except ImportError:
760        return None
761    proto = Protocol.getProtocolByName(protocol_name)
762    if proto is None:
763        raise error('protocol not found')
764    return proto.getProto()
765
766def _realsocket(family = AF_INET, sock_type = SOCK_STREAM, protocol=0):
767    assert family in (AF_INET, AF_INET6), "Only AF_INET and AF_INET6 sockets are currently supported on jython"
768    assert sock_type in (SOCK_DGRAM, SOCK_STREAM), "Only SOCK_STREAM and SOCK_DGRAM sockets are currently supported on jython"
769    if sock_type == SOCK_STREAM:
770        if protocol != 0:
771            assert protocol == IPPROTO_TCP, "Only IPPROTO_TCP supported on SOCK_STREAM sockets"
772        else:
773            protocol = IPPROTO_TCP
774        result = _tcpsocket()
775    else:
776        if protocol != 0:
777            assert protocol == IPPROTO_UDP, "Only IPPROTO_UDP supported on SOCK_DGRAM sockets"
778        else:
779            protocol = IPPROTO_UDP
780        result = _udpsocket()
781    setattr(result, "family", family)
782    setattr(result, "type",   sock_type)
783    setattr(result, "proto",  protocol)
784    return result
785
786#
787# Attempt to provide IDNA (RFC 3490) support.
788#
789# Try java.net.IDN, built into java 6
790#
791
792idna_libraries = [
793    ('java.net.IDN', 'toASCII', 'toUnicode',
794        'ALLOW_UNASSIGNED', 'USE_STD3_ASCII_RULES',
795        java.lang.IllegalArgumentException)
796]
797
798for idna_lib, efn, dfn, au, usar, exc in idna_libraries:
799    try:
800        m = __import__(idna_lib, globals(), locals(), [efn, dfn, au, usar])
801        encode_fn = getattr(m, efn)
802        def _encode_idna(name):
803            try:
804                return encode_fn(name)
805            except exc:
806                raise UnicodeEncodeError(name)
807        decode_fn = getattr(m, dfn)
808        def _decode_idna(name, flags=0):
809            try:
810                jflags = 0
811                if flags & NI_IDN_ALLOW_UNASSIGNED:
812                    jflags |= au
813                if flags & NI_IDN_USE_STD3_ASCII_RULES:
814                    jflags |= usar
815                return decode_fn(name, jflags)
816            except Exception, x:
817                raise UnicodeDecodeError(name)
818        supports('idna', True)
819        break
820    except (AttributeError, ImportError), e:
821        pass
822else:
823    _encode_idna = lambda x: x.encode("ascii")
824    _decode_idna = lambda x, y=0: x.decode("ascii")
825
826#
827# Define data structures to support IPV4 and IPV6.
828#
829
830class _ip_address_t: pass
831
832class _ipv4_address_t(_ip_address_t):
833
834    def __init__(self, sockaddr, port, jaddress):
835        self.sockaddr = sockaddr
836        self.port     = port
837        self.jaddress = jaddress
838
839    def __getitem__(self, index):
840        if   0 == index:
841            return self.sockaddr
842        elif 1 == index:
843            return self.port
844        else:
845            raise IndexError()
846
847    def __len__(self):
848        return 2
849
850    def __str__(self):
851        return "('%s', %d)" % (self.sockaddr, self.port)
852
853    __repr__ = __str__
854
855class _ipv6_address_t(_ip_address_t):
856
857    def __init__(self, sockaddr, port, jaddress):
858        self.sockaddr = sockaddr
859        self.port     = port
860        self.jaddress = jaddress
861
862    def __getitem__(self, index):
863        if   0 == index:
864            return self.sockaddr
865        elif 1 == index:
866            return self.port
867        elif 2 == index:
868            return 0
869        elif 3 == index:
870            return self.jaddress.scopeId
871        else:
872            raise IndexError()
873
874    def __len__(self):
875        return 4
876
877    def __str__(self):
878        return "('%s', %d, 0, %d)" % (self.sockaddr, self.port, self.jaddress.scopeId)
879
880    __repr__ = __str__
881
882def _get_jsockaddr(address_object, family, sock_type, proto, flags):
883    # Is this an object that was returned from getaddrinfo? If so, it already contains an InetAddress
884    if isinstance(address_object, _ip_address_t):
885        return java.net.InetSocketAddress(address_object.jaddress, address_object[1])
886    # The user passed an address tuple, not an object returned from getaddrinfo
887    # So we must call getaddrinfo, after some translations and checking
888    if address_object is None:
889        address_object = ("", 0)
890    error_message = "Address must be a 2-tuple (ipv4: (host, port)) or a 4-tuple (ipv6: (host, port, flow, scope))"
891    if not isinstance(address_object, tuple) or \
892            ((family == AF_INET and len(address_object) != 2) or (family == AF_INET6 and len(address_object) not in [2,4] )) or \
893            not isinstance(address_object[0], (basestring, types.NoneType)) or \
894            not isinstance(address_object[1], (int, long)):
895        raise TypeError(error_message)
896    if len(address_object) == 4 and not isinstance(address_object[3], (int, long)):
897        raise TypeError(error_message)
898    hostname = address_object[0]
899    if hostname is not None:
900        hostname = hostname.strip()
901    port = address_object[1]
902    if family == AF_INET and sock_type == SOCK_DGRAM and hostname == "<broadcast>":
903        hostname = INADDR_BROADCAST
904    if hostname in ["", None]:
905        if flags & AI_PASSIVE:
906            hostname = {AF_INET: INADDR_ANY, AF_INET6: IN6ADDR_ANY_INIT}[family]
907        else:
908            hostname = "localhost"
909    if isinstance(hostname, unicode):
910        hostname = _encode_idna(hostname)
911    addresses = getaddrinfo(hostname, port, family, sock_type, proto, flags)
912    if len(addresses) == 0:
913        raise gaierror(errno.EGETADDRINFOFAILED, 'getaddrinfo failed')
914    return java.net.InetSocketAddress(addresses[0][4].jaddress, port)
915
916# Workaround for this (predominantly windows) issue
917# http://wiki.python.org/jython/NewSocketModule#IPV6_address_support
918
919_ipv4_addresses_only = False
920
921def _use_ipv4_addresses_only(value):
922    global _ipv4_addresses_only
923    _ipv4_addresses_only = value
924
925def _getaddrinfo_get_host(host, family, flags):
926    if not isinstance(host, basestring) and host is not None:
927        raise TypeError("getaddrinfo() argument 1 must be string or None")
928    if flags & AI_NUMERICHOST:
929        if not is_ip_address(host):
930            raise gaierror(EAI_NONAME, "Name or service not known")
931        if family == AF_INET and not is_ipv4_address(host):
932            raise gaierror(EAI_ADDRFAMILY, "Address family for hostname not supported")
933        if family == AF_INET6 and not is_ipv6_address(host):
934            raise gaierror(EAI_ADDRFAMILY, "Address family for hostname not supported")
935    if isinstance(host, unicode):
936        host = _encode_idna(host)
937    return host
938
939def _getaddrinfo_get_port(port, flags):
940    if isinstance(port, basestring):
941        try:
942            int_port = int(port)
943        except ValueError:
944            if flags & AI_NUMERICSERV:
945                raise gaierror(EAI_NONAME, "Name or service not known")
946            # Lookup the service by name
947            try:
948                int_port = getservbyname(port)
949            except error:
950                raise gaierror(EAI_SERVICE, "Servname not supported for ai_socktype")
951    elif port is None:
952        int_port = 0
953    elif not isinstance(port, (int, long)):
954        raise error("Int or String expected")
955    else:
956        int_port = int(port)
957    return int_port % 65536
958
959@raises_java_exception
960def getaddrinfo(host, port, family=AF_UNSPEC, socktype=0, proto=0, flags=0):
961    if _ipv4_addresses_only:
962        family = AF_INET
963    if not family in [AF_INET, AF_INET6, AF_UNSPEC]:
964        raise gaierror(errno.EIO, 'ai_family not supported')
965    host = _getaddrinfo_get_host(host, family, flags)
966    port = _getaddrinfo_get_port(port, flags)
967    if socktype not in [0, SOCK_DGRAM, SOCK_STREAM]:
968        raise error(errno.ESOCKTNOSUPPORT, "Socket type %s is not supported" % _constant_to_name(socktype, ['SOCK_']))
969    filter_fns = []
970    filter_fns.append({
971        AF_INET:   lambda x: isinstance(x, java.net.Inet4Address),
972        AF_INET6:  lambda x: isinstance(x, java.net.Inet6Address),
973        AF_UNSPEC: lambda x: isinstance(x, java.net.InetAddress),
974    }[family])
975    if host in [None, ""]:
976        if flags & AI_PASSIVE:
977             hosts = {AF_INET: [INADDR_ANY], AF_INET6: [IN6ADDR_ANY_INIT], AF_UNSPEC: [INADDR_ANY, IN6ADDR_ANY_INIT]}[family]
978        else:
979             hosts = ["localhost"]
980    else:
981        hosts = [host]
982    results = []
983    for h in hosts:
984        for a in java.net.InetAddress.getAllByName(h):
985            if len([f for f in filter_fns if f(a)]):
986                family = {java.net.Inet4Address: AF_INET, java.net.Inet6Address: AF_INET6}[a.getClass()]
987                if flags & AI_CANONNAME:
988                    canonname = asPyString(a.getCanonicalHostName())
989                else:
990                    canonname = ""
991                sockaddr = asPyString(a.getHostAddress())
992                # TODO: Include flowinfo and scopeid in a 4-tuple for IPv6 addresses
993                sock_tuple = {AF_INET : _ipv4_address_t, AF_INET6 : _ipv6_address_t}[family](sockaddr, port, a)
994                if socktype == 0:
995                    socktypes = [SOCK_DGRAM, SOCK_STREAM]
996                else:
997                    socktypes = [socktype]
998                for result_socktype in socktypes:
999                    result_proto = {SOCK_DGRAM: IPPROTO_UDP, SOCK_STREAM: IPPROTO_TCP}[result_socktype]
1000                    if proto in [0, result_proto]:
1001                        # The returned socket will only support the result_proto
1002                        # If this does not match the requested proto, don't return it
1003                        results.append((family, result_socktype, result_proto, canonname, sock_tuple))
1004    return results
1005
1006def _getnameinfo_get_host(address, flags):
1007    if not isinstance(address, basestring):
1008        raise TypeError("getnameinfo() address 1 must be string, not None")
1009    if isinstance(address, unicode):
1010        address = _encode_idna(address)
1011    jia = java.net.InetAddress.getByName(address)
1012    result = jia.getCanonicalHostName()
1013    if flags & NI_NAMEREQD:
1014        if is_ip_address(result):
1015            raise gaierror(EAI_NONAME, "Name or service not known")
1016    elif flags & NI_NUMERICHOST:
1017        result = jia.getHostAddress()
1018    # Ignoring NI_NOFQDN for now
1019    if flags & NI_IDN:
1020        result = _decode_idna(result, flags)
1021    return result
1022
1023def _getnameinfo_get_port(port, flags):
1024    if not isinstance(port, (int, long)):
1025        raise TypeError("getnameinfo() port number must be an integer")
1026    if flags & NI_NUMERICSERV:
1027        return port
1028    proto = None
1029    if flags & NI_DGRAM:
1030        proto = "udp"
1031    return getservbyport(port, proto)
1032
1033@raises_java_exception
1034def getnameinfo(sock_addr, flags):
1035    if not isinstance(sock_addr, tuple) or len(sock_addr) < 2:
1036        raise TypeError("getnameinfo() argument 1 must be a tuple")
1037    host = _getnameinfo_get_host(sock_addr[0], flags)
1038    port = _getnameinfo_get_port(sock_addr[1], flags)
1039    return (host, port)
1040
1041def getdefaulttimeout():
1042    return _defaulttimeout
1043
1044def _calctimeoutvalue(value):
1045    if value is None:
1046        return None
1047    try:
1048        floatvalue = float(value)
1049    except:
1050        raise TypeError('Socket timeout value must be a number or None')
1051    if floatvalue < 0.0:
1052        raise ValueError("Socket timeout value cannot be negative")
1053    if floatvalue < 0.000001:
1054        return 0.0
1055    return floatvalue
1056
1057def setdefaulttimeout(timeout):
1058    global _defaulttimeout
1059    try:
1060        _defaulttimeout = _calctimeoutvalue(timeout)
1061    finally:
1062        _nonblocking_api_mixin.timeout = _defaulttimeout
1063
1064def htons(x): return x
1065def htonl(x): return x
1066def ntohs(x): return x
1067def ntohl(x): return x
1068
1069@raises_java_exception
1070def inet_pton(family, ip_string):
1071    if family == AF_INET:
1072        if not is_ipv4_address(ip_string):
1073            raise error("illegal IP address string passed to inet_pton")
1074    elif family == AF_INET6:
1075        if not is_ipv6_address(ip_string):
1076            raise error("illegal IP address string passed to inet_pton")
1077    else:
1078        raise error(errno.EAFNOSUPPORT, "Address family not supported by protocol")
1079    ia = java.net.InetAddress.getByName(ip_string)
1080    bytes = []
1081    for byte in ia.getAddress():
1082        if byte < 0:
1083            bytes.append(byte+256)
1084        else:
1085            bytes.append(byte)
1086    return "".join([chr(byte) for byte in bytes])
1087
1088@raises_java_exception
1089def inet_ntop(family, packed_ip):
1090    jByteArray = jarray.array(packed_ip, 'b')
1091    if family == AF_INET:
1092        if len(jByteArray) != 4:
1093            raise ValueError("invalid length of packed IP address string")
1094    elif family == AF_INET6:
1095        if len(jByteArray) != 16:
1096            raise ValueError("invalid length of packed IP address string")
1097    else:
1098        raise ValueError("unknown address family %s" % family)
1099    ia = java.net.InetAddress.getByAddress(jByteArray)
1100    return ia.getHostAddress()
1101
1102def inet_aton(ip_string):
1103    return inet_pton(AF_INET, ip_string)
1104
1105def inet_ntoa(packed_ip):
1106    return inet_ntop(AF_INET, packed_ip)
1107
1108class _nonblocking_api_mixin:
1109
1110    mode            = MODE_BLOCKING
1111    reference_count = 0
1112    close_lock      = threading.Lock()
1113
1114    def __init__(self):
1115        self.timeout = _defaulttimeout
1116        if self.timeout is not None:
1117            self.mode = MODE_TIMEOUT
1118        self.pending_options = {
1119            (SOL_SOCKET, SO_REUSEADDR):  0,
1120        }
1121
1122    def gettimeout(self):
1123        return self.timeout
1124
1125    def settimeout(self, timeout):
1126        self.timeout = _calctimeoutvalue(timeout)
1127        if self.timeout is None:
1128            self.mode = MODE_BLOCKING
1129        elif self.timeout < 0.000001:
1130            self.mode = MODE_NONBLOCKING
1131        else:
1132            self.mode = MODE_TIMEOUT
1133        self._config()
1134
1135    def setblocking(self, flag):
1136        if flag:
1137            self.mode = MODE_BLOCKING
1138            self.timeout = None
1139        else:
1140            self.mode = MODE_NONBLOCKING
1141            self.timeout = 0.0
1142        self._config()
1143
1144    def getblocking(self):
1145        return self.mode == MODE_BLOCKING
1146
1147    @raises_java_exception
1148    def setsockopt(self, level, optname, value):
1149        if self.sock_impl:
1150            self.sock_impl.setsockopt(level, optname, value)
1151        else:
1152            self.pending_options[ (level, optname) ] = value
1153
1154    @raises_java_exception
1155    def getsockopt(self, level, optname):
1156        # Handle "pseudo" options first
1157        if level == SOL_SOCKET and optname == SO_TYPE:
1158            return getattr(self, "type")
1159        if level == SOL_SOCKET and optname == SO_ERROR:
1160            return_value = self._last_error
1161            self._last_error = 0
1162            return return_value
1163        # Now handle "real" options
1164        if self.sock_impl:
1165            return self.sock_impl.getsockopt(level, optname)
1166        else:
1167            return self.pending_options.get( (level, optname), None)
1168
1169    @raises_java_exception
1170    def shutdown(self, how):
1171        assert how in (SHUT_RD, SHUT_WR, SHUT_RDWR)
1172        if not self.sock_impl:
1173            raise error(errno.ENOTCONN, "Transport endpoint is not connected")
1174        self.sock_impl.shutdown(how)
1175
1176    @raises_java_exception
1177    def close(self):
1178        if self.sock_impl:
1179            self.sock_impl.close()
1180
1181    @raises_java_exception
1182    def getsockname(self):
1183        if self.sock_impl is None:
1184            # If the user has already bound an address, return that
1185            if self.local_addr:
1186                return self.local_addr
1187            # The user has not bound, connected or listened
1188            # This is what cpython raises in this scenario
1189            raise error(errno.EINVAL, "Invalid argument")
1190        return self.sock_impl.getsockname()
1191
1192    @raises_java_exception
1193    def getpeername(self):
1194        if self.sock_impl is None:
1195            raise error(errno.ENOTCONN, "Socket is not connected")
1196        return self.sock_impl.getpeername()
1197
1198    def _config(self):
1199        assert self.mode in _permitted_modes
1200        if self.sock_impl:
1201            self.sock_impl.config(self.mode, self.timeout)
1202            for level, optname in self.pending_options.keys():
1203                if optname != SO_REUSEADDR:
1204                    self.sock_impl.setsockopt(level, optname, self.pending_options[ (level, optname) ])
1205
1206    def getchannel(self):
1207        if not self.sock_impl:
1208            return None
1209        return self.sock_impl.getchannel()
1210
1211    def fileno(self):
1212        if not self.sock_impl:
1213            return None
1214        return self.sock_impl.fileno()
1215
1216    def _get_jsocket(self):
1217        return self.sock_impl.jsocket
1218
1219class _tcpsocket(_nonblocking_api_mixin):
1220
1221    sock_impl   = None
1222    istream     = None
1223    ostream     = None
1224    local_addr  = None
1225    server      = 0
1226    _last_error = 0
1227
1228    def __init__(self):
1229        _nonblocking_api_mixin.__init__(self)
1230
1231    def getsockopt(self, level, optname):
1232        if level == SOL_SOCKET and optname == SO_ACCEPTCONN:
1233            return self.server
1234        return _nonblocking_api_mixin.getsockopt(self, level, optname)
1235
1236    @raises_java_exception
1237    def bind(self, addr):
1238        assert not self.sock_impl
1239        assert not self.local_addr
1240        # Do the address format check
1241        _get_jsockaddr(addr, self.family, self.type, self.proto, AI_PASSIVE)
1242        self.local_addr = addr
1243
1244    @raises_java_exception
1245    def listen(self, backlog):
1246        "This signifies a server socket"
1247        assert not self.sock_impl
1248        self.server = 1
1249        self.sock_impl = _server_socket_impl(_get_jsockaddr(self.local_addr, self.family, self.type, self.proto, AI_PASSIVE),
1250                              backlog, self.pending_options[ (SOL_SOCKET, SO_REUSEADDR) ])
1251        self._config()
1252
1253    @raises_java_exception
1254    def accept(self):
1255        "This signifies a server socket"
1256        if not self.sock_impl:
1257            self.listen()
1258        assert self.server
1259        new_sock = self.sock_impl.accept()
1260        if not new_sock:
1261            raise would_block_error()
1262        cliconn = _tcpsocket()
1263        cliconn.pending_options[ (SOL_SOCKET, SO_REUSEADDR) ] = new_sock.jsocket.getReuseAddress()
1264        cliconn.sock_impl = new_sock
1265        cliconn._setup()
1266        return cliconn, new_sock.getpeername()
1267
1268    def _do_connect(self, addr):
1269        assert not self.sock_impl
1270        self.sock_impl = _client_socket_impl()
1271        if self.local_addr: # Has the socket been bound to a local address?
1272            self.sock_impl.bind(_get_jsockaddr(self.local_addr, self.family, self.type, self.proto, 0),
1273                                 self.pending_options[ (SOL_SOCKET, SO_REUSEADDR) ])
1274        self._config() # Configure timeouts, etc, now that the socket exists
1275        self.sock_impl.connect(_get_jsockaddr(addr, self.family, self.type, self.proto, 0))
1276
1277    @raises_java_exception
1278    def connect(self, addr):
1279        "This signifies a client socket"
1280        self._do_connect(addr)
1281        self._setup()
1282
1283    @raises_java_exception
1284    def connect_ex(self, addr):
1285        "This signifies a client socket"
1286        if not self.sock_impl:
1287            self._do_connect(addr)
1288        if self.sock_impl.finish_connect():
1289            self._setup()
1290            if self.mode == MODE_NONBLOCKING:
1291                return errno.EISCONN
1292            return 0
1293        return errno.EINPROGRESS
1294
1295    def _setup(self):
1296        if self.mode != MODE_NONBLOCKING:
1297            self.istream = self.sock_impl.jsocket.getInputStream()
1298            self.ostream = self.sock_impl.jsocket.getOutputStream()
1299
1300    @raises_java_exception
1301    def recv(self, n):
1302        if not self.sock_impl: raise error(errno.ENOTCONN, 'Socket is not connected')
1303        if self.sock_impl.jchannel.isConnectionPending():
1304            self.sock_impl.jchannel.finishConnect()
1305        data = jarray.zeros(n, 'b')
1306        m = self.sock_impl.read(data)
1307        if m == -1:#indicates EOF has been reached, so we just return the empty string
1308            return ""
1309        elif m <= 0:
1310            if self.mode == MODE_NONBLOCKING:
1311                raise would_block_error()
1312            return ""
1313        if m < n:
1314            data = data[:m]
1315        return data.tostring()
1316
1317    @raises_java_exception
1318    def recvfrom(self, n):
1319        return self.recv(n), self.getpeername()
1320
1321    @raises_java_exception
1322    def send(self, s):
1323        if not self.sock_impl: raise error(errno.ENOTCONN, 'Socket is not connected')
1324        if self.sock_impl.jchannel.isConnectionPending():
1325            self.sock_impl.jchannel.finishConnect()
1326        numwritten = self.sock_impl.write(s)
1327        if numwritten == 0 and self.mode == MODE_NONBLOCKING:
1328            raise would_block_error()
1329        return numwritten
1330
1331    sendall = send
1332
1333    @raises_java_exception
1334    def close(self):
1335        if self.istream:
1336            self.istream.close()
1337        if self.ostream:
1338            self.ostream.close()
1339        if self.sock_impl:
1340            self.sock_impl.close()
1341
1342
1343class _udpsocket(_nonblocking_api_mixin):
1344
1345    sock_impl   = None
1346    connected   = False
1347    local_addr  = None
1348    _last_error = 0
1349
1350    def __init__(self):
1351        _nonblocking_api_mixin.__init__(self)
1352
1353    @raises_java_exception
1354    def bind(self, addr):
1355        assert not self.sock_impl
1356        assert not self.local_addr
1357        # Do the address format check
1358        _get_jsockaddr(addr, self.family, self.type, self.proto, AI_PASSIVE)
1359        self.local_addr = addr
1360        self.sock_impl = _datagram_socket_impl(_get_jsockaddr(self.local_addr, self.family, self.type, self.proto, AI_PASSIVE),
1361                                                self.pending_options[ (SOL_SOCKET, SO_REUSEADDR) ])
1362        self._config()
1363
1364    def _do_connect(self, addr):
1365        assert not self.connected, "Datagram Socket is already connected"
1366        if not self.sock_impl:
1367            self.sock_impl = _datagram_socket_impl()
1368            self._config()
1369        self.sock_impl.connect(_get_jsockaddr(addr, self.family, self.type, self.proto, 0))
1370        self.connected = True
1371
1372    @raises_java_exception
1373    def connect(self, addr):
1374        self._do_connect(addr)
1375
1376    @raises_java_exception
1377    def connect_ex(self, addr):
1378        if not self.sock_impl:
1379            self._do_connect(addr)
1380        return 0
1381
1382    @raises_java_exception
1383    def sendto(self, data, p1, p2=None):
1384        if not p2:
1385            flags, addr = 0, p1
1386        else:
1387            flags, addr = 0, p2
1388        if not self.sock_impl:
1389            self.sock_impl = _datagram_socket_impl()
1390            self._config()
1391        byte_array = java.lang.String(data).getBytes('iso-8859-1')
1392        result = self.sock_impl.sendto(byte_array, _get_jsockaddr(addr, self.family, self.type, self.proto, 0), flags)
1393        return result
1394
1395    @raises_java_exception
1396    def send(self, data, flags=None):
1397        if not self.connected: raise error(errno.ENOTCONN, "Socket is not connected")
1398        byte_array = java.lang.String(data).getBytes('iso-8859-1')
1399        return self.sock_impl.send(byte_array, flags)
1400
1401    @raises_java_exception
1402    def recvfrom(self, num_bytes, flags=None):
1403        """
1404        There is some disagreement as to what the behaviour should be if
1405        a recvfrom operation is requested on an unbound socket.
1406        See the following links for more information
1407        http://bugs.jython.org/issue1005
1408        http://bugs.sun.com/view_bug.do?bug_id=6621689
1409        """
1410        # This is the old 2.1 behaviour
1411        #assert self.sock_impl
1412        # This is amak's preferred interpretation
1413        #raise error(errno.ENOTCONN, "Recvfrom on unbound udp socket meaningless operation")
1414        # And this is the option for cpython compatibility
1415        if not self.sock_impl:
1416            self.sock_impl = _datagram_socket_impl()
1417            self._config()
1418        return self.sock_impl.recvfrom(num_bytes, flags)
1419
1420    @raises_java_exception
1421    def recv(self, num_bytes, flags=None):
1422        if not self.sock_impl:
1423            raise error(errno.ENOTCONN, "Socket is not connected")
1424        return self.sock_impl.recv(num_bytes, flags)
1425
1426    def __del__(self):
1427        self.close()
1428
1429_socketmethods = (
1430    'bind', 'connect', 'connect_ex', 'fileno', 'listen',
1431    'getpeername', 'getsockname', 'getsockopt', 'setsockopt',
1432    'sendall', 'setblocking',
1433    'settimeout', 'gettimeout', 'shutdown', 'getchannel')
1434
1435# All the method names that must be delegated to either the real socket
1436# object or the _closedsocket object.
1437_delegate_methods = ("recv", "recvfrom", "recv_into", "recvfrom_into",
1438                     "send", "sendto")
1439
1440class _closedsocket(object):
1441    __slots__ = []
1442    def _dummy(*args):
1443        raise error(errno.EBADF, 'Bad file descriptor')
1444    # All _delegate_methods must also be initialized here.
1445    send = recv = recv_into = sendto = recvfrom = recvfrom_into = _dummy
1446    __getattr__ = _dummy
1447
1448_active_sockets = set()
1449
1450def _closeActiveSockets():
1451    for socket in _active_sockets.copy():
1452        try:
1453            socket.close()
1454        except error:
1455            msg = 'Problem closing socket: %s: %r' % (socket, sys.exc_info())
1456            print >> sys.stderr, msg
1457
1458class _socketobject(object):
1459
1460    __doc__ = _realsocket.__doc__
1461
1462    __slots__ = ["_sock", "__weakref__"] + list(_delegate_methods)
1463
1464    def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None):
1465        if _sock is None:
1466            _sock = _realsocket(family, type, proto)
1467            _sock.reference_count += 1
1468        elif isinstance(_sock, _nonblocking_api_mixin):
1469            _sock.reference_count += 1
1470        self._sock = _sock
1471        for method in _delegate_methods:
1472            meth = getattr(_sock, method, None)
1473            if meth:
1474                setattr(self, method, meth)
1475        _active_sockets.add(self)
1476
1477    def close(self):
1478        try:
1479            _active_sockets.remove(self)
1480        except KeyError:
1481            pass
1482        _sock = self._sock
1483        if isinstance(_sock, _nonblocking_api_mixin):
1484            _sock.close_lock.acquire()
1485            try:
1486                _sock.reference_count -=1
1487                if not _sock.reference_count:
1488                    _sock.close()
1489                self._sock = _closedsocket()
1490                dummy = self._sock._dummy
1491                for method in _delegate_methods:
1492                    setattr(self, method, dummy)
1493                self.send = self.recv = self.sendto = self.recvfrom = \
1494                    self._sock._dummy
1495            finally:
1496                _sock.close_lock.release()
1497    #close.__doc__ = _realsocket.close.__doc__
1498
1499    def accept(self):
1500        sock, addr = self._sock.accept()
1501        return _socketobject(_sock=sock), addr
1502    #accept.__doc__ = _realsocket.accept.__doc__
1503
1504    def dup(self):
1505        """dup() -> socket object
1506
1507        Return a new socket object connected to the same system resource."""
1508        _sock = self._sock
1509        if not isinstance(_sock, _nonblocking_api_mixin):
1510            return _socketobject(_sock=_sock)
1511
1512        _sock.close_lock.acquire()
1513        try:
1514            duped = _socketobject(_sock=_sock)
1515        finally:
1516            _sock.close_lock.release()
1517        return duped
1518
1519    def makefile(self, mode='r', bufsize=-1):
1520        """makefile([mode[, bufsize]]) -> file object
1521
1522        Return a regular file object corresponding to the socket.  The mode
1523        and bufsize arguments are as for the built-in open() function."""
1524        _sock = self._sock
1525        if not isinstance(_sock, _nonblocking_api_mixin):
1526            return _fileobject(_sock, mode, bufsize)
1527
1528        _sock.close_lock.acquire()
1529        try:
1530            fileobject = _fileobject(_sock, mode, bufsize)
1531        finally:
1532            _sock.close_lock.release()
1533        return fileobject
1534
1535    family = property(lambda self: self._sock.family, doc="the socket family")
1536    type = property(lambda self: self._sock.type, doc="the socket type")
1537    proto = property(lambda self: self._sock.proto, doc="the socket protocol")
1538
1539    _s = ("def %s(self, *args): return self._sock.%s(*args)\n\n"
1540          #"%s.__doc__ = _realsocket.%s.__doc__\n")
1541          )
1542    for _m in _socketmethods:
1543        #exec _s % (_m, _m, _m, _m)
1544        exec _s % (_m, _m)
1545    del _m, _s
1546
1547socket = SocketType = _socketobject
1548
1549class _fileobject(object):
1550    """Faux file object attached to a socket object."""
1551
1552    default_bufsize = 8192
1553    name = "<socket>"
1554
1555    __slots__ = ["mode", "bufsize", "softspace",
1556                 # "closed" is a property, see below
1557                 "_sock", "_rbufsize", "_wbufsize", "_rbuf", "_wbuf",
1558                 "_close"]
1559
1560    def __init__(self, sock, mode='rb', bufsize=-1, close=False):
1561        self._sock = sock
1562        if isinstance(sock, _nonblocking_api_mixin):
1563            sock.reference_count += 1
1564        self.mode = mode # Not actually used in this version
1565        if bufsize < 0:
1566            bufsize = self.default_bufsize
1567        self.bufsize = bufsize
1568        self.softspace = False
1569        if bufsize == 0:
1570            self._rbufsize = 1
1571        elif bufsize == 1:
1572            self._rbufsize = self.default_bufsize
1573        else:
1574            self._rbufsize = bufsize
1575        self._wbufsize = bufsize
1576        self._rbuf = "" # A string
1577        self._wbuf = [] # A list of strings
1578        self._close = close
1579
1580    def _getclosed(self):
1581        return self._sock is None
1582    closed = property(_getclosed, doc="True if the file is closed")
1583
1584    def close(self):
1585        try:
1586            if self._sock:
1587                self.flush()
1588        finally:
1589            if self._sock:
1590                if isinstance(self._sock, _nonblocking_api_mixin):
1591                    self._sock.reference_count -= 1
1592                    if not self._sock.reference_count or self._close:
1593                        self._sock.close()
1594                elif self._close:
1595                    self._sock.close()
1596            self._sock = None
1597
1598    def __del__(self):
1599        try:
1600            self.close()
1601        except:
1602            # close() may fail if __init__ didn't complete
1603            pass
1604
1605    def flush(self):
1606        if self._wbuf:
1607            buffer = "".join(self._wbuf)
1608            self._wbuf = []
1609            self._sock.sendall(buffer)
1610
1611    def fileno(self):
1612        return self._sock.fileno()
1613
1614    def write(self, data):
1615        data = str(data) # XXX Should really reject non-string non-buffers
1616        if not data:
1617            return
1618        self._wbuf.append(data)
1619        if (self._wbufsize == 0 or
1620            self._wbufsize == 1 and '\n' in data or
1621            self._get_wbuf_len() >= self._wbufsize):
1622            self.flush()
1623
1624    def writelines(self, list):
1625        # XXX We could do better here for very long lists
1626        # XXX Should really reject non-string non-buffers
1627        self._wbuf.extend(filter(None, map(str, list)))
1628        if (self._wbufsize <= 1 or
1629            self._get_wbuf_len() >= self._wbufsize):
1630            self.flush()
1631
1632    def _get_wbuf_len(self):
1633        buf_len = 0
1634        for x in self._wbuf:
1635            buf_len += len(x)
1636        return buf_len
1637
1638    def read(self, size=-1):
1639        data = self._rbuf
1640        if size < 0:
1641            # Read until EOF
1642            buffers = []
1643            if data:
1644                buffers.append(data)
1645            self._rbuf = ""
1646            if self._rbufsize <= 1:
1647                recv_size = self.default_bufsize
1648            else:
1649                recv_size = self._rbufsize
1650            while True:
1651                data = self._sock.recv(recv_size)
1652                if not data:
1653                    break
1654                buffers.append(data)
1655            return "".join(buffers)
1656        else:
1657            # Read until size bytes or EOF seen, whichever comes first
1658            buf_len = len(data)
1659            if buf_len >= size:
1660                self._rbuf = data[size:]
1661                return data[:size]
1662            buffers = []
1663            if data:
1664                buffers.append(data)
1665            self._rbuf = ""
1666            while True:
1667                left = size - buf_len
1668                recv_size = max(self._rbufsize, left)
1669                data = self._sock.recv(recv_size)
1670                if not data:
1671                    break
1672                buffers.append(data)
1673                n = len(data)
1674                if n >= left:
1675                    self._rbuf = data[left:]
1676                    buffers[-1] = data[:left]
1677                    break
1678                buf_len += n
1679            return "".join(buffers)
1680
1681    def readline(self, size=-1):
1682        data = self._rbuf
1683        if size < 0:
1684            # Read until \n or EOF, whichever comes first
1685            if self._rbufsize <= 1:
1686                # Speed up unbuffered case
1687                assert data == ""
1688                buffers = []
1689                recv = self._sock.recv
1690                while data != "\n":
1691                    data = recv(1)
1692                    if not data:
1693                        break
1694                    buffers.append(data)
1695                return "".join(buffers)
1696            nl = data.find('\n')
1697            if nl >= 0:
1698                nl += 1
1699                self._rbuf = data[nl:]
1700                return data[:nl]
1701            buffers = []
1702            if data:
1703                buffers.append(data)
1704            self._rbuf = ""
1705            while True:
1706                data = self._sock.recv(self._rbufsize)
1707                if not data:
1708                    break
1709                buffers.append(data)
1710                nl = data.find('\n')
1711                if nl >= 0:
1712                    nl += 1
1713                    self._rbuf = data[nl:]
1714                    buffers[-1] = data[:nl]
1715                    break
1716            return "".join(buffers)
1717        else:
1718            # Read until size bytes or \n or EOF seen, whichever comes first
1719            nl = data.find('\n', 0, size)
1720            if nl >= 0:
1721                nl += 1
1722                self._rbuf = data[nl:]
1723                return data[:nl]
1724            buf_len = len(data)
1725            if buf_len >= size:
1726                self._rbuf = data[size:]
1727                return data[:size]
1728            buffers = []
1729            if data:
1730                buffers.append(data)
1731            self._rbuf = ""
1732            while True:
1733                data = self._sock.recv(self._rbufsize)
1734                if not data:
1735                    break
1736                buffers.append(data)
1737                left = size - buf_len
1738                nl = data.find('\n', 0, left)
1739                if nl >= 0:
1740                    nl += 1
1741                    self._rbuf = data[nl:]
1742                    buffers[-1] = data[:nl]
1743                    break
1744                n = len(data)
1745                if n >= left:
1746                    self._rbuf = data[left:]
1747                    buffers[-1] = data[:left]
1748                    break
1749                buf_len += n
1750            return "".join(buffers)
1751
1752    def readlines(self, sizehint=0):
1753        total = 0
1754        list = []
1755        while True:
1756            line = self.readline()
1757            if not line:
1758                break
1759            list.append(line)
1760            total += len(line)
1761            if sizehint and total >= sizehint:
1762                break
1763        return list
1764
1765    # Iterator protocols
1766
1767    def __iter__(self):
1768        return self
1769
1770    def next(self):
1771        line = self.readline()
1772        if not line:
1773            raise StopIteration
1774        return line
1775
1776_GLOBAL_DEFAULT_TIMEOUT = object()
1777
1778def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,
1779                      source_address=None):
1780    """Connect to *address* and return the socket object.
1781
1782    Convenience function.  Connect to *address* (a 2-tuple ``(host,
1783    port)``) and return the socket object.  Passing the optional
1784    *timeout* parameter will set the timeout on the socket instance
1785    before attempting to connect.  If no *timeout* is supplied, the
1786    global default timeout setting returned by :func:`getdefaulttimeout`
1787    is used.  If *source_address* is set it must be a tuple of (host, port)
1788    for the socket to bind as a source address before making the connection.
1789    An host of '' or port 0 tells the OS to use the default.
1790    """
1791
1792    host, port = address
1793    err = None
1794    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
1795        af, socktype, proto, canonname, sa = res
1796        sock = None
1797        try:
1798            sock = socket(af, socktype, proto)
1799            if timeout is not _GLOBAL_DEFAULT_TIMEOUT:
1800                sock.settimeout(timeout)
1801            if source_address:
1802                sock.bind(source_address)
1803            sock.connect(sa)
1804            return sock
1805
1806        except error as _:
1807            err = _
1808            if sock is not None:
1809                sock.close()
1810
1811    if err is not None:
1812        raise err
1813    else:
1814        raise error("getaddrinfo returns an empty list")
1815
1816# Define the SSL support
1817
1818class ssl:
1819
1820    @raises_java_exception
1821    def __init__(self, jython_socket_wrapper, keyfile=None, certfile=None):
1822        self.jython_socket_wrapper = jython_socket_wrapper
1823        jython_socket = self.jython_socket_wrapper._sock
1824        self.java_ssl_socket = self._make_ssl_socket(jython_socket)
1825        self._in_buf = java.io.BufferedInputStream(self.java_ssl_socket.getInputStream())
1826        self._out_buf = java.io.BufferedOutputStream(self.java_ssl_socket.getOutputStream())
1827
1828    def _make_ssl_socket(self, jython_socket, auto_close=0):
1829        java_net_socket = jython_socket._get_jsocket()
1830        assert isinstance(java_net_socket, java.net.Socket)
1831        host = java_net_socket.getInetAddress().getHostAddress()
1832        port = java_net_socket.getPort()
1833        factory = javax.net.ssl.SSLSocketFactory.getDefault();
1834        java_ssl_socket = factory.createSocket(java_net_socket, host, port, auto_close)
1835        java_ssl_socket.setEnabledCipherSuites(java_ssl_socket.getSupportedCipherSuites())
1836        java_ssl_socket.startHandshake()
1837        return java_ssl_socket
1838
1839    @raises_java_exception
1840    def read(self, n=4096):
1841        data = jarray.zeros(n, 'b')
1842        m = self._in_buf.read(data, 0, n)
1843        if m <= 0:
1844            return ""
1845        if m < n:
1846            data = data[:m]
1847        return data.tostring()
1848
1849    recv = read
1850
1851    @raises_java_exception
1852    def write(self, s):
1853        self._out_buf.write(s)
1854        self._out_buf.flush()
1855        return len(s)
1856
1857    send = sendall = write
1858
1859    def makefile(self, mode='r', bufsize=-1):
1860        return _fileobject(self, mode, bufsize)
1861
1862    def _get_server_cert(self):
1863        return self.java_ssl_socket.getSession().getPeerCertificates()[0]
1864
1865    @raises_java_exception
1866    def server(self):
1867        cert = self._get_server_cert()
1868        return cert.getSubjectDN().toString()
1869
1870    @raises_java_exception
1871    def issuer(self):
1872        cert = self._get_server_cert()
1873        return cert.getIssuerDN().toString()
1874
1875    def close(self):
1876        self.jython_socket_wrapper.close()
1877
1878def test():
1879    s = socket(AF_INET, SOCK_STREAM)
1880    s.connect(("", 80))
1881    s.send("GET / HTTP/1.0\r\n\r\n")
1882    while 1:
1883        data = s.recv(2000)
1884        print data
1885        if not data:
1886            break
1887
1888if __name__ == '__main__':
1889    test()
1890