Exemplo n.º 1
0
    def _connect(self):
        debug_log("start three-way handshake")
        syn_segment = self.segment_factory.create_syn()
        self.seq_num = syn_segment.seq_num
        debug_log("send syn to server")

        # send syn to the server, resend if timeout
        self._send_segment(syn_segment)
        try:
            ack_syn_segment = self._receive_ack(1, 0)
        except TimeoutError:
            self._send_segment(syn_segment)
            try:
                ack_syn_segment = self._receive_ack(1, 0)
            except TimeoutError:
                # exit the program if still timeout
                sys.exit(-1)
                error_log("failed to create a TCP connection")

        debug_log("receive ack syn from server")
        # add 1 to the sequence number
        self.seq_num += 1
        # set the ack number
        self.ack_num = ack_syn_segment.seq_num + 1
        ack_segment = self.segment_factory.create_ack(self.seq_num,
                                                      self.ack_num)
        self._send_segment(ack_segment)
        debug_log("send ack to server")
        debug_log("complete three-way handshake")
Exemplo n.º 2
0
 def _receive_datagram(self):
     while True:
         ip_datagram = dissemble(self.eth_socket.receive())
         if ip_datagram is not None:
             debug_log("receive datagram from " + ip_datagram.src_ip +
                       " to " + ip_datagram.dest_ip)
             if ip_datagram.src_ip == self.dest_ip and ip_datagram.dest_ip == self.src_ip:
                 return ip_datagram
Exemplo n.º 3
0
 def _send_data_in_queue(self):
     # window size should be min(cwnd, awnd)
     wnd_size = min(self.cwnd * MSS, self.awnd)
     while wnd_size > 0 and len(self.sender_queue) > 0:
         data_segment = self.sender_queue.popleft()
         if len(data_segment.data) < wnd_size:
             debug_log("send request data to the server, sequence number: " + str(self.seq_num))
             self._send_segment(data_segment)
             expected_ack_num = self.seq_num + len(data_segment.data)
             self.unacked_segments[expected_ack_num] = data_segment
             wnd_size -= len(data_segment.data)
         else:
             self.sender_queue.appendleft(data_segment)
             break
Exemplo n.º 4
0
    def _get_remote_mac(self, src_ip, src_mac, gate_ip):
        spa = src_ip
        sha = src_mac
        tpa = gate_ip
        tha = self.dest_mac

        sent_arp_pac = arp_packet.ARPPacket(sha, spa, tha, tpa)
        sent_arp_data = arp_packet.assemble(sent_arp_pac)
        debug_log("send arp request")
        self.send(sent_arp_data, type_num=HTYPE_ARP)

        recv_arp_data = self.receive(type_num=HTYPE_ARP)
        debug_log("receive arp response")
        recv_arp_pac = arp_packet.dissemble(recv_arp_data)
        return recv_arp_pac.sha
Exemplo n.º 5
0
 def _partition_data(self, data):
     seg_seq_num = self.seq_num
     total_len = len(data)
     remain_len = total_len
     start_index = 0
     while remain_len > MSS:
         partitioned_data = data[start_index: start_index + MSS]
         debug_log("partition data: " + partitioned_data + ", seq_num: " + str(seg_seq_num))
         partitioned_data_seg = self.segment_factory.create_psh_ack(seg_seq_num, self.ack_num, partitioned_data)
         seg_seq_num += MSS
         start_index += MSS
         remain_len -= MSS
         # add the segment into the sender queue
         self.sender_queue.append(partitioned_data_seg)
     # add the last segment
     last_data = data[start_index: total_len]
     last_data_seg = self.segment_factory.create_psh_ack(seg_seq_num, self.ack_num, last_data)
     self.sender_queue.append(last_data_seg)
Exemplo n.º 6
0
    def _receive_data_and_send_ack(self):
        init_data_index = self.ack_num
        unordered_data = dict()
        while True:
            segment = self._receive_segment()
            data = segment.data
            segment_index = segment.seq_num - init_data_index
            expected_index = self.ack_num - init_data_index
            # if the server sends fin and all data before has been received, break the auto ack mode
            if segment.fin == 1 and segment_index == expected_index:
                if len(data) != 0:
                    self._handle_ordered_data(data)
                # ack to fin
                self.ack_num += 1
                fin_ack_segment = self.segment_factory.create_fin_ack(
                    self.seq_num,
                    self.ack_num)
                self._send_segment(fin_ack_segment)
                debug_log("ack to fin")
                if self._receive_segment().ack == 1:
                    debug_log("successfully close the connection")
                    self.connection_closed = True
                    break

            # duplicate segment, drop it and ack (the ack number should be correct)
            if segment_index < expected_index:
                debug_log("get duplicate segment")
                ack_segment = self.segment_factory.create_ack(self.seq_num,
                                                              segment_index + init_data_index)
                self._send_segment(ack_segment)
                continue
            # new ordered segment (handle it and all cached unordered data)
            elif segment_index == expected_index:
                debug_log("get ordered segment")
                self._handle_ordered_data(data)
                self._handle_unordered_data(unordered_data)
            # unordered data, cache it
            else:
                debug_log("get unordered segment")
                unordered_data[segment_index] = segment.data
            ack_segment = self.segment_factory.create_ack(self.seq_num,
                                                          self.ack_num)
            self._send_segment(ack_segment)
Exemplo n.º 7
0
    def close(self):
        if not self.connection_closed:
            fin_segment = self.segment_factory.create_fin(self.seq_num,
                                                          self.ack_num)
            # send fin to the server, resend if timeout
            self._send_segment(fin_segment)
            try:
                ack_fin_segment = self._receive_ack(0, 1)
            except TimeoutError:
                self._send_segment(fin_segment)
                try:
                    ack_fin_segment = self._receive_ack(0, 1)
                except TimeoutError:
                    # return False if still timeout
                    return False

                debug_log("receive ack fin from server")
                self.seq_num += 1
                self.ack_num += 1
                ack_segment = self.segment_factory.create_ack(self.seq_num,
                                                              self.ack_num)
                self._send_segment(ack_segment)
                debug_log("send ack to server")
                debug_log("complete connection teardown")

        return True