Example #1
0
 	def __init__(self, src_ip_ = '', dest_ip_ = '', data_ = ''):
 		self.src_ip = src_ip_
 		self.dest_ip = dest_ip_
 		self.src_port = 0
 		self.dest_port = 0
 		self.seq_num = 0
 		self.ack_num = 0
 		# use the socket provided by network layer
 		self.sock = IpSocket()
 		self.pre_seq = 0 # to store the packet seq and ack number for retransmission
		self.pre_ack = 0
		self.cwnd = 1 # the congestion window used to congestion control
		self.MSS = 536
Example #2
0
    def __init__(self):
        self.src_ip = ''
        self.src_port = 0
        self.des_ip = ''
        self.des_port = 0
        self.seq = 0
        self.ack = 0
        self.s = IpSocket()
        self.my_stamp = 0
        self.echo_stamp = 0

        self.last_time = 0

        self.ack_count = 0
        self.pre_ack = -1
        self.pre_seq = -1
Example #3
0
class TcpSocket:
 	def __init__(self, src_ip_ = '', dest_ip_ = '', data_ = ''):
 		self.src_ip = src_ip_
 		self.dest_ip = dest_ip_
 		self.src_port = 0
 		self.dest_port = 0
 		self.seq_num = 0
 		self.ack_num = 0
 		# use the socket provided by network layer
 		self.sock = IpSocket()
 		self.pre_seq = 0 # to store the packet seq and ack number for retransmission
		self.pre_ack = 0
		self.cwnd = 1 # the congestion window used to congestion control
		self.MSS = 536
 	##########################################################
 	# connect : hostname, dest_port -> None
 	# This method does the three way handshake and store the final
 	# ack num and seq num for sending data and receiving data
 	##########################################################
 	def connect(self, hostname, dest_port = 80):

 		self.dest_port = dest_port
 		src_ip_ = _get_local_host()
 		dest_ip_ = socket.gethostbyname(hostname)
 		self.dest_ip = dest_ip_
 		self.src_ip = src_ip_
 		self.src_port = _get_port() # here we can randomly pick one, but I'm not sure whether it is correct
 		
 		# new a packet and start the three way hand shake
 		self.data = ''
 		tcp_packet = TcpPacket(self.src_port, self.dest_port, self.src_ip, self.dest_ip, self.data)
 		tcp_packet.syn = 1
 		# generate sequence number randomly
 		self.seq_num = randint(0, 65535)
 		# tcp_packet.set_seq_num(self.seq_num)
 		tcp_packet.seq_num = self.seq_num
 		count = 0
 		while True:
 			if count >= 3:
	 			print "no response for 3 min, exit"
	 			sys.exit(0)
	 		self._send(tcp_packet.wrap())
	 		tcp_packet = self._recv_until_timeout()
	 		# raw_packet = self.sock.recv()
	 		if tcp_packet == '' and count < 3:
	 			count += 1
	 			print count
	 			continue
	 		if tcp_packet.rst == 1:
	 			print "error due to reset"
	 			sys.exit(0)
	 		else:
	 			# receive the ack msg from server successfully
	 			if tcp_packet.syn == 1 and tcp_packet.ack == 1 and tcp_packet.ack_num == self.seq_num + 1:
	 				self.seq_num = tcp_packet.ack_num
	 				self.ack_num = tcp_packet.seq_num
	 				break
	 			else:
	 				count += 1
	 				print count
	 				continue

 		tcp_packet = TcpPacket(self.src_port, self.dest_port, self.src_ip, self.dest_ip, self.data)
 		tcp_packet.ack = 1
 		tcp_packet.seq_num = self.seq_num
 		tcp_packet.ack_num = self.ack_num + 1
 		self.ack_num = self.ack_num + 1
 		self._send(tcp_packet.wrap())
 		# til now, three way shakes finished

 	##########################################################
 	# send : data -> None
 	# This method is used to send data to the server using the 
 	# the seq number and ack number stored at the end of the 
 	# three handshake or other part. This method implements 
 	# congestion control. Also, it will wait for the ack for the
 	# data sent. After for 1 minute, it will resend the data. And
 	# if for 3 mintues no response, the program will exit
 	##########################################################
 	def send(self, data):
 		# build a new tcp packet and send it to the dest ip, then wait for the ack. 
 		# If the wait time exceeds the timeout, retransmit this packet
 		# slow start
 		self.cwnd = self.MSS
 		while len(data) > 0:
 			send_data = data[:self.cwnd]
 			data = data[self.cwnd:]
	 		tcp_packet = TcpPacket(self.src_port, self.dest_port, self.src_ip, self.dest_ip, data)
	 		tcp_packet.seq_num = self.seq_num
	 		tcp_packet.ack_num = self.ack_num
	 		tcp_packet.ack = 1
	 		tcp_packet.psh = 1
	 		tcp_packet.data = send_data
	 		# send the packet out using the send method provided by network layer

	 		self._send(tcp_packet.wrap())
	 		# receive process 
	 		while True:
		 		tcp_packet_receive = self._recv_until_timeout()
		 		if tcp_packet_receive == '':
		 			print "received ack errors"
		 			tcp_packet_retrans = TcpPacket(self.src_port, self.dest_port, self.src_ip, self.dest_ip, data)
		 			tcp_packet_retrans.seq_num = self.seq_num
		 			tcp_packet_retrans.ack_num = self.ack_num
		 			tcp_packet_retrans.ack = 1
		 			tcp_packet_retrans.psh = 1
		 			# can't receive the ack, decrease the cwnd
		 			if self.cwnd > 1:
		 				self.cwnd /= 2
		 			else:
		 				self.cwnd = self.MSS
		 			tcp_packet_retrans.data = send_data
		 			try:
		 				self._send(tcp_packet_retrans.wrap())
		 			except:
		 				continue
		 			# tcp_packet.reset()
		 		else:
		 			# filter the packet, the packet we want should be a ack packet
		 			# and the ack num should be the seq_num we send + data size(the next seq_num the 
		 			# receiver wants)
					# print tcp_packet_receive.ack_num, self.seq_num + min(self.cwnd, len(send_data))
		 			if tcp_packet_receive.rst == 1:
		 				print "error due to reset"
		 				sys.exit(0)
		 			if tcp_packet_receive.ack == 1 and tcp_packet_receive.ack_num == (self.seq_num + min(self.cwnd, len(send_data))):
		 				# succeeds receiving ack, increase the cwnd
		 				self.cwnd *= 2
		 				self.pre_ack = self.ack_num
		 				self.pre_seq = self.seq_num
		 				self.seq_num = tcp_packet_receive.ack_num
		 				self.ack_num = tcp_packet_receive.seq_num
		 				
		 				# self.data = data
		 				break
		 			else:
		 				continue

 	##########################################################
 	# recv_all : None -> data
 	# This method is used to receive the data sent from the server
 	# It will check the seq number of the data received and tell
 	# whether it is the packet previously acked. If not, this metod
 	# will request for the retransmission. The method will continue
 	# receiving the data until the server sends the fin for tearing
 	# down the connection.
 	##########################################################

 	def recv_all(self):
 		result_data = []
 		# ack_count = 0
 		while True:
	 		tcp_packet = self._recv_until_timeout()
	 		# timeout, nothing get, exit the program
	 		if tcp_packet == '':
	 			print "received errors"
	 			sys.exit(0)
	 		# if we receive a reset packet, the connection is done, exit the program
	 		if tcp_packet.rst == 1:
	 			print "received errors"
	 			sys.exit(0)
	 		else:
	 			# check the seq number, if it is the packet we want, ack new packet
	 			# otherwise request for retransmission
	 			if tcp_packet.seq_num == self.pre_ack:
	 				# If the server sends the finish packet, ack this finish packet
	 				# and ends the receiving process
		 			if tcp_packet.fin == 1 :	
		 				self.ack_num = tcp_packet.seq_num + len(tcp_packet.data) + 1
		 				self.seq_num = tcp_packet.ack_num
		 				tcp_packet_for_ack_fin = TcpPacket(self.src_port, self.dest_port, self.src_ip, self.dest_ip, '')
			 			tcp_packet_for_ack_fin.ack = 1
			 			tcp_packet_for_ack_fin.ack_num = self.ack_num
			 			tcp_packet_for_ack_fin.seq_num = self.seq_num
			 			self._send(tcp_packet_for_ack_fin.wrap())
			 			self.pre_ack = self.ack_num
			 			self.pre_seq = self.seq_num
		 				break
		 			# if the packet is not a finished pacekt, continue reveiving the data
		 			else:
		 				result_data.append(tcp_packet.data)
		 				self.seq_num = tcp_packet.ack_num
		 				self.ack_num = tcp_packet.seq_num + len(tcp_packet.data)
		 				tcp_packet_for_ack_next = TcpPacket(self.src_port, self.dest_port, self.src_ip, self.dest_ip, '')
		 				tcp_packet_for_ack_next.ack = 1
		 				tcp_packet_for_ack_next.seq_num = self.seq_num
		 				tcp_packet_for_ack_next.ack_num = self.ack_num
			 			self._send(tcp_packet_for_ack_next.wrap())
			 			self.pre_seq = self.seq_num
			 			self.pre_ack = self.ack_num
			 	# If the received packet is wrong, do retransmission process
	 			elif tcp_packet.seq_num != self.pre_ack:
		 			tcp_packet_ack_loss_packet = TcpPacket(self.src_port, self.dest_port, self.src_ip, self.dest_ip, '')
		 			tcp_packet_ack_loss_packet.ack_num = self.pre_ack
		 			tcp_packet_ack_loss_packet.seq_num = self.pre_seq
		 			tcp_packet_ack_loss_packet.ack = 1
	 				self._send(tcp_packet_ack_loss_packet.wrap())

	 	return ''.join(result_data)
	##########################################################
 	# close : None -> None
 	# This method is used to finish a connection. First, it will
 	# send the fin+ack packet to the server. If no response, exit
 	# the method, if the server sends the fin+ack, it will send
 	# the ack as well.
 	##########################################################
	def close(self):
		# send the fin+ack packet to the server
		tcp_packet_for_fin = TcpPacket(self.src_port, self.dest_port, self.src_ip, self.dest_ip, '')
		tcp_packet_for_fin.fin = 1
		tcp_packet_for_fin.ack = 1
		tcp_packet_for_fin.ack_num = self.ack_num
		tcp_packet_for_fin.seq_num = self.seq_num
		self._send(tcp_packet_for_fin.wrap())
		# wait for the response
		tcp_packet = self._recv_until_timeout()
		# timeout and no response, exit 
		if tcp_packet == '':
			print 'can\'t receive ack, client finishes itself'
			sys.exit(0)
		# get a reset packet, exit
		if tcp_packet.rst == 1:
			print "error due to reset"
			sys.exit(0)
		else:
			# received a fin+ack packet, send the ack packet to server and ends the close method
			if self.ack_num == tcp_packet.seq_num and self.seq_num + 1== tcp_packet.ack_num and tcp_packet.fin == 1 and tcp_packet.ack == 1:
				print "correct"
				self.ack_num = tcp_packet.seq_num + 1
				self.seq_num = tcp_packet.ack_num
				tcp_packet = TcpPacket(self.src_port, self.dest_port, self.src_ip, self.dest_ip, '')
				tcp_packet.ack_num = self.ack_num
				tcp_packet.seq_num = self.seq_num
				tcp_packet.fin = 1
				self._send(tcp_packet.wrap())
				return 
			# received a ack packet, end the close method
			elif self.ack_num == tcp_packet.seq_num and self.seq_num + 1== tcp_packet.ack_num and tcp_packet.ack == 1 and tcp_packet.fin == 0:
				# print "finish"
				return 
			else:
				print "some error happens"
				sys.exit(0)
	######################################################
	# _send : encoded tcp_packet -> None
	# This method is a private method for sending data use the
	# socket provided by the network layer. It will contiune
	# trying to send the data until it succeeds or 10 times 
	######################################################
	def _send(self, tcp_packet):
 		count = 0
 		while True:
 			try:
 				self.sock.send(self.src_ip, self.dest_ip, tcp_packet)
 				break
 			except:
 				if count > 10:
 					print "some errors happens, please check you device and try again"
 					sys.exit(0)
 				count += 1
 				continue
 	######################################################
 	# _recv_until_timeout : None -> tcp packet object
	# This method is a private method for receiving the data
	# it will contiune trying to receive the right tcp packet
	# until it succeeds or time out 
	#######################################################
 	def _recv_until_timeout(self):
 		start = time.time()
 		tcp_packet = TcpPacket()
 		while time.time() - start < MAX_TIMEOUT:
 			# try the recv() method provided network layer
 			try:
 				raw_packet = self.sock.recv(socket.IPPROTO_TCP)
 			except:
 				continue
 			# do the checksum 
 			tcp_packet.src_ip = self.dest_ip
			tcp_packet.dest_ip = self.src_ip
 			try:
 				tcp_packet.unwrap(raw_packet)
 			except ValueError:
 				continue
 			# if the packet port is correct, return the tcp packet object-
 			if tcp_packet.src_port == self.dest_port and tcp_packet.dest_port == self.src_port:
 				return tcp_packet
 			else:
 				continue
 		return ''
