Ejemplo n.º 1
0
    def send(self, msg):
        floor = 0
        payload_size = 512
        packets = []

        # chunk data into packets
        while floor < len(msg):
            if floor + payload_size <= len(msg):
                payload = msg[floor: floor + payload_size]
            else:
                payload = msg[floor:]

            data_packet = RxPPacket(
                self.port_number,
                self.destination[1],
                seq_number=self.seq_number,
                payload=payload
            )
            packets.append(data_packet)
            self.seq_number += 1
            floor += payload_size

        kill_packet = RxPPacket(
            self.port_number,
            self.destination[1],
            seq_number=self.seq_number
        )
        kills_sent = 0  # allow to be sent 3 times before dropping client cxn
        kill_seq_number = kill_packet.seq_number
        packets.append(kill_packet)  # put that shit at the end after we've added all the other packets
        self.seq_number += 1

        self.logger.debug('Placing packets in window to be sent now...')
        window = SlidingWindow(packets, self.window_size)
        time_sent = time.time()
        time_remaining = self.retransmit_timer.timeout

        self.cxn_status = RxPConnectionStatus.SEND
        for data_packet in window.window:
            self.io.send_queue.put((data_packet, self.destination))

        while not window.is_empty():
            try:
                ack_packet, address = self.io.recv_queue.get(True, time_remaining)

            # resend entire send window (all packets that weren't yet ACK'd by the receiver)
            except Queue.Empty:
                self.logger.debug(
                    'Timed out waiting for ack during data transmission; retransmitting unacknowledged packets.')
                time_sent = time.time()
                time_remaining = self.retransmit_timer.timeout

                for data_packet in window.window:
                    if kill_seq_number == data_packet.seq_number:
                        kills_sent += 1
                        if kills_sent > 3:  # if retransmitted 3 times already, kill cxn with client
                            self.logger.debug(
                                'Kill packet failed to be acknowledged; unable to end connection, closing now.')
                            return

                    if not window.acknowledged_packets.get(data_packet.seq_number):
                        data_packet.frequency += 1
                        data_packet.update_checksum()
                        self.io.send_queue.put((data_packet, self.destination))
                continue

            # if still getting SYN/ACK, retransmit ACK
            if self.__verify_syn_ack(ack_packet, address, 1):
                self.logger.debug('Received SYN/ACK retransmission; retransmitting ACK.')
                ack_packet = RxPPacket(
                    self.port_number,
                    self.destination[1],
                    ack_number=ack_packet.seq_number + 1,
                    seq_number=2,
                    ack=True
                )
                self.io.send_queue.put((ack_packet, self.destination))
                time_remaining = 0

            # if a packet in window is acknowledged, slide the window past said received packet
            elif self.__verify_is_ack(ack_packet, address) and window.index_of_packet(ack_packet) >= 0:
                self.retransmit_timer.update(ack_packet.frequency, time.time() - time_sent)
                self.logger.debug(
                    'ACK received. Updated retransmit timer; timeout is now ' + str(self.retransmit_timer.timeout))
                window.acknowledge_packet(ack_packet)

                if self.__verify_ack(ack_packet, address, window.window[0].seq_number):
                    additions = window.slide()
                    # send newly added packets if they were added
                    if additions > 0:
                        while additions > 0:
                            self.io.send_queue.put((window.window[-additions], self.destination))
                            self.seq_number += 1
                            additions -= 1

            # otherwise, update time remaining
            else:
                time_remaining -= time.time() - time_sent / 4  # decay
                if time_remaining < time.time():
                    time_remaining = .5
                self.logger.debug('Trash packet receive; time remaining before next timeout: ' + str(time_remaining))

        self.cxn_status = RxPConnectionStatus.IDLE
Ejemplo n.º 2
0
    def mf_write(self, data):
        start = 0
        payload_size = 512
        packets = []

        # chunk data into packets
        while start < len(data):
            if start + payload_size <= len(data):
                payload = data[start : start + payload_size]
            else:
                payload = data[start :]

            data_packet = MFPacket(
                self.port_number,
                self.destination[1],
                sequence_number = self.sequence_number,
                payload = payload
            )
            packets.append(data_packet)
            self.sequence_number += 1
            start += payload_size

        terminator_packet = MFPacket(
            self.port_number,
            self.destination[1],
            sequence_number = self.sequence_number
        )
        packets.append(terminator_packet)
        self.terminator_packet_seq_num = self.sequence_number
        self.terminator_packet_num_sent = 0
        self.sequence_number += 1

        # populate window and send all packets
        window = SlidingWindow(packets, self.window_size)

        last_sent = time.time()
        time_remaining = self.retransmit_timer.timeout
        self.logger.debug('sending data packets in window.')
        for data_packet in window.window:
            self.io_loop.send_queue.put((data_packet, self.destination))
            #print data_packet.data_offset

        while not window.is_empty():
            try:
                # wait for incoming packet
                ack_packet, address = self.io_loop.receive_queue.get(True, time_remaining)
            except Queue.Empty:
                # timeout, go back n
                self.logger.debug('timed out waiting for ack during data transmission. retransmitting window.')
                last_sent = time.time()
                time_remaining = self.retransmit_timer.timeout

                for data_packet in window.window:

                    if self.terminator_packet_seq_num == data_packet.sequence_number:
                        self.terminator_packet_num_sent += 1
                        if self.terminator_packet_num_sent > 3:
                            self.logger.debug('Unable to end connection, terminating now')
                            return

                    data_packet.frequency += 1
                    data_packet.recalculate_checksum()
                    self.io_loop.send_queue.put((data_packet, self.destination))



                continue

            # if still getting syn/ack, retransmit ack
            if self.__verify_syn_ack(ack_packet, address, 1):
                self.logger.debug('received syn/ack retransmission. retransmitting ack.')
                ack_packet = MFPacket(
                    self.port_number,
                    self.destination[1],
                    ack_number = ack_packet.sequence_number + 1,
                    sequence_number = 2,
                    ack = True
                )
                self.io_loop.send_queue.put((ack_packet, self.destination))
                time_remaining = 0
            # if first packet in pipeline is acknowledged, slide the window
            elif self.__verify_ack(ack_packet, address, window.window[0].sequence_number):
                self.retransmit_timer.update(ack_packet.frequency, time.time() - last_sent)
                self.logger.debug('updated retransmit timer. timeout is now ' + str(self.retransmit_timer.timeout))
                window.slide()
                if not window.is_emptying():
                    self.io_loop.send_queue.put((window.window[-1], self.destination))
                    self.sequence_number += 1
                    #print "executing"
            # otherwise, update time remaining
            else:
                time_remaining -= time.time() - last_sent/4
                if time_remaining < time.time():
                    time_remaining = .5
                self.logger.debug('bunk packet received. time remaining before timeout: ' + str(time_remaining))