/src/sockets.py
Python | 757 lines | 535 code | 67 blank | 155 comment | 94 complexity | 411b3d086446cb3889f59e69d0b28ac3 MD5 | raw file
1# -*- coding: iso-8859-1 -*- 2# ----------------------------------------------------------------------------- 3# sockets.py - TCP/Unix Socket for the Kaa Framework 4# ----------------------------------------------------------------------------- 5# kaa.base - The Kaa Application Framework 6# Copyright 2005-2012 Dirk Meyer, Jason Tackaberry, et al. 7# 8# Please see the file AUTHORS for a complete list of authors. 9# 10# This library is free software; you can redistribute it and/or modify 11# it under the terms of the GNU Lesser General Public License version 12# 2.1 as published by the Free Software Foundation. 13# 14# This library is distributed in the hope that it will be useful, but 15# WITHOUT ANY WARRANTY; without even the implied warranty of 16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17# Lesser General Public License for more details. 18# 19# You should have received a copy of the GNU Lesser General Public 20# License along with this library; if not, write to the Free Software 21# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 22# 02110-1301 USA 23# 24# ----------------------------------------------------------------------------- 25from __future__ import absolute_import 26 27__all__ = [ 'Socket', 'SocketError' ] 28 29import sys 30import errno 31import os 32import re 33import socket 34import logging 35import ctypes.util 36import collections 37 38from .errors import SocketError 39from .utils import property, tempfile 40from .thread import threaded 41from .async import InProgress 42from .io import IO_READ, IO_WRITE, IOChannel, WeakIOMonitor 43 44# get logging object 45log = logging.getLogger('kaa.base.sockets') 46 47 48TIMEOUT_SENTINEL = getattr(socket, '_GLOBAL_DEFAULT_TIMEOUT', object()) 49 50 51# Implement functions for converting between interface names and indexes. 52# Unfortunately these functions are not provided by the standard Python 53# socket library, so we must implement them ourselves with ctypes. 54 55def _libc(): 56 """ 57 On-demand loading of libc. Don't do this at initial import as the overhead 58 is non-trivial. 59 """ 60 try: 61 return _libc._lib 62 except AttributeError: 63 pass 64 65 _libc._lib = None 66 if ctypes.util.find_library('c'): 67 # ctypes in python >= 2.6 supports errno. 68 kwargs = {'use_errno': True} if sys.hexversion >= 0x02060000 else {} 69 _libc._lib = ctypes.CDLL(ctypes.util.find_library('c'), **kwargs) 70 return _libc._lib 71 72 73def if_nametoindex(name): 74 """ 75 Returns the interface index number for the given interface name. 76 77 :param name: name of the interface 78 :type name: str 79 :returns: integer of the interface id 80 :raises: ValueError if the interface name cannot be found; 81 NotImplementedError on unsupported platforms. 82 """ 83 try: 84 idx = _libc().if_nametoindex(name) 85 except AttributeError: 86 raise NotImplementedError('Platform does not support if_nametoindex()') 87 88 if idx <= 0: 89 raise ValueError('Interface "%s" not found' % name) 90 return idx 91 92 93def if_indextoname(idx): 94 """ 95 Returns the interface name for the given interface index number. 96 97 :param idx: the index for the interface 98 :type idx: int 99 :returns: name of the index 100 :raises: ValueError if the interface index is not found; 101 NotImplementedError on unsupported platforms. 102 """ 103 # Array must be at least IF_NAMESIZE, which is 16. Double it for good measure. 104 name = ctypes.create_string_buffer(32) 105 try: 106 ret = _libc().if_indextoname(idx, name) 107 except AttributeError: 108 raise NotImplementedError('Platform does not support if_indextoname()') 109 110 if not ret: 111 err = 'Failed to lookup interface index %d' % idx 112 if hasattr(ctypes, 'get_errno'): 113 err += ': ' + os.strerror(ctypes.get_errno()) 114 raise ValueError(err) 115 116 return name.value 117 118 119 120class Socket(IOChannel): 121 """ 122 Communicate over TCP or Unix sockets, implementing fully asynchronous reads 123 and writes. 124 125 kaa.Socket requires an IPv6-capable stack, and favors IPv6 connectivity 126 when available. This should generally be completely transparent on 127 IPv4-only networks. See :meth:`~kaa.Socket.connect` for more information. 128 """ 129 __kaasignals__ = { 130 'new-client-connecting': 131 ''' 132 Emitted when a new client is attempting to connect to a listening 133 socket, but before the connection is accepted. 134 135 ``def callback(...)`` 136 137 If :attr:`~kaa.Socket.auto_accept` is True (default), this signal 138 can be used to prevent the client connection by returning False from 139 the callback. If False, the callback must explicitly call 140 :meth:`~kaa.Socket.listen` or the client will not be connected. 141 ''', 142 143 'new-client': 144 ''' 145 Emitted when a new client connects to a listening socket. 146 147 ``def callback(client, ...)`` 148 149 :param client: the new client that just connected. 150 :type client: :class:`~kaa.Socket` object 151 ''' 152 } 153 154 @staticmethod 155 def normalize_address(addr): 156 """ 157 Converts supported address formats into a normalized 4-tuple (hostname, 158 port, flowinfo, scope). See connect() and listen() for supported 159 formats. 160 161 Service names are resolved to port numbers, and interface names are 162 resolved to scope ids. However, hostnames are not resolved to IPs 163 since that can block. Unspecified port or interface name will produced 164 0 values for those fields. 165 166 A non-absolute unix socket name will converted to a full path using 167 kaa.tempfile(). 168 169 If we can't make sense of the given address, a ValueError exception will 170 be raised. 171 """ 172 if isinstance(addr, int): 173 # Only port number specified; translate to tuple that can be 174 # used with socket.bind() 175 return ('', addr, 0, 0) 176 elif isinstance(addr, basestring): 177 m = re.match(r'^(\d+\.\d+\.\d+\.\d+)(?::(\d+))?', addr) 178 if m: 179 # It's an IPv4 address. 180 return (m.group(1), int(m.group(2) or 0), 0, 0) 181 elif ':' not in addr: 182 # Treat as unix socket. 183 return tempfile(addr) if not addr.startswith('/') else addr 184 185 # See if it's an IPv6 address 186 m = re.match(r'^ (\[(?:[\da-fA-F:]+)\] | (?:[^:]+) )? (?::(\w+))? (?:%(\w+))? ', addr, re.X) 187 if not m: 188 raise ValueError('Invalid format for address') 189 addr = m.group(1) or '', m.group(2) or 0, 0, m.group(3) or 0 190 if addr[0].isdigit(): 191 # Sanity check: happens when given ipv6 address without [] 192 raise ValueError('Invalid hostname: perhaps ipv6 address is not wrapped in []?') 193 194 elif not isinstance(addr, (tuple, list)) or len(addr) not in (2, 4): 195 raise ValueError('Invalid address specification (must be str, or 2- or 4-tuple)') 196 197 if len(addr) == 2: 198 # Coerce to 4-tuple, assume 0 for both scope and flowid. 199 addr = addr + (0, 0) 200 201 host, service, flowinfo, scopeid = addr 202 # Strip [] from ipv6 addr 203 if host.startswith('[') and host.endswith(']'): 204 host = host[1:-1] 205 # Resolve service name to port number 206 if isinstance(service, basestring): 207 service = int(service) if service.isdigit() else socket.getservbyname(service) 208 # Resolve interface names to index values 209 if isinstance(scopeid, basestring): 210 scopeid = int(scopeid) if scopeid.isdigit() else if_nametoindex(scopeid) 211 212 return host, service, flowinfo, scopeid 213 214 215 216 @staticmethod 217 def create_connection(addr=None, timeout=TIMEOUT_SENTINEL, source_address=None, 218 overwrite=False, ipv6=True): 219 addr = Socket.normalize_address(addr) if addr else None 220 source_address = Socket.normalize_address(source_address) if source_address else None 221 222 if isinstance(addr, str) or isinstance(source_address, str): 223 sockaddr = addr or source_address 224 if overwrite and os.path.exists(sockaddr): 225 # Unix socket exists; test to see if it's active. 226 try: 227 dummy = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) 228 dummy.connect(sockaddr) 229 except socket.error, (err, msg): 230 if err == errno.ECONNREFUSED: 231 # Socket is not active, so we can remove it. 232 log.debug('Replacing dead unix socket at %s' % sockaddr) 233 else: 234 # Reraise unexpected exception 235 raise 236 else: 237 # We were able to connect to the existing socket, so it's 238 # in use. We won't overwrite it. 239 raise IOError(errno.EADDRINUSE, 'Address already in use') 240 os.unlink(sockaddr) 241 242 sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) 243 if addr: 244 sock.connect(addr) 245 else: 246 sock.bind(source_address) 247 return sock 248 249 250 # Not a unix socket ... 251 req_family = socket.AF_UNSPEC if ipv6 else socket.AF_INET 252 addr_addrinfo = source_addrinfo = None 253 if source_address: 254 # If link-local address is specified, make sure the scopeid is given. 255 if source_address[0].lower().startswith('fe80::'): 256 if not source_address[3]: 257 raise ValueError('Binding to a link-local address requires scopeid') 258 elif not source_address[0]: 259 source_addrinfo = [(socket.AF_INET, socket.SOCK_STREAM, 0, 0, source_address)] 260 elif source_address[0] == '::' and ipv6: 261 source_addrinfo = [(socket.AF_INET6, socket.SOCK_STREAM, 0, 0, source_address)] 262 else: 263 source_addrinfo = socket.getaddrinfo(source_address[0], source_address[1], 264 req_family, socket.SOCK_STREAM) 265 if not source_addrinfo: 266 raise socket.error('getaddrinfo returned empty list for source address') 267 268 if addr: 269 addr_addrinfo = socket.getaddrinfo(addr[0], addr[1], req_family, socket.SOCK_STREAM) 270 if not addr_addrinfo: 271 raise socket.error('getaddrinfo returned empty list for destination address') 272 273 # At least on Linux, returned list is ordered to prefer IPv6 addresses 274 # provided that a route is available to them. We try all addresses 275 # until we get a connection, and if all addresses fail, then we raise 276 # the _first_ exception. 277 err = sock = None 278 279 for res in (source_addrinfo or [(None,) * 5]): 280 b_af, b_socktype, b_proto, b_cn, b_sa = res 281 if b_af is not None: 282 try: 283 sock = socket.socket(b_af, b_socktype, b_proto) 284 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 285 b_sa = b_sa[:2] + source_address[2:] 286 sock.bind(b_sa if b_af == socket.AF_INET6 else b_sa[:2]) 287 except socket.error: 288 err = sys.exc_info() if not err else err 289 sock = None 290 continue 291 292 if not addr_addrinfo and sock: 293 # Nothing to connect to and we bound successfully, so done. 294 return sock 295 296 for (af, socktype, proto, cn, sa) in addr_addrinfo: 297 if b_af is not None and af != b_af: 298 # Different address family than socket was bound to. 299 continue 300 301 try: 302 if not sock: 303 sock = socket.socket(af, socktype, proto) 304 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 305 if timeout is not TIMEOUT_SENTINEL: 306 sock.settimeout(timeout) 307 sock.connect(sa) 308 return sock 309 except socket.error: 310 err = sys.exc_info() if not err else err 311 sock = None 312 else: 313 if err: 314 raise err[0], err[1], err[2] 315 else: 316 raise socket.error('destination had no addresses in source address family') 317 318 319 320 def __init__(self, buffer_size=None, chunk_size=1024*1024): 321 self._connecting = False 322 self._listening = False 323 self._buffer_size = buffer_size 324 # Requested hostname passed to connect() 325 self._reqhost = None 326 self._auto_accept = True 327 # If an InProgress object then there is an accept() call in progress, 328 # otherwise None. 329 self._accept_inprogress = None 330 331 super(Socket, self).__init__(chunk_size=chunk_size) 332 333 334 def _make_new(self): 335 return self.__class__() 336 337 338 @IOChannel.fileno.getter 339 def fileno(self): 340 # If fileno() is accessed on a closed socket, socket.error is 341 # railsed. So we override our superclass's implementation to 342 # handle this case. 343 try: 344 return self._channel.fileno() 345 except (AttributeError, socket.error): 346 return None 347 348 @property 349 def auto_accept(self): 350 """ 351 If True (default), automatically accept new clients connecting to 352 listening sockets. 353 354 See :meth:`listen` for more details. 355 """ 356 return self._auto_accept 357 358 359 @auto_accept.setter 360 def auto_accept(self, value): 361 self._auto_accept = value 362 363 364 @property 365 def address(self): 366 """ 367 This property is deprecated; use *peer* instead. 368 """ 369 log.warning('Socket.address is deprecated; use Socket.peer instead') 370 return self.local[:2] 371 372 373 @property 374 def local(self): 375 """ 376 Information about the local side of the socket. 377 378 This is either the tuple ``(host, port, flowinfo, scopeid, scope)`` 379 representing the local end of a TCP socket, or the string containing 380 the name of a Unix socket. 381 382 *scope* is the interface name represented by *scopeid*, and is None if 383 *scopeid* is 0. 384 385 On Python 2.6 and later, the returned value is a namedtuple. 386 """ 387 return self._make_address_tuple(self._channel.getsockname()) 388 389 390 @property 391 def peer(self): 392 """ 393 Information about the remote side of the socket. 394 395 This is a tuple ``(host, port, flowinfo, scopeid, scope, reqhost)`` 396 representing the remote end of the socket. 397 398 *scope* is the interface name represented by *scopeid*, and is None if 399 *scopeid* is 0. *reqhost* is the requested hostname if 400 :meth:`~kaa.Socket.connect` was called, or None if this is a listening 401 socket. 402 403 On Python 2.6 and later, the returned value is a namedtuple. 404 """ 405 return self._make_address_tuple(self._channel.getpeername(), self._reqhost) 406 407 408 @property 409 def listening(self): 410 """ 411 True if this is a listening socket, and False otherwise. 412 """ 413 return self._listening 414 415 416 @property 417 def connecting(self): 418 """ 419 True if the socket is in the process of establishing a connection 420 but is not yet connected. 421 422 Once the socket is connected, the connecting property will be False, 423 but the :attr:`connected` property will be True. 424 """ 425 return self._connecting 426 427 428 @property 429 def connected(self): 430 """ 431 True when the socket is currently connected to a peer. 432 433 When a socket is in the process of :attr:`connecting`, it is not 434 considered connected, although it is considered :attr:`alive`. 435 436 .. note:: 437 This property will not change until a :meth:`read` or :meth:`write` 438 is attempted on the socket. Only then can it be determined if 439 the socket has disconnected. 440 441 .. warning:: 442 When you want to read all data from the socket until it closes, 443 you should use the :attr:`readable` property instead. 444 """ 445 return self._channel != None and not self._close_inprogress and not self._listening 446 447 448 @property 449 def alive(self): 450 """ 451 True if the socket is :attr:`connected`, :attr:`listening`, or 452 :attr:`connecting`. 453 """ 454 # Unroll these properties: connected or connecting 455 return (self._channel != None and not self._close_inprogress) or self._connecting 456 457 458 @IOChannel.readable.getter 459 def readable(self): 460 """ 461 True if :meth:`read` may be called. 462 463 A socket is considered readable when it is :attr:`alive`, or if it's 464 closed but there is buffered data to be read. 465 466 Because of the presence of a read buffer, you should test this property 467 to determine if you should :meth:`read`, not the :attr:`connected` 468 property:: 469 470 while socket.readable: 471 data = yield socket.read() 472 [...] 473 474 .. note:: 475 A value of True does not mean there **is** data available, but 476 rather that there could be and that a :meth:`read` call is possible 477 (however that :meth:`read` call may return None, in which case the 478 readable property will subsequently be False because the socket is 479 disconnected). 480 481 """ 482 # Note: this property is used in superclass's _update_read_monitor() 483 # Unroll these properties: alive or super(readable) 484 return (self._channel != None and not self._close_inprogress) or \ 485 self._connecting or self._read_queue.tell() > 0 486 487 488 @property 489 def buffer_size(self): 490 """ 491 Size of the send and receive socket buffers (SO_SNDBUF and SO_RCVBUF) 492 in bytes. 493 494 Setting this to higher values (say 1M) improves performance when 495 sending large amounts of data across the socket. Note that the upper 496 bound may be restricted by the kernel. (Under Linux, this can be tuned 497 by adjusting /proc/sys/net/core/[rw]mem_max) 498 """ 499 return self._buffer_size 500 501 502 @buffer_size.setter 503 def buffer_size(self, size): 504 self._buffer_size = size 505 if self._channel and size: 506 self._set_buffer_size(self._channel, size) 507 508 509 def _set_buffer_size(self, s, size): 510 """ 511 Sets the send and receive buffers of the given socket s to size. 512 """ 513 s.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, size) 514 s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, size) 515 516 517 def _make_address_tuple(self, addr, *args): 518 """ 519 Converts an AF_INET6 socket address to a 5- or 6-tuple for use with the 520 *local* and *peer* properties. IPv4-mapped IPv6 addresses are 521 converted to standard IPv4 dotted quads. 522 523 On Python 2.6 and later, this returns a namedtuple. 524 """ 525 if isinstance(addr, basestring): 526 # Unix socket 527 return addr 528 529 if len(addr) == 2: 530 addr += (None, None, None) 531 else: 532 try: 533 addr += (if_indextoname(addr[3]),) 534 except (ValueError, NotImplementedError): 535 addr += (None,) 536 537 # reqhost = args[0] if args else None 538 addr += (args[0] if args else None,) 539 # ip = addr[0][7:] if addr[0].lower().startswith('::ffff:') else addr[0] 540 #addr = (ip,) + addr[1:] + (scope,) + ((reqhost,) if args else ()) 541 if sys.hexversion < 0x02060000: 542 return addr 543 544 fields = 'host port flowinfo scopeid scope' + (' reqhost' if args else '') 545 return collections.namedtuple('address', fields)(*addr) 546 547 548 549 def listen(self, addr, backlog=5, ipv6=True): 550 """ 551 Set the socket to accept incoming connections. 552 553 :param addr: Binds the socket to this address. If an int, this 554 specifies a TCP port that is bound on all interfaces; if a 555 str, it is either a Unix socket path or represents a TCP 556 socket when in the form ``[host]:[service][%scope]``. 557 See below for further details. 558 :type addr: int, str, or 2- or 4-tuple 559 :param backlog: the maximum length to which the queue of pending 560 connections for the socket may grow. 561 :type backlog: int 562 :param ipv6: if True, will prefer binding to IPv6 addresses if addr is 563 a hostname that contains both AAAA and A records. If addr 564 is specified as an IP address, this argument does nothing. 565 :type ipv6: bool 566 :raises: ValueError if *addr* is invalid, or socket.error if the bind fails. 567 568 If *addr* is given as a 4-tuple, it is in the form ``(host, service, 569 flowinfo, scope)``. If passed as a 2-tuple, it is in the form 570 ``(host, service)``, and in this case, it is assumed that *flowinfo* and 571 *scope* are both 0. See :meth:`~kaa.Socket.connect` for more 572 information. 573 574 If *host* is given as a string, it is treated as a Unix socket path if it 575 does not contain ``:``, otherwise it is specified as ``[host]:[service][%scope]``, 576 where ``[x]`` indicates that ``x`` is optional, and where: 577 578 * *host* is a hostname, an IPv4 dotted quad, or an IPv6 address 579 wrapped in square brackets. e.g. localhost, 192.168.0.1, 580 [3000::1]. If host is not specified, the socket will listen on 581 all interfaces. 582 * *service* is a service name or port number. e.g. http, 80 583 * *scope* is an interface name or number. e.g. eth0, 2 584 585 When binding to a link-local address (``fe80::/16``), *scope* must be 586 specified. Relative Unix socket names (those not prefixed with 587 ``/``) are created via kaa.tempfile. 588 589 .. warning:: 590 591 If the bind address supplied is a hostname rather than an IPv4 or 592 IPv6 address, this function will block in order to resolve the 593 hostname if the name is not specified in /etc/hosts. (In other words, 594 ``localhost`` is probably safe.) 595 596 Once listening, new connections are automatically accepted, and the 597 :attr:`~kaa.Socket.signals.new-client` signal is emitted for each new 598 connection. Callbacks connecting to the signal will receive a new 599 Socket object representing the client connection. 600 """ 601 sock = Socket.create_connection(source_address=addr, overwrite=True) 602 sock.listen(backlog) 603 self._listening = True 604 self.wrap(sock, IO_READ | IO_WRITE) 605 606 607 @threaded() 608 def _connect(self, addr, source_address=None, ipv6=True): 609 sock = Socket.create_connection(addr, source_address=source_address, ipv6=ipv6) 610 # Normalize and store hostname 611 addr = Socket.normalize_address(addr) 612 if type(addr) == str: 613 # Unix socket, just connect. 614 self._reqhost = addr 615 else: 616 self._reqhost = addr[0] 617 618 try: 619 self.wrap(sock, IO_READ | IO_WRITE) 620 finally: 621 self._connecting = False 622 623 624 def connect(self, addr, source_address=None, ipv6=True): 625 """ 626 Connects to the host specified in address. 627 628 :param addr: Address for a remote host, or a Unix socket. If a str, 629 it is either a Unix socket path or represents a TCP 630 socket when in the form ``host:service[%scope]``. See 631 below for further details. 632 :type addr: str, or 2- or 4-tuple 633 :param ipv6: if True, will connect to the remote host using IPv6 if 634 it is reachable via IPv6. This is perfectly safe for IPv4 635 only hosts too. Set this to False if the remote host 636 has a AAAA record and the local host has an IPv6 route to 637 it, but you want to force IPv4 anyway. 638 :returns: An :class:`~kaa.InProgress` object. 639 640 If *addr* is given as a 4-tuple, it is in the form ``(host, service, 641 flowinfo, scope)``. If given as a 2-tuple, it is in the form ``(host, 642 service)``, and in this case the *flowinfo* and *scope* are assumed to 643 be 0. 644 645 The *flowinfo* and *scope* fields are only relevant for IPv6 hosts, 646 where they represent the ``sin6_flowinfo`` and ``sin6_scope_id`` 647 members in :const:`struct sockaddr_in6` in C. *scope* may be the name 648 of an interface (e.g. ``eth0``) or an interface id, and is needed when 649 connecting to link-local addresses (``fe80::/16``). 650 651 If *addr* is given as a string, it is treated as a Unix socket path if it 652 does not contain ``:``, otherwise it is specified as ``host:service[%scope]``, 653 where ``[x]`` indicates that ``x`` is optional, and where: 654 655 * *host* is a hostname, an IPv4 dotted quad, or an IPv6 address 656 wrapped in square brackets. e.g. freevo.org, 192.168.0.1, 657 [3000::1] 658 * *service* is a service name or port number. e.g. http, 80 659 * *scope* is an interface name or number. e.g. eth0, 2 660 661 When connecting to a link-local address (fe80::/16), *scope* must be 662 specified. Relative Unix socket names (those not prefixed with ``/``) 663 are created via :func:`kaa.tempfile`. 664 665 This function is executed in a thread to avoid blocking. It therefore 666 returns an InProgress object. If the socket is connected, the InProgress 667 is finished with no arguments. If the connection cannot be established, 668 an exception is thrown to the InProgress. 669 """ 670 if self._connecting: 671 raise SocketError('connection already in progress') 672 elif self.connected: 673 raise SocketError('socket already connected') 674 self._connecting = True 675 return self._connect(addr, source_address, ipv6) 676 677 678 def wrap(self, sock, mode=IO_READ|IO_WRITE): 679 """ 680 Wraps an existing low-level socket object. 681 682 addr specifies the 4-tuple address corresponding to the socket. 683 """ 684 super(Socket, self).wrap(sock, mode) 685 if sock and self._buffer_size: 686 self._set_buffer_size(sock, self._buffer_size) 687 return self 688 689 690 def _is_read_connected(self): 691 return self._listening or super(Socket, self)._is_read_connected() 692 693 694 def _set_non_blocking(self): 695 self._channel.setblocking(False) 696 697 698 def _read(self, size): 699 return self._channel.recv(size) 700 701 702 def _write(self, data): 703 return self._channel.send(data) 704 705 706 def _accept(self): 707 """ 708 Accept a new connection and return a new Socket object. 709 """ 710 sock, addr = self._channel.accept() 711 # create new Socket from the same class this object is 712 client_socket = self._make_new() 713 client_socket.wrap(sock, IO_READ | IO_WRITE) 714 self.signals['new-client'].emit(client_socket) 715 if self._accept_inprogress: 716 accept_inprogress = self._accept_inprogress 717 self._accept_inprogress = None 718 accept_inprogress.finish(client_socket) 719 720 721 def accept(self): 722 if not self._accept_inprogress: 723 self._accept_inprogress = InProgress() 724 725 return self._accept_inprogress 726 727 728 def _handle_read(self): 729 if self._listening: 730 # Give callbacks on the new-client-connecting signal the chance to 731 # abort the autoaccept (if applicable). If we have an explicit 732 # accept() in progress then it can't be aborted, but we still emit 733 # anyway for notification purposes. 734 aborted = self.signals['new-client-connecting'].emit() == False 735 if (self._auto_accept and not aborted) or self._accept_inprogress: 736 return self._accept() 737 738 return super(Socket, self)._handle_read() 739 740 741 def _close(self): 742 super(Socket, self)._close() 743 self._reqhost = None 744 if self._listening and isinstance(self.local, basestring) and self.local.startswith('/'): 745 # Remove unix socket if it exists. 746 try: 747 os.unlink(self.local) 748 except OSError: 749 pass 750 751 752 def steal(self, socket): 753 if not isinstance(socket, Socket): 754 raise TypeError('Can only steal from other sockets') 755 756 self._buffer_size = socket._buffer_size 757 return super(Socket, self).steal(socket)