Пример #1
0
 def _on_registered_or_started(self, component, manager=None):
     if self._poller is None:
         if isinstance(component, BasePoller):
             self._poller = component
             self.fire(ready(self))
         else:
             if component is not self:
                 return
             component = findcmp(self.root, BasePoller)
             if component is not None:
                 self._poller = component
                 self.fire(ready(self))
             else:
                 self._poller = Poller().register(self)
                 self.fire(ready(self))
Пример #2
0
 def _on_registered_or_started(self, component, manager=None):
     if self._poller is None:
         if isinstance(component, BasePoller):
             self._poller = component
             self._poller.addReader(self, self._sock)
             self.fire(ready(self, (self.host, self.port)))
         else:
             if component is not self:
                 return
             component = findcmp(self.root, BasePoller)
             if component is not None:
                 self._poller = component
                 self._poller.addReader(self, self._sock)
                 self.fire(ready(self, (self.host, self.port)))
             else:
                 try:
                     self._poller = Poller().register(self)
                 except EnvironmentError as err:
                     self.fire(error(err))
                 else:
                     self._poller.addReader(self, self._sock)
                     self.fire(ready(self, (self.host, self.port)))
Пример #3
0
 def _on_registered_or_started(self, component, manager=None):
     if self._poller is None:
         if isinstance(component, BasePoller):
             self._poller = component
             self.fire(ready(self))
         else:
             if component is not self:
                 return
             component = findcmp(self.root, BasePoller)
             if component is not None:
                 self._poller = component
                 self.fire(ready(self))
             else:
                 self._poller = Poller().register(self)
                 self.fire(ready(self))
Пример #4
0
def test():
    m = Manager()

    poller = Poller().register(m)

    TCPServer(0).register(m)
    TCPClient().register(m)

    m.start()

    try:
        pollers = findtype(m, BasePoller, all=True)
        assert len(pollers) == 1
        assert pollers[0] is poller
    finally:
        m.stop()
Пример #5
0
class Client(BaseComponent):

    channel = "client"

    socket_family = AF_INET
    socket_type = SOCK_STREAM
    socket_protocol = IPPROTO_IP
    socket_options = []

    def __init__(self, bind=None, bufsize=BUFSIZE, channel=channel, **kwargs):
        super(Client, self).__init__(channel=channel, **kwargs)

        if isinstance(bind, SocketType):
            self._bind = bind.getsockname()
            self._sock = bind
        else:
            self._bind = self.parse_bind_parameter(bind)
            self._sock = self._create_socket()

        self._bufsize = bufsize

        self._ssock = None
        self._poller = None
        self._buffer = deque()
        self._closeflag = False
        self._connected = False

        self.host = None
        self.port = 0
        self.secure = False

        self.server = {}
        self.issuer = {}

    def parse_bind_parameter(self, bind_parameter):
        return parse_ipv4_parameter(bind_parameter)

    @property
    def connected(self):
        return getattr(self, "_connected", None)

    @handler("registered", "started", channel="*")
    def _on_registered_or_started(self, component, manager=None):
        if self._poller is None:
            if isinstance(component, BasePoller):
                self._poller = component
                self.fire(ready(self))
            else:
                if component is not self:
                    return
                component = findcmp(self.root, BasePoller)
                if component is not None:
                    self._poller = component
                    self.fire(ready(self))
                else:
                    self._poller = Poller().register(self)
                    self.fire(ready(self))

    @handler("stopped", channel="*")
    def _on_stopped(self, component):
        self.fire(close())

    @handler("read_value_changed")
    def _on_read_value_changed(self, value):
        if isinstance(value, binary_type):
            self.fire(write(value))

    @handler("prepare_unregister", channel="*")
    def _on_prepare_unregister(self, event, c):
        if event.in_subtree(self):
            self._close()

    def _close(self):
        if not self._connected:
            return

        self._poller.discard(self._sock)

        self._buffer.clear()
        self._closeflag = False
        self._connected = False

        try:
            self._sock.shutdown(2)
        except SocketError:
            pass
        try:
            self._sock.close()
        except SocketError:
            pass

        self.fire(disconnected())

    @handler("close")
    def close(self):
        if not self._buffer:
            self._close()
        elif not self._closeflag:
            self._closeflag = True

    def _read(self):
        try:
            try:
                if self.secure and self._ssock:
                    data = self._ssock.read(self._bufsize)
                else:
                    data = self._sock.recv(self._bufsize)
            except SSLError as exc:
                if exc.errno in (SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE):
                    return
                raise

            if data:
                self.fire(read(data)).notify = True
            else:
                self.close()
        except SocketError as e:
            if e.args[0] == EWOULDBLOCK:
                return
            else:
                self.fire(error(e))
                self._close()

    def _write(self, data):
        try:
            if self.secure and self._ssock:
                nbytes = self._ssock.write(data)
            else:
                nbytes = self._sock.send(data)

            if nbytes < len(data):
                self._buffer.appendleft(data[nbytes:])
        except SocketError as e:
            if e.args[0] in (EPIPE, ENOTCONN):
                self._close()
            else:
                self.fire(error(e))

    @handler("write")
    def write(self, data):
        if not self._poller.isWriting(self._sock):
            self._poller.addWriter(self, self._sock)
        self._buffer.append(data)

    @handler("_disconnect", priority=1)
    def __on_disconnect(self, sock):
        self._close()

    @handler("_read", priority=1)
    def __on_read(self, sock):
        self._read()

    @handler("_write", priority=1)
    def __on_write(self, sock):
        if self._buffer:
            data = self._buffer.popleft()
            self._write(data)

        if not self._buffer:
            if self._closeflag:
                self._close()
            elif self._poller.isWriting(self._sock):
                self._poller.removeWriter(self._sock)

    def _create_socket(self):
        sock = socket(self.socket_family, self.socket_type, self.socket_protocol)

        for option in self.socket_options:
            sock.setsockopt(*option)
        sock.setblocking(False)
        if self._bind is not None:
            sock.bind(self._bind)
        return sock
