예제 #1
0
    def push(data, remote_ip):
        # print
        # print('[static method]received data from ip, it\'s from', remote_ip)
        tcp = TCP()
        tcp.from_bytes(data)
        # print('current buffer_list is')
        # print(buffer_list)

        # print('src_port is', tcp.src_port, end=' ')
        # print('dst_port is', tcp.dst_port, end=' ')
        # print('content is', str(tcp))

        # print()
        # print basic info
        # names = ['CWR','ECE','URG','ACK','PSH','RST','SYN','FIN']
        # byte = tcp.flag_bits
        # byte = bin(int.from_bytes(byte, 'little'))[2:]
        # print(bytes)
        # for i in range(8):
        #     print("{}:{}".format(names[i], byte[i]))
        #
        # if tcp.SYN == 1 and tcp.ACK != 1:
        #     b
        remote_address = (remote_ip, tcp.src_port)
        if tcp.RST:
            raise ConnectionResetError
        try:
            if tcp.SYN == 1 and tcp.ACK == 1:
                print('detect second handshake')
                try:
                    buffer_list['connecting'][remote_address].append(data)
                except:
                    server_isn = tcp.sequence_number
                    client_isn = tcp.acknowledgement_number
                    remote_port = tcp.src_port
                    local_port = tcp.dst_port
                    tcp = TCP()
                    tcp.sequence_number = client_isn
                    tcp.acknowledgement_number = server_isn
                    tcp.src_port = local_port
                    tcp.dst_port = remote_port
                    tmp_ip = IP.IP(protocol=IP.PROTOCOL_TCP,
                                   src_ip=local_ip,
                                   dst_ip=remote_ip)
                    print('retransmitted', tcp.sequence_number,
                          tcp.acknowledge_number)
                    print("str", str(tcp))
                    tmp_ip.send(bytes(tcp))

            elif tcp.SYN == 1:
                # it's first handshake
                print('detect first handshake')
                buffer_list['listening'][tcp.dst_port]['queue'].append(
                    (data, remote_address))
            else:
                # it's not first handshake

                # self.__last_acked_number = tcp.acknowledgement_number # todo update last_acked_number

                # check whether it's a third handshake
                if remote_address in buffer_list['connected']['objects'].keys(
                ):
                    print('detect normal message')
                    # it's not a third handshake
                    # buffer_list['connected'][remote_address].append((data, remote_address))

                    # get tcp object
                    obj = buffer_list['connected']['objects'][remote_address]

                    # let obj add data
                    obj._add_data(data)
                else:
                    # it's a third handshake
                    print('detect third handshake')
                    buffer_list['connecting'][remote_address].append(
                        (data, remote_address))
        except:
            local_port = tcp.dst_port
            remote_port = tcp.src_port
            sequence_number = tcp.acknowledgement_number
            acknowledge_number = tcp.sequence_number
            tcp = TCP()
            tcp.RST = 1
            tcp.ACK = 0
            tcp.src_port = local_port
            tcp.dst_port = remote_port
            tcp.sequence_number = sequence_number
            tcp.acknowledgement_number = acknowledge_number
            tmp_ip = IP.IP(protocol=IP.PROTOCOL_TCP,
                           src_ip=local_ip,
                           dst_ip=remote_ip)
            tmp_ip.send(bytes(tcp))
