예제 #1
0
 def __wait_windows(self, poller, wait):
     if self.socket is not None:
         if wait == Stream.W_RECV:
             read_flags = (win32file.FD_READ | win32file.FD_ACCEPT
                           | win32file.FD_CLOSE)
             try:
                 win32file.WSAEventSelect(self.socket, self._read.hEvent,
                                          read_flags)
             except pywintypes.error as e:
                 vlog.err("failed to associate events with socket: %s" %
                          e.strerror)
             poller.fd_wait(self._read.hEvent, ovs.poller.POLLIN)
         else:
             write_flags = (win32file.FD_WRITE | win32file.FD_CONNECT
                            | win32file.FD_CLOSE)
             try:
                 win32file.WSAEventSelect(self.socket, self._write.hEvent,
                                          write_flags)
             except pywintypes.error as e:
                 vlog.err("failed to associate events with socket: %s" %
                          e.strerror)
             poller.fd_wait(self._write.hEvent, ovs.poller.POLLOUT)
     else:
         if wait == Stream.W_RECV:
             if self._read:
                 poller.fd_wait(self._read.hEvent, ovs.poller.POLLIN)
         elif wait == Stream.W_SEND:
             if self._write:
                 poller.fd_wait(self._write.hEvent, ovs.poller.POLLOUT)
         elif wait == Stream.W_CONNECT:
             return
예제 #2
0
    def test_functional(self):
        # This is not really a unit test, but it does exercise the code
        # quite well and can serve as an example of WSAEventSelect and
        # WSAEnumNetworkEvents usage.
        port = socket.socket()
        port.setblocking(0)
        port_event = win32event.CreateEvent(None, 0, 0, None)
        win32file.WSAEventSelect(port, port_event,
                                 win32file.FD_ACCEPT |
                                 win32file.FD_CLOSE)
        port.bind(("127.0.0.1", 0))
        port.listen(10)

        client = socket.socket()
        client.setblocking(0)
        client_event = win32event.CreateEvent(None, 0, 0, None)
        win32file.WSAEventSelect(client, client_event,
                                 win32file.FD_CONNECT |
                                 win32file.FD_READ |
                                 win32file.FD_WRITE |
                                 win32file.FD_CLOSE)
        err = client.connect_ex(port.getsockname())
        self.assertEquals(err, win32file.WSAEWOULDBLOCK)

        res = win32event.WaitForSingleObject(port_event, 1000)
        self.assertEquals(res, win32event.WAIT_OBJECT_0)
        events = win32file.WSAEnumNetworkEvents(port, port_event)
        self.assertEquals(events, {win32file.FD_ACCEPT: 0})

        server, addr = port.accept()
        server.setblocking(0)
        server_event = win32event.CreateEvent(None, 1, 0, None)
        win32file.WSAEventSelect(server, server_event,
                                 win32file.FD_READ |
                                 win32file.FD_WRITE |
                                 win32file.FD_CLOSE)
        res = win32event.WaitForSingleObject(server_event, 1000)
        self.assertEquals(res, win32event.WAIT_OBJECT_0)
        events = win32file.WSAEnumNetworkEvents(server, server_event)
        self.assertEquals(events, {win32file.FD_WRITE: 0})

        res = win32event.WaitForSingleObject(client_event, 1000)
        self.assertEquals(res, win32event.WAIT_OBJECT_0)
        events = win32file.WSAEnumNetworkEvents(client, client_event)
        self.assertEquals(events, {win32file.FD_CONNECT: 0,
                                   win32file.FD_WRITE: 0})
        sent = 0
        data = str2bytes("x") * 16 * 1024
        while sent < 16 * 1024 * 1024:
            try:
                sent += client.send(data)
            except socket.error, e:
                if e.args[0] == win32file.WSAEINTR:
                    continue
                elif e.args[0] in (win32file.WSAEWOULDBLOCK, win32file.WSAENOBUFS):
                    break
                else:
                    raise
 def test_basics(self):
     s = socket.socket()
     e = win32event.CreateEvent(None, 1, 0, None)
     win32file.WSAEventSelect(s, e, 0)
     self.assertEquals(win32file.WSAEnumNetworkEvents(s), {})
     self.assertEquals(win32file.WSAEnumNetworkEvents(s, e), {})
     self.assertRaises(TypeError, win32file.WSAEnumNetworkEvents, s, e, 3)
     self.assertRaises(TypeError, win32file.WSAEnumNetworkEvents, s, "spam")
     self.assertRaises(TypeError, win32file.WSAEnumNetworkEvents, "spam", e)
     self.assertRaises(TypeError, win32file.WSAEnumNetworkEvents, "spam")
     f = open("NUL")
     h = win32file._get_osfhandle(f.fileno())
     self.assertRaises(win32file.error, win32file.WSAEnumNetworkEvents, h)
     self.assertRaises(win32file.error, win32file.WSAEnumNetworkEvents, s,
                       h)
     try:
         win32file.WSAEnumNetworkEvents(h)
     except win32file.error as e:
         self.assertEquals(e.winerror, win32file.WSAENOTSOCK)
     try:
         win32file.WSAEnumNetworkEvents(s, h)
     except win32file.error as e:
         # According to the docs it would seem reasonable that
         # this would fail with WSAEINVAL, but it doesn't.
         self.assertEquals(e.winerror, win32file.WSAENOTSOCK)