Пример #6
0
class Server(BaseComponent):

    channel = "server"
    socket_protocol = IPPROTO_IP

    def __init__(self, bind, secure=False, backlog=BACKLOG,
                 bufsize=BUFSIZE, channel=channel, **kwargs):
        super(Server, self).__init__(channel=channel)

        self.socket_options = self.socket_options[:] + kwargs.get('socket_options', [])
        self._bind = self.parse_bind_parameter(bind)

        self._backlog = backlog
        self._bufsize = bufsize

        if isinstance(bind, socket):
            self._sock = bind
        else:
            self._sock = self._create_socket()

        self._closeq = []
        self._clients = []
        self._poller = None
        self._buffers = defaultdict(deque)

        self.__starttls = set()

        self.secure = secure
        self.certfile = kwargs.get("certfile")
        self.keyfile = kwargs.get("keyfile", None)
        self.cert_reqs = kwargs.get("cert_reqs", CERT_NONE)
        self.ssl_version = kwargs.get("ssl_version", PROTOCOL_SSLv23)
        self.ca_certs = kwargs.get("ca_certs", None)
        if self.secure and not self.certfile:
            raise RuntimeError("certfile must be specified for server-side operations")

    def parse_bind_parameter(self, bind_parameter):
        return parse_ipv4_parameter(bind_parameter)

    @property
    def connected(self):
        return True

    @property
    def host(self):
        if getattr(self, "_sock", None) is not None:
            try:
                sockname = self._sock.getsockname()
                if isinstance(sockname, tuple):
                    return sockname[0]
                else:
                    return sockname
            except SocketError:
                return None

    @property
    def port(self):
        if getattr(self, "_sock", None) is not None:
            try:
                sockname = self._sock.getsockname()
                if isinstance(sockname, tuple):
                    return sockname[1]
            except SocketError:
                return None

    @handler("registered", "started", channel="*")
    def _on_registered_or_started(self, component, manager=None):
        if self._poller is None:
            if isinstance(component, BasePoller):
                self._poller = component
                self._poller.addReader(self, self._sock)
                self.fire(ready(self, (self.host, self.port)))
            else:
                if component is not self:
                    return
                component = findcmp(self.root, BasePoller)
                if component is not None:
                    self._poller = component
                    self._poller.addReader(self, self._sock)
                    self.fire(ready(self, (self.host, self.port)))
                else:
                    self._poller = Poller().register(self)
                    self._poller.addReader(self, self._sock)
                    self.fire(ready(self, (self.host, self.port)))

    @handler("stopped", channel="*")
    def _on_stopped(self, component):
        self.fire(close())

    @handler("read_value_changed")
    def _on_read_value_changed(self, value):
        if isinstance(value.value, binary_type):
            sock = value.event.args[0]
            self.fire(write(sock, value.value))

    def _close(self, sock):
        if sock is None:
            return

        if sock != self._sock and sock not in self._clients:
            return

        self._poller.discard(sock)

        if sock in self._buffers:
            del self._buffers[sock]

        if sock in self._clients:
            self._clients.remove(sock)
        else:
            self._sock = None

        if sock in self.__starttls:
            self.__starttls.remove(sock)

        try:
            sock.shutdown(2)
        except SocketError:
            pass
        try:
            sock.close()
        except SocketError:
            pass

        self.fire(disconnect(sock))

    @handler("close")
    def close(self, sock=None):
        is_closed = sock is None

        if sock is None:
            socks = [self._sock]
            socks.extend(self._clients[:])
        else:
            socks = [sock]

        for sock in socks:
            if not self._buffers[sock]:
                self._close(sock)
            elif sock not in self._closeq:
                self._closeq.append(sock)

        if is_closed:
            self.fire(closed())

    def _read(self, sock):
        if sock not in self._clients:
            return

        try:
            data = sock.recv(self._bufsize)
            if data:
                self.fire(read(sock, data)).notify = True
            else:
                self.close(sock)
        except SocketError as e:
            if e.args[0] == EWOULDBLOCK:
                return
            else:
                self.fire(error(sock, e))
                self._close(sock)

    def _write(self, sock, data):
        if sock not in self._clients:
            return

        try:
            nbytes = sock.send(data)
            if nbytes < len(data):
                self._buffers[sock].appendleft(data[nbytes:])
        except SocketError as e:
            if e.args[0] not in (EINTR, EWOULDBLOCK, ENOBUFS):
                self.fire(error(sock, e))
                self._close(sock)
            else:
                self._buffers[sock].appendleft(data)

    @handler("write")
    def write(self, sock, data):
        if not self._poller.isWriting(sock):
            self._poller.addWriter(self, sock)
        self._buffers[sock].append(data)

    def _accept(self):
        try:
            newsock, host = self._sock.accept()
        except SocketError as e:
            if e.args[0] in (EWOULDBLOCK, EAGAIN):
                return
            elif e.args[0] == EPERM:
                # Netfilter on Linux may have rejected the
                # connection, but we get told to try to accept()
                # anyway.
                return
            elif e.args[0] in (EMFILE, ENOBUFS, ENFILE, ENOMEM, ECONNABORTED):
                # Linux gives EMFILE when a process is not allowed
                # to allocate any more file descriptors.  *BSD and
                # Win32 give (WSA)ENOBUFS.  Linux can also give
                # ENFILE if the system is out of inodes, or ENOMEM
                # if there is insufficient memory to allocate a new
                # dentry.  ECONNABORTED is documented as possible on
                # both Linux and Windows, but it is not clear
                # whether there are actually any circumstances under
                # which it can happen (one might expect it to be
                # possible if a client sends a FIN or RST after the
                # server sends a SYN|ACK but before application code
                # calls accept(2), however at least on Linux this
                # _seems_ to be short-circuited by syncookies.
                return
            else:
                raise

        if self.secure and HAS_SSL:
            for _ in self._do_handshake(newsock):
                yield
        else:
            self._on_accept_done(newsock)

    def _do_handshake(self, sock, fire_connect_event=True):
        sslsock = ssl_socket(
            sock,
            server_side=True,
            keyfile=self.keyfile,
            ca_certs=self.ca_certs,
            certfile=self.certfile,
            cert_reqs=self.cert_reqs,
            ssl_version=self.ssl_version,
            do_handshake_on_connect=False
        )

        for _ in do_handshake(sslsock, self._on_accept_done, self._on_handshake_error, (fire_connect_event,)):
            yield _

    def _on_accept_done(self, sock, fire_connect_event=True):
        sock.setblocking(False)
        self._poller.addReader(self, sock)
        self._clients.append(sock)
        if fire_connect_event:
            try:
                self.fire(connect(sock, *sock.getpeername()))
            except SocketError as exc:
                # errno 107 (ENOTCONN): the client already disconnected
                self._on_handshake_error(sock, exc)

    def _on_handshake_error(self, sock, err):
        self.fire(error(sock, err))
        self._close(sock)

    @handler('starttls')
    def starttls(self, sock):
        if not HAS_SSL:
            raise RuntimeError('Cannot start TLS. No TLS support.')
        if sock in self.__starttls:
            raise RuntimeError('Cannot reuse socket for already started STARTTLS.')
        self.__starttls.add(sock)
        self._poller.removeReader(sock)
        self._clients.remove(sock)
        for _ in self._do_handshake(sock, False):
            yield

    @handler("_disconnect", priority=1)
    def _on_disconnect(self, sock):
        self._close(sock)

    @handler("_read", priority=1)
    def _on_read(self, sock):
        if sock == self._sock:
            return self._accept()
        else:
            self._read(sock)

    @handler("_write", priority=1)
    def _on_write(self, sock):
        if self._buffers[sock]:
            data = self._buffers[sock].popleft()
            self._write(sock, data)

        if not self._buffers[sock]:
            if sock in self._closeq:
                self._closeq.remove(sock)
                self._close(sock)
            elif self._poller.isWriting(sock):
                self._poller.removeWriter(sock)

    def _create_socket(self):
        sock = socket(self.socket_family, self.socket_type, self.socket_protocol)

        for option in self.socket_options:
            sock.setsockopt(*option)
        sock.setblocking(False)
        if self._bind is not None:
            sock.bind(self._bind)
        return sock
