예제 #1
0
    def test_syn(self, mock_socket):
        # mock variables
        syn_packet = packet.create_syn_packet()
        mock_socket.recvfrom.return_value = (packet.pack_packet(syn_packet), "127.0.0.1")

        expected_response = packet.pack_packet(packet.create_synack_packet(syn_packet))
        r = host.Receiver(mock_socket, 10, "127.0.0.1", 10)
        r.wait_for_syn()

        mock_socket.sendto.assert_called_with(expected_response, ("127.0.0.1", 10))
예제 #2
0
    def test_dup_syn(self, mock_socket):
        syn_packet = packet.create_syn_packet()
        mock_socket.recvfrom.side_effect = [(packet.pack_packet(syn_packet), "127.0.0.1"),
                                            (packet.pack_packet(syn_packet), "127.0.0.1")]

        expected_response = packet.pack_packet(packet.create_synack_packet(syn_packet))
        r = host.Receiver(mock_socket, 10, "127.0.0.1", 10)
        r.wait_for_syn()
        r.handle_next_packet()
        mock_socket.sendto.assert_called_with(expected_response, ("127.0.0.1", 10)) # assert_called_with = most recent call
예제 #3
0
    def test_dup_data(self, mock_socket):
        data = bytes([128] * 512)
        latest_data = packet.create_data_packets(data, 0)[0]
        mock_socket.recvfrom.return_value = (packet.pack_packet(latest_data), "127.0.0.1")

        latest_ack = packet.create_ack_packet_from_data(latest_data, 0)

        r = host.Receiver(mock_socket, 10, "127.0.0.1", 10)
        r.latest_ack = latest_ack
        r.ack_num = 512

        r.handle_next_packet()

        mock_socket.sendto.assert_called_with(packet.pack_packet(latest_ack), ("127.0.0.1", 10))
예제 #4
0
    def wait_for_syn(self):
        while(True):
            pkt = self.wait_for_packet(False)
            if(pkt.flags == packet.Type.FIN):
                print("received FIN packet, finishing up")
                self.is_done = True
                self.finish_status = DONE
                return
            elif(pkt.flags == (packet.Type.EOT | packet.Type.ACK)):
                print("received EOT/ACK packet while waiting for SYN; remote side didn't receive final ACK, retransmitting")
                self.sock.sendto(packet.pack_packet(packet.create_ack_packet(0, 0)), (self.emulator, self.port))
            elif(pkt.flags == packet.Type.SYN):
                break

        print("received SYN packet; responding with SYN/ACK")
        self.latest_ack = packet.create_synack_packet(pkt)
        response = packet.pack_packet(self.latest_ack)
        self.sock.sendto(response, (self.emulator, self.port))
        self.ack_num = 1
예제 #5
0
    def test_data_timeout(self, mock_socket):
        mock_socket.recvfrom.side_effect = socket.timeout("timed out")

        latest_ack = packet.create_synack_packet(packet.create_syn_packet())
        r = host.Receiver(mock_socket, 10, "127.0.0.1", 10)
        r.latest_ack = latest_ack

        r.handle_next_packet()

        mock_socket.sendto.assert_called_with(packet.pack_packet(latest_ack), ("127.0.0.1", 10))
예제 #6
0
    def send_data(self):
        self.current_offset = self.seq_num - 1
        self.bytes_left = self.file_size - self.current_offset
        self.bytes_to_read = min(self.bytes_left, packet.MAX_DATA_LENGTH * self.window_size)

        if (self.bytes_to_read == 0):
            self.send_eot()

        end = self.current_offset + self.bytes_to_read

        packets = packet.create_data_packets(self.read_data[self.current_offset:end], self.seq_num)
        for p in packets:
            self.sock.sendto(packet.pack_packet(p), (self.emulator, self.port))
            print("sent DATA packet with seq {} and data len {} to {} on port {}".format(p.seq_num, p.data_len, self.emulator, self.port))
예제 #7
0
    def test_packing(self):
        # Input: a data packet containing MAX_LENGTH bytes of data
        buf = bytes([128] * (packet.MAX_LENGTH))
        p = Packet(
                    packet.Type.DATA,
                    0,
                    0,
                    buf)

        packed = packet.pack_packet(p)
        unpacked = packet.unpack_packet(packed)
        
        # Expected output (after packing and unpacking: a packet identical to the packed one
        self.assertEqual(unpacked.flags, p.flags)
        self.assertEqual(unpacked.ack_num, p.ack_num)
        self.assertEqual(unpacked.seq_num, p.seq_num)
        self.assertEqual(unpacked.data_len, p.data_len)
        self.assertEqual(unpacked.data, p.data)
