Пример #1
0
class SslHandshakingTransport(BaseSocketTransport):
    __slots__ = ["connected_dfr"]

    def __init__(self, reactor, sslsock):
        BaseSocketTransport.__init__(self, reactor, sslsock)
        self.connected_dfr = ReactorDeferred(self.reactor)

    def handshake(self):
        if not self.connected_dfr.is_set():
            self._handshake()
        return self.connected_dfr

    def _handshake(self):
        try:
            self.sock.do_handshake()
        except ssl.SSLError as ex:
            if ex.errno == ssl.SSL_ERROR_WANT_READ:
                self.reactor.register_read(self)
            elif ex.errno == ssl.SSL_ERROR_WANT_WRITE:
                self.reactor.register_write(self)
            else:
                self.connected_dfr.throw(ex)
        else:
            sock = self.sock
            self.detach()
            trns = SslStreamTransport(self.reactor, sock)
            self.connected_dfr.set(trns)

    def on_read(self):
        self.reactor.unregister_read(self)
        self._handshake()

    def on_write(self):
        self.reactor.unregister_write(self)
        self._handshake()
Пример #2
0
    def recvfrom(self, count=-1):
        if count < 0 or count > self.MAX_DATAGRAM_SIZE:
            count = self.MAX_DATAGRAM_SIZE
        if self._ongoing_read:
            raise OverlappingRequestError("overlapping recvfrom")
        self._ongoing_read = True

        def read_finished(size, exc):
            self._ongoing_read = False
            if exc:
                dfr.throw(exc)
            else:
                data = buf[:size]
                addrinfo = (sockaddr.addr_str, sockaddr.port)
                dfr.set((data, addrinfo))

        dfr = ReactorDeferred(self.reactor)
        overlapped = self.reactor._get_overlapped(read_finished)
        try:
            buf, sockaddr, _ = winsock.WSARecvFromSocket(
                self.sock, count, overlapped)
        except Exception as ex:
            self._ongoing_read = False
            self.reactor._discard_overlapped(overlapped)
            dfr.throw(ex)
        return dfr
Пример #3
0
class SslHandshakingTransport(BaseSocketTransport):
    __slots__ = ["connected_dfr"]

    def __init__(self, reactor, sslsock):
        BaseSocketTransport.__init__(self, reactor, sslsock)
        self.connected_dfr = ReactorDeferred(self.reactor)

    def handshake(self):
        if not self.connected_dfr.is_set():
            self._handshake()
        return self.connected_dfr

    def _handshake(self):
        try:
            self.sock.do_handshake()
        except ssl.SSLError as ex:
            if ex.errno == ssl.SSL_ERROR_WANT_READ:
                self.reactor.register_read(self)
            elif ex.errno == ssl.SSL_ERROR_WANT_WRITE:
                self.reactor.register_write(self)
            else:
                self.connected_dfr.throw(ex)
        else:
            sock = self.sock
            self.detach()
            trns = SslStreamTransport(self.reactor, sock)
            self.connected_dfr.set(trns)

    def on_read(self):
        self.reactor.unregister_read(self)
        self._handshake()

    def on_write(self):
        self.reactor.unregister_write(self)
        self._handshake()
Пример #4
0
 def __init__(self):
     self._active = False
     self._jobs = MinHeap()
     self._callbacks = []
     #self._rcallbacks = []
     self._subsystems = []
     self.started = ReactorDeferred(weakref.proxy(self))
Пример #5
0
    def recvfrom(self, count = -1):
        if count < 0 or count > self.MAX_DATAGRAM_SIZE:
            count = self.MAX_DATAGRAM_SIZE
        if self._ongoing_read:
            raise OverlappingRequestError("overlapping recvfrom")
        self._ongoing_read = True

        def read_finished(size, exc):
            self._ongoing_read = False
            if exc:
                dfr.throw(exc)
            else:
                data = buf[:size]
                addrinfo = (sockaddr.addr_str, sockaddr.port)
                dfr.set((data, addrinfo))

        dfr = ReactorDeferred(self.reactor)
        overlapped = self.reactor._get_overlapped(read_finished)
        try:
            buf, sockaddr, _ = winsock.WSARecvFromSocket(self.sock, count, overlapped)
        except Exception as ex:
            self._ongoing_read = False
            self.reactor._discard_overlapped(overlapped)
            dfr.throw(ex)
        return dfr
Пример #6
0
class Process(object):
    def __init__(self, reactor, proc, cmdline):
        self.reactor = reactor
        self.cmdline = cmdline
        self._proc = proc
        self.stdin = BufferedTransport(self.reactor.io._wrap_pipe(proc.stdin, "w"))
        self.stdout = BufferedTransport(self.reactor.io._wrap_pipe(proc.stdout, "r"))
        self.stderr = BufferedTransport(self.reactor.io._wrap_pipe(proc.stderr, "r"))
        self.pid = proc.pid
        self.wait_dfr = ReactorDeferred(self.reactor)
    def __repr__(self):
        return "<Process %r: %r (%s)>" % (self.pid, self.cmdline,
            "alive" if self.is_alive() else "dead")
    def on_termination(self):
        self.wait_dfr.set(self.returncode)
    @property
    def returncode(self):
        return self._proc.returncode
    def is_alive(self):
        return self._proc.poll() is None
    def signal(self, sig):
        self._proc.send_signal(sig)
    @reactive
    def terminate(self):
        self._proc.terminate()
    def wait(self):
        return self.wait_dfr