Пример #7
0
class Serial(Component):

    channel = "serial"

    def __init__(self,
                 port,
                 baudrate=115200,
                 bufsize=BUFSIZE,
                 timeout=TIMEOUT,
                 channel=channel):
        super(Serial, self).__init__(channel=channel)

        if serial is None:
            raise RuntimeError("No serial support available")

        self._port = port
        self._baudrate = baudrate
        self._bufsize = bufsize

        self._serial = None
        self._poller = None
        self._buffer = deque()
        self._closeflag = False

    @handler("ready")
    def _on_ready(self, component):
        self.fire(_open(), self.channel)

    @handler("_open")
    def _on_open(self, port=None, baudrate=None, bufsize=None):
        self._port = port or self._port
        self._baudrate = baudrate or self._baudrate
        self._bufsize = bufsize or self._bufsize

        self._serial = serial.Serial(port=self._port,
                                     baudrate=self._baudrate,
                                     timeout=0)
        self._fd = self._serial.fileno()  # not portable!

        self._poller.addReader(self, self._fd)

        self.fire(opened(self._port, self._baudrate))

    @handler("registered", "started", channel="*")
    def _on_registered_or_started(self, component, manager=None):
        if self._poller is None:
            if isinstance(component, BasePoller):
                self._poller = component
                self.fire(ready(self))
            else:
                if component is not self:
                    return
                component = findcmp(self.root, BasePoller)
                if component is not None:
                    self._poller = component
                    self.fire(ready(self))
                else:
                    self._poller = Poller().register(self)
                    self.fire(ready(self))

    @handler("stopped", channel="*")
    def _on_stopped(self, component):
        self.fire(close())

    @handler("prepare_unregister", channel="*")
    def _on_prepare_unregister(self, event, c):
        if event.in_subtree(self):
            self._close()

    def _close(self):
        if self._closeflag:
            return

        self._poller.discard(self._fd)

        self._buffer.clear()
        self._closeflag = False
        self._connected = False

        try:
            self._serial.close()
        except:
            pass

        self.fire(closed())

    def close(self):
        if not self._buffer:
            self._close()
        elif not self._closeflag:
            self._closeflag = True

    def _read(self):
        try:
            data = self._serial.read(self._bufsize)
            if not isinstance(data, binary_type):
                data = data.encode(self._encoding)

            if data:
                self.fire(read(data)).notify = True
        except (OSError, IOError) as e:
            self.fire(error(e))
            self._close()

    def _write(self, data):
        try:
            if not isinstance(data, binary_type):
                data = data.encode(self._encoding)

            try:
                nbytes = self._serial.write(data)
            except (serial.SerialTimeoutException) as e:
                nbytes = 0
            if nbytes < len(data):
                self._buffer.appendleft(data[nbytes:])
        except (OSError, IOError) as e:
            self.fire(error(e))
            self._close()

    def write(self, data):
        if self._poller is not None and not self._poller.isWriting(self._fd):
            self._poller.addWriter(self, self._fd)
        self._buffer.append(data)

    @handler("_disconnect")
    def __on_disconnect(self, sock):
        self._close()

    @handler("_read")
    def __on_read(self, sock):
        self._read()

    @handler("_write")
    def __on_write(self, sock):
        if self._buffer:
            data = self._buffer.popleft()
            self._write(data)

        if not self._buffer:
            if self._closeflag:
                self._close()
            elif self._poller.isWriting(self._fd):
                self._poller.removeWriter(self._fd)
