#include "capthread.h"
#include <QDateTime>
#include <QDebug>

CapThread::CapThread(struct pcap *pcap, QObject *parent) : QThread(parent), pcap(pcap) {
    connect(this, &QThread::finished, this, &QThread::deleteLater);
}

void CapThread::run() {
    pcap_pkthdr *header;
    const u_char *pkt_data;

//    qDebug("The program is working......\n");
//    qDebug("The capture file is saving as 'data.txt'\n");
//    qDebug("You can input 'ctrl + C' to stop the program\n");
    int res;
    while((res = pcap_next_ex(pcap, &header, &pkt_data)) >= 0) {
        if (res == 0) continue; //超时
        packet.time = QDateTime::fromSecsSinceEpoch(header->ts.tv_sec).toString("yy-MM-dd HH:mm:ss.")+QString::number(header->ts.tv_usec);
        packet.len = header->len;
        //输出编号、时间戳和包长度
        qDebug("=======================\n");
        qDebug()<<packet.time<<" len:"<<header->caplen<<"/"<<header->len;
        QString data_str;
        char line[LINE_LEN + 1];
        int l = 0;
        for(uint i=0; i < header->caplen; i++) {
            data_str.append(QString::asprintf("%.2x ", pkt_data[i]));
            if(i > 13) {
                if(isgraph(pkt_data[i]) || pkt_data[i] == ' ') line[l] = pkt_data[i];
                else line[l] = '.';
                if(l==15) {
                    line[16] = '\0';
                    data_str.append("      ");
                    data_str.append(line);
                    data_str.append("\n");
                    memset(line, 0, LINE_LEN);
                    l = 0;
                } else l++;
            } else if(i == 13) {
                data_str.append("\n");
            }
        }
        packet.data = data_str;
        qDebug()<<packet.data.toUtf8().constData();

        //分析数据包
        //ethernet_protocol_packet_handle(NULL, header, pkt_data);

        //packet_list->append(packet);
        //emit newPacket();
    }
    qDebug("Error reading the packets: %s\n", pcap_geterr(pcap));

}

// TCP协议处理
//u_short sport;
//u_short dport;
//u_int sequence;			// 序列码
//u_int ack;				// 回复码
//u_char hdrLen;			// 首部长度保留字
//u_char flags;				// 标志
//u_short windows;			// 窗口大小
//u_short checksum;			// 校验和
//u_short urgent_pointer;	// 紧急指针
void CapThread::tcp_protocol_packet_handle(u_char *arg, const struct pcap_pkthdr *pkt_header, const u_char *pkt_content) {
    packet.tcp_header = *(TcpHeader*) (pkt_content + 14 + 20);
//    qDebug("===================TCP Protocol=================\n");

//    qDebug("Source Port: %i\n", ntohs(tcp_protocol->sport));
//    qDebug("Destination Port: %i\n", ntohs(tcp_protocol->dport));
//    qDebug("Sequence number: %d\n", ntohl(tcp_protocol->sequence));
//    qDebug("Acknowledgment number: %d\n", ntohl(tcp_protocol->ack));
//    qDebug("Header Length: %d\n", (tcp_protocol->hdrLen >> 4) * 4);
//    qDebug("Flags: 0x%.3x ", tcp_protocol->flags);
//    if (tcp_protocol->flags & 0x08) qDebug("(PSH)");
//    if (tcp_protocol->flags & 0x10) qDebug("(ACK)");
//    if (tcp_protocol->flags & 0x02) qDebug("(SYN)");
//    if (tcp_protocol->flags & 0x20) qDebug("(URG)");
//    if (tcp_protocol->flags & 0x01) qDebug("(FIN)");
//    if (tcp_protocol->flags & 0x04) qDebug("(RST)");
//    qDebug("\n");
//    qDebug("Windows Size: %i\n", ntohs(tcp_protocol->windows));
//    qDebug("Checksum: 0x%.4x\n", ntohs(tcp_protocol->checksum));
//    qDebug("Urgent Pointer: %i\n", ntohs(tcp_protocol->urgent_pointer));
}

// UDP协议处理
//u_short sport;			// 源端口
//u_short dport;			// 目标端口
//u_short datalen;			// UDP数据长度
//u_short checksum;			// 校验和
void CapThread::udp_protocol_packet_handle(u_char *arg, const struct pcap_pkthdr *pkt_header, const u_char *pkt_content) {
    packet.udp_header = *(UdpHeader*)(pkt_content + 14 + 20);
//    qDebug("===================UDP Protocol=================\n");
//    qDebug("Source Port: %i\n", ntohs(udp_protocol->sport));
//    qDebug("Destination Port: %i\n", ntohs(udp_protocol->dport));
//    qDebug("Datalen: %i\n", ntohs(udp_protocol->datalen));
//    qDebug("Checksum: 0x%.4x\n", ntohs(udp_protocol->checksum));
}

