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