Пример #8
0
 def _on_started(self, event, component):
     if self._poller is None:
         self._poller = Poller().register(self)
         self.fire(ready(self))
         event.stop()
Пример #9
0
class Client(BaseComponent):

    channel = "client"

    def __init__(self, bind=None, bufsize=BUFSIZE, channel=channel, **kwargs):
        super(Client, self).__init__(channel=channel, **kwargs)

        if isinstance(bind, SocketType):
            self._bind = bind.getsockname()
            self._sock = bind
        else:
            self._bind = self.parse_bind_parameter(bind)
            self._sock = self._create_socket()

        self._bufsize = bufsize

        self._ssock = None
        self._poller = None
        self._buffer = deque()
        self._closeflag = False
        self._connected = False

        self.host = None
        self.port = 0
        self.secure = False

        self.server = {}
        self.issuer = {}

    def parse_bind_parameter(self, bind_parameter):
        return parse_ipv4_parameter(bind_parameter)

    @property
    def connected(self):
        return getattr(self, "_connected", None)

    @handler("registered", "started", channel="*")
    def _on_registered_or_started(self, component, manager=None):
        if self._poller is None:
            if isinstance(component, BasePoller):
                self._poller = component
                self.fire(ready(self))
            else:
                if component is not self:
                    return
                component = findcmp(self.root, BasePoller)
                if component is not None:
                    self._poller = component
                    self.fire(ready(self))
                else:
                    self._poller = Poller().register(self)
                    self.fire(ready(self))

    @handler("stopped", channel="*")
    def _on_stopped(self, component):
        self.fire(close())

    @handler("read_value_changed")
    def _on_read_value_changed(self, value):
        if isinstance(value, binary_type):
            self.fire(write(value))

    @handler("prepare_unregister", channel="*")
    def _on_prepare_unregister(self, event, c):
        if event.in_subtree(self):
            self._close()

    def _close(self):
        if not self._connected:
            return

        self._poller.discard(self._sock)

        self._buffer.clear()
        self._closeflag = False
        self._connected = False

        try:
            self._sock.shutdown(2)
        except SocketError:
            pass
        try:
            self._sock.close()
        except SocketError:
            pass

        self.fire(disconnected())

    @handler("close")
    def close(self):
        if not self._buffer:
            self._close()
        elif not self._closeflag:
            self._closeflag = True

    def _read(self):
        try:
            if self.secure and self._ssock:
                data = self._ssock.read(self._bufsize)
            else:
                try:
                    data = self._sock.recv(self._bufsize)
                except SSLError as exc:
                    if exc.errno in (SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE):
                        return
                    raise

            if data:
                self.fire(read(data)).notify = True
            else:
                self.close()
        except SocketError as e:
            if e.args[0] == EWOULDBLOCK:
                return
            else:
                self.fire(error(e))
                self._close()

    def _write(self, data):
        try:
            if self.secure and self._ssock:
                nbytes = self._ssock.write(data)
            else:
                nbytes = self._sock.send(data)

            if nbytes < len(data):
                self._buffer.appendleft(data[nbytes:])
        except SocketError as e:
            if e.args[0] in (EPIPE, ENOTCONN):
                self._close()
            else:
                self.fire(error(e))

    @handler("write")
    def write(self, data):
        if not self._poller.isWriting(self._sock):
            self._poller.addWriter(self, self._sock)
        self._buffer.append(data)

    @handler("_disconnect", priority=1)
    def __on_disconnect(self, sock):
        self._close()

    @handler("_read", priority=1)
    def __on_read(self, sock):
        self._read()

    @handler("_write", priority=1)
    def __on_write(self, sock):
        if self._buffer:
            data = self._buffer.popleft()
            self._write(data)

        if not self._buffer:
            if self._closeflag:
                self._close()
            elif self._poller.isWriting(self._sock):
                self._poller.removeWriter(self._sock)
