def print_all_packets(trace):
    ipv4_address_list = {}
    for i in range(len(trace)):
        packet = raw(trace[i])
        dest_mac , source_mac,ethernet_name,internet_protocol,remaining_bytes = ethernet_layer.fully_analyze_ethernet(packet)

        if internet_protocol == "IPv4":
            transport_protocol,source_ip,dest_ip,remaining_bytes = internet_layer.unpack_ipv4_header(remaining_bytes)

            if source_ip in ipv4_address_list.keys():
                ipv4_address_list[source_ip] += 1
            else:
                ipv4_address_list.update({source_ip : 1})

            if transport_protocol == "TCP":
                source_port,dest_port,flag_u,flag_a,flag_p,flag_r,flag_s,flag_f,remaining_bytes = transport_layer.unpack_tcp_header(remaining_bytes)
                application_protocol = transport_layer.determine_application_protocol_for_tcp(source_port,dest_port)
                print_general_data(packet,i+1,ethernet_name,source_mac,dest_mac,internet_protocol, source_ip , dest_ip , transport_protocol , source_port , dest_port , application_protocol)
            elif transport_protocol == "UDP":
                source_port,dest_port,remaining_bytes = transport_layer.unpack_udp_header(remaining_bytes)
                application_protocol = transport_layer.determine_application_protocol_for_udp(source_port,dest_port)
                print_general_data(packet,i+1,ethernet_name,source_mac,dest_mac,internet_protocol, source_ip , dest_ip , transport_protocol , source_port , dest_port , application_protocol)
            else:
                print_general_data(packet,i+1,ethernet_name,source_mac,dest_mac,internet_protocol, source_ip , dest_ip , transport_protocol)
        else:
            print_general_data(packet,i+1,ethernet_name,source_mac,dest_mac,internet_protocol)
        print("______________________________________________")

    print_ips_and_max(ipv4_address_list)
def print_all_tftp(all_valid_packets):                 
    current_source_ip = ""
    current_dest_ip = ""
    for i in all_valid_packets:
        packet = i[0]
        dest_mac , source_mac,ethernet_name,internet_protocol,remaining_bytes = ethernet_layer.fully_analyze_ethernet(packet)
        transport_protocol,source_ip,dest_ip,remaining_bytes = internet_layer.unpack_ipv4_header(remaining_bytes)
        source_port,dest_port,remaining_bytes = transport_layer.unpack_udp_header(remaining_bytes)
        application_protocol = transport_layer.determine_application_protocol_for_udp(source_port,dest_port)

        if application_protocol == "unknown application protocol":
            application_protocol = "TFTP-pokracovanie"

        if current_source_ip == "" and current_dest_ip == "":
            current_source_ip = source_ip
            current_dest_ip = dest_ip
            print("JEDNA KOMUNIKACIA\n")
        elif ((source_ip == current_source_ip and dest_ip == current_dest_ip ) or (dest_ip == current_source_ip and source_ip == current_dest_ip )) == False:
            print("KONIEC KOMUNIKACIE\n")
            print("DALSIA KOMUNIKACIA\n")
            current_source_ip = source_ip
            current_dest_ip = dest_ip

        print_general_data(packet,i[1],ethernet_name,source_mac,dest_mac,internet_protocol, source_ip , dest_ip , transport_protocol , source_port , dest_port , application_protocol)
        print("______________________________________________")
def filter_packets(trace,requested_protocol):
     matches_number = 0
     all_valid_packets = []
     arp_requests = []
     arp_replies = []
     tftp_source_port = 0
     tftp_dest_port = 0
     tftp = 0
     for i in range(len(trace)):
        packet = raw(trace[i])
        dest_mac , source_mac,ethernet_name,internet_protocol,remaining_bytes = ethernet_layer.fully_analyze_ethernet(packet)
        if requested_protocol == internet_protocol: #ARP
                matches_number +=1
                type,source_mac,source_ip,dest_mac,dest_ip,remaining_bytes = internet_layer.unpack_arp_header(remaining_bytes)
                if type=="REQUEST":
                    arp_requests.append([packet,i+1])
                elif type == "REPLY":
                    arp_replies.append([packet,i+1])
        else:
              transport_protocol,source_ip,dest_ip,remaining_bytes = internet_layer.unpack_ipv4_header(remaining_bytes)
              if requested_protocol == transport_protocol: #ICMP
                    matches_number +=1
                    all_valid_packets.append([packet,i+1])
              else:
                    application_protocol = ""
                    if transport_protocol == "UDP":
                        source_port,dest_port,remaining_bytes = transport_layer.unpack_udp_header(remaining_bytes)
                        application_protocol = transport_layer.determine_application_protocol_for_udp(source_port,dest_port)      
                        if application_protocol == "unknown application protocol":  #TFTP  pokracovanie
                            if (tftp == 1) and (source_port == tftp_source_port or source_port == tftp_dest_port or dest_port == tftp_source_port or dest_port == tftp_dest_port):
                                all_valid_packets.append([packet,i+1])                          
                                continue
                    elif transport_protocol == "TCP":
                        source_port,dest_port,flag_u,flag_a,flag_p,flag_r,flag_s,flag_f,remaining_bytes = transport_layer.unpack_tcp_header(remaining_bytes)
                        application_protocol = transport_layer.determine_application_protocol_for_tcp(source_port,dest_port)
                    
                    if application_protocol == requested_protocol:    
                        matches_number +=1
                        if requested_protocol == "TFTP":                    
                           tftp_source_port = source_port
                           tftp_dest_port = dest_port
                           tftp = 1
                           all_valid_packets.append([packet,i+1])
                        else:    
                            tftp = 0
                            all_valid_packets.append([packet,i+1])
                            continue
    
     if requested_protocol == "ARP":
         print_matching_arps(arp_requests,arp_replies)
     elif requested_protocol == "ICMP":
         print_all_icmp(all_valid_packets)
     elif requested_protocol == "TFTP":
         print_all_tftp(all_valid_packets)
     else:
        print_first_complete_and_incomplete(all_valid_packets)

     if matches_number == 0:
         print("Nenasli sa ziadne ramce obsahujuce protokol "+requested_protocol)