Пример #7
0
 def read(self, count):
     if self._read_req:
         raise OverlappingRequestError("overlapping reads")
     dfr = ReactorDeferred(self.reactor)
     if self._eof:
         dfr.set(None)
     elif count <= 0:
         dfr.set("")
     else:
         self._read_req = (dfr, count)
         self.reactor.register_read(self)
     return dfr
Пример #8
0
 def __init__(self, reactor, proc, cmdline):
     self.reactor = reactor
     self.cmdline = cmdline
     self._proc = proc
     self.stdin = BufferedTransport(
         self.reactor.io._wrap_pipe(proc.stdin, "w"))
     self.stdout = BufferedTransport(
         self.reactor.io._wrap_pipe(proc.stdout, "r"))
     self.stderr = BufferedTransport(
         self.reactor.io._wrap_pipe(proc.stderr, "r"))
     self.pid = proc.pid
     self.wait_dfr = ReactorDeferred(self.reactor)
Пример #9
0
class PipeTransport(StreamTransport):
    #__slots__ = ["mode", "name", "_flush_dfr", "auto_flush"]
    def __init__(self, reactor, fileobj, mode, auto_flush=True):
        if mode not in ("r", "w", "rw"):
            raise ValueError("invalid mode")
        StreamTransport.__init__(self, reactor, fileobj)
        self.name = getattr(self.fileobj, "name", None)
        self.mode = mode
        self._flush_dfr = None
        self.auto_flush = auto_flush
        if "r" not in mode:
            self.read = self._wrong_mode
            self.properties.pop("readable", None)
        if "w" not in mode:
            self.flush = self._wrong_mode
            self.write = self._wrong_mode
            self.properties.pop("writable", None)
        if fcntl:
            self._unblock(self.fileno())

    @staticmethod
    def _wrong_mode(*args):
        raise IOError("wrong mode for operation")

    @staticmethod
    def _unblock(fd):
        flags = fcntl.fcntl(fd, fcntl.F_GETFL, 0)
        fcntl.fcntl(fd, fcntl.F_SETFL, flags | os.O_NONBLOCK)

    def isatty(self):
        return self.fileobj.isatty()

    def flush(self):
        if not self._flush_dfr:
            self._flush_dfr = ReactorDeferred(self.reactor)
            self.reactor.register_write(self)
        return self._flush_dfr

    def _flush(self):
        self.fileobj.flush()
        os.fsync(self.fileno())
        if self._flush_dfr:
            self._flush_dfr.set()
            self._flush_dfr = None

    def on_write(self):
        StreamTransport.on_write(self)
        if self.auto_flush or self._flush_dfr:
            self._flush()
Пример #10
0
 def recvfrom(self, count=-1):
     if self._read_req:
         raise OverlappingRequestError("overlapping recvfrom")
     dfr = ReactorDeferred(self.reactor)
     self._read_req = (dfr, count)
     self.reactor.register_read(self)
     return dfr
Пример #11
0
 def write(self, data):
     if self._write_req:
         raise OverlappingRequestError("overlapping writes")
     dfr = ReactorDeferred(self.reactor)
     self._write_req = (dfr, data)
     self.reactor.register_write(self)
     return dfr
Пример #12
0
 def __init__(self):
     self._active = False
     self._jobs = MinHeap()
     self._callbacks = []
     #self._rcallbacks = []
     self._subsystems = []
     self.started = ReactorDeferred(weakref.proxy(self))
Пример #13
0
class PipeTransport(StreamTransport):
    #__slots__ = ["mode", "name", "_flush_dfr", "auto_flush"]
    def __init__(self, reactor, fileobj, mode, auto_flush = True):
        if mode not in ("r", "w", "rw"):
            raise ValueError("invalid mode")
        StreamTransport.__init__(self, reactor, fileobj)
        self.name = getattr(self.fileobj, "name", None)
        self.mode = mode
        self._flush_dfr = None
        self.auto_flush = auto_flush
        if "r" not in mode:
            self.read = self._wrong_mode
            self.properties.pop("readable", None)
        if "w" not in mode:
            self.flush = self._wrong_mode
            self.write = self._wrong_mode
            self.properties.pop("writable", None)
        if fcntl:
            self._unblock(self.fileno())

    @staticmethod
    def _wrong_mode(*args):
        raise IOError("wrong mode for operation")
    @staticmethod
    def _unblock(fd):
        flags = fcntl.fcntl(fd, fcntl.F_GETFL, 0)
        fcntl.fcntl(fd, fcntl.F_SETFL, flags | os.O_NONBLOCK)
    def isatty(self):
        return self.fileobj.isatty()

    def flush(self):
        if not self._flush_dfr:
            self._flush_dfr = ReactorDeferred(self.reactor)
            self.reactor.register_write(self)
        return self._flush_dfr

    def _flush(self):
        self.fileobj.flush()
        os.fsync(self.fileno())
        if self._flush_dfr:
            self._flush_dfr.set()
            self._flush_dfr = None

    def on_write(self):
        StreamTransport.on_write(self)
        if self.auto_flush or self._flush_dfr:
            self._flush()