Пример #10
0
class Server(BaseComponent):

    channel = "server"

    def __init__(self, bind, secure=False, backlog=BACKLOG,
                 bufsize=BUFSIZE, channel=channel, **kwargs):
        super(Server, self).__init__(channel=channel)

        self._bind = self.parse_bind_parameter(bind)

        self._backlog = backlog
        self._bufsize = bufsize

        if isinstance(bind, socket):
            self._sock = bind
        else:
            self._sock = self._create_socket()

        self._closeq = []
        self._clients = []
        self._poller = None
        self._buffers = defaultdict(deque)

        self.secure = secure

        if self.secure:
            try:
                self.certfile = kwargs["certfile"]
            except KeyError:
                raise RuntimeError(
                    "certfile must be specified for server-side operations")
            self.keyfile = kwargs.get("keyfile", None)
            self.cert_reqs = kwargs.get("cert_reqs", CERT_NONE)
            self.ssl_version = kwargs.get("ssl_version", PROTOCOL_SSLv23)
            self.ca_certs = kwargs.get("ca_certs", None)

    def parse_bind_parameter(self, bind_parameter):
        return parse_ipv4_parameter(bind_parameter)

    @property
    def connected(self):
        return True

    @property
    def host(self):
        if getattr(self, "_sock", None) is not None:
            try:
                sockname = self._sock.getsockname()
                if isinstance(sockname, tuple):
                    return sockname[0]
                else:
                    return sockname
            except SocketError:
                return None

    @property
    def port(self):
        if getattr(self, "_sock", None) is not None:
            try:
                sockname = self._sock.getsockname()
                if isinstance(sockname, tuple):
                    return sockname[1]
            except SocketError:
                return None

    @handler("registered", "started", channel="*")
    def _on_registered_or_started(self, component, manager=None):
        if self._poller is None:
            if isinstance(component, BasePoller):
                self._poller = component
                self._poller.addReader(self, self._sock)
                self.fire(ready(self, (self.host, self.port)))
            else:
                if component is not self:
                    return
                component = findcmp(self.root, BasePoller)
                if component is not None:
                    self._poller = component
                    self._poller.addReader(self, self._sock)
                    self.fire(ready(self, (self.host, self.port)))
                else:
                    self._poller = Poller().register(self)
                    self._poller.addReader(self, self._sock)
                    self.fire(ready(self, (self.host, self.port)))

    @handler("stopped", channel="*")
    def _on_stopped(self, component):
        self.fire(close())

    @handler("read_value_changed")
    def _on_read_value_changed(self, value):
        if isinstance(value.value, binary_type):
            sock = value.event.args[0]
            self.fire(write(sock, value.value))

    def _close(self, sock):
        if sock is None:
            return

        if sock != self._sock and sock not in self._clients:
            return

        self._poller.discard(sock)

        if sock in self._buffers:
            del self._buffers[sock]

        if sock in self._clients:
            self._clients.remove(sock)
        else:
            self._sock = None

        try:
            sock.shutdown(2)
        except SocketError:
            pass
        try:
            sock.close()
        except SocketError:
            pass

        self.fire(disconnect(sock))

    @handler("close")
    def close(self, sock=None):
        is_closed = sock is None

        if sock is None:
            socks = [self._sock]
            socks.extend(self._clients[:])
        else:
            socks = [sock]

        for sock in socks:
            if not self._buffers[sock]:
                self._close(sock)
            elif sock not in self._closeq:
                self._closeq.append(sock)

        if is_closed:
            self.fire(closed())

    def _read(self, sock):
        if sock not in self._clients:
            return

        try:
            data = sock.recv(self._bufsize)
            if data:
                self.fire(read(sock, data)).notify = True
            else:
                self.close(sock)
        except SocketError as e:
            if e.args[0] == EWOULDBLOCK:
                return
            else:
                self.fire(error(sock, e))
                self._close(sock)

    def _write(self, sock, data):
        if sock not in self._clients:
            return

        try:
            nbytes = sock.send(data)
            if nbytes < len(data):
                self._buffers[sock].appendleft(data[nbytes:])
        except SocketError as e:
            if e.args[0] not in (EINTR, EWOULDBLOCK, ENOBUFS):
                self.fire(error(sock, e))
                self._close(sock)
            else:
                self._buffers[sock].appendleft(data)

    @handler("write")
    def write(self, sock, data):
        if not self._poller.isWriting(sock):
            self._poller.addWriter(self, sock)
        self._buffers[sock].append(data)

    def _accept(self):  # noqa
        # XXX: C901: This has a high McCacbe complexity score of 10.
        # TODO: Refactor this!

        def on_done(sock, host):
            sock.setblocking(False)
            self._poller.addReader(self, sock)
            self._clients.append(sock)
            self.fire(connect(sock, *host))

        def on_error(sock, err):
            self.fire(error(sock, err))
            self._close(sock)

        try:
            newsock, host = self._sock.accept()
        except SocketError as e:
            if e.args[0] in (EWOULDBLOCK, EAGAIN):
                return
            elif e.args[0] == EPERM:
                # Netfilter on Linux may have rejected the
                # connection, but we get told to try to accept()
                # anyway.
                return
            elif e.args[0] in (EMFILE, ENOBUFS, ENFILE, ENOMEM, ECONNABORTED):
                # Linux gives EMFILE when a process is not allowed
                # to allocate any more file descriptors.  *BSD and
                # Win32 give (WSA)ENOBUFS.  Linux can also give
                # ENFILE if the system is out of inodes, or ENOMEM
                # if there is insufficient memory to allocate a new
                # dentry.  ECONNABORTED is documented as possible on
                # both Linux and Windows, but it is not clear
                # whether there are actually any circumstances under
                # which it can happen (one might expect it to be
                # possible if a client sends a FIN or RST after the
                # server sends a SYN|ACK but before application code
                # calls accept(2), however at least on Linux this
                # _seems_ to be short-circuited by syncookies.
                return
            else:
                raise

        if self.secure and HAS_SSL:
            sslsock = ssl_socket(
                newsock,
                server_side=True,
                keyfile=self.keyfile,
                ca_certs=self.ca_certs,
                certfile=self.certfile,
                cert_reqs=self.cert_reqs,
                ssl_version=self.ssl_version,
                do_handshake_on_connect=False
            )

            for _ in do_handshake(sslsock, on_done, on_error, extra_args=(host,)):
                yield
        else:
            on_done(newsock, host)

    @handler("_disconnect", priority=1)
    def _on_disconnect(self, sock):
        self._close(sock)

    @handler("_read", priority=1)
    def _on_read(self, sock):
        if sock == self._sock:
            return self._accept()
        else:
            self._read(sock)

    @handler("_write", priority=1)
    def _on_write(self, sock):
        if self._buffers[sock]:
            data = self._buffers[sock].popleft()
            self._write(sock, data)

        if not self._buffers[sock]:
            if sock in self._closeq:
                self._closeq.remove(sock)
                self._close(sock)
            elif self._poller.isWriting(sock):
                self._poller.removeWriter(sock)