def print_first_complete_and_incomplete(all_valid_packets):
    complete_exists = 0
    incomplete_exists = 0

    first_communiation_ended = 0
    current_source_mac = ""
    current_dest_mac = ""
    first_packet_number = 0
    recent_packet_number = 0
    whole_communication = []
    for i in all_valid_packets:
        packet = i[0]
        dest_mac , src_mac,ethernet_name,internet_protocol,remaining_bytes = ethernet_layer.fully_analyze_ethernet(packet)
        transport_protocol,source_ip,dest_ip,remaining_bytes = internet_layer.unpack_ipv4_header(remaining_bytes)
        source_port,dest_port,flag_u,flag_a,flag_p,flag_r,flag_s,flag_f,remaining_bytes = transport_layer.unpack_tcp_header(remaining_bytes)
        application_protocol = transport_layer.determine_application_protocol_for_tcp(source_port,dest_port)

        if current_source_mac == "":
            current_source_mac = src_mac
            current_dest_mac = dest_mac
            first_packet_number = i[1]      

        if ((src_mac == current_source_mac and dest_mac == current_dest_mac) or (src_mac == current_dest_mac and dest_mac == current_source_mac)): #and ((i[1] == first_packet_number) or (i[1] == recent_packet_number + 1)):
            whole_communication.append(i)
            recent_packet_number = i[1]
        else:       #ak nastane else znamena to ze jedna komunikacia skoncila a nasleduje ina
            first_communiation_ended = 1
            if complete_exists == 0 and incomplete_exists == 0:     #ak skoncila prva, vypiseme ju
                whole_communication = shorten_communication(whole_communication)
                complete_exists,incomplete_exists = test_communication(complete_exists,incomplete_exists,whole_communication)
                print_communication(complete_exists,whole_communication)
                current_source_mac = src_mac
                current_dest_mac = dest_mac
                whole_communication.clear
                whole_communication.append(i)
                recent_packet_number = i[1]
            else:     #ak bola prva kompletna, vypiseme iba dalsiu nekompletnu , a naopak
                whole_communication = shorten_communication(whole_communication)
                complete_exists,incomplete_exists = test_communication(complete_exists,incomplete_exists,whole_communication)
                if complete_exists == 1 and incomplete_exists == 1:
                    print_communication(complete_exists,whole_communication)
                    break
    
    if first_communiation_ended == 0:    #toto nastane ak bol cely subor iba jedna komunikacia, alebo ziadna
        if len(whole_communication ) > 0:
             whole_communication = shorten_communication(whole_communication)
             complete_exists,incomplete_exists = test_communication(complete_exists,incomplete_exists,whole_communication)
             print_communication(complete_exists,whole_communication)

    if complete_exists == 0 :
        print("\nUkoncena komunikacia neexistuje")
    if incomplete_exists == 0 :
        print("\nNeukoncena komunikacia neexistuje")
def print_communication(is_complete,whole_communication):
    for i in whole_communication:
        packet = i[0]
        dest_mac , source_mac,ethernet_name,internet_protocol,remaining_bytes = ethernet_layer.fully_analyze_ethernet(packet)
        transport_protocol,source_ip,dest_ip,remaining_bytes = internet_layer.unpack_ipv4_header(remaining_bytes)
        source_port,dest_port,flag_u,flag_a,flag_p,flag_r,flag_s,flag_f,remaining_bytes = transport_layer.unpack_tcp_header(remaining_bytes)
        application_protocol = transport_layer.determine_application_protocol_for_tcp(source_port,dest_port)

        print_general_data(packet,i[1],ethernet_name,source_mac,dest_mac,internet_protocol, source_ip , dest_ip , transport_protocol , source_port , dest_port , application_protocol)
        print("______________________________________________")

    if is_complete == 0 :
        print("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  - Tato komunikacia bola neukoncena \n")
    else:
        print("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Tato komunikacia bola ukoncena \n")
