예제 #1
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
예제 #2
0
 def __init__(self):
     self._active = False
     self._jobs = MinHeap()
     self._callbacks = []
     #self._rcallbacks = []
     self._subsystems = []
     self.started = ReactorDeferred(weakref.proxy(self))
예제 #3
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
예제 #4
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
예제 #5
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
예제 #6
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)
예제 #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 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
예제 #9
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
예제 #10
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
예제 #11
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
예제 #12
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
예제 #13
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)
예제 #14
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
예제 #15
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
예제 #16
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
예제 #17
0
 def flush(self):
     if not self._flush_dfr:
         self._flush_dfr = ReactorDeferred(self.reactor)
         self.reactor.register_write(self)
     return self._flush_dfr
예제 #18
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
예제 #19
0
 def call(self, func, *args, **kwargs):
     dfr = ReactorDeferred(self.reactor)
     self._tasks.put((dfr, func, args, kwargs))
     self._spawn_workers()
     return dfr
예제 #20
0
 def __init__(self, reactor, sock, addr):
     BaseSocketTransport.__init__(self, reactor, sock)
     self.addr = addr
     self.connected_dfr = ReactorDeferred(self.reactor)
     self._connecting = False
예제 #21
0
 def __init__(self, reactor, sslsock):
     BaseSocketTransport.__init__(self, reactor, sslsock)
     self.connected_dfr = ReactorDeferred(self.reactor)