Пример #14
0
 def sendto(self, addr, data):
     if len(data) > self.MAX_DATAGRAM_SIZE:
         raise TransportError("data too long")
     if self._write_req:
         raise OverlappingRequestError("overlapping sendto")
     dfr = ReactorDeferred(self.reactor)
     self._write_req = (dfr, addr, data)
     self.reactor.register_write(self)
     return dfr
Пример #15
0
 def __init__(self, reactor, proc, cmdline):
     self.reactor = reactor
     self.cmdline = cmdline
     self._proc = proc
     self.stdin = BufferedTransport(self.reactor.io._wrap_pipe(proc.stdin, "w"))
     self.stdout = BufferedTransport(self.reactor.io._wrap_pipe(proc.stdout, "r"))
     self.stderr = BufferedTransport(self.reactor.io._wrap_pipe(proc.stderr, "r"))
     self.pid = proc.pid
     self.wait_dfr = ReactorDeferred(self.reactor)
Пример #16
0
    def accept(self):
        def accept_finished(size, exc):
            if exc:
                self.reactor.call(trns.close)
                dfr.throw(exc)
            else:
                dfr.set(trns)

        dfr = ReactorDeferred(self.reactor)
        overlapped = self.reactor._get_overlapped(accept_finished)
        try:
            sock = socket.socket(self.sock.family, self.sock.type)
            # this is needed here to register the new socket with its IOCP
            trns = self.factory(self.reactor, sock)
            fd = sock.fileno()
            buffer = win32file.AllocateReadBuffer(win32file.CalculateSocketEndPointSize(fd))
            win32file.AcceptEx(self.fileno(), fd, buffer, overlapped)
        except Exception as ex:
            self.reactor._discard_overlapped(overlapped)
            dfr.throw(ex)
        return dfr
Пример #17
0
    def schedule(self, interval, func, *args, **kwargs):
        def wrapper():
            try:
                res = func(*args, **kwargs)
            except Exception as ex:
                dfr.throw(ex)
            else:
                dfr.set(res)

        functools.update_wrapper(wrapper, func)
        dfr = ReactorDeferred(self.reactor)
        self.reactor.call_at(time.time() + interval, wrapper)
        return dfr
Пример #18
0
    def accept(self):
        def accept_finished(size, exc):
            if exc:
                self.reactor.call(trns.close)
                dfr.throw(exc)
            else:
                dfr.set(trns)

        dfr = ReactorDeferred(self.reactor)
        overlapped = self.reactor._get_overlapped(accept_finished)
        try:
            sock = socket.socket(self.sock.family, self.sock.type)
            # this is needed here to register the new socket with its IOCP
            trns = self.factory(self.reactor, sock)
            fd = sock.fileno()
            buffer = win32file.AllocateReadBuffer(
                win32file.CalculateSocketEndPointSize(fd))
            win32file.AcceptEx(self.fileno(), fd, buffer, overlapped)
        except Exception as ex:
            self.reactor._discard_overlapped(overlapped)
            dfr.throw(ex)
        return dfr
Пример #19
0
    def sendto(self, addr, data):
        if len(data) > self.MAX_DATAGRAM_SIZE:
            raise TransportError("data too long")
        if self._ongoing_write:
            raise OverlappingRequestError("overlapping sendto")
        self._ongoing_write = True

        def write_finished(size, exc):
            self._ongoing_write = False
            if exc:
                dfr.throw(exc)
            else:
                dfr.set(size)  # return actual sent size

        dfr = ReactorDeferred(self.reactor)
        overlapped = self.reactor._get_overlapped(write_finished)
        try:
            winsock.WSASendToSocket(self.sock, data, addr, overlapped)
        except Exception as ex:
            self._ongoing_read = False
            self.reactor._discard_overlapped(overlapped)
            dfr.throw(ex)
        return dfr
Пример #20
0
    def sendto(self, addr, data):
        if len(data) > self.MAX_DATAGRAM_SIZE:
            raise TransportError("data too long")
        if self._ongoing_write:
            raise OverlappingRequestError("overlapping sendto")
        self._ongoing_write = True

        def write_finished(size, exc):
            self._ongoing_write = False
            if exc:
                dfr.throw(exc)
            else:
                dfr.set(size) # return actual sent size

        dfr = ReactorDeferred(self.reactor)
        overlapped = self.reactor._get_overlapped(write_finished)
        try:
            winsock.WSASendToSocket(self.sock, data, addr, overlapped)
        except Exception as ex:
            self._ongoing_read = False
            self.reactor._discard_overlapped(overlapped)
            dfr.throw(ex)
        return dfr