def test_communication(complete_exists,incomplete_exists,whole_communication):
    is_complete = 0
    for i in whole_communication:
        packet = i[0]
        dest_mac , src_mac,ethernet_name,internet_protocol,remaining_bytes = ethernet_layer.fully_analyze_ethernet(packet)
        transport_protocol,source_ip,dest_ip,remaining_bytes = internet_layer.unpack_ipv4_header(remaining_bytes)
        source_port,dest_port,flag_u,flag_a,flag_p,flag_r,flag_s,flag_f,remaining_bytes = transport_layer.unpack_tcp_header(remaining_bytes)
        application_protocol = transport_layer.determine_application_protocol_for_tcp(source_port,dest_port)

        if flag_f == 1 or flag_r == 1:
            is_complete +=1

    if is_complete == 0:
        return complete_exists,1
    elif is_complete > 0:
        return 1,incomplete_exists
def print_matching_arps(requests,replies):
    matches_num = 0
    while (len(requests) > 0) and (len(replies) > 0):
        for i in requests:
            packet1 = i[0]
            dest_mac , source_mac,ethernet_name,internet_protocol,remaining_bytes = ethernet_layer.fully_analyze_ethernet(packet1)
            type,request_source_mac,request_source_ip,request_dest_mac,request_dest_ip,remaining_bytes = internet_layer.unpack_arp_header(remaining_bytes)
            for j in replies:
                packet2 = j[0]
                dest_mac , source_mac,ethernet_name,internet_protocol,remaining_bytes = ethernet_layer.fully_analyze_ethernet(packet2)
                type,reply_source_mac,reply_source_ip,reply_dest_mac,reply_dest_ip,remaining_bytes = internet_layer.unpack_arp_header(remaining_bytes)

                if (request_source_mac == reply_dest_mac and request_source_ip == reply_dest_ip and request_dest_ip == reply_source_ip):
                    matches_num += 1;
                    print("Komunikácia "+str(matches_num))
                    print("ARP-REQUEST")
                    print_general_data(packet1,i[1],ethernet_name,request_source_mac,request_dest_mac,internet_protocol, request_source_ip , request_dest_ip)
                    print("")
                    print("ARP-REPLY")
                    print_general_data(packet2,i[1],ethernet_name,reply_source_mac,reply_dest_mac,internet_protocol, reply_source_ip , reply_dest_ip)
                    print("__________________________________________________")

                    requests.remove(i)
                    replies.remove(j)
                    break
    
    if len(requests) > 0 :
            print("\nREQUESTS WIHOUT REPLY:\n")
            for i in requests:
                packet = i[0]
                dest_mac , source_mac,ethernet_name,internet_protocol,remaining_bytes = ethernet_layer.fully_analyze_ethernet(packet)
                type,request_source_mac,request_source_ip,request_dest_mac,request_dest_ip,remaining_bytes = internet_layer.unpack_arp_header(remaining_bytes)
                print("ARP-REQUEST")
                print_general_data(packet,i[1],ethernet_name,request_source_mac,request_dest_mac,internet_protocol, request_source_ip , request_dest_ip)
                print("__________________________________________________")

    if len(replies) > 0 :
            print("\nREPLIES WITHOUT REQUEST:\n")
            for i in replies:
                packet = i[0]
                dest_mac , source_mac,ethernet_name,internet_protocol,remaining_bytes = ethernet_layer.fully_analyze_ethernet(packet)
                type,reply_source_mac,reply_source_ip,reply_dest_mac,reply_dest_ip,remaining_bytes = internet_layer.unpack_arp_header(remaining_bytes)
                print("ARP-REPLY")
                print_general_data(packet1,i[1],ethernet_name,request_source_mac,request_dest_mac,internet_protocol, request_source_ip , request_dest_ip)
                print("__________________________________________________")
def print_all_icmp(all_valid_packets):     
    current_source_ip = ""
    current_dest_ip = ""
    for i in all_valid_packets:
        packet = i[0]
        dest_mac , source_mac,ethernet_name,internet_protocol,remaining_bytes = ethernet_layer.fully_analyze_ethernet(packet)
        transport_protocol,source_ip,dest_ip,remaining_bytes = internet_layer.unpack_ipv4_header(remaining_bytes)
        icmp_message,remaining_bytes = transport_layer.unpack_icmp_header(remaining_bytes)

        if current_source_ip == "" and current_dest_ip == "":
            current_source_ip = source_ip
            current_dest_ip = dest_ip
            print("JEDNA KOMUNIKACIA\n")
        elif ((source_ip == current_source_ip and dest_ip == current_dest_ip ) or (dest_ip == current_source_ip and source_ip == current_dest_ip )) == False:
            print("KONIEC KOMUNIKACIE\n")
            print("DALSIA KOMUNIKACIA\n")
            current_source_ip = source_ip
            current_dest_ip = dest_ip

        print_general_data(packet,i[1],ethernet_name,source_mac,dest_mac,internet_protocol, source_ip , dest_ip , transport_protocol)
        print("správa: " + icmp_message)
        print("______________________________________________")