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))
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