예제 #4
0
def check_connection_completion(sock):
    if sys.platform == "win32":
        p = ovs.poller.SelectPoll()
        event = winutils.get_new_event(None, False, True, None)
        # Receive notification of readiness for writing, of completed
        # connection or multipoint join operation, and of socket closure.
        win32file.WSAEventSelect(sock, event,
                                 win32file.FD_WRITE |
                                 win32file.FD_CONNECT |
                                 win32file.FD_CLOSE)
        p.register(event, ovs.poller.POLLOUT)
    else:
        p = ovs.poller.get_system_poll()
        p.register(sock, ovs.poller.POLLOUT)
    pfds = p.poll(0)
    if len(pfds) == 1:
        revents = pfds[0][1]
        if revents & ovs.poller.POLLERR or revents & ovs.poller.POLLHUP:
            try:
                # The following should raise an exception.
                sock.send("\0".encode(), socket.MSG_DONTWAIT)

                # (Here's where we end up if it didn't.)
                # XXX rate-limit
                vlog.err("poll return POLLERR but send succeeded")
                return errno.EPROTO
            except socket.error as e:
                return get_exception_errno(e)
        else:
            return 0
    else:
        return errno.EAGAIN
예제 #5
0
 def test_basics(self):
     s = socket.socket()
     e = win32event.CreateEvent(None, 1, 0, None)
     win32file.WSAEventSelect(s, e, 0)
     assert win32file.WSAEnumNetworkEvents(s) == {}
     assert win32file.WSAEnumNetworkEvents(s, e) == {}
     with pytest.raises(TypeError):
         win32file.WSAEnumNetworkEvents(s, e, 3)
     with pytest.raises(TypeError):
         win32file.WSAEnumNetworkEvents(s, "spam")
     with pytest.raises(TypeError):
         win32file.WSAEnumNetworkEvents("spam", e)
     with pytest.raises(TypeError):
         win32file.WSAEnumNetworkEvents("spam")
     f = open("NUL")
     h = win32file._get_osfhandle(f.fileno())
     with pytest.raises(win32file.error):
         win32file.WSAEnumNetworkEvents(h)
     with pytest.raises(win32file.error):
         win32file.WSAEnumNetworkEvents(s, h)
     try:
         win32file.WSAEnumNetworkEvents(h)
     except win32file.error as e:
         assert e.winerror == win32file.WSAENOTSOCK
     try:
         win32file.WSAEnumNetworkEvents(s, h)
     except win32file.error as e:
         # According to the docs it would seem reasonable that
         # this would fail with WSAEINVAL, but it doesn't.
         assert e.winerror == win32file.WSAENOTSOCK
