def send_packet_to_server(): global_data.get_value("main_socket").bind( (global_data.get_value("interface"), 0)) global_data.get_value("main_socket").send( global_data.get_value("eth_header")) last_packet_sent_time = time.time() global_data.set_value("last_packet_sent_time", last_packet_sent_time)
def build_ip_header(): ihl = 5 ver = 4 tos = 0 id_of_ip_pkt = 54321 fragm_off = 0 ttl = 225 protocol = socket.IPPROTO_TCP checksum_for_ip = 0 source_add_for_ip = socket.inet_aton(global_data.get_value("local_ip")) dest_add_for_ip = socket.inet_aton(global_data.get_value("server_ip")) ihl_ver = (ver << 4) + ihl tot_length = 4 * ihl + len(global_data.get_value("tcp_header")) ip_header = struct.pack('!BBHHHBBH4s4s', ihl_ver, tos, tot_length, id_of_ip_pkt, fragm_off, ttl, protocol, checksum_for_ip, source_add_for_ip, dest_add_for_ip) checksum = util.ip_checksum(ip_header) """ add checksum into ip header """ ip_header = struct.pack('!BBHHHBBH4s4s', ihl_ver, tos, tot_length, id_of_ip_pkt, fragm_off, ttl, protocol, checksum, source_add_for_ip, dest_add_for_ip) ip_header = ''.join([ip_header, global_data.get_value("tcp_header")]) global_data.set_value("ip_header", ip_header)
def build_http_header(): http_header = "GET " + global_data.get_value("url") + " HTTP/1.0\r\n\r\n" http_request = http_header global_data.set_value("http_request", http_request) http_request_length = len(http_header) global_data.set_value("http_request_length", http_request_length)
def build_tcp_header(source_of_tcp_p, dest_of_tcp_p, seq_of_tcp_p, ack_seq_of_tcp_p, d_off_tcp_p, fin_p, syn_p, rst_p, psh_p, ack_p): # TCP Header Section # source port source_port = source_of_tcp_p # destination port destination_port = dest_of_tcp_p seq_num = seq_of_tcp_p ack_num = ack_seq_of_tcp_p d_offset = 5 # flags fin = fin_p syn = syn_p rst = rst_p psh = psh_p ack = ack_p urg = 0 # size of max allowed window size window_size = socket.htons(5840) checksum = 0 urg_pointer = 0 offset_res_of_tcp = (d_offset << 4) + 0 flags = fin + (syn << 1) + (rst << 2) + (psh << 3) + (ack << 4) + ( urg << 5) tcp_header_p = struct.pack("!HHLLBBHHH", source_port, destination_port, seq_num, ack_num, offset_res_of_tcp, flags, window_size, checksum, urg_pointer) source_address = socket.inet_aton(global_data.get_value("local_ip")) dest_address = socket.inet_aton(global_data.get_value("server_ip")) placeholder = 0 protocol = socket.IPPROTO_TCP tcp_length = len(tcp_header_p) + len(global_data.get_value("http_request")) psh = struct.pack('!4s4sBBH', source_address, dest_address, placeholder, protocol, tcp_length) psh = psh + tcp_header_p + global_data.get_value("http_request") checksum = util.tcp_checksum(psh) # add correct tcp header checksum tcp_header = struct.pack( '!HHLLBBH', source_port, destination_port, seq_num, ack_num, offset_res_of_tcp, flags, window_size) + struct.pack( 'H', checksum) + struct.pack('!H', urg_pointer) tcp_header = ''.join([tcp_header, global_data.get_value("http_request")]) # save into global data value global_data.set_value("tcp_header", tcp_header)
def get_server_ip_and_downloaded_file_name(url): if url.startswith('http://'): url_content = url[7:] url_separated_with_slash = url_content.split("/") if url_separated_with_slash[0] == url_content: downloaded_file_name = "index.html" server_web_address = url_content else: server_web_address = url_separated_with_slash[0] url_content_length = len(url_separated_with_slash) downloaded_file_name = url_separated_with_slash[url_content_length - 1] if downloaded_file_name.find(".") == -1: downloaded_file_name = "index.html" else: print "--- Wrong URL format ---" raise Exception global_data.set_value("downloaded_file_name", downloaded_file_name) server_ip = socket.gethostbyname(server_web_address) return server_ip
def build_ethernet_header_for_ip(): ether_type = 2048 header_of_eth = struct.pack('!6s6sH', global_data.get_value("gateway_mac_binary"), global_data.get_value("local_mac_binary"), ether_type) eth_header = ''.join([header_of_eth, global_data.get_value("ip_header")]) global_data.set_value("eth_header", eth_header)
def receive_data_from_server(): """ receive data from the server, for three way handshake and for receive http response data """ downloaded_file_name = global_data.get_value("downloaded_file_name") main_socket = global_data.get_value("main_socket") local_port = global_data.get_value("local_port") server_ip = global_data.get_value("server_ip") local_ip = global_data.get_value("local_ip") f = open(downloaded_file_name, 'a') while True: if (time.time() - global_data.get_value("last_packet_sent_time")) > 180: print "Program, rawhttpget, does not receive any data from the remote server for three minutes. Please retry again." sys.exit(0) packet = main_socket.recvfrom(65565) packet = packet[0] ethernet_header_length = struct.calcsize('!6s6sH') ip_header = packet[ethernet_header_length:ethernet_header_length + 20] global_data.set_value("ip_header", ip_header) iph = struct.unpack('!BBHHHBBH4s4s', ip_header) version_ihl = iph[0] ihl = version_ihl & 0xF iph_length = ihl * 4 server_as_source_address = socket.inet_ntoa(iph[8]) local_as_destination_address = socket.inet_ntoa(iph[9]) tcp_header = packet[ethernet_header_length + iph_length:ethernet_header_length + iph_length + 20] global_data.set_value("tcp_header", tcp_header) tcph = struct.unpack('!HHLLBBHHH', tcp_header) server_as_source_port = tcph[0] local_as_destination_port = tcph[1] sequence_number = tcph[2] global_data.set_value("sequence_number", sequence_number) acknowledge_number = tcph[3] global_data.set_value("acknowledge_number", acknowledge_number) data_offset_reserved = tcph[4] tcp_flags = tcph[5] flag_fin = tcp_flags & int(hex(1), 16) flag_syn = (tcp_flags >> 1) & int(hex(1), 16) flag_ack = (tcp_flags >> 4) & int(hex(1), 16) tcph_length = data_offset_reserved >> 4 header_size = ethernet_header_length + iph_length + tcph_length * 4 data_size = len(packet) - header_size data = packet[header_size:] if local_as_destination_port != local_port or server_as_source_port != 80 \ or server_as_source_address != server_ip or local_as_destination_address != local_ip: continue else: if flag_ack == 1 and flag_syn == 1: old_sequence_number = sequence_number + 1 global_data.set_value("old_sequence_number", old_sequence_number) break if data_size > 6 and global_data.get_value( "current_cwnd_size") <= 1000: if global_data.get_value("old_sequence_number") + global_data.get_value("old_data_length") == \ global_data.get_value("sequence_number") and util.tcp_checksum(global_data.get_value("ip_header")) == 0: if (time.time() - global_data.get_value("last_packet_sent_time") ) < 60: if data.split('\r\n\r\n')[0] == data: """ directly write data into file """ f.write(data) else: data_containing_header = data.split('\r\n\r\n')[0] http_status = data_containing_header.split(' ')[1] if http_status == "200": f.write(data.split('\r\n\r\n')[1]) else: print "Only 200 will be considered!" break old_sequence_number = global_data.get_value( "sequence_number") global_data.set_value("old_sequence_number", old_sequence_number) old_data_length = data_size global_data.set_value("old_data_length", old_data_length) """ solve the retransmit packet needs to be ACK """ if global_data.get_value( "number_of_retransmit_packet_to_be_ACK") > 0: new_number_of_retransmit_packet_to_be_ACK = global_data.get_value( "number_of_retransmit_packet_to_be_ACK") - 1 global_data.set_value( "number_of_retransmit_packet_to_be_ACK", new_number_of_retransmit_packet_to_be_ACK) """ normal cwnd size """ if 0 < global_data.get_value( "current_cwnd_size") + 1 < 1000: new_current_cwnd_size = global_data.get_value( "current_cwnd_size") + 1 global_data.set_value("current_cwnd_size", new_current_cwnd_size) else: new_current_cwnd_size = 1 global_data.set_value("current_cwnd_size", new_current_cwnd_size) send_ack_to_server( global_data.get_value("sequence_number")) else: print "retransmit because the 60 seconds limit" send_ack_retransmit_to_server( global_data.get_value("old_sequence_number")) else: if global_data.get_value( "current_cwnd_size" ) + 1 <= 0 or global_data.get_value( "current_cwnd_size") + 1 >= 1000: new_current_cwnd_size = 1 global_data.set_value("current_cwnd_size", new_current_cwnd_size) else: new_current_cwnd_size = global_data.get_value( "current_cwnd_size") + 1 global_data.set_value("current_cwnd_size", new_current_cwnd_size) new_number_of_retransmit_packet_to_be_ACK = 1 global_data.set_value( "number_of_retransmit_packet_to_be_ACK", new_number_of_retransmit_packet_to_be_ACK) print "retransmit because sequence number or checksum error" send_ack_retransmit_to_server( global_data.get_value("old_sequence_number")) if flag_fin == 1 and global_data.get_value( "number_of_retransmit_packet_to_be_ACK") == 0: f.close() send_fin_ack_to_server() break sys.exit(0)
def build_empty_http_header(): http_request = "" global_data.set_value("http_request", http_request)