// ICMP协议处理
//u_char type;				// ICMP类型
//u_char code;				// 代码
//u_short checksum;			// 校验和
//u_short identification;	// 标识
//u_short sequence;			// 序列号
//u_long timestamp;			// 时间戳
void CapThread::icmp_protocol_packet_handle(u_char *arg, const struct pcap_pkthdr *pkt_header, const u_char *pkt_content) {
    packet.icmp_header = *(IcmpHeader*)(pkt_content + 14 + 20);
//    qDebug("==================ICMP Protocol=================\n");
//    qDebug("Type: %d ", icmp_protocol->type);
//    switch (icmp_protocol->type)
//    {
//    case 8:
//        qDebug("(request)\n");
//        break;
//    case 0:
//        qDebug("(reply)\n");
//        break;
//    default:
//        qDebug("\n");
//        break;
//    }
//    qDebug("Code: %d\n", icmp_protocol->code);
//    qDebug("CheckSum: 0x%.4x\n", ntohs(icmp_protocol->checksum));
//    qDebug("Identification: 0x%.4x\n", ntohs(icmp_protocol->identification));
//    qDebug("Sequence: 0x%.4x\n", ntohs(icmp_protocol->sequence));
}

// ARP协议处理
//u_short hardware_type;					// 格式化的硬件地址
//u_short protocol_type;					// 协议地址格式
//u_char hardware_length;					// 硬件地址长度
//u_char protocol_length;					// 协议地址长度
//u_short operation_code;					// 操作码
//u_char source_ethernet_address[6];		// 发送者硬件地址
//u_char source_ip_address[4];				// 发送者协议地址
//u_char destination_ethernet_address[6];	// 目的方硬件地址
//u_char destination_ip_address[4];			// 目的方协议地址
void CapThread::arp_protocol_packet_handle(u_char *arg, const struct pcap_pkthdr *pkt_header, const u_char *pkt_content) {
    packet.arp_header = *(ArpHeader*)(pkt_content + 14);
//    qDebug("==================ARP Protocol==================\n");
//    qDebug("Hardware Type: ");
//    switch (ntohs(arp_protocol->hardware_type))
//    {
//    case 1:
//        qDebug("Ethernet");
//        break;
//    default:
//        break;
//    }
//    qDebug(" (%d)\n", ntohs(arp_protocol->hardware_type));
//    qDebug("Protocol Type: \n");
//    switch (ntohs(arp_protocol->protocol_type))
//    {
//    case 0x0800:
//        qDebug("%s", "IP");
//        break;
//    case 0x0806:
//        qDebug("%s", "ARP");
//        break;
//    case 0x0835:
//        qDebug("%s", "RARP");
//        break;
//    default:
//        qDebug("%s", "Unknown Protocol");
//        break;
//    }
//    qDebug(" (0x%04x)\n", ntohs(arp_protocol->protocol_type));
//    qDebug("Hardware Length: %d\n", arp_protocol->hardware_length);
//    qDebug("Protocol Length: %d\n", arp_protocol->protocol_length);
//    qDebug("Operation Code: ");
//    switch (ntohs(arp_protocol->operation_code))
//    {
//    case 1:
//        qDebug("request");
//        break;
//    case 2:
//        qDebug("reply");
//        break;
//    default:
//        break;
//    }
//    qDebug(" (%i)\n", ntohs(arp_protocol->operation_code));
}

