PageRenderTime 41ms CodeModel.GetById 12ms app.highlight 23ms RepoModel.GetById 1ms app.codeStats 0ms

/src/sockets.py

https://github.com/Dischi/kaa-base
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)