Пример #11
0
class Serial(Component):

    channel = "serial"

    def __init__(self, port, baudrate=115200, bufsize=BUFSIZE,
                 timeout=TIMEOUT, channel=channel):
        super(Serial, self).__init__(channel=channel)

        if serial is None:
            raise RuntimeError("No serial support available")

        self._port = port
        self._baudrate = baudrate
        self._bufsize = bufsize

        self._serial = None
        self._poller = None
        self._buffer = deque()
        self._closeflag = False

    @handler("ready")
    def _on_ready(self, component):
        self.fire(_open(), self.channel)

    @handler("_open")
    def _on_open(self, port=None, baudrate=None, bufsize=None):
        self._port = port or self._port
        self._baudrate = baudrate or self._baudrate
        self._bufsize = bufsize or self._bufsize

        self._serial = serial.Serial(
            port=self._port, baudrate=self._baudrate, timeout=0)
        self._fd = self._serial.fileno()  # not portable!

        self._poller.addReader(self, self._fd)

        self.fire(opened(self._port, self._baudrate))

    @handler("registered", "started", channel="*")
    def _on_registered_or_started(self, component, manager=None):
        if self._poller is None:
            if isinstance(component, BasePoller):
                self._poller = component
                self.fire(ready(self))
            else:
                if component is not self:
                    return
                component = findcmp(self.root, BasePoller)
                if component is not None:
                    self._poller = component
                    self.fire(ready(self))
                else:
                    self._poller = Poller().register(self)
                    self.fire(ready(self))

    @handler("stopped", channel="*")
    def _on_stopped(self, component):
        self.fire(close())

    @handler("prepare_unregister", channel="*")
    def _on_prepare_unregister(self, event, c):
        if event.in_subtree(self):
            self._close()

    def _close(self):
        if self._closeflag:
            return

        self._poller.discard(self._fd)

        self._buffer.clear()
        self._closeflag = False
        self._connected = False

        try:
            self._serial.close()
        except:
            pass

        self.fire(closed())

    def close(self):
        if not self._buffer:
            self._close()
        elif not self._closeflag:
            self._closeflag = True

    def _read(self):
        try:
            data = self._serial.read(self._bufsize)
            if not isinstance(data, binary_type):
                data = data.encode(self._encoding)

            if data:
                self.fire(read(data)).notify = True
        except (OSError, IOError) as e:
            self.fire(error(e))
            self._close()

    def _write(self, data):
        try:
            if not isinstance(data, binary_type):
                data = data.encode(self._encoding)

            try:
                nbytes = self._serial.write(data)
            except (serial.SerialTimeoutException) as e:
                nbytes = 0
            if nbytes < len(data):
                self._buffer.appendleft(data[nbytes:])
        except (OSError, IOError) as e:
            self.fire(error(e))
            self._close()

    def write(self, data):
        if self._poller is not None and not self._poller.isWriting(self._fd):
            self._poller.addWriter(self, self._fd)
        self._buffer.append(data)

    @handler("_disconnect")
    def __on_disconnect(self, sock):
        self._close()

    @handler("_read")
    def __on_read(self, sock):
        self._read()

    @handler("_write")
    def __on_write(self, sock):
        if self._buffer:
            data = self._buffer.popleft()
            self._write(data)

        if not self._buffer:
            if self._closeflag:
                self._close()
            elif self._poller.isWriting(self._fd):
                self._poller.removeWriter(self._fd)