예제 #8
0
    def run(self):
        try:
            print("waiting for SYN packet...")
            self.wait_for_syn()
            if(self.is_done):
                print("finished running, returning status {}".format("SWITCH" if self.finish_status == SWITCH else "DONE"))
                return self.finish_status
        
            print("entering main receiver loop")
            while(not self.is_done):
                self.handle_next_packet()
        except KeyboardInterrupt:
            print("\ncaught keyboard interrupt, sending FIN")
            self.sock.sendto(packet.pack_packet(packet.create_fin_packet()), (self.emulator, self.port))
            self.finish_status = DONE

        print("finished running, returning status {}".format("SWITCH" if self.finish_status == SWITCH else "DONE"))
        return self.finish_status
예제 #9
0
    def run(self):
        while(True):
            if(self.is_recv):
                self.file = open(self.rcv_prefix + str(self.rcv_count), 'wb')
                self.rcv_count += 1
                receiver = Receiver(self.sock, self.config["port"], self.config["emulator"], self.config["window_size"], self.file)
                result = receiver.run()
                if(result == DONE):
                    self.file.close()
                    return
                else:
                    self.is_recv = False
                    self.file.close()
            else:
                if(self.send_idx + 1 > len(self.file_list)):
                    response = packet.pack_packet(packet.create_fin_packet())
                    self.sock.sendto(response, (self.config["emulator"], self.config["port"]))
                    return
                else:
                    try:
                        self.file = open(self.file_list[self.send_idx], "rb")
                        read_data = self.file.read()
                        file_size = os.stat(self.file_list[self.send_idx]).st_size
                        self.send_idx += 1
                        sender = emu.sender.Sender(self.sock, self.config["port"], self.config["emulator"], self.config["window_size"], read_data, file_size)

                        result = sender.run()
                        if(result == SWITCH):
                            self.is_recv = True
                            self.file.close()
                        else:
                            self.file.close()
                            return
                    except Exception as e:
                        print(str(e))
                        print("error while processing file {}, sending FIN".format(self.file_list[self.send_idx-1]))
                        response = packet.create_fin_packet()
                        self.sock.sendto(response, (self.config["emulator"], self.config["port"]))
                        return
예제 #10
0
 def send_fin(self):
     self.sock.sendto(packet.pack_packet(packet.create_fin_packet()), (self.emulator, self.port))
예제 #11
0
 def send_eot(self):
     self.sock.sendto(packet.pack_packet(packet.create_eot_packet()), (self.emulator, self.port))
     self.sent_eot = True
예제 #12
0
 def send_ack(self):
     response = packet.pack_packet(packet.create_ack_packet(0, 0))
     self.sock.sendto(response, (self.emulator, self.port))
예제 #13
0
 def send_syn(self):
     response = packet.pack_packet(packet.create_syn_packet())
     self.sock.sendto(response, (self.emulator, self.port))
     self.seq_num = 1
     self.rcvd_window_bytes = 0
     self.latest_rcvd = None
예제 #14
0
    def handle_next_packet(self):
        if(self.rcvd_window_bytes == (self.window_size * packet.MAX_DATA_LENGTH) or self.ack_now):
            print("sending ack {}".format(self.ack_num))
            response = packet.pack_packet(self.latest_ack)
            self.sock.sendto(response, (self.emulator, self.port))
            
            self.ack_now = False
            self.reacked = False
            self.rcvd_window_bytes = 0

            # write buffer to file and create an empty buffer
            self.file.write(self.buf)
            self.buf = bytearray()

        print("waiting for next packet...")
        rcvd = self.wait_for_packet(True)

        # wait_for_packet returns None on timeout
        if(rcvd == None):
            self.reacked = False
            if(not self.got_eot):
                # re-send last ACK
                print("timed out while waiting for packet; retransmitting ack with ack number {}".format(self.ack_num))
                response = packet.pack_packet(self.latest_ack)
                self.sock.sendto(response, (self.emulator, self.port))
            else:
                # need to resend EOT/ACK
                print("timed out while waiting for final ACK; retransmitting EOT/ACK")
                self.sock.sendto(packet.pack_packet(packet.create_eot_ack_packet()), (self.emulator, self.port))

        elif(rcvd.flags == packet.Type.SYN):
            print("received another SYN packet; responding with SYN/ACK")
            response = packet.pack_packet(packet.create_synack_packet(rcvd))
            self.sock.sendto(response, (self.emulator, self.port))

        elif(rcvd.flags == packet.Type.FIN):
            print("received FIN packet, finishing up")
            self.is_done = True
            self.finish_status = DONE

        elif(rcvd.flags == packet.Type.ACK and self.got_eot):
            print("received ACK for EOT/ACK, switching modes")
            self.is_done = True
            self.finish_status = SWITCH

        elif(rcvd.flags == packet.Type.EOT and not self.got_eot):
            print("received EOT packet, responding with EOT/ACK")
            self.sock.sendto(packet.pack_packet(packet.create_eot_ack_packet()), (self.emulator, self.port))
            self.got_eot = True

        elif(rcvd.flags == packet.Type.DATA):
            # we got a spurious retransmission
            if(rcvd.seq_num != self.ack_num):
                if(rcvd.seq_num < self.ack_num):
                    print("spurious retransmission with sequence number {}".format(rcvd.seq_num))
                    if(not self.reacked):
                        print("retransmitting ACK in response to spurious retransmission")
                        response = packet.pack_packet(self.latest_ack)
                        self.sock.sendto(response, (self.emulator, self.port))
                        self.reacked_seq_num = rcvd.seq_num
                        self.reacked = True
                    elif(rcvd.seq_num == self.reacked_seq_num):
                        print("retransmitting ACK in response to spurious retransmission")
                        response = packet.pack_packet(self.latest_ack)
                        self.sock.sendto(response, (self.emulator, self.port))
                    return
                else:
                    # != and ! < , so it's greater than the ACK number we were expecting, AKA packets were dropped (or re-ordered, but that's unlikely)
                    print("received packet with sequence number {}, packet with sequence number {} was dropped".format(rcvd.seq_num, self.ack_num))
                    return

            # the sender will always send max data unless it's almost out of data
            # in that case, we don't want to wait for the timeout
            # we should receive an EOT after this (but it shouldn't actually cause problems if not)
            if(rcvd.data_len < packet.MAX_DATA_LENGTH):
                print("packet had length {}; acking now".format(str(rcvd.data_len)))
                self.ack_now = True

            self.rcvd_window_bytes += rcvd.data_len
            self.latest_ack = packet.create_ack_packet_from_data(rcvd, self.seq_num)
            self.ack_num += rcvd.data_len
            print("received packet with sequence number {}; received {} bytes this window, current ack number is {}".format(rcvd.seq_num, self.rcvd_window_bytes, self.ack_num))
            self.buf.extend(rcvd.data)