예제 #2
0
    def _sending_thread(self):
        # build empty tcp object
        tcp = TCP()
        tcp.build(type=tcp.SEND_DATA,
                  src_port=self.__local_address[1],
                  dst_port=self.__remote_address[1])
        tcp.sequence_number = self.__next_sequence_number
        tcp.acknowledgement_number = self.__last_acked_sent
        print('built empty tcp object')

        while 1:
            time.sleep(0.2)
            # print('sending thread begin')
            # detect whether there is act_to_be_sent
            if self.__ack_to_be_sent != []:
                tcp.ACK = 1
                tcp.acknowledgement_number = self.__ack_to_be_sent.pop()
                self.__last_acked_sent = tcp.acknowledgement_number
                print(
                    'detect there is ack_to_be_sent({}), added to current tcp object, last_acked_number updated'
                    .format(tcp.acknowledgement_number))

            # check time_out
            if self.__is_time_out:
                print('detect time out')

                # get first send_but_not_acked data in tcp.data
                try:
                    tcp_bytes = self.__sent_but_not_acked[0]

                    tcp = TCP()
                    tcp.from_bytes(tcp_bytes)

                    # modify tcp.sequence_number
                    # tcp.sequence_number = waiting_ack_number - len(tcp.data)

                    # double timeout
                    self.__time_out *= 2

                    if self.__time_out <= 1:
                        self.__time_out = 1

                    # cancel SampleRTT recording for this object
                    self.__sample_RTT_to_record[tcp.sequence_number +
                                                len(tcp.data)] = None

                    # Done with here
                    self.__is_time_out = False

                    self.__timer = threading.Thread()
                    self.__timer_pid = None

                    print(self.__time_out)
                except:
                    self.__is_time_out = False

                    self.__timer = threading.Thread()
                    self.__timer_pid = None
            else:
                # print('no timeout detected')

                # calculate the spare room in sent_but_not_acked
                spare_room_in_window = self.__window_size - (
                    self.__next_sequence_number - self.__last_ack_received)

                if self.__send_buffer != b'' and spare_room_in_window != 0:  # specify squence number andNextSeqNum
                    NextSeqNum = self.__next_sequence_number

                    # prepare data
                    data = self.__send_buffer[:self.__segment_size]

                    # delete that data from send_buffer
                    self.__send_buffer = self.__send_buffer[self.
                                                            __segment_size:]

                    # update tcp object
                    tcp.data = data
                    tcp.sequence_number = NextSeqNum

            # check tcp modified
            if tcp.data != b'' or tcp.ACK == 1:
                # set sequence number
                # tcp.sequence_number = self.__next_sequence_number

                # if data included, update next_sequence_number
                if tcp.data != b'':
                    self.__next_sequence_number += len(data)

                # if the tcp contains data
                if tcp.data != b'':
                    # check the data is first sent or not

                    # add current value to sent_but_not_acked
                    if bytes(tcp) not in self.__sent_but_not_acked:
                        self.__sent_but_not_acked.append(bytes(tcp))

                    if (tcp.sequence_number + len(tcp.data)
                        ) not in self.__sample_RTT_to_record.keys():
                        # it's first sent.

                        # record send time
                        send_time = time.time()
                        self.__sample_RTT_to_record[tcp.sequence_number +
                                                    len(tcp.data)] = send_time
                        # print('----------')
                        # print('record time')
                        # print(self.__sample_RTT_to_record)
                        # print('----------')

                        # check whether there is already a tiemr
                        print('check timer', self.__timer.is_alive())
                        if not self.__timer.is_alive():
                            # there is no timer

                            # calculate a new time_out
                            self.__time_out = self._get_new_timeout()

                            # start a new timer
                            self.__timer = threading.Thread(
                                target=self.__check_time,
                                args=(time.time(), self.__time_out))
                            self.__timer.start()
                    else:
                        # it's not first sent

                        # double timeout
                        print(
                            'detect not first send message, the sequence_number is {}, the ack_number is {}, content:{}'
                            .format(tcp.sequence_number,
                                    tcp.acknowledgement_number, str(tcp)))
                        print(self.__sample_RTT_to_record)
                        self.__time_out *= 2
                        self.__timer = threading.Thread(
                            target=self.__check_time,
                            args=(time.time(), self.__time_out))
                        self.__timer.start()

                # send tcp object
                self.__ip.send(bytes(tcp))
                print(
                    'send tcp object with \tsequence number {} and \tacknowledge number {}.'
                    .format(tcp.sequence_number, tcp.acknowledgement_number))
                print('content', str(tcp))

                # build new tcp object
                tcp = TCP()
                tcp.build(type=tcp.SEND_DATA,
                          src_port=self.__local_address[1],
                          dst_port=self.__remote_address[1])
                tcp.sequence_number = self.__next_sequence_number
                tcp.acknowledgement_number = self.__last_acked_sent