Пример #1
0
 def close(self):
     if self.iocp:
         poverlapped = LPOVERLAPPED()
         nbytes = DWORD()
         completion_key = c_ulong()
         while 1:
             rc = GetQueuedCompletionStatus(
                 self.iocp, # HANDLE CompletionPort
                 byref(nbytes), # LPDWORD lpNumberOfBytes
                 byref(completion_key), # PULONG_PTR lpCompletionKey
                 byref(poverlapped),
                 0
             )
             if not poverlapped:
                 break
             else:
                 act = poverlapped.contents.object
                 if act in self.tokens:
                     del self.tokens[act]
                     CancelIo(act.sock._fd.fileno())
                 else:
                     import warnings
                     warnings.warn("act(%s) not in self.tokens" % act)
         CloseHandle(self.iocp)
         self.iocp = None
         if self.tokens:
             import warnings
             warnings.warn("self.tokens still pending: %s" % self.tokens)
     super(self.__class__, self).close()
Пример #2
0
def perform_sendall(act, overlapped):
    wsabuf = WSABUF()
    wsabuf.buf = c_char_p(act.buff[act.sent:])
    wsabuf.len = len(act.buff)-act.sent
    nbytes = c_ulong()
    act.flags = wsabuf, nbytes

    return WSASend(
        act.sock._fd.fileno(), # SOCKET s
        byref(wsabuf), # LPWSABUF lpBuffers
        1, # DWORD dwBufferCount
        byref(nbytes), # LPDWORD lpNumberOfBytesSent
        0, # DWORD dwFlags
        overlapped, # LPWSAOVERLAPPED lpOverlapped
        None # LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
    ), nbytes
Пример #3
0
def perform_recv(act, overlapped):
    wsabuf = WSABUF()
    buf = create_string_buffer(act.len)
    wsabuf.buf = cast(buf, c_char_p)
    wsabuf.len = act.len
    nbytes = c_ulong(0)
    flags = c_ulong(0)
    act.flags = buf

    rc = WSARecv(
        act.sock._fd.fileno(), # SOCKET s
        byref(wsabuf), # LPWSABUF lpBuffers
        1, # DWORD dwBufferCount
        byref(nbytes), # LPDWORD lpNumberOfBytesRecvd
        byref(flags), # LPDWORD lpFlags
        overlapped, # LPWSAOVERLAPPED lpOverlapped
        None # LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
    )
    return rc, nbytes.value
Пример #4
0
def perform_accept(act, overlapped):
    act.conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    act.cbuff = create_string_buffer((sizeof(sockaddr_in) + 16) * 2)
    nbytes = c_ulong()

    prot_info = WSAPROTOCOL_INFO()
    prot_info_len = c_int(sizeof(prot_info))
    getsockopt(act.sock.fileno(), SOL_SOCKET, SO_PROTOCOL_INFOA, cast(byref(prot_info), c_char_p), byref(prot_info_len))

    # BOOL
    return AcceptEx(
        act.sock._fd.fileno(), # SOCKET sListenSocket
        act.conn.fileno(), # SOCKET sAcceptSocket
        cast(act.cbuff, c_void_p), # PVOID lpOutputBuffer
        0, # DWORD dwReceiveDataLength
        prot_info.iMaxSockAddr + 16, # DWORD dwLocalAddressLength
        prot_info.iMaxSockAddr + 16, # DWORD dwRemoteAddressLength
        nbytes, # LPDWORD lpdwBytesReceived
        overlapped # LPOVERLAPPED lpOverlapped
    ), 0
