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
def __init__(self): self._active = False self._jobs = MinHeap() self._callbacks = [] #self._rcallbacks = [] self._subsystems = [] self.started = ReactorDeferred(weakref.proxy(self))
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
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
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
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 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
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
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
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
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
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
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)
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
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
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 flush(self): if not self._flush_dfr: self._flush_dfr = ReactorDeferred(self.reactor) self.reactor.register_write(self) return self._flush_dfr
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
def call(self, func, *args, **kwargs): dfr = ReactorDeferred(self.reactor) self._tasks.put((dfr, func, args, kwargs)) self._spawn_workers() return dfr
def __init__(self, reactor, sock, addr): BaseSocketTransport.__init__(self, reactor, sock) self.addr = addr self.connected_dfr = ReactorDeferred(self.reactor) self._connecting = False
def __init__(self, reactor, sslsock): BaseSocketTransport.__init__(self, reactor, sslsock) self.connected_dfr = ReactorDeferred(self.reactor)