Example #4
0
class TcpSocket:

    def __init__(self):
        self.src_ip = ''
        self.src_port = 0
        self.des_ip = ''
        self.des_port = 0
        self.seq = 0
        self.ack = 0
        self.s = IpSocket()
        self.my_stamp = 0
        self.echo_stamp = 0

        self.last_time = 0

        self.ack_count = 0
        self.pre_ack = -1
        self.pre_seq = -1

    def connect(self,des_addr, des_port_=80):
        self.des_ip = socket.gethostbyname(des_addr)
        self.des_port = des_port_

        self.src_ip = self.get_self_ip()
        self.src_port = self.get_free_port()

        #self.s.src = self.src_ip
        #self.s.des = self.des_ip

        # three way hand shake begins:
        self.seq = randint(0, 65535)
        packet = self.new_out_packet()
        packet.flag_syn = 1

        # send syn
        self._send(self.src_ip, self.des_ip, packet)

        # receive syn+ack
        packet.reset()
        packet = self._recv()
        if packet == '':
            print 'Socket time out(0)'
            sys.exit(0)
        if packet.ack_no == (self.seq + 1) and packet.flag_syn == 1 and packet.flag_ack == 1:
            self.ack = packet.seq_no + 1
            self.seq = packet.ack_no
        else:
            print 'Malformed SYN+ACK packet(1)'
            sys.exit(0)

        # send ack
        packet = self.new_out_packet()
        packet.flag_ack = 1
        #packet.data = 'GET /home/cbw/networks.html HTTP/1.1\n\n'
        self._send(self.src_ip, self.des_ip, packet)


    def send(self, _data):
        'Send the packet'
        packet = self.new_out_packet()
        packet.flag_ack = 1
        packet.flag_psh = 1
        packet.data = _data
        self._send(self.src_ip, self.des_ip, packet)

        'Get ack of the sent packet'
        packet.reset()
        packet = self._recv()
        if packet == '':
            print 'Socket timeout(2)'
            sys.exit(0)
        if packet.ack_no == (self.seq + len(_data)):
            self.ack = packet.seq_no + len(packet.data)
            self.seq = packet.ack_no
        else:
            print 'Malformed ACK packet(3)'
            sys.exit(0)

    def recv(self):
        tcp_data = ''
        #st_time = time.time()
        packet = IpPacket()
        while 1: #(time.time() - st_time) < 0.5:
            if self.ack_count > 1:
                'send ack packet'
                packet = self.new_out_packet()
                'set ack to previous packet'
                packet.ack_no = self.pre_ack
                packet.seq_np = self.pre_seq
                packet.flag_ack = 1
                self._send(self.src_ip, self.des_ip, packet)
                'after send ack, decrease ack_count by 1'
                self.ack_count -= 1

            'recv packet'
            packet.reset()
            packet = self._recv()
            if packet == '':
                break
            'first set previous ack# to current ack'
            if self.ack_count > 0:
                self.pre_ack = self.ack
                self.pre_seq = self.seq
            self.ack = packet.seq_no + len(packet.data)
            self.seq = packet.ack_no
            tcp_data += packet.data
            'add 1 to ack_count, for acknowledge'
            self.ack_count += 1

            #packet = self.new_out_packet()
            #packet.flag_ack = 1
            #self._send(self.src_ip, self.des_ip, packet)
            #'''
            #'''

        return tcp_data

    def close(self):
        'send fin+ack'
        packet = self.new_out_packet()
        packet.flag_fin = 1
        #packet.data = 'aaaaa'
        if self.ack_count > 0:
            packet.flag_ack = 1
        packet.flag_psh = 1
        self._send(self.src_ip, self.des_ip, packet)


        'recv fin+ack'
        packet.reset()
        packet = self._recv()
        if packet == '':
            return 0
        self.ack = packet.seq_no + 1
        self.seq = packet.ack_no

        'send ack'
        packet = self.new_out_packet()
        packet.flag_ack = 1
        self._send(self.src_ip, self.des_ip, packet)

    def new_out_packet(self):
        packet = TcpPacket()
        packet.source = self.src_port
        packet.destination = self.des_port
        packet.src_ip = self.src_ip
        packet.des_ip = self.des_ip
        packet.seq_no = self.seq
        packet.ack_no = self.ack
        return packet

    def get_self_ip(self):
        return get_address('eth0', 'ip')
        '''
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(('www.google.com', 80))
        ip = s.getsockname()[0]
        s.close()
        return ip
        '''


    def get_free_port(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind(('', 0))
        s.listen(1)
        port = s.getsockname()[1]
        s.close()
        return port

    def _send(self, src_ip_, des_ip_, packet_):
        self.s.send(src_ip_, des_ip_, packet_.assemble())
        #print 'send:'
        #packet_.print_packet()

    def _recv(self):
        packet = TcpPacket()
        st_time = time.time()
        while (time.time() - st_time) < TIME_OUT:
            packet.reset()
            try:
                pkt = self.s.recv()
            except:
                continue
            'packet received'
            packet.src_ip = self.des_ip
            packet.des_ip = self.src_ip
            packet.disassemble(pkt)
            #print 'recv:'
            #packet.print_packet()
            if packet.source == self.des_port and packet.destination == self.src_port:
                return packet
        return ''