// IP协议处理
//u_char version_hlen;		// 首部长度 版本
//u_char tos;				// 服务质量
//u_short tlen;				// 总长度
//u_short identification;	// 身份识别
//u_short flags_offset;		// 标识 分组偏移
//u_char ttl;				// 生命周期
//u_char proto;				// 协议类型
//u_short checksum;			// 包头测验码
//u_int saddr;				// 源IP地址
//u_int daddr;				// 目的IP地址
void CapThread::ip_protocol_packet_handle(u_char *arg, const struct pcap_pkthdr *pkt_header, const u_char *pkt_content) {
    sockaddr_in source, dest;
    char sourceIP[MAX_ADDR_LEN], destIP[MAX_ADDR_LEN];

    auto ip_protocol = (IpHeader*)(pkt_content + 14);
    source.sin_addr.s_addr = ip_protocol->saddr;
    dest.sin_addr.s_addr = ip_protocol->daddr;
    strncpy(sourceIP, inet_ntoa(source.sin_addr), MAX_ADDR_LEN);
    strncpy(destIP, inet_ntoa(dest.sin_addr), MAX_ADDR_LEN);

    packet.ip_header = *ip_protocol;

//    qDebug("===================IP Protocol==================\n");
//    qDebug("Version: %d\n", ip_protocol->version_hlen >> 4);
//    qDebug("Header Length: %d bytes\n", (ip_protocol->version_hlen & 0x0f) * 4);
//    qDebug("Tos: %d\n", ip_protocol->tos);
//    qDebug("Total Length: %d\n", ntohs(ip_protocol->tlen));
//    qDebug("Identification: 0x%.4x (%i)\n", ntohs(ip_protocol->identification), ntohs(ip_protocol->identification));
//    qDebug("Flags: %d\n", ntohs(ip_protocol->flags_offset) >> 13);
//    qDebug("---Reserved bit: %d\n", (ntohs(ip_protocol->flags_offset) & 0x8000) >> 15);
//    qDebug("---Don't fragment: %d\n", (ntohs(ip_protocol->flags_offset) & 0x4000) >> 14);
//    qDebug("---More fragment: %d\n", (ntohs(ip_protocol->flags_offset) & 0x2000) >> 13);
//    qDebug("Fragment offset: %d\n", ntohs(ip_protocol->flags_offset) & 0x1fff);
//    qDebug("Time to live: %d\n", ip_protocol->ttl);
//    qDebug("Protocol Type: ");
    switch (ip_protocol->proto)
    {
    case 1:
//        qDebug("ICMP");
        packet.protocol = "ICMP";
        break;
    case 6:
//        qDebug("TCP");
        packet.protocol = "TCP";
        break;
    case 17:
//        qDebug("UDP");
        packet.protocol = "UDP";
        break;
    default:
        break;
    }
//    qDebug(" (%d)\n", ip_protocol->proto);
//    qDebug("Header checkSum: 0x%.4x\n", ntohs(ip_protocol->checksum));
//    qDebug("Source: %s\n", sourceIP);
//    qDebug("Destination: %s\n", destIP);

    if (ip_protocol->proto == htons(0x0600))
        tcp_protocol_packet_handle(arg, pkt_header, pkt_content);
    else if (ip_protocol->proto == htons(0x1100))
        udp_protocol_packet_handle(arg, pkt_header, pkt_content);
    else if (ip_protocol->proto == htons(0x0100))
        icmp_protocol_packet_handle(arg, pkt_header, pkt_content);
}
// Ethernet协议处理
void CapThread::ethernet_protocol_packet_handle(u_char *arg, const struct pcap_pkthdr *pkt_header, const u_char *pkt_content) {
    packet.ether_header = *(EtherHeader*)pkt_content;
    u_short ethernet_type;			//以太网类型
    u_char *mac_string;				//以太网地址
                                    //获取以太网数据内容
    ethernet_type = ntohs(packet.ether_header.ether_type);

//    qDebug("==============Ethernet Protocol=================\n");

//    //以太网目标地址
//    mac_string = ethernet_protocol->ether_dhost;

//    qDebug("Destination Mac Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
//        *mac_string,
//        *(mac_string + 1),
//        *(mac_string + 2),
//        *(mac_string + 3),
//        *(mac_string + 4),
//        *(mac_string + 5));

//    //以太网源地址
//    mac_string = ethernet_protocol->ether_shost;

//    qDebug("Source Mac Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
//        *mac_string,
//        *(mac_string + 1),
//        *(mac_string + 2),
//        *(mac_string + 3),
//        *(mac_string + 4),
//        *(mac_string + 5));

//    qDebug("Ethernet type: ");
    switch (ethernet_type)
    {
    case 0x0800:
//        qDebug("%s", "IP");
        break;
    case 0x0806:
//        qDebug("%s", "ARP");
        packet.protocol = "ARP";
        break;
    case 0x0835:
//        qDebug("%s", "RARP");
//        packet_data.setRarp_flag(true);
        break;
    default:
//        qDebug("%s", "Unknown Protocol");
        packet.protocol = "Unknown Protocol";
        break;
    }
//    qDebug(" (0x%04x)\n", ethernet_type);

    switch (ethernet_type)
    {
    case 0x0800:
        ip_protocol_packet_handle(arg, pkt_header, pkt_content);
        break;
    case 0x0806:
        arp_protocol_packet_handle(arg, pkt_header, pkt_content);
        break;
//    case 0x0835:
//        qDebug("==============RARP Protocol=================\n");
//        qDebug("RARP\n");
//        break;
//    default:
//        qDebug("==============Unknown Protocol==============\n");
//        qDebug("Unknown Protocol\n");
//        break;
    }
}