Пример #12
0
class File(Component):

    channel = "file"

    def init(self, filename, mode="r", bufsize=BUFSIZE, encoding=None,
             channel=channel):
        self._mode = mode
        self._bufsize = bufsize
        self._filename = filename
        self._encoding = encoding or getdefaultencoding()

        self._fd = None
        self._poller = None
        self._buffer = deque()
        self._closeflag = False

    @property
    def closed(self):
        return getattr(self._fd, "closed", True) \
            if hasattr(self, "_fd") else True

    @property
    def filename(self):
        return getattr(self, "_filename", None)

    @property
    def mode(self):
        return getattr(self, "_mode", None)

    @handler("ready")
    def _on_ready(self, component):
        self.fire(_open(), self.channel)

    @handler("_open")
    def _on_open(self, filename=None, mode=None, bufsize=None):
        self._filename = filename or self._filename
        self._bufsize = bufsize or self._bufsize
        self._mode = mode or self._mode

        if isinstance(self._filename, string_types[0]):
            kwargs = {"encoding": self._encoding} if PY3 else {}
            self._fd = open(self.filename, self.mode, **kwargs)
        else:
            self._fd = self._filename
            self._mode = self._fd.mode
            self._filename = self._fd.name
            self._encoding = getattr(self._fd, "encoding", self._encoding)

        if fcntl is not None:
            # Set non-blocking file descriptor (non-portable)
            flag = fcntl.fcntl(self._fd, fcntl.F_GETFL)
            flag = flag | O_NONBLOCK
            fcntl.fcntl(self._fd, fcntl.F_SETFL, flag)

        if "r" in self.mode or "+" in self.mode:
            self._poller.addReader(self, self._fd)

        self.fire(opened(self.filename, self.mode))

    @handler("registered", "started", channel="*")
    def _on_registered_or_started(self, component, manager=None):
        if self._poller is None:
            if isinstance(component, BasePoller):
                self._poller = component
                self.fire(ready(self))
            else:
                if component is not self:
                    return
                component = findcmp(self.root, BasePoller)
                if component is not None:
                    self._poller = component
                    self.fire(ready(self))
                else:
                    self._poller = Poller().register(self)
                    self.fire(ready(self))

    @handler("stopped", channel="*")
    def _on_stopped(self, component):
        self.fire(close())

    @handler("prepare_unregister", channel="*")
    def _on_prepare_unregister(self, event, c):
        if event.in_subtree(self):
            self._close()

    def _close(self):
        if self.closed:
            return

        self._poller.discard(self._fd)

        self._buffer.clear()
        self._closeflag = False
        self._connected = False

        try:
            self._fd.close()
        except:
            pass

        self.fire(closed())

    def close(self):
        if not self._buffer:
            self._close()
        elif not self._closeflag:
            self._closeflag = True

    def _read(self):
        try:
            data = fd_read(self._fd.fileno(), self._bufsize)
            if not isinstance(data, binary_type):
                data = data.encode(self._encoding)

            if data:
                self.fire(read(data)).notify = True
            else:
                self.fire(eof())
                if not any(m in self.mode for m in ("a", "+")):
                    self.close()
                else:
                    self._poller.discard(self._fd)
        except (OSError, IOError) as e:
            if e.args[0] in (EWOULDBLOCK, EINTR):
                return
            else:
                self.fire(error(e))
                self._close()

    def seek(self, offset, whence=0):
        self._fd.seek(offset, whence)

    def _write(self, data):
        try:
            if not isinstance(data, binary_type):
                data = data.encode(self._encoding)

            nbytes = fd_write(self._fd.fileno(), data)

            if nbytes < len(data):
                self._buffer.appendleft(data[nbytes:])
        except (OSError, IOError) as e:
            if e.args[0] in (EWOULDBLOCK, EINTR):
                return
            else:
                self.fire(error(e))
                self._close()

    def write(self, data):
        if self._poller is not None and not self._poller.isWriting(self._fd):
            self._poller.addWriter(self, self._fd)
        self._buffer.append(data)

    @handler("_disconnect")
    def __on_disconnect(self, sock):
        self._close()

    @handler("_read")
    def __on_read(self, sock):
        self._read()

    @handler("_write")
    def __on_write(self, sock):
        if self._buffer:
            data = self._buffer.popleft()
            self._write(data)

        if not self._buffer:
            if self._closeflag:
                self._close()
            elif self._poller.isWriting(self._fd):
                self._poller.removeWriter(self._fd)