Пример #21
0
class Process(object):
    def __init__(self, reactor, proc, cmdline):
        self.reactor = reactor
        self.cmdline = cmdline
        self._proc = proc
        self.stdin = BufferedTransport(
            self.reactor.io._wrap_pipe(proc.stdin, "w"))
        self.stdout = BufferedTransport(
            self.reactor.io._wrap_pipe(proc.stdout, "r"))
        self.stderr = BufferedTransport(
            self.reactor.io._wrap_pipe(proc.stderr, "r"))
        self.pid = proc.pid
        self.wait_dfr = ReactorDeferred(self.reactor)

    def __repr__(self):
        return "<Process %r: %r (%s)>" % (self.pid, self.cmdline, "alive"
                                          if self.is_alive() else "dead")

    def on_termination(self):
        self.wait_dfr.set(self.returncode)

    @property
    def returncode(self):
        return self._proc.returncode

    def is_alive(self):
        return self._proc.poll() is None

    def signal(self, sig):
        self._proc.send_signal(sig)

    @reactive
    def terminate(self):
        self._proc.terminate()

    def wait(self):
        return self.wait_dfr
Пример #22
0
    def read(self, count):
        # XXX:
        # The ReadFile function may fail with ERROR_INVALID_USER_BUFFER or
        # ERROR_NOT_ENOUGH_MEMORY whenever there are too many outstanding
        # asynchronous I/O requests.
        #
        # XXX:
        # http://support.microsoft.com/kb/156932 -- ReadFile may return
        # immediately, need to check that condition

        if self._ongoing_read:
            raise OverlappingRequestError("overlapping reads")
        self._ongoing_read = True

        def read_finished(size, exc):
            if size == 0:
                data = None  # EOF
            else:
                data = bytes(buf[:size])
            self._ongoing_read = False
            if exc:
                dfr.throw(exc)
            else:
                dfr.set(data)

        dfr = ReactorDeferred(self.reactor)
        count = min(count, self.MAX_READ_SIZE)
        if count <= 0:
            self._ongoing_read = False
            dfr.set("")
            return dfr
        overlapped = self._get_read_overlapped(read_finished)
        try:
            buf = win32file.AllocateReadBuffer(count)
            win32file.ReadFile(self.fileno(), buf, overlapped)
        except Exception as ex:
            self.reactor._discard_overlapped(overlapped)
            self._ongoing_read = False
            if isinstance(ex, pywintypes.error
                          ) and ex.winerror in win32iocp.IGNORED_ERRORS:
                # why can't windows be just a little consistent?!
                # why can't a set of APIs share the same semantics for all kinds
                # of handles? grrrrr
                dfr.set(None)
            else:
                dfr.throw(ex)
        return dfr
Пример #23
0
class ConnectingSocketTransport(BaseSocketTransport):
    __slots__ = ["addr", "connected_dfr", "_connecting"]

    def __init__(self, reactor, sock, addr):
        BaseSocketTransport.__init__(self, reactor, sock)
        self.addr = addr
        self.connected_dfr = ReactorDeferred(self.reactor)
        self._connecting = False

    def connect(self, timeout=None):
        if self._connecting:
            raise OverlappingRequestError("already connecting")
        self._connecting = True
        if timeout is not None:
            self.reactor.jobs.schedule(timeout, self._cancel)
        self.reactor.register_write(self)
        self._attempt_connect()
        return self.connected_dfr

    def on_write(self):
        self._attempt_connect()

    def _attempt_connect(self):
        if self.connected_dfr.is_set():
            self.detach()
            return
        err = self.sock.connect_ex(self.addr)
        if err in (errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK):
            return
        if err == errno.EINVAL and sys.platform == "win32":
            return

        sock = self.sock
        self.detach()
        if err in (0, errno.EISCONN):
            self.connected_dfr.set(SocketStreamTransport(self.reactor, sock))
        else:
            self.connected_dfr.throw(socket.error(err, errno.errorcode[err]))

    def _cancel(self):
        if self.connected_dfr.is_set():
            return
        self.close()
        self.connected_dfr.throw(socket.timeout("connection timed out"))
Пример #24
0
class ConnectingSocketTransport(BaseSocketTransport):
    __slots__ = ["addr", "connected_dfr", "_connecting"]
    def __init__(self, reactor, sock, addr):
        BaseSocketTransport.__init__(self, reactor, sock)
        self.addr = addr
        self.connected_dfr = ReactorDeferred(self.reactor)
        self._connecting = False

    def connect(self, timeout = None):
        if self._connecting:
            raise OverlappingRequestError("already connecting")
        self._connecting = True
        if timeout is not None:
            self.reactor.jobs.schedule(timeout, self._cancel)
        self.reactor.register_write(self)
        self._attempt_connect()
        return self.connected_dfr

    def on_write(self):
        self._attempt_connect()

    def _attempt_connect(self):
        if self.connected_dfr.is_set():
            self.detach()
            return
        err = self.sock.connect_ex(self.addr)
        if err in (errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK):
            return
        if err == errno.EINVAL and sys.platform == "win32":
            return

        sock = self.sock
        self.detach()
        if err in (0, errno.EISCONN):
            self.connected_dfr.set(SocketStreamTransport(self.reactor, sock))
        else:
            self.connected_dfr.throw(socket.error(err, errno.errorcode[err]))

    def _cancel(self):
        if self.connected_dfr.is_set():
            return
        self.close()
        self.connected_dfr.throw(socket.timeout("connection timed out"))