Пример #5
0
    def run(self, timeout = 0):
        """
        Calls GetQueuedCompletionStatus and handles completion via
        process_op.
        """
        # same resolution as epoll
        ptimeout = int(
            timeout.days * 86400000 +
            timeout.microseconds / 1000 +
            timeout.seconds * 1000
            if timeout else (self.m_resolution if timeout is None else 0)
        )
        if self.tokens:
            scheduler = self.scheduler
            urgent = None
            # we use urgent as a optimisation: the last operation is returned
            #directly to the scheduler (the sched might just run it till it
            #goes to sleep) and not added in the sched.active queue
            while 1:
                try:
                    poverlapped = LPOVERLAPPED()
                    nbytes = DWORD()
                    completion_key = c_ulong()
                    #~ BOOL WINAPI GetQueuedCompletionStatus(
                      #~ __in   HANDLE CompletionPort,
                      #~ __out  LPDWORD lpNumberOfBytes,
                      #~ __out  PULONG_PTR lpCompletionKey,
                      #~ __out  LPOVERLAPPED *lpOverlapped,
                      #~ __in   DWORD dwMilliseconds
                    #~ );

                    rc = GetQueuedCompletionStatus(
                        self.iocp, # HANDLE CompletionPort
                        byref(nbytes), # LPDWORD lpNumberOfBytes
                        byref(completion_key), # PULONG_PTR lpCompletionKey
                        byref(poverlapped),
                        0 if urgent else ptimeout
                    )
                    overlap = poverlapped and poverlapped.contents
                    nbytes = nbytes.value
                except RuntimeError, e:
                    import warnings
                    warnings.warn("RuntimeError(%s) on GetQueuedCompletionStatus." % e)
                    # we will get "This overlapped object has lost all its
                    # references so was destroyed" when we remove a operation,
                    # it is garbage collected and the overlapped completes
                    # afterwards
                    break

                # well, this is a bit weird, if we get a aborted rc (via CancelIo
                #i suppose) evaluating the overlap crashes the interpeter
                #with a memory read error
                # also, we might get a "wait operation timed out", and no overlap pointer
                if rc != WSA_OPERATION_ABORTED and overlap:

                    if urgent:
                        op, coro = urgent
                        urgent = None
                        if op.prio & priority.OP:
                            # imediately run the asociated coroutine step
                            op, coro = scheduler.process_op(
                                coro.run_op(op, scheduler),
                                coro
                            )
                        if coro:
                            #TODO, what "op and "
                            if op and (op.prio & priority.CORO):
                                scheduler.active.appendleft( (op, coro) )
                            else:
                                scheduler.active.append( (op, coro) )
                    if overlap.object:
                        assert overlap.object in self.tokens
                        urgent = self.process_op(rc, nbytes, overlap)
                else:
                    #~ import warnings
                    #~ warnings.warn("rc=(%s: %s) overlap=(%s)" % (rc, ctypes.FormatError(rc), overlap))
                    break
            return urgent
Пример #6
0
    act.conn = act.sock.__class__(_sock=act.conn)
    return act

def perform_connect(act, overlapped):
    # ConnectEx requires that the socket be bound beforehand
    try:
        # just in case we get a already-bound socket
        act.sock.bind(('0.0.0.0', 0))
    except socket.error, exc:
        if exc[0] not in (errno.EINVAL, errno.WSAEINVAL):
            raise
    fileno = act.sock._fd.fileno()

    prot_info = WSAPROTOCOL_INFO()
    prot_info_len = c_int(sizeof(prot_info))
    getsockopt(fileno, SOL_SOCKET, SO_PROTOCOL_INFOA, cast(byref(prot_info), c_char_p), byref(prot_info_len))

    hints = addrinfo()
    hints.ai_family = prot_info.iAddressFamily
    hints.ai_socktype = prot_info.iSocketType
    hints.ai_protocol = prot_info.iProtocol

    result = addrinfo_p()
    getaddrinfo(act.addr[0], str(act.addr[1]), byref(hints), byref(result));

    act.flags = result

    #~ act.sock.bind(('0.0.0.0', 0))
    return ConnectEx(
        fileno, # SOCKET s
        result.contents.ai_addr, result.contents.ai_addrlen,