Пример #13
0
class File(Component):

    channel = "file"

    def init(self, filename, mode="r", bufsize=BUFSIZE, encoding=None,
             channel=channel):
        self._mode = mode
        self._bufsize = bufsize
        self._filename = filename
        self._encoding = encoding or getdefaultencoding()

        self._fd = None
        self._poller = None
        self._buffer = deque()
        self._closeflag = False

    @property
    def closed(self):
        return getattr(self._fd, "closed", True) \
            if hasattr(self, "_fd") else True

    @property
    def filename(self):
        return getattr(self, "_filename", None)

    @property
    def mode(self):
        return getattr(self, "_mode", None)

    @handler("ready")
    def _on_ready(self, component):
        self.fire(_open(), self.channel)

    @handler("_open")
    def _on_open(self, filename=None, mode=None, bufsize=None):
        self._filename = filename or self._filename
        self._bufsize = bufsize or self._bufsize
        self._mode = mode or self._mode

        if isinstance(self._filename, string_types[0]):
            kwargs = {"encoding": self._encoding} if PY3 else {}
            self._fd = open(self.filename, self.mode, **kwargs)
        else:
            self._fd = self._filename
            self._mode = self._fd.mode
            self._filename = self._fd.name
            self._encoding = getattr(self._fd, "encoding", self._encoding)

        if fcntl is not None:
            # Set non-blocking file descriptor (non-portable)
            flag = fcntl.fcntl(self._fd, fcntl.F_GETFL)
            flag = flag | O_NONBLOCK
            fcntl.fcntl(self._fd, fcntl.F_SETFL, flag)

        if "r" in self.mode or "+" in self.mode:
            self._poller.addReader(self, self._fd)

        self.fire(opened(self.filename, self.mode))

    @handler("registered", "started", channel="*")
    def _on_registered_or_started(self, component, manager=None):
        if self._poller is None:
            if isinstance(component, BasePoller):
                self._poller = component
                self.fire(ready(self))
            else:
                if component is not self:
                    return
                component = findcmp(self.root, BasePoller)
                if component is not None:
                    self._poller = component
                    self.fire(ready(self))
                else:
                    self._poller = Poller().register(self)
                    self.fire(ready(self))

    @handler("stopped", channel="*")
    def _on_stopped(self, component):
        self.fire(close())

    @handler("prepare_unregister", channel="*")
    def _on_prepare_unregister(self, event, c):
        if event.in_subtree(self):
            self._close()

    def _close(self):
        if self.closed:
            return

        self._poller.discard(self._fd)

        self._buffer.clear()
        self._closeflag = False
        self._connected = False

        try:
            self._fd.close()
        except:
            pass

        self.fire(closed())

    def close(self):
        if not self._buffer:
            self._close()
        elif not self._closeflag:
            self._closeflag = True

    def _read(self):
        try:
            data = fd_read(self._fd.fileno(), self._bufsize)
            if not isinstance(data, binary_type):
                data = data.encode(self._encoding)

            if data:
                self.fire(read(data)).notify = True
            else:
                self.fire(eof())
                if not any(m in self.mode for m in ("a", "+")):
                    self.close()
                else:
                    self._poller.discard(self._fd)
        except (OSError, IOError) as e:
            if e.args[0] in (EWOULDBLOCK, EINTR):
                return
            else:
                self.fire(error(e))
                self._close()

    def seek(self, offset, whence=0):
        self._fd.seek(offset, whence)

    def _write(self, data):
        try:
            if not isinstance(data, binary_type):
                data = data.encode(self._encoding)

            nbytes = fd_write(self._fd.fileno(), data)

            if nbytes < len(data):
                self._buffer.appendleft(data[nbytes:])
        except (OSError, IOError) as e:
            if e.args[0] in (EWOULDBLOCK, EINTR):
                return
            else:
                self.fire(error(e))
                self._close()

    def write(self, data):
        if self._poller is not None and not self._poller.isWriting(self._fd):
            self._poller.addWriter(self, self._fd)
        self._buffer.append(data)

    @handler("_disconnect")
    def __on_disconnect(self, sock):
        self._close()

    @handler("_read")
    def __on_read(self, sock):
        self._read()

    @handler("_write")
    def __on_write(self, sock):
        if self._buffer:
            data = self._buffer.popleft()
            self._write(data)

        if not self._buffer:
            if self._closeflag:
                self._close()
            elif self._poller.isWriting(self._fd):
                self._poller.removeWriter(self._fd)