Пример #25
0
 def read(self, count):
     if self._read_req:
         raise OverlappingRequestError("overlapping reads")
     dfr = ReactorDeferred(self.reactor)
     if self._eof:
         dfr.set(None)
     elif count <= 0:
         dfr.set("")
     else:
         self._read_req = (dfr, count)
         self.reactor.register_read(self)
     return dfr
Пример #26
0
    def schedule_every(self, interval, func, *args, **kwargs):
        def wrapper():
            try:
                res = func(*args, **kwargs)
            except Exception as ex:
                dfr.throw(ex)
            else:
                if res is False:
                    dfr.set()
                else:
                    ts = t0 + (((time.time() - t0) // interval) + 1) * interval
                    self.reactor.call_at(ts, wrapper)

        functools.update_wrapper(wrapper, func)
        dfr = ReactorDeferred(self.reactor)
        t0 = time.time()
        self.reactor.call_at(t0, wrapper)
        return dfr
Пример #27
0
    def read(self, count):
        # XXX:
        # The ReadFile function may fail with ERROR_INVALID_USER_BUFFER or
        # ERROR_NOT_ENOUGH_MEMORY whenever there are too many outstanding
        # asynchronous I/O requests.
        #
        # XXX:
        # http://support.microsoft.com/kb/156932 -- ReadFile may return
        # immediately, need to check that condition

        if self._ongoing_read:
            raise OverlappingRequestError("overlapping reads")
        self._ongoing_read = True

        def read_finished(size, exc):
            if size == 0:
                data = None   # EOF
            else:
                data = bytes(buf[:size])
            self._ongoing_read = False
            if exc:
                dfr.throw(exc)
            else:
                dfr.set(data)

        dfr = ReactorDeferred(self.reactor)
        count = min(count, self.MAX_READ_SIZE)
        if count <= 0:
            self._ongoing_read = False
            dfr.set("")
            return dfr
        overlapped = self._get_read_overlapped(read_finished)
        try:
            buf = win32file.AllocateReadBuffer(count)
            win32file.ReadFile(self.fileno(), buf, overlapped)
        except Exception as ex:
            self.reactor._discard_overlapped(overlapped)
            self._ongoing_read = False
            if isinstance(ex, pywintypes.error) and ex.winerror in win32iocp.IGNORED_ERRORS:
                # why can't windows be just a little consistent?!
                # why can't a set of APIs share the same semantics for all kinds
                # of handles? grrrrr
                dfr.set(None)
            else:
                dfr.throw(ex)
        return dfr
Пример #28
0
    def write(self, data):
        # XXX:
        # The WriteFile function may fail with ERROR_INVALID_USER_BUFFER or
        # ERROR_NOT_ENOUGH_MEMORY whenever there are too many outstanding
        # asynchronous I/O requests.
        #
        # XXX:
        # http://support.microsoft.com/kb/156932 -- WriteFile may return
        # immediately, need to check that condition

        if self._ongoing_write:
            raise OverlappingRequestError("overlapping writes")

        self._ongoing_write = True
        remaining = [data]

        def write_finished(size, exc):
            remaining[0] = remaining[0][size:]
            if exc:
                dfr.throw(exc)
            elif not remaining[0]:
                self._ongoing_write = False
                dfr.set()
            else:
                write_some()

        def write_some():
            if not remaining[0]:
                self._ongoing_write = False
                dfr.set()
                return
            chunk = remaining[0][:self.MAX_READ_SIZE]
            overlapped = self._get_read_overlapped(write_finished)
            try:
                win32file.WriteFile(self.fileno(), chunk, overlapped)
            except Exception as ex:
                self._ongoing_write = False
                self.reactor._discard_overlapped(overlapped)
                dfr.throw(ex)

        dfr = ReactorDeferred(self.reactor)
        write_some()
        return dfr
Пример #29
0
    def call(self, func, *args, **kwargs):
        def worker():
            try:
                res = func(*args, **kwargs)
            except Exception as ex:
                dfr.throw(ex)
            else:
                dfr.set(res)
            finally:
                self._threads.discard(thd)
            self.reactor._wakeup()

        dfr = ReactorDeferred(self.reactor)
        tid = self.ID_GENERATOR.next()
        thd = threading.Thread(name="thread-%d" % (tid, ), target=worker)
        self._threads.add(thd)
        thd.setDaemon(True)
        thd.start()
        return dfr
Пример #30
0
    def connect_tcp(self, host, port, timeout=None):
        def connect_finished(size, overlapped):
            trns_dfr.set(trns)

        yield self.reactor.started
        hostaddr = yield self.resolve(host)
        trns_dfr = ReactorDeferred(self.reactor)
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.setblocking(False)
        sock.bind(('0.0.0.0', 0))  # ConnectEx requires the socket to be bound
        # this is required here to register the new socket with its IOCP
        trns = SocketStreamTransport(self.reactor, sock)
        overlapped = self.reactor._get_overlapped(connect_finished)
        try:
            win32file.ConnectEx(sock.fileno(), (hostaddr, port), overlapped)
        except Exception:
            self.reactor._discard_overlapped(overlapped)
            raise
        yield trns_dfr
        rreturn(trns)
Пример #31
0
class BaseReactor(object):
    if sys.platform == "win32":
        MAX_TIMEOUT = 0.2   # to process Ctrl+C
    else:
        MAX_TIMEOUT = 1
    SUBSYSTEMS = GENERIC_SUBSYSTEMS
    
    def __init__(self):
        self._active = False
        self._jobs = MinHeap()
        self._callbacks = []
        #self._rcallbacks = []
        self._subsystems = []
        self.started = ReactorDeferred(weakref.proxy(self))

    @classmethod
    def supported(cls):
        return False
    
    #===========================================================================
    # Core
    #===========================================================================
    def install_subsystem(self, factory):
        subs = factory(weakref.proxy(self))
        if hasattr(self, subs.NAME):
            raise ValueError("attribute %r already exists" % (subs.NAME,))
        setattr(self, subs.NAME, subs)
        subs._init()
        self._subsystems.append(subs.NAME)
    
    def uninstall_subsystem(self, name):
        subs = getattr(self, name)
        subs._unload()
        #subs.reactor = None
    
    def _install_builtin_subsystems(self):
        for factory in self.SUBSYSTEMS:
            self.install_subsystem(factory)
    
    def start(self):
        if self._active:
            raise ReactorError("reactor already running")
        self._active = True
        self.started.set()
        try:
            while self._active:
                self._work()
        except KeyboardInterrupt:
            pass
        finally:
            self._active = False
    
    def stop(self):
        if not self._active:
            return
        self._active = False
        self.started.cancel()
        for name in self._subsystems:
            self.call(self.uninstall_subsystem, name)
        self._wakeup()
    
    def run(self, func):
        self.call(func, self)
        self.start()
    
    #===========================================================================
    # Internal
    #===========================================================================
    def _wakeup(self):
        raise NotImplementedError()
    
    def _work(self):
        now = time.time()
        timeout = self._process_jobs(now)
        if self._callbacks:
            timeout = 0
        self._handle_transports(min(timeout, self.MAX_TIMEOUT))
        self._process_callbacks()
    
    def _process_jobs(self, now):
        while self._jobs:
            ts, func, args, kwargs  = self._jobs.peek()
            if now < ts:
                return ts - now
            self._jobs.pop()
            self._callbacks.append((func, args, kwargs))
        return self.MAX_TIMEOUT
    
    def _process_callbacks(self):
        callbacks = self._callbacks
        self._callbacks = []
        for cb, args, kwargs in callbacks:
            cb(*args, **kwargs)
    
    #===========================================================================
    # Callbacks
    #===========================================================================
    def call(self, func, *args, **kwargs):
        self._callbacks.append((func, args, kwargs))
    def call_at(self, ts, func, *args, **kwargs):
        self._jobs.push((ts, func, args, kwargs))
Пример #32
0
 def accept(self):
     if self._accept_dfr:
         raise OverlappingRequestError("overlapping accept")
     self._accept_dfr = ReactorDeferred(self.reactor)
     self.reactor.register_read(self)
     return self._accept_dfr
Пример #33
0
 def __init__(self, reactor, sock, addr):
     BaseSocketTransport.__init__(self, reactor, sock)
     self.addr = addr
     self.connected_dfr = ReactorDeferred(self.reactor)
     self._connecting = False
Пример #34
0
 def __init__(self, reactor, sock, addr):
     BaseSocketTransport.__init__(self, reactor, sock)
     self.addr = addr
     self.connected_dfr = ReactorDeferred(self.reactor)
     self._connecting = False
Пример #35
0
 def call(self, func, *args, **kwargs):
     dfr = ReactorDeferred(self.reactor)
     self._tasks.put((dfr, func, args, kwargs))
     self._spawn_workers()
     return dfr
Пример #36
0
 def __init__(self, reactor, sslsock):
     BaseSocketTransport.__init__(self, reactor, sslsock)
     self.connected_dfr = ReactorDeferred(self.reactor)
Пример #37
0
class BaseReactor(object):
    if sys.platform == "win32":
        MAX_TIMEOUT = 0.2  # to process Ctrl+C
    else:
        MAX_TIMEOUT = 1
    SUBSYSTEMS = GENERIC_SUBSYSTEMS

    def __init__(self):
        self._active = False
        self._jobs = MinHeap()
        self._callbacks = []
        #self._rcallbacks = []
        self._subsystems = []
        self.started = ReactorDeferred(weakref.proxy(self))

    @classmethod
    def supported(cls):
        return False

    #===========================================================================
    # Core
    #===========================================================================
    def install_subsystem(self, factory):
        subs = factory(weakref.proxy(self))
        if hasattr(self, subs.NAME):
            raise ValueError("attribute %r already exists" % (subs.NAME, ))
        setattr(self, subs.NAME, subs)
        subs._init()
        self._subsystems.append(subs.NAME)

    def uninstall_subsystem(self, name):
        subs = getattr(self, name)
        subs._unload()
        #subs.reactor = None

    def _install_builtin_subsystems(self):
        for factory in self.SUBSYSTEMS:
            self.install_subsystem(factory)

    def start(self):
        if self._active:
            raise ReactorError("reactor already running")
        self._active = True
        self.started.set()
        try:
            while self._active:
                self._work()
        except KeyboardInterrupt:
            pass
        finally:
            self._active = False

    def stop(self):
        if not self._active:
            return
        self._active = False
        self.started.cancel()
        for name in self._subsystems:
            self.call(self.uninstall_subsystem, name)
        self._wakeup()

    def run(self, func):
        self.call(func, self)
        self.start()

    #===========================================================================
    # Internal
    #===========================================================================
    def _wakeup(self):
        raise NotImplementedError()

    def _work(self):
        now = time.time()
        timeout = self._process_jobs(now)
        if self._callbacks:
            timeout = 0
        self._handle_transports(min(timeout, self.MAX_TIMEOUT))
        self._process_callbacks()

    def _process_jobs(self, now):
        while self._jobs:
            ts, func, args, kwargs = self._jobs.peek()
            if now < ts:
                return ts - now
            self._jobs.pop()
            self._callbacks.append((func, args, kwargs))
        return self.MAX_TIMEOUT

    def _process_callbacks(self):
        callbacks = self._callbacks
        self._callbacks = []
        for cb, args, kwargs in callbacks:
            cb(*args, **kwargs)

    #===========================================================================
    # Callbacks
    #===========================================================================
    def call(self, func, *args, **kwargs):
        self._callbacks.append((func, args, kwargs))

    def call_at(self, ts, func, *args, **kwargs):
        self._jobs.push((ts, func, args, kwargs))
Пример #38
0
 def _request_console_read(self):
     self._assure_started()
     if not self._console_input_dfr or self._console_input_dfr.is_set():
         self._console_input_dfr = ReactorDeferred(self.reactor)
     return self._console_input_dfr
Пример #39
0
 def flush(self):
     if not self._flush_dfr:
         self._flush_dfr = ReactorDeferred(self.reactor)
         self.reactor.register_write(self)
     return self._flush_dfr
Пример #40
0
 def flush(self):
     if not self._flush_dfr:
         self._flush_dfr = ReactorDeferred(self.reactor)
         self.reactor.register_write(self)
     return self._flush_dfr
Пример #41
0
 def _request_console_read(self):
     self._assure_started()
     if not self._console_input_dfr or self._console_input_dfr.is_set():
         self._console_input_dfr = ReactorDeferred(self.reactor)
     return self._console_input_dfr
Пример #42
0
 def __init__(self, reactor, sslsock):
     BaseSocketTransport.__init__(self, reactor, sslsock)
     self.connected_dfr = ReactorDeferred(self.reactor)
Пример #43
0
class IOSubsystem(Subsystem):
    NAME = "io"

    def _init(self):
        #        self._console_thd = None
        #        if winconsole.Console.is_attached():
        #            print "console attached"
        #            self.console = winconsole.Console()
        #            self._console_buffer = ""
        #            self._console_input_dfr = None
        #            self._console_thd = threading.Thread(target = self._console_input_thread)
        #            self._console_thd.daemon = True
        #            self._console_thd_started = False
        #        else:
        #            self.console = None
        #            # check if stdin has FLAG_FILE_FLAG_OVERLAPPED by trying to register
        #            # it with the IOCP
        #            handle = msvcrt.get_osfhandle(sys.stdin.fileno())
        #            try:
        #                self.reactor._port.register(handle)
        #            except win32file.error:
        #                print "no OVERLAPPED"
        #                self._console_buffer = ""
        #                self._console_input_dfr = None
        #                self._console_thd = threading.Thread(target = self._console_input_thread)
        #                self._console_thd.daemon = True
        #                self._console_thd_started = False
        #            else:
        #                print "OVERLAPPED enabled"
        #                # successfully registered with IOCP -- PipeTransport will work
        #                # just fine
        #                pass
        self._stdin = None
        self._stdout = None
        self._stderr = None

    #def _unload(self):
    #    if self.console:
    #        self.console.close()
    #        self.console = None

    @property
    def stdin(self):
        if not self._stdin:
            #if getattr(self, "_console_thd", False):
            #    self._stdin = ConsoleInputTransport(self.reactor)
            #else:
            self._stdin = PipeTransport(self.reactor, sys.stdin, "r")
        return self._stdin

    @property
    def stdout(self):
        if not self._stdout:
            #if getattr(self, "_console_thd", False):
            #    self._stdout = BlockingStreamTransport(self, sys.stdout)
            #else:
            self._stdout = PipeTransport(self.reactor, sys.stdout, "w")
        return self._stdout

    @property
    def stderr(self):
        if not self._stderr:
            #if getattr(self, "_console_thd", False):
            #    self._stderr = BlockingStreamTransport(self, sys.stdout)
            #else:
            self._stderr = PipeTransport(self.reactor, sys.stderr, "w")
        return self._stderr

    def _assure_started(self):
        if getattr(self, "_console_thd",
                   False) and not self._console_thd_started:
            self._console_thd.start()
            self._console_thd_started = True

    def _request_console_read(self):
        self._assure_started()
        if not self._console_input_dfr or self._console_input_dfr.is_set():
            self._console_input_dfr = ReactorDeferred(self.reactor)
        return self._console_input_dfr

    def _console_input_thread(self):
        while self.reactor._active:
            data = os.read(sys.stdin.fileno(), 1000)
            self._console_buffer += data

            if self._console_input_dfr and not self._console_input_dfr.is_set(
            ):
                self._console_input_dfr.set(self._console_buffer)
                self._console_buffer = ""
                self._console_input_dfr = None
                self.reactor._wakeup()

    def _wrap_pipe(self, fileobj, mode):
        return PipeTransport(self.reactor, fileobj, mode)

    @reactive
    def open(self, filename, mode):
        yield self.reactor.started
        fobj, access = win32iocp.WinFile.open(filename, mode)
        rreturn(FileTransport(self.reactor, fobj, access))

    @reactive
    def pipe(self):
        yield self.reactor.started
        rh, wh = win32iocp.create_overlapped_pipe()
        rtrns = PipeTransport(self.reactor, win32iocp.WinFile(rh), "r")
        wtrns = PipeTransport(self.reactor, win32iocp.WinFile(wh), "w")
        rreturn((rtrns, wtrns))
Пример #44
0
class IOSubsystem(Subsystem):
    NAME = "io"
    
    def _init(self):
#        self._console_thd = None
#        if winconsole.Console.is_attached():
#            print "console attached"
#            self.console = winconsole.Console()
#            self._console_buffer = ""
#            self._console_input_dfr = None
#            self._console_thd = threading.Thread(target = self._console_input_thread)
#            self._console_thd.daemon = True
#            self._console_thd_started = False
#        else:
#            self.console = None
#            # check if stdin has FLAG_FILE_FLAG_OVERLAPPED by trying to register 
#            # it with the IOCP
#            handle = msvcrt.get_osfhandle(sys.stdin.fileno())
#            try:
#                self.reactor._port.register(handle)
#            except win32file.error:
#                print "no OVERLAPPED"
#                self._console_buffer = ""
#                self._console_input_dfr = None
#                self._console_thd = threading.Thread(target = self._console_input_thread)
#                self._console_thd.daemon = True
#                self._console_thd_started = False
#            else:
#                print "OVERLAPPED enabled"
#                # successfully registered with IOCP -- PipeTransport will work 
#                # just fine
#                pass
        self._stdin = None
        self._stdout = None
        self._stderr = None
    
    #def _unload(self):
    #    if self.console:
    #        self.console.close()
    #        self.console = None
    
    @property
    def stdin(self):
        if not self._stdin:
            #if getattr(self, "_console_thd", False):
            #    self._stdin = ConsoleInputTransport(self.reactor)
            #else:
            self._stdin = PipeTransport(self.reactor, sys.stdin, "r")
        return self._stdin
    
    @property
    def stdout(self):
        if not self._stdout:
            #if getattr(self, "_console_thd", False):
            #    self._stdout = BlockingStreamTransport(self, sys.stdout)
            #else:
            self._stdout = PipeTransport(self.reactor, sys.stdout, "w")
        return self._stdout
    
    @property
    def stderr(self):
        if not self._stderr:
            #if getattr(self, "_console_thd", False):
            #    self._stderr = BlockingStreamTransport(self, sys.stdout)
            #else:
            self._stderr = PipeTransport(self.reactor, sys.stderr, "w")
        return self._stderr
    
    def _assure_started(self):
        if getattr(self, "_console_thd", False) and not self._console_thd_started:
            self._console_thd.start()
            self._console_thd_started = True
    
    def _request_console_read(self):
        self._assure_started()
        if not self._console_input_dfr or self._console_input_dfr.is_set():
            self._console_input_dfr = ReactorDeferred(self.reactor)
        return self._console_input_dfr
    
    def _console_input_thread(self):
        while self.reactor._active:
            data = os.read(sys.stdin.fileno(), 1000)
            self._console_buffer += data
            
            if self._console_input_dfr and not self._console_input_dfr.is_set():
                self._console_input_dfr.set(self._console_buffer)
                self._console_buffer = ""
                self._console_input_dfr = None
                self.reactor._wakeup()
    
    def _wrap_pipe(self, fileobj, mode):
        return PipeTransport(self.reactor, fileobj, mode)
    
    @reactive
    def open(self, filename, mode):
        yield self.reactor.started
        fobj, access = win32iocp.WinFile.open(filename, mode)
        rreturn(FileTransport(self.reactor, fobj, access))
    
    @reactive
    def pipe(self):
        yield self.reactor.started
        rh, wh = win32iocp.create_overlapped_pipe()
        rtrns = PipeTransport(self.reactor, win32iocp.WinFile(rh), "r")
        wtrns = PipeTransport(self.reactor, win32iocp.WinFile(wh), "w")
        rreturn((rtrns, wtrns))