예제 #15
0
            if(args):
                if(len(args) > 1):
                    print("syntax: help [command name]")
                elif(not args[0] in commands):
                    print("Invalid command {}. Type help for a list of commands.".format(args[0]))
                else:
                    print("{}".format(commands[args[0]]))
            else:
                print("Type help [command] to view more detail for a command")
                for cmd in command_briefs:
                    print(cmd)

        elif(command == "SYN"):
            if(args):
                print("SYN doesn't take any arguments. Sending SYN anyway")
            sock.sendto(packet.pack_packet(packet.create_syn_packet()), (dest, port))
            print("sent SYN packet to {} on port {}".format(dest, port))

        elif(command == "SYNACK"):
            if(args):
                print("SYNACK doesn't take any arguments. Sending SYN/ACK anyway")
            sock.sendto(packet.pack_packet(packet.create_synack_packet(packet.create_syn_packet())), (dest, port))
            print("sent SYN/ACK packet with to {} on port {}".format(dest, port))

        elif(command == "ACK"):
            if(len(args) != 1):
                print("usage: ACK [ack_num] (enter 'help ACK' for more)")
            else:
                sock.sendto(packet.pack_packet(packet.create_ack_packet(int(args[0]), 0)), (dest, port))
                print("sent ACK packet with ack {} to {} on port {}".format(args[0], dest, port))
예제 #16
0
    def test_data(self, mock_socket):
        data = bytes([128] * packet.MAX_LENGTH * 10)
        data_packets = packet.create_data_packets(data, 1)
        # return a different value on each call
        mock_socket.recvfrom.side_effect = [(packet.pack_packet(data_packets[0]), "127.0.0.1"),
                                            (packet.pack_packet(data_packets[1]), "127.0.0.1"),
                                            (packet.pack_packet(data_packets[2]), "127.0.0.1"),
                                            (packet.pack_packet(data_packets[3]), "127.0.0.1"),
                                            (packet.pack_packet(data_packets[4]), "127.0.0.1"),
                                            (packet.pack_packet(data_packets[5]), "127.0.0.1"),
                                            (packet.pack_packet(data_packets[6]), "127.0.0.1"),
                                            (packet.pack_packet(data_packets[7]), "127.0.0.1"),
                                            (packet.pack_packet(data_packets[8]), "127.0.0.1"),
                                            (packet.pack_packet(data_packets[9]), "127.0.0.1"),
                                            (packet.pack_packet(packet.create_fin_packet()), "127.0.0.1")]

        expected_ack = packet.create_ack_packet_from_data(data_packets[9], 0)
        r = host.Receiver(mock_socket, 10, "127.0.0.1", 10)
        r.latest_ack = packet.create_synack_packet(packet.create_syn_packet())
        r.ack_num = 1

        for i in range(11):
            r.handle_next_packet()

        mock_socket.sendto.assert_called_with(packet.pack_packet(expected_ack), ("127.0.0.1", 10))
        self.assertEqual(r.ack_num, 14611)