예제 #6
0
    def SvcDoRun(self):
        """Starts the XML-RPC Service.

    This method is invoked when the Windows service manager wants to start this
    service.  This method stays running for the duration of the time the
    service is running.
    """
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                              servicemanager.PYS_SERVICE_STARTING,
                              (self._svc_name_, ''))

        self._StartXMLRPCServer()
        if self.rpcserver is None:
            log.LogError('Could not start XML-RPC server')
            return

        wait_for_objects = (self.h_wait_stop, self.h_sock_event)
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                              servicemanager.PYS_SERVICE_STARTED,
                              (self._svc_name_, ''))

        while True:
            win32file.WSAEventSelect(self.rpcserver, self.h_sock_event,
                                     win32file.FD_ACCEPT)
            rc = win32event.WaitForMultipleObjects(wait_for_objects, 0,
                                                   win32event.INFINITE)
            # win32 WSAEventSelect set the socket to non-blocking mode and won't
            # allow blocking mode until all NetworkEvent flags are cleared (0).
            win32file.WSAEventSelect(self.rpcserver, self.h_sock_event, 0)
            if rc == win32event.WAIT_OBJECT_0:
                break
            elif rc == win32event.WAIT_OBJECT_0 + 1:
                self.rpcserver.handle_request()

        win32file.WSAEventSelect(self.rpcserver, self.h_sock_event, 0)
        self.rpcserver.server_close()
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                              servicemanager.PYS_SERVICE_STOPPED,
                              (self._svc_name_, ''))
예제 #7
0
 def test_basics(self):
     s = socket.socket()
     e = win32event.CreateEvent(None, 1, 0, None)
     win32file.WSAEventSelect(s, e, 0)
     self.assertEquals(win32file.WSAEnumNetworkEvents(s), {})
     self.assertEquals(win32file.WSAEnumNetworkEvents(s, e), {})
     self.assertRaises(TypeError, win32file.WSAEnumNetworkEvents, s, e, 3)
     self.assertRaises(TypeError, win32file.WSAEnumNetworkEvents, s, "spam")
     self.assertRaises(TypeError, win32file.WSAEnumNetworkEvents, "spam", e)
     self.assertRaises(TypeError, win32file.WSAEnumNetworkEvents, "spam")
     f = open("NUL")
     h = win32file._get_osfhandle(f.fileno())
     self.assertRaises(win32file.error, win32file.WSAEnumNetworkEvents, h)
     self.assertRaises(win32file.error, win32file.WSAEnumNetworkEvents, s, h)
     try:
         win32file.WSAEnumNetworkEvents(h)
     except win32file.error, e:
         self.assertEquals(e.winerror, win32file.WSAENOTSOCK)
예제 #8
0
    def run(self):
        # Initializes the service
        self.init()

        # Creates the updater
        self.updater = updater.Updater()
        self.running = True

        # Handling events...
        while self.running:

            # Creates an event to handle IO on the socket
            socket_event = win32event.CreateEvent(None, True, False, None)
            win32file.WSAEventSelect(self.updater.management_socket,
                                     socket_event,
                                     win32file.FD_READ | win32file.FD_CLOSE)

            # Waits for either an event on the socket or a stop request of the service, waits indefinitely
            logging.info("Waiting for packet...")
            event_result = win32event.WaitForMultipleObjects(
                [socket_event, self.stop_event_handle], 0, win32event.INFINITE)

            if event_result == win32event.WAIT_TIMEOUT:
                # Timeout occurred, ignoring...
                pass
            elif event_result == win32event.WAIT_OBJECT_0 + 0:
                # socket_event occurred, The socket has some IO that needs to be handled
                self.updater.receive_message()
                if self.updater.message:
                    self.updater.handle_message()
            elif event_result == win32event.WAIT_OBJECT_0 + 1:
                # stop_event occurred
                logging.info(
                    "Request to stop service detected. Stopping service...")
                self.stop()
            else:
                # Error occurred
                logging.critical("WaitForMultipleObjects failed!")
                self.stop()
예제 #9
0
    def communication_win(self, is_check):
        import win32event
        import win32file
        import win32api
        import pywintypes
        import winerror

        # event for the socket
        hEvent_sock = win32event.CreateEvent(None, 0, 0, None)
        win32file.WSAEventSelect(self.comms_socket, hEvent_sock,
                                 win32file.FD_READ)

        # event, overlapped struct for the pipe or tunnel
        hEvent_pipe = win32event.CreateEvent(None, 0, 0,
                                             None)  # for reading from the pipe
        overlapped_pipe = pywintypes.OVERLAPPED()
        overlapped_pipe.hEvent = hEvent_pipe

        # buffer for the packets
        message_readfile = win32file.AllocateReadBuffer(4096)

        # showing if we already async reading or not
        not_reading_already = True
        first_run = True
        while not self._stop:
            try:
                if not self.tunnel_r:
                    # user is not authenticated yet, so there is no pipe
                    # only checking the socket for data
                    rc = win32event.WaitForSingleObject(
                        hEvent_sock, int(self.timeout * 1000))
                    if rc == winerror.WAIT_TIMEOUT:
                        # timed out, just rerun and wait
                        continue
                else:
                    # client mode so we have the socket and tunnel as well
                    # or the client authenticated and the pipe was created
                    if first_run or not_reading_already:
                        # no ReadFile was called before or finished, so we
                        # are calling it again
                        hr, _ = win32file.ReadFile(self.tunnel_r,
                                                   message_readfile,
                                                   overlapped_pipe)
                        not_reading_already = first_run = False

                    if (hr == winerror.ERROR_IO_PENDING):
                        # well, this was an async read, so we need to wait
                        # until it happens
                        rc = win32event.WaitForMultipleObjects(
                            [hEvent_sock, hEvent_pipe], 0,
                            int(self.timeout * 1000))
                        if rc == winerror.WAIT_TIMEOUT:
                            # timed out, just rerun and wait
                            continue
                    else:
                        if hr != 0:
                            common.internal_print(
                                "{0} ReadFile failed: {1}".format(
                                    self.module_short, hr), -1)
                            raise

                if rc < 0x80:  # STATUS_ABANDONED_WAIT_0
                    if rc == 0:
                        # socket got signalled
                        not_reading_already = False
                        messages = self.recv()
                        for message in messages:
                            # looping through the messages from socket
                            if len(message) == 0:
                                # this could happen when the socket died or
                                # partial message was read.
                                continue

                            if common.is_control_channel(message[0:1]):
                                # parse control messages
                                if self.controlchannel.handle_control_messages(
                                        self,
                                        message[len(common.CONTROL_CHANNEL_BYTE
                                                    ):], None):
                                    continue
                                else:
                                    self.stop()
                                    break

                            if self.authenticated:
                                try:
                                    # write packet to the tunnel
                                    self.packet_writer(
                                        message[len(common.CONTROL_CHANNEL_BYTE
                                                    ):])
                                except OSError as e:
                                    print(e)  # wut?
                                except Exception as e:
                                    if e.args[0] == 995:
                                        common.internal_print(
                                            "Interface disappered, exiting thread: {0}"
                                            .format(e), -1)
                                        self.stop()
                                        continue

                    if rc == 1:
                        # pipe/tunnel got signalled
                        not_reading_already = True
                        if (overlapped_pipe.InternalHigh <
                                4) or (message_readfile[0:1] !=
                                       "\x45"):  #Only care about IPv4
                            # too small which should not happen or not IPv4, so we just drop it.
                            continue

                        # reading out the packet from the buffer and discarding the rest
                        readytogo = message_readfile[0:overlapped_pipe.
                                                     InternalHigh]
                        self.send(common.DATA_CHANNEL_BYTE, readytogo, None)

            except win32api.error as e:
                common.internal_print("TCP Exception: {0}".format(e), -1)

        self.cleanup()

        return True
    def test_functional(self):
        # This is not really a unit test, but it does exercise the code
        # quite well and can serve as an example of WSAEventSelect and
        # WSAEnumNetworkEvents usage.
        port = socket.socket()
        port.setblocking(0)
        port_event = win32event.CreateEvent(None, 0, 0, None)
        win32file.WSAEventSelect(port, port_event,
                                 win32file.FD_ACCEPT | win32file.FD_CLOSE)
        port.bind(("127.0.0.1", 0))
        port.listen(10)

        client = socket.socket()
        client.setblocking(0)
        client_event = win32event.CreateEvent(None, 0, 0, None)
        win32file.WSAEventSelect(
            client, client_event, win32file.FD_CONNECT | win32file.FD_READ
            | win32file.FD_WRITE | win32file.FD_CLOSE)
        err = client.connect_ex(port.getsockname())
        self.assertEquals(err, win32file.WSAEWOULDBLOCK)

        res = win32event.WaitForSingleObject(port_event, 1000)
        self.assertEquals(res, win32event.WAIT_OBJECT_0)
        events = win32file.WSAEnumNetworkEvents(port, port_event)
        self.assertEquals(events, {win32file.FD_ACCEPT: 0})

        server, addr = port.accept()
        server.setblocking(0)
        server_event = win32event.CreateEvent(None, 1, 0, None)
        win32file.WSAEventSelect(
            server, server_event,
            win32file.FD_READ | win32file.FD_WRITE | win32file.FD_CLOSE)
        res = win32event.WaitForSingleObject(server_event, 1000)
        self.assertEquals(res, win32event.WAIT_OBJECT_0)
        events = win32file.WSAEnumNetworkEvents(server, server_event)
        self.assertEquals(events, {win32file.FD_WRITE: 0})

        res = win32event.WaitForSingleObject(client_event, 1000)
        self.assertEquals(res, win32event.WAIT_OBJECT_0)
        events = win32file.WSAEnumNetworkEvents(client, client_event)
        self.assertEquals(events, {
            win32file.FD_CONNECT: 0,
            win32file.FD_WRITE: 0
        })
        sent = 0
        data = str2bytes("x") * 16 * 1024
        while sent < 16 * 1024 * 1024:
            try:
                sent += client.send(data)
            except socket.error as e:
                if e.args[0] == win32file.WSAEINTR:
                    continue
                elif e.args[0] in (win32file.WSAEWOULDBLOCK,
                                   win32file.WSAENOBUFS):
                    break
                else:
                    raise
        else:
            self.fail("could not find socket buffer limit")

        events = win32file.WSAEnumNetworkEvents(client)
        self.assertEquals(events, {})

        res = win32event.WaitForSingleObject(server_event, 1000)
        self.assertEquals(res, win32event.WAIT_OBJECT_0)
        events = win32file.WSAEnumNetworkEvents(server, server_event)
        self.assertEquals(events, {win32file.FD_READ: 0})

        received = 0
        while received < sent:
            try:
                received += len(server.recv(16 * 1024))
            except socket.error as e:
                if e.args[0] in [win32file.WSAEINTR, win32file.WSAEWOULDBLOCK]:
                    continue
                else:
                    raise

        self.assertEquals(received, sent)
        events = win32file.WSAEnumNetworkEvents(server)
        self.assertEquals(events, {})

        res = win32event.WaitForSingleObject(client_event, 1000)
        self.assertEquals(res, win32event.WAIT_OBJECT_0)
        events = win32file.WSAEnumNetworkEvents(client, client_event)
        self.assertEquals(events, {win32file.FD_WRITE: 0})

        client.shutdown(socket.SHUT_WR)
        res = win32event.WaitForSingleObject(server_event, 1000)
        self.assertEquals(res, win32event.WAIT_OBJECT_0)
        # strange timing issues...
        for i in range(5):
            events = win32file.WSAEnumNetworkEvents(server, server_event)
            if events: break
            win32api.Sleep(100)
        else:
            raise AssertionError("failed to get events")
        self.assertEquals(events, {win32file.FD_CLOSE: 0})
        events = win32file.WSAEnumNetworkEvents(client)
        self.assertEquals(events, {})

        server.close()
        res = win32event.WaitForSingleObject(client_event, 1000)
        self.assertEquals(res, win32event.WAIT_OBJECT_0)
        events = win32file.WSAEnumNetworkEvents(client, client_event)
        self.assertEquals(events, {win32file.FD_CLOSE: 0})

        client.close()
        events = win32file.WSAEnumNetworkEvents(port)
        self.assertEquals(events, {})
예제 #11
0
    def communication_win(self, is_check):
        import win32event
        import win32file
        import win32api
        import pywintypes
        import winerror

        # event for the socket
        hEvent_sock = win32event.CreateEvent(None, 0, 0, None)
        win32file.WSAEventSelect(self.comms_socket, hEvent_sock,
                                 win32file.FD_READ)

        # descriptor list
        self.rlist = [self.comms_socket]
        # overlapped list
        self.olist = [0]
        # event list
        self.elist = [hEvent_sock]
        # message buffer list
        self.mlist = [0]
        # id of the read object - put in this if it was read
        self.ulist = []
        if not self.serverorclient and self.tunnel:
            # client mode
            # objects created for the tunnel and put in the corresponding
            # lists
            hEvent_pipe = win32event.CreateEvent(
                None, 0, 0, None)  # for reading from the pipe
            overlapped_pipe = pywintypes.OVERLAPPED()
            overlapped_pipe.hEvent = hEvent_pipe
            message_buffer = win32file.AllocateReadBuffer(4096)
            self.rlist.append(self.tunnel)
            self.olist.append(overlapped_pipe)
            self.elist.append(hEvent_pipe)
            self.mlist.append(message_buffer)
            self.ulist.append(1)

        while not self._stop:
            try:
                if not self.tunnel:
                    # check or server mode without client only with socket
                    #message, addr = self.comms_socket.recvfrom(1508)
                    rc = win32event.WaitForSingleObject(
                        hEvent_sock, int(self.timeout * 1000))
                    if rc == winerror.WAIT_TIMEOUT:
                        # timed out, just rerun and wait
                        continue

                else:
                    if self.ulist:
                        # there is somebody waiting to be read
                        for idx in self.ulist:
                            # issueing ReadFile on all not yet read mailslots/tunnel
                            hr, _ = win32file.ReadFile(self.rlist[idx],
                                                       self.mlist[idx],
                                                       self.olist[idx])
                            if (hr != 0) and (hr != winerror.ERROR_IO_PENDING):
                                common.internal_print(
                                    "UDP ReadFile failed: {0}".format(hr), -1)
                                raise

                        self.ulist = []

                    # waiting to get some data somewhere
                    rc = win32event.WaitForMultipleObjects(
                        self.elist, 0, int(self.timeout * 1000))
                    if rc == winerror.WAIT_TIMEOUT:
                        # timed out, just rerun and wait
                        continue

                if rc < 0x80:  # STATUS_ABANDONED_WAIT_0
                    if rc > 0:
                        # the tunnel or one of the mailslots got signalled
                        self.ulist.append(rc)
                        if (self.olist[rc].InternalHigh <
                                4) or (self.mlist[rc][0:1] !=
                                       "\x45"):  #Only care about IPv4
                            continue

                        readytogo = self.mlist[rc][0:self.olist[rc].
                                                   InternalHigh]

                        if self.serverorclient:
                            c = self.lookup_client_priv(readytogo)
                            if c:
                                # if the differece between the received and set sequences too big
                                # some routers/firewalls just drop older sequences. If it gets
                                # too big, we just drop the older ones and use the latest X packet
                                # this helps on stabality.
                                if (c.get_ICMP_received_sequence() -
                                        c.get_ICMP_sent_sequence()
                                    ) >= self.TRACKING_THRESHOLD:
                                    c.set_ICMP_sent_sequence(
                                        c.get_ICMP_received_sequence() -
                                        self.TRACKING_ADJUST)

                                # get client related values: identifier and sequence number
                                identifier = c.get_ICMP_sent_identifier()
                                sequence = c.get_ICMP_sent_sequence()

                                # queueing every packet first
                                c.queue_put(readytogo)
                                # are there any packets to answer?
                                if (c.get_ICMP_received_sequence() -
                                        sequence) == 0:
                                    continue
                                else:
                                    request_num = 0
                                    # if there is less packet than that we have in the queue
                                    # then we cap the outgoing packet number
                                    if (c.get_ICMP_received_sequence() -
                                            sequence) < (c.queue_length()):
                                        number_to_get = (
                                            c.get_ICMP_received_sequence() -
                                            sequence)
                                    else:
                                        # send all packets from the queue
                                        number_to_get = c.queue_length()

                                    for i in range(0, number_to_get):
                                        # get first packet
                                        readytogo = c.queue_get()
                                        # is it he last one we are sending now?
                                        if i == (number_to_get - 1):
                                            # if the last one and there is more in the queue
                                            # then we ask for dummy packets
                                            request_num = c.queue_length()
                                        # go packets go!
                                        self.send(common.DATA_CHANNEL_BYTE,
                                                  readytogo,
                                                  ((socket.inet_ntoa(
                                                      c.get_public_ip_addr()),
                                                    c.get_public_src_port()),
                                                   identifier, sequence + i +
                                                   1, request_num))

                                    sequence = (sequence + i + 1) % 65536
                                    c.set_ICMP_sent_sequence(sequence)
                            else:
                                # there is no client with that IP
                                common.internal_print(
                                    "Client not found, strange?!", 0,
                                    self.verbosity, common.DEBUG)
                                continue
                        else:
                            if self.authenticated:
                                # whatever we have from the tunnel, just encapsulate it
                                # and send it out
                                self.ICMP_sequence = (self.ICMP_sequence +
                                                      1) % 65536
                                self.send(
                                    common.DATA_CHANNEL_BYTE, readytogo,
                                    (self.server_tuple, self.ICMP_identifier,
                                     self.ICMP_sequence, 0))  #??
                            else:
                                common.internal_print(
                                    "Spoofed packets, strange?!", 0,
                                    self.verbosity, common.DEBUG)
                                continue
                    if rc == 0:
                        # socket got signalled
                        message, addr, identifier, sequence, queue_length = self.recv(
                        )

                        if len(message) == 0:
                            continue

                        c = None
                        if self.serverorclient:
                            self.authenticated = False
                            c = self.lookup_client_pub((addr, 0))
                            if c:
                                c.set_ICMP_received_identifier(identifier)
                                # packets does not arrive in order sometime
                                # if higher sequence arrived already, then we
                                # do not modify
                                # 16bit integer MAX could be a bit tricky, a
                                # threshold had to be introduced to make it
                                # fail safe. Hacky but should work.
                                ICMP_THRESHOLD = 100
                                if (sequence > c.get_ICMP_received_sequence()
                                    ) or ((sequence < ICMP_THRESHOLD) and
                                          ((sequence + 65536) >
                                           c.get_ICMP_received_sequence()) and
                                          (c.get_ICMP_received_sequence() >
                                           ICMP_THRESHOLD)):
                                    c.set_ICMP_received_sequence(sequence)
                        else:
                            if queue_length:
                                common.internal_print(
                                    "sending {0} dummy packets".format(
                                        queue_length), 0, self.verbosity,
                                    common.DEBUG)
                                for i in range(queue_length + 10):
                                    self.ICMP_sequence = (self.ICMP_sequence +
                                                          1) % 65536
                                    self.do_dummy_packet(
                                        self.ICMP_identifier,
                                        self.ICMP_sequence)

                        if common.is_control_channel(message[0:1]):
                            if self.controlchannel.handle_control_messages(
                                    self,
                                    message[len(common.CONTROL_CHANNEL_BYTE):],
                                (addr, identifier, sequence, 0)):
                                continue
                            else:
                                self.stop()
                                break

                        if c:
                            self.authenticated = c.get_authenticated()

                        if self.authenticated:
                            try:
                                self.packet_writer(
                                    message[len(common.CONTROL_CHANNEL_BYTE):])
                            except OSError as e:
                                print(e)

            except win32api.error as e:
                common.internal_print("UDP Exception: {0}".format(e), -1)
            except socket.error as se:
                if se.args[0] == 10054:  # port is unreachable
                    common.internal_print(
                        "Server's port is unreachable: {0}".format(se), -1)
                    self._stop = True

        return True
예제 #12
0
    def communication_win(self, is_check):
        import win32event
        import win32file
        import win32api
        import pywintypes
        import winerror

        # event for the socket
        hEvent_sock = win32event.CreateEvent(None, 0, 0, None)
        win32file.WSAEventSelect(self.comms_socket, hEvent_sock,
                                 win32file.FD_READ)

        # descriptor list
        self.rlist = [self.comms_socket]
        # overlapped list
        self.olist = [0]
        # event list
        self.elist = [hEvent_sock]
        # message buffer list
        self.mlist = [0]
        # id of the read object - put in this if it was read
        self.ulist = []
        if not self.serverorclient and self.tunnel:
            # client mode
            # objects created for the tunnel and put in the corresponding
            # lists
            hEvent_pipe = win32event.CreateEvent(
                None, 0, 0, None)  # for reading from the pipe
            overlapped_pipe = pywintypes.OVERLAPPED()
            overlapped_pipe.hEvent = hEvent_pipe
            message_buffer = win32file.AllocateReadBuffer(4096)
            self.rlist.append(self.tunnel)
            self.olist.append(overlapped_pipe)
            self.elist.append(hEvent_pipe)
            self.mlist.append(message_buffer)
            self.ulist.append(1)

        while not self._stop:
            try:
                if not self.tunnel:
                    # check or server mode without client only with socket
                    rc = win32event.WaitForSingleObject(
                        hEvent_sock, int(self.timeout * 1000))
                    if rc == winerror.WAIT_TIMEOUT:
                        # timed out, just rerun and wait
                        continue
                else:
                    if self.ulist:
                        # there is somebody waiting to be read
                        for idx in self.ulist:
                            # issueing ReadFile on all not yet read mailslots/tunnel
                            hr, _ = win32file.ReadFile(self.rlist[idx],
                                                       self.mlist[idx],
                                                       self.olist[idx])
                            if (hr != 0) and (hr != winerror.ERROR_IO_PENDING):
                                common.internal_print(
                                    "UDP ReadFile failed: {0}".format(hr), -1)
                                raise

                        self.ulist = []

                    # waiting to get some data somewhere
                    rc = win32event.WaitForMultipleObjects(
                        self.elist, 0, int(self.timeout * 1000))
                    if rc == winerror.WAIT_TIMEOUT:
                        # timed out, just rerun and wait
                        continue

                if rc < 0x80:  # STATUS_ABANDONED_WAIT_0
                    if rc > 0:
                        # the tunnel or one of the mailslots got signalled
                        self.ulist.append(rc)
                        if (self.olist[rc].InternalHigh <
                                4) or (self.mlist[rc][0:1] !=
                                       "\x45"):  #Only care about IPv4
                            continue

                        readytogo = self.mlist[rc][0:self.olist[rc].
                                                   InternalHigh]
                        if self.serverorclient:
                            c = self.lookup_client_priv(readytogo)
                            if c:
                                self.send(
                                    common.DATA_CHANNEL_BYTE, readytogo,
                                    ((socket.inet_ntoa(c.get_public_ip_addr()),
                                      c.get_public_src_port()), None))
                            else:
                                common.internal_print(
                                    "Client not found, strange?!", 0,
                                    self.verbosity, common.DEBUG)
                                continue
                        else:
                            if self.authenticated:
                                self.send(common.DATA_CHANNEL_BYTE, readytogo,
                                          (self.server_tuple, None))
                    if rc == 0:
                        # socket got signalled
                        messages = self.recv()
                        if len(messages) == 0:
                            continue

                        for addr in messages:
                            for message in messages[addr]:
                                c = None
                                if self.serverorclient:
                                    self.authenticated = False
                                    c = self.lookup_client_pub((addr, 0))

                                if common.is_control_channel(message[0:1]):
                                    if self.controlchannel.handle_control_messages(
                                            self, message[len(
                                                common.CONTROL_CHANNEL_BYTE):],
                                        (addr, None)):
                                        continue
                                    else:
                                        self.stop()
                                        break

                                if c:
                                    self.authenticated = c.get_authenticated()

                                if self.authenticated:
                                    try:
                                        self.packet_writer(message[
                                            len(common.CONTROL_CHANNEL_BYTE):])
                                    except OSError as e:
                                        print(e)

            except win32api.error as e:
                common.internal_print("UDP Exception: {0}".format(e), -1)
            except socket.error as se:
                if se.args[0] == 10054:  # port is unreachable
                    common.internal_print(
                        "Server's port is unreachable: {0}".format(se), -1)
                    self._stop = True

        return True