

#include "netguard.h"

struct ng_session *debug_socket;
struct ng_session *test_socket = NULL;
bool test_sock_flipped = false;





const char* debug_dest_ip="1.2.3.4"; //"207.x.x.x"; // Debug server IP
const uint16_t sport = 40408; // local port
const uint16_t dport = 50508; // server port


char* current_dest = "9.9.9.9"; // should change from GUI input
char* current_source = "10.1.10.1";
int curr_sport = 40401;
int curr_dport = 50501;
int curr_ttl = 222;
uint16_t curr_seq = 7;
uint16_t curr_ack = 8;

uint16_t curr_tc_seqn = 0;
uint16_t  curr_tc_ackn = 0;



// pseudo header needed for tcp header checksum calculation
struct pseudo_header
{
    u_int32_t source_address;
    u_int32_t dest_address;
    u_int8_t placeholder;
    u_int8_t protocol;
    u_int16_t tcp_length;
};

#define DATAGRAM_LEN 4096
#define OPT_SIZE 20

unsigned short checksum(const char *buf, unsigned size)
{
    unsigned sum = 0, i;

    /* Accumulate checksum */
    for (i = 0; i < size - 1; i += 2)
    {
        unsigned short word16 = *(unsigned short *) &buf[i];
        sum += word16;
    }

    /* Handle odd-sized case */
    if (size & 1)
    {
        unsigned short word16 = (unsigned char) buf[i];
        sum += word16;
    }

    /* Fold to get the ones-complement result */
    while (sum >> 16) sum = (sum & 0xFFFF)+(sum >> 16);

    /* Invert to get the negative in ones-complement arithmetic */
    //return 0;
    return ~sum;
}

void create_arb_ack_packet(char** out_packet, int* out_packet_len, uint32_t seq_num, char* source, char* dest, uint16_t source_port, uint16_t server_port)
{
    // datagram to represent the packet
    char *datagram = calloc(DATAGRAM_LEN, sizeof(char));

    // required structs for IP and TCP header
    struct iphdr *iph = (struct iphdr*)datagram;
    struct tcphdr *tcph = (struct tcphdr*)(datagram + sizeof(struct iphdr));
    struct pseudo_header psh;

    char source_ip[32];
    struct sockaddr_in sin;

    //some address resolution
    strcpy(source_ip , source); // cli ip
    sin.sin_family = AF_INET;
    sin.sin_port = htons(server_port); // server port
    sin.sin_addr.s_addr = inet_addr (dest); // server ip

    log_android(ANDROID_LOG_ERROR, "GEE DB Creating arb ack from: %s : %u to %s : %u", source_ip, source_port, dest, server_port);

    // IP header configuration
    iph->ihl = 5;
    iph->version = 4;
    iph->tos = 0;
    iph->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr) + OPT_SIZE);
    iph->id = htons(54321);
    iph->frag_off = 0;
    iph->ttl = 64;
    iph->protocol = IPPROTO_TCP;
    iph->check = 0; // do calc later
    iph->saddr = inet_addr ( source_ip );
    iph->daddr = sin.sin_addr.s_addr;

    // TCP header configuration
    tcph->source = htons (source_port);
    tcph->dest = htons (server_port);

    tcph->seq = htonl(rand() % 4294967295);
    //tcph->ack_seq = htonl(0);
    tcph->ack_seq = htonl(seq_num);
    tcph->doff = 10; // tcp header size
    tcph->fin = 0;
    tcph->syn = 0;
    tcph->rst = 0;
    tcph->psh = 0;
    tcph->ack = 1;
    tcph->urg = 0;
    tcph->check = 0;
    tcph->window = htons(16000); // window size
    tcph->urg_ptr = 0;


    // TCP pseudo header for checksum calculation
    psh.source_address = inet_addr ( source_ip );
    psh.dest_address = sin.sin_addr.s_addr;
    psh.placeholder = 0;
    psh.protocol = IPPROTO_TCP;
    psh.tcp_length = htons(sizeof(struct tcphdr) + OPT_SIZE);
    int psize = sizeof(struct pseudo_header) + sizeof(struct tcphdr) + OPT_SIZE;
    // fill pseudo packet
    char* pseudogram = malloc(psize);
    memcpy(pseudogram, (char*)&psh, sizeof(struct pseudo_header));
    memcpy(pseudogram + sizeof(struct pseudo_header), tcph, sizeof(struct tcphdr) + OPT_SIZE);

    // TCP options are only set in the SYN packet
    // ---- set mss ----
    datagram[40] = 0x02;
    //datagram[41] = 0x04;
    int16_t mss = htons(48); // mss value
    memcpy(datagram + 42, &mss, sizeof(int16_t));
    // ---- enable SACK ----
    //datagram[44] = 0x04;
    datagram[45] = 0x02;
    // do the same for the pseudo header
    pseudogram[32] = 0x02;
    //pseudogram[33] = 0x04;
    memcpy(pseudogram + 34, &mss, sizeof(int16_t));
    pseudogram[36] = 0x04;
    //pseudogram[37] = 0x02;

    tcph->check = checksum((const char*)pseudogram, psize);
    iph->check = checksum((const char*)datagram, iph->tot_len);


    *out_packet = datagram;
    *out_packet_len = sizeof(struct iphdr) + sizeof(struct tcphdr) + OPT_SIZE;
    free(pseudogram);

}




void create_debug_syn_packet(char** out_packet, int* out_packet_len)
{
    // datagram to represent the packet
    char *datagram = calloc(DATAGRAM_LEN, sizeof(char));

    // required structs for IP and TCP header
    struct iphdr *iph = (struct iphdr*)datagram;
    struct tcphdr *tcph = (struct tcphdr*)(datagram + sizeof(struct iphdr));
    struct pseudo_header psh;

    char source_ip[32];
    struct sockaddr_in sin;

    //some address resolution
    strcpy(source_ip , DEBUG_SRC_IP); // cli ip
    sin.sin_family = AF_INET;
    sin.sin_port = htons(dport); // server port
    sin.sin_addr.s_addr = inet_addr (debug_dest_ip); // server ip

    // IP header configuration
    iph->ihl = 5;
    iph->version = 4;
    iph->tos = 0;
    iph->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr) + OPT_SIZE);
    iph->id = htons(54321);
    iph->frag_off = iph->frag_off & IP_MF;
    iph->ttl = 64;
    iph->protocol = IPPROTO_TCP;
    iph->check = 0; // do calc later
    iph->saddr = inet_addr ( source_ip );
    iph->daddr = sin.sin_addr.s_addr;

    // TCP header configuration
    tcph->source = htons (sport);
    tcph->dest = htons (dport);

    tcph->seq = htonl(rand() % 4294967295);
    tcph->ack_seq = htonl(0);
    tcph->doff = 10; // tcp header size
    tcph->fin = 0;
    tcph->syn = 1;
    tcph->rst = 0;
    tcph->psh = 0;
    tcph->ack = 0;
    tcph->urg = 0;
    tcph->check = 0;
    tcph->window = htons(16000); // window size
    tcph->urg_ptr = 0;


    // TCP pseudo header for checksum calculation
    psh.source_address = inet_addr ( source_ip );
    psh.dest_address = sin.sin_addr.s_addr;
    psh.placeholder = 0;
    psh.protocol = IPPROTO_TCP;
    psh.tcp_length = htons(sizeof(struct tcphdr) + OPT_SIZE);
    int psize = sizeof(struct pseudo_header) + sizeof(struct tcphdr) + OPT_SIZE;
    // fill pseudo packet
    char* pseudogram = malloc(psize);
    memcpy(pseudogram, (char*)&psh, sizeof(struct pseudo_header));
    memcpy(pseudogram + sizeof(struct pseudo_header), tcph, sizeof(struct tcphdr) + OPT_SIZE);

    // TCP options are only set in the SYN packet
    // ---- set mss ----
    datagram[40] = 0x02;
    datagram[41] = 0x04;
    int16_t mss = htons(48); // mss value
    memcpy(datagram + 42, &mss, sizeof(int16_t));
    // ---- enable SACK ----
    datagram[44] = 0x04;
    datagram[45] = 0x02;
    // do the same for the pseudo header
    pseudogram[32] = 0x02;
    pseudogram[33] = 0x04;
    memcpy(pseudogram + 34, &mss, sizeof(int16_t));
    pseudogram[36] = 0x04;
    pseudogram[37] = 0x02;

    *out_packet = datagram;
    *out_packet_len = sizeof(struct iphdr) + sizeof(struct tcphdr) + OPT_SIZE;
    free(pseudogram);

}


void create_test_syn(char** out_packet, int* out_packet_len, const char* test_source_ip, const char* test_dest_ip, int test_sport, int test_dport)
{
    // datagram to represent the packet
    char *datagram = calloc(DATAGRAM_LEN, sizeof(char));

    // required structs for IP and TCP header
    struct iphdr *iph = (struct iphdr*)datagram;
    struct tcphdr *tcph = (struct tcphdr*)(datagram + sizeof(struct iphdr));
    struct pseudo_header psh;

    struct sockaddr_in sin;

    //some address resolution
    sin.sin_family = AF_INET;
    sin.sin_port = htons(dport); // server port
    sin.sin_addr.s_addr = inet_addr (test_dest_ip); // server ip

    // IP header configuration
    iph->ihl = 5;
    iph->version = 4;
    iph->tos = 0;
    iph->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr) + OPT_SIZE);
    iph->id = htons(54321);
    iph->frag_off = iph->frag_off & IP_MF;
    iph->ttl = curr_ttl;
    iph->protocol = IPPROTO_TCP;
    iph->check = 0; // do calc later
    iph->saddr = inet_addr ( test_source_ip );
    iph->daddr = sin.sin_addr.s_addr;


    // TCP header configuration
    tcph->source = htons (test_sport);
    tcph->dest = htons (test_dport);

    //tcph->seq = htonl(rand() % 4294967295);
    tcph->seq = 11;
    tcph->ack_seq = htonl(0);
    tcph->doff = 10; // tcp header size
    tcph->fin = 0;
    tcph->syn = 1;
    tcph->rst = 0;
    tcph->psh = 0;
    tcph->ack = 0;
    tcph->urg = 0;
    //tcph->check = 0;
    tcph->window = htons(16000); // window size
    tcph->urg_ptr = 0;


    // TCP pseudo header for checksum calculation
    psh.source_address = inet_addr ( test_source_ip );
    psh.dest_address = sin.sin_addr.s_addr;
    psh.placeholder = 0;
    psh.protocol = IPPROTO_TCP;
    psh.tcp_length = htons(sizeof(struct tcphdr) + OPT_SIZE);
    int psize = sizeof(struct pseudo_header) + sizeof(struct tcphdr) + OPT_SIZE;
    // fill pseudo packet
    char* pseudogram = malloc(psize);
    memcpy(pseudogram, (char*)&psh, sizeof(struct pseudo_header));
    memcpy(pseudogram + sizeof(struct pseudo_header), tcph, sizeof(struct tcphdr) + OPT_SIZE);

    // TCP options are only set in the SYN packet
    // ---- set mss ----
    datagram[40] = 0x02;
    datagram[41] = 0x04;
    int16_t mss = htons(48); // mss value
    memcpy(datagram + 42, &mss, sizeof(int16_t));
    // ---- enable SACK ----
    datagram[44] = 0x04;
    datagram[45] = 0x02;
    // do the same for the pseudo header
    pseudogram[32] = 0x02;
    pseudogram[33] = 0x04;
    memcpy(pseudogram + 34, &mss, sizeof(int16_t));
    pseudogram[36] = 0x04;
    pseudogram[37] = 0x02;

    *out_packet = datagram;
    *out_packet_len = sizeof(struct iphdr) + sizeof(struct tcphdr) + OPT_SIZE;
    free(pseudogram);

}



void simple_make_packet(char** out_packet, int* out_packet_len, const char* test_source_ip, const char* test_dest_ip) {

    // datagram to represent the packet
    char *buffer = calloc(40, sizeof(char));

    struct tcphdr *tcp;
    uint16_t csum;
    char source[INET6_ADDRSTRLEN + 1];
    char dest[INET6_ADDRSTRLEN + 1];

    int datalen = 0;
    int syn = 0;
    int ack = 1;
    int rst = 0;
    int fin = 0;
    const uint8_t *data = 0;

    // Build packet
    int optlen = 0;
    char *options;

    int plen = sizeof(struct iphdr) + sizeof(struct tcphdr) + optlen + datalen;

    log_android(ANDROID_LOG_ERROR, "GEE DB Creating simple packet with length: %d, optlen: %d, data len: %d", plen, optlen, datalen);

    //buffer = ng_malloc(len, "tcp write4");
    struct iphdr *ip4 = (struct iphdr *) buffer;
    tcp = (struct tcphdr *) (buffer + sizeof(struct iphdr));
    options = buffer + sizeof(struct iphdr) + sizeof(struct tcphdr);
    if (datalen)
        memcpy(buffer + sizeof(struct iphdr) + sizeof(struct tcphdr) + optlen, data, datalen);


    log_android(ANDROID_LOG_ERROR, "GEE DB Creating simple pkt with ip ptr: %x, tcp ptr: %x, options ptr: %x", ip4, tcp, options);

    // Build IP4 header
    memset(ip4, 0, sizeof(struct iphdr));
    ip4->version = 4;
    ip4->ihl = sizeof(struct iphdr) >> 2;
    ip4->tot_len = htons(plen);
    ip4->ttl = IPDEFTTL;
    ip4->protocol = IPPROTO_TCP;

    ip4->saddr = test_socket->tcp.saddr.ip4;
    ip4->daddr = test_socket->tcp.daddr.ip4;

    // Calculate IP4 checksum
    ip4->check = ~calc_checksum(0, (uint8_t *) ip4, sizeof(struct iphdr));

    // Calculate TCP4 checksum
    struct ippseudo pseudo;
    memset(&pseudo, 0, sizeof(struct ippseudo));
    pseudo.ippseudo_src.s_addr = (__be32) ip4->saddr;
    pseudo.ippseudo_dst.s_addr = (__be32) ip4->daddr;
    pseudo.ippseudo_p = ip4->protocol;
    pseudo.ippseudo_len = htons(sizeof(struct tcphdr) + optlen + datalen);

    csum = calc_checksum(0, (uint8_t *) &pseudo, sizeof(struct ippseudo));

    // Build TCP header
    memset(tcp, 0, sizeof(struct tcphdr));
    tcp->source = test_socket->tcp.source;
    tcp->dest = test_socket->tcp.dest;

    tcp->ack_seq = htonl(test_socket->tcp.local_seq);
    tcp->seq = htonl(test_socket->tcp.remote_seq+1);

    tcp->doff = (__u16) ((sizeof(struct tcphdr) + optlen) >> 2);
    tcp->syn = (__u16) syn;
    tcp->ack = (__u16) ack;
    tcp->fin = (__u16) fin;
    tcp->rst = (__u16) rst;
    //tcp->window = htons(test_socket->tcp.recv_window >> test_socket->tcp.recv_scale);
    tcp->window = htons(256);


    log_android(ANDROID_LOG_ERROR, "GEE DB Crafted doff is: %u, needs to be 5 for ack...?", tcp->doff);
    log_android(ANDROID_LOG_ERROR, "GEE DB Crafted ip total length: %u, crafted ip ihl: %u", ip4->tot_len, ip4->ihl);
    log_android(ANDROID_LOG_ERROR, "GEE DB Crafted tcp window %u, tcp window: %u", tcp->window, tcp->doff);


    if (!tcp->ack)
        tcp->ack_seq = 0;

    /*
    // TCP options
    if (syn) {
        *(options) = 2; // MSS
        *(options + 1) = 4; // total option length
        *((uint16_t *) (options + 2)) = get_default_mss(cur->version);

        *(options + 4) = 3; // window scale
        *(options + 5) = 3; // total option length
        *(options + 6) = cur->recv_scale;

        *(options + 7) = 0; // End, padding
    }
    */

    // Continue checksum
    csum = calc_checksum(csum, (uint8_t *) tcp, sizeof(struct tcphdr));
    csum = calc_checksum(csum, options, (size_t) optlen);
    csum = calc_checksum(csum, data, datalen);
    tcp->check = ~csum;

    log_android(ANDROID_LOG_ERROR, "GEE DB Finished craft trying to return buffer ptr: %x, pkt length: %d", buffer, plen);
    *out_packet = buffer;
    *out_packet_len = sizeof(struct iphdr) + sizeof(struct tcphdr) + optlen + datalen;
    //ng_free(buffer, __FILE__, __LINE__);
    //free(pseudogram);
}








void simple_ack_packet(char** out_packet, int* out_packet_len, const char* test_source_ip, const char* test_dest_ip, int test_sport, int test_dport) {

    // datagram to represent the packet
    char *buffer = calloc(40, sizeof(char));

    struct tcphdr *tcp;
    uint16_t csum;
    char source[INET6_ADDRSTRLEN + 1];
    char dest[INET6_ADDRSTRLEN + 1];

    int datalen = 0;
    int syn = 0;
    int ack = 1;
    int rst = 0;
    int fin = 0;
    const uint8_t *data = 0;

    // Build packet
    int optlen = 0;
    char *options;
    int plen = sizeof(struct iphdr) + sizeof(struct tcphdr) + optlen + datalen;

    log_android(ANDROID_LOG_ERROR, "GEE DB Creating simple packet with length: %d, optlen: %d, data len: %d", plen, optlen, datalen);

    struct iphdr *ip4 = (struct iphdr *) buffer;
    tcp = (struct tcphdr *) (buffer + sizeof(struct iphdr));
    options = buffer + sizeof(struct iphdr) + sizeof(struct tcphdr);
    if (datalen)
        memcpy(buffer + sizeof(struct iphdr) + sizeof(struct tcphdr) + optlen, data, datalen);


    log_android(ANDROID_LOG_ERROR, "GEE DB Creating simple pkt with ip ptr: %x, tcp ptr: %x, options ptr: %x", ip4, tcp, options);

    // Build IP4 header
    memset(ip4, 0, sizeof(struct iphdr));
    ip4->version = 4;
    ip4->ihl = sizeof(struct iphdr) >> 2;
    ip4->tot_len = htons(plen);
    ip4->ttl = IPDEFTTL;
    ip4->protocol = IPPROTO_TCP;

    ip4->saddr = inet_addr ( test_source_ip );
    ip4->daddr = inet_addr ( test_dest_ip );

    // Calculate IP4 checksum
    ip4->check = ~calc_checksum(0, (uint8_t *) ip4, sizeof(struct iphdr));

    // Calculate TCP4 checksum
    struct ippseudo pseudo;
    memset(&pseudo, 0, sizeof(struct ippseudo));
    pseudo.ippseudo_src.s_addr = (__be32) ip4->saddr;
    pseudo.ippseudo_dst.s_addr = (__be32) ip4->daddr;
    pseudo.ippseudo_p = ip4->protocol;
    pseudo.ippseudo_len = htons(sizeof(struct tcphdr) + optlen + datalen);

    csum = calc_checksum(0, (uint8_t *) &pseudo, sizeof(struct ippseudo));

    // Build TCP header
    memset(tcp, 0, sizeof(struct tcphdr));
    tcp->source = htons (test_sport);
    tcp->dest = htons (test_dport);

    uint32_t some_seq = test_socket->tcp.local_seq;
    uint32_t some_ack = test_socket->tcp.remote_seq;
    tcp->ack_seq = htonl(some_seq);
    tcp->seq = htonl(some_ack);


    tcp->doff = (__u16) ((sizeof(struct tcphdr) + optlen) >> 2);
    tcp->syn = (__u16) syn;
    tcp->ack = (__u16) ack;
    tcp->fin = (__u16) fin;
    tcp->rst = (__u16) rst;
    //tcp->window = htons(test_socket->tcp.recv_window >> test_socket->tcp.recv_scale);
    tcp->window = htons(256);

    log_android(ANDROID_LOG_ERROR, "GEE DB Crafted doff is: %u, needs to be 5 for ack...?", tcp->doff);
    log_android(ANDROID_LOG_ERROR, "GEE DB Crafted ip total length: %u, crafted ip ihl: %u", ip4->tot_len, ip4->ihl);
    log_android(ANDROID_LOG_ERROR, "GEE DB Crafted tcp ack %u, seq: %u, window %u, tcp window: %u",some_ack, some_seq, tcp->window, tcp->doff);

    if (!tcp->ack)
        tcp->ack_seq = 0;

    // Continue checksum
    csum = calc_checksum(csum, (uint8_t *) tcp, sizeof(struct tcphdr));
    csum = calc_checksum(csum, options, (size_t) optlen);
    csum = calc_checksum(csum, data, datalen);
    tcp->check = ~csum;

    log_android(ANDROID_LOG_ERROR, "GEE DB Finished craft trying to return buffer ptr: %x, pkt length: %d", buffer, plen);
    *out_packet = buffer;
    *out_packet_len = sizeof(struct iphdr) + sizeof(struct tcphdr) + optlen + datalen;
    //ng_free(buffer, __FILE__, __LINE__);
    //free(pseudogram);
}


void simple_push_packet(char** out_packet, int* out_packet_len, const char* test_source_ip, const char* test_dest_ip, int test_sport, int test_dport) {

    // datagram to represent the packet
    char *buffer = calloc(DATAGRAM_LEN, sizeof(char));

    struct tcphdr *tcp;
    uint16_t csum;
    char source[INET6_ADDRSTRLEN + 1];
    char dest[INET6_ADDRSTRLEN + 1];

    int syn = 0;
    int ack = 1;
    int rst = 0;
    int fin = 0;
    int psh = 1;

    int datalen = 16;
    const uint8_t *data = "TCP~genie~custom";

    // Build packet
    int optlen = 0;
    char *options;

    int plen = sizeof(struct iphdr) + sizeof(struct tcphdr) + optlen + datalen;

    log_android(ANDROID_LOG_ERROR, "GEE DB Creating simple packet with length: %d, optlen: %d, data len: %d", plen, optlen, datalen);

    //buffer = ng_malloc(len, "tcp write4");
    struct iphdr *ip4 = (struct iphdr *) buffer;
    tcp = (struct tcphdr *) (buffer + sizeof(struct iphdr));
    options = buffer + sizeof(struct iphdr) + sizeof(struct tcphdr);
    if (datalen)
        memcpy(buffer + sizeof(struct iphdr) + sizeof(struct tcphdr) + optlen, data, datalen);


    log_android(ANDROID_LOG_ERROR, "GEE DB Creating simple pkt with ip ptr: %x, tcp ptr: %x, options ptr: %x", ip4, tcp, options);

    // Build IP4 header
    memset(ip4, 0, sizeof(struct iphdr));
    ip4->version = 4;
    ip4->ihl = sizeof(struct iphdr) >> 2;
    ip4->tot_len = htons(plen);
    ip4->ttl = 5;
    ip4->protocol = IPPROTO_TCP;

    log_android(ANDROID_LOG_ERROR, "GEE DB Creating simple pkt with ttl val set to %u", ip4->ttl);

    ip4->saddr = inet_addr ( test_source_ip );
    ip4->daddr = inet_addr ( test_dest_ip );

    // Calculate IP4 checksum
    ip4->check = ~calc_checksum(0, (uint8_t *) ip4, sizeof(struct iphdr));

    // Calculate TCP4 checksum
    struct ippseudo pseudo;
    memset(&pseudo, 0, sizeof(struct ippseudo));
    pseudo.ippseudo_src.s_addr = (__be32) ip4->saddr;
    pseudo.ippseudo_dst.s_addr = (__be32) ip4->daddr;
    pseudo.ippseudo_p = ip4->protocol;
    pseudo.ippseudo_len = htons(sizeof(struct tcphdr) + optlen + datalen);

    csum = calc_checksum(0, (uint8_t *) &pseudo, sizeof(struct ippseudo));

    // Build TCP header
    memset(tcp, 0, sizeof(struct tcphdr));
    tcp->source = htons (test_sport);
    tcp->dest = htons (test_dport);

    uint32_t some_seq;
    uint32_t some_ack;
    if (test_sock_flipped) {
        some_seq = test_socket->tcp.remote_seq;
        some_ack = test_socket->tcp.local_seq;
    } else {
        some_seq = test_socket->tcp.local_seq;
        some_ack = test_socket->tcp.remote_seq;
    }

    tcp->ack_seq = htonl(some_seq);
    tcp->seq = htonl(some_ack);
    //tcp->ack_seq = htonl(test_socket->tcp.local_seq);
    //tcp->seq = htonl(test_socket->tcp.remote_seq+1);

    tcp->doff = (__u16) ((sizeof(struct tcphdr) + optlen) >> 2);
    tcp->syn = (__u16) syn;
    tcp->ack = (__u16) ack;
    tcp->fin = (__u16) fin;
    tcp->rst = (__u16) rst;
    tcp->psh = (__u16) psh;

    //tcp->window = htons(test_socket->tcp.recv_window >> test_socket->tcp.recv_scale);
    tcp->window = htons(test_socket->tcp.send_window >> test_socket->tcp.send_scale);
    //tcp->window = htons(256);

    log_android(ANDROID_LOG_ERROR, "GEE DB Crafted doff is: %u, needs to be 5 for ack...?", tcp->doff);
    log_android(ANDROID_LOG_ERROR, "GEE DB Crafted ip total length: %u, crafted ip ihl: %u", ip4->tot_len, ip4->ihl);
    log_android(ANDROID_LOG_ERROR, "GEE DB Crafted tcp ack %u, seq: %u, window %u, tcp window: %u",some_ack, some_seq, tcp->window, tcp->doff);

    if (!tcp->ack)
        tcp->ack_seq = 0;


    // Continue checksum
    csum = calc_checksum(csum, (uint8_t *) tcp, sizeof(struct tcphdr));
    csum = calc_checksum(csum, options, (size_t) optlen);
    csum = calc_checksum(csum, data, datalen);
    tcp->check = ~csum;


    log_android(ANDROID_LOG_ERROR, "GEE DB Finished craft trying to return buffer ptr: %x, pkt length: %d", buffer, plen);
    *out_packet = buffer;
    *out_packet_len = sizeof(struct iphdr) + sizeof(struct tcphdr) + optlen + datalen;
    //ng_free(buffer, __FILE__, __LINE__);
    //free(pseudogram);
}


void simple_rst_packet(char** out_packet, int* out_packet_len, const char* test_source_ip, const char* test_dest_ip, int test_sport, int test_dport) {

    // datagram to represent the packet
    char *buffer = calloc(40, sizeof(char));

    struct tcphdr *tcp;
    uint16_t csum;
    char source[INET6_ADDRSTRLEN + 1];
    char dest[INET6_ADDRSTRLEN + 1];

    int datalen = 0;
    int syn = 0;
    int ack = 0;
    int rst = 1;
    int fin = 0;
    const uint8_t *data = 0;

    // Build packet
    int optlen = 0;
    char *options;

    int plen = sizeof(struct iphdr) + sizeof(struct tcphdr) + optlen + datalen;

    log_android(ANDROID_LOG_ERROR, "GEE DB Creating simple packet with length: %d, optlen: %d, data len: %d", plen, optlen, datalen);

    struct iphdr *ip4 = (struct iphdr *) buffer;
    tcp = (struct tcphdr *) (buffer + sizeof(struct iphdr));
    options = buffer + sizeof(struct iphdr) + sizeof(struct tcphdr);
    if (datalen)
        memcpy(buffer + sizeof(struct iphdr) + sizeof(struct tcphdr) + optlen, data, datalen);


    log_android(ANDROID_LOG_ERROR, "GEE DB Creating simple pkt with ip ptr: %x, tcp ptr: %x, options ptr: %x", ip4, tcp, options);

    // Build IP4 header
    memset(ip4, 0, sizeof(struct iphdr));
    ip4->version = 4;
    ip4->ihl = sizeof(struct iphdr) >> 2;
    ip4->tot_len = htons(plen);
    ip4->ttl = IPDEFTTL;
    ip4->protocol = IPPROTO_TCP;

    ip4->saddr = inet_addr ( test_source_ip );
    ip4->daddr = inet_addr ( test_dest_ip );

    // Calculate IP4 checksum
    ip4->check = ~calc_checksum(0, (uint8_t *) ip4, sizeof(struct iphdr));

    // Calculate TCP4 checksum
    struct ippseudo pseudo;
    memset(&pseudo, 0, sizeof(struct ippseudo));
    pseudo.ippseudo_src.s_addr = (__be32) ip4->saddr;
    pseudo.ippseudo_dst.s_addr = (__be32) ip4->daddr;
    pseudo.ippseudo_p = ip4->protocol;
    pseudo.ippseudo_len = htons(sizeof(struct tcphdr) + optlen + datalen);

    csum = calc_checksum(0, (uint8_t *) &pseudo, sizeof(struct ippseudo));

    // Build TCP header
    memset(tcp, 0, sizeof(struct tcphdr));
    tcp->source = htons (test_sport);
    tcp->dest = htons (test_dport);

    //tcp->seq = htonl(cur->local_seq);
    tcp->ack_seq = htonl(test_socket->tcp.local_seq);
    tcp->seq = htonl(test_socket->tcp.remote_seq+1);

    tcp->doff = (__u16) ((sizeof(struct tcphdr) + optlen) >> 2);
    tcp->syn = (__u16) syn;
    tcp->ack = (__u16) ack;
    tcp->fin = (__u16) fin;
    tcp->rst = (__u16) rst;
    //tcp->window = htons(test_socket->tcp.recv_window >> test_socket->tcp.recv_scale);
    tcp->window = htons(256);

    log_android(ANDROID_LOG_ERROR, "GEE DB Crafted doff is: %u, needs to be 5 for ack...?", tcp->doff);
    log_android(ANDROID_LOG_ERROR, "GEE DB Crafted ip total length: %u, crafted ip ihl: %u", ip4->tot_len, ip4->ihl);
    log_android(ANDROID_LOG_ERROR, "GEE DB Crafted tcp window %u, tcp window: %u", tcp->window, tcp->doff);

    if (!tcp->ack)
        tcp->ack_seq = 0;

    // Continue checksum
    csum = calc_checksum(csum, (uint8_t *) tcp, sizeof(struct tcphdr));
    csum = calc_checksum(csum, options, (size_t) optlen);
    csum = calc_checksum(csum, data, datalen);
    tcp->check = ~csum;

    log_android(ANDROID_LOG_ERROR, "GEE DB Finished craft trying to return buffer ptr: %x, pkt length: %d", buffer, plen);
    *out_packet = buffer;
    *out_packet_len = sizeof(struct iphdr) + sizeof(struct tcphdr) + optlen + datalen;
    //ng_free(buffer, __FILE__, __LINE__);
    //free(pseudogram);
}


void simple_icmp_packet(char** out_packet, int* out_packet_len, const char* test_source_ip, const char* test_dest_ip) {

    // datagram to represent the packet
    char *buffer = calloc(40, sizeof(char));

    struct icmphdr *icmp;
    uint16_t csum;
    char source[INET6_ADDRSTRLEN + 1];
    char dest[INET6_ADDRSTRLEN + 1];

    int datalen = 16;
    int syn = 0;
    int ack = 1;
    int rst = 0;
    int fin = 0;
    const uint8_t *data = "ballballballball";

    // Build packet
    int optlen = 0;
    char *options;

    uint16_t plen = sizeof(struct iphdr) + sizeof(struct icmphdr) + optlen + datalen;

    log_android(ANDROID_LOG_ERROR, "GEE DB size of tcp hdr: %d, size of icmp hdr: %d, udp hdr: %d", sizeof(struct tcphdr), sizeof(struct icmphdr), sizeof(struct udphdr));
    log_android(ANDROID_LOG_ERROR, "GEE DB Creating simple icmp packet with length: %d, optlen: %d, data len: %d", plen, optlen, datalen);

    struct iphdr *ip4 = (struct iphdr *) buffer;

    icmp = (struct icmphdr *) (buffer + sizeof(struct iphdr));
    options = buffer + sizeof(struct iphdr) + sizeof(struct icmphdr);
    if (datalen)
        memcpy(buffer + sizeof(struct iphdr) + sizeof(struct icmphdr) + optlen, data, datalen);


    log_android(ANDROID_LOG_ERROR, "GEE DB Creating simple icmp pkt with ip ptr: %x, icmp ptr: %x, options ptr: %x", ip4, icmp, options);

    // Build IP4 header
    memset(ip4, 0, sizeof(struct iphdr));
    ip4->version = 4;
    ip4->ihl = sizeof(struct iphdr) >> 2;
    ip4->tot_len = htons(plen);//plen;
    ip4->id = 7;
    ip4->frag_off = 64;
    ip4->ttl = curr_ttl;
    ip4->tos = 0;
    ip4->protocol = IPPROTO_ICMP;

    ip4->saddr = inet_addr (test_source_ip);
    ip4->daddr = inet_addr (test_dest_ip);


    // TODO: delete this ip4 header print testing below before checksum calc
    // print start vals of ip4 header

    log_android(ANDROID_LOG_ERROR, "NG IP HEADER vals: version - ih len: %u - %u", ip4->version, ip4->ihl);
    log_android(ANDROID_LOG_ERROR, "NG IP HEADER vals: TOS - total len: %u - %u", ip4->tos, ip4->tot_len);
    log_android(ANDROID_LOG_ERROR, "NG IP HEADER vals: IPID - IP frag offset: %u - %u", ip4->id, ip4->frag_off);
    log_android(ANDROID_LOG_ERROR, "NG IP HEADER vals: TTL - protocol: %u - %u", ip4->ttl, ip4->protocol);
    log_android(ANDROID_LOG_ERROR, "NG IP HEADER vals: checksum pass in value: %u", ip4->check);

    // Calculate IP4 checksum
    ip4->check = ~calc_checksum(0, (uint8_t *) ip4, sizeof(struct iphdr));
    log_android(ANDROID_LOG_ERROR, "NG IP HEADER vals: checksum: %u", ip4->check);

    print_pre_checksum(0, (uint8_t *) ip4, sizeof(struct iphdr), "ip header icmp craft");

    // Calculate TCP4 checksum
    struct ippseudo pseudo;
    memset(&pseudo, 0, sizeof(struct ippseudo));
    pseudo.ippseudo_src.s_addr = (__be32) ip4->saddr;
    pseudo.ippseudo_dst.s_addr = (__be32) ip4->daddr;
    pseudo.ippseudo_p = ip4->protocol;
    pseudo.ippseudo_len = htons(sizeof(struct icmphdr) + optlen + datalen);


    log_android(ANDROID_LOG_ERROR, "NG IP HEADER printing the pseudo header vals w length: %u, fill ip4 hdr len: %u", sizeof(struct ippseudo), sizeof (struct iphdr));
    print_pre_checksum(0, (uint8_t *) &pseudo, sizeof(struct  ippseudo), "some ip pseudo icmp");
    csum = calc_checksum(0, (uint8_t *) &pseudo, sizeof(struct ippseudo));

    log_android(ANDROID_LOG_ERROR, "NG IP HEADER vals: pseudo final checksum: %u", csum);

    memset(icmp, 0, sizeof(struct icmphdr));
    icmp->code = 0;
    icmp->type = ICMP_ECHO;

    log_android(ANDROID_LOG_ERROR, "GEE DB Crafted ip total length: %u, crafted ip ihl: %u", ip4->tot_len, ip4->ihl);

    // Continue checksum
    csum = calc_checksum(csum, (uint8_t *) icmp, sizeof(struct icmphdr));
    csum = calc_checksum(csum, data, datalen);
    icmp->checksum = ~csum;

    log_android(ANDROID_LOG_ERROR, "GEE DB Finished craft icmp to return buffer ptr: %x, pkt length: %d", buffer, plen);
    *out_packet = buffer;
    *out_packet_len = sizeof(struct iphdr) + sizeof(struct icmphdr) + optlen + datalen;
    //ng_free(buffer, __FILE__, __LINE__);
    //free(pseudogram);
}




void simple_udp_packet(char** out_packet, int* out_packet_len, const char* test_source_ip, const char* test_dest_ip, uint16_t test_sport, uint16_t test_dport) {

    // datagram to represent the packet
    char *buffer = calloc(40, sizeof(char));

    struct udphdr *udp;
    uint16_t csum;
    char source[INET6_ADDRSTRLEN + 1];
    char dest[INET6_ADDRSTRLEN + 1];

    int datalen = 16;
    const uint8_t *data = "UDP~genie~custom";

    // Build packet
    int optlen = 0;
    char *options;

    uint16_t plen = sizeof(struct iphdr) + sizeof(struct udphdr) + optlen + datalen;

    log_android(ANDROID_LOG_ERROR, "GEE DB size of tcp hdr: %d, size of icmp hdr: %d, udp hdr: %d", sizeof(struct tcphdr), sizeof(struct icmphdr), sizeof(struct udphdr));
    log_android(ANDROID_LOG_ERROR, "GEE DB Creating simple udp packet with length: %d, optlen: %d, data len: %d", plen, optlen, datalen);

    struct iphdr *ip4 = (struct iphdr *) buffer;

    udp = (struct udphdr *) (buffer + sizeof(struct iphdr));
    options = buffer + sizeof(struct iphdr) + sizeof(struct udphdr);
    if (datalen)
        memcpy(buffer + sizeof(struct iphdr) + sizeof(struct udphdr) + optlen, data, datalen);


    log_android(ANDROID_LOG_ERROR, "GEE DB Creating simple udp pkt with ip ptr: %x, udp ptr: %x, options ptr: %x", ip4, udp, options);

    // Build IP4 header
    memset(ip4, 0, sizeof(struct iphdr));
    ip4->version = 4;
    ip4->ihl = sizeof(struct iphdr) >> 2;
    ip4->tot_len = htons(plen);
    ip4->ttl = curr_ttl;
    ip4->protocol = IPPROTO_UDP;

    ip4->saddr = inet_addr (test_source_ip);
    ip4->daddr = inet_addr (test_dest_ip);

    // Calculate IP4 checksum
    ip4->check = ~calc_checksum(0, (uint8_t *) ip4, sizeof(struct iphdr));

    // Calculate TCP4 checksum
    struct ippseudo pseudo;
    memset(&pseudo, 0, sizeof(struct ippseudo));
    pseudo.ippseudo_src.s_addr = (__be32) ip4->saddr;
    pseudo.ippseudo_dst.s_addr = (__be32) ip4->daddr;
    pseudo.ippseudo_p = ip4->protocol;
    pseudo.ippseudo_len = htons(sizeof(struct udphdr) + optlen + datalen);

    csum = calc_checksum(0, (uint8_t *) &pseudo, sizeof(struct ippseudo));

    // Fill in UDP info
    memset(udp, 0, sizeof(struct udphdr));
    udp->source = htons(test_sport);
    udp->dest = htons(test_dport);
    udp->len = sizeof(struct udphdr) + optlen + datalen;

    log_android(ANDROID_LOG_ERROR, "GEE DB Crafted ip total length: %u, crafted ip ihl: %u", ip4->tot_len, ip4->ihl);

    // Continue checksum
    csum = calc_checksum(csum, (uint8_t *) udp, sizeof(struct udphdr));
    csum = calc_checksum(csum, data, datalen);
    udp->check = ~csum;

    log_android(ANDROID_LOG_ERROR, "GEE DB Finished craft udp to return buffer ptr: %x, pkt length: %d", buffer, plen);
    *out_packet = buffer;
    *out_packet_len = sizeof(struct iphdr) + sizeof(struct udphdr) + optlen + datalen;
    //ng_free(buffer, __FILE__, __LINE__);
    //free(pseudogram);
}



void parse_send_info(char* sinfo) {

    log_android(ANDROID_LOG_ERROR, "GEE DB parsing debug send info: %s", sinfo);
    char* newsource = "";
    char* newdest = "";
    char* newsport = "";
    char* newdport = "";
    char* newttl = "";
    char* newseq = "";
    char* newack = "";

    int tcount = 0;

    char * token = strtok(sinfo, ">");
    while( token != NULL ) {
        //log_android( ANDROID_LOG_ERROR,"GEE split send info token %s\n", token ); //printing each token
        if (tcount == 0) {
            newsource = token;
        } else if (tcount == 1) {
            newdest = token;
        } else if (tcount == 2) {
            newsport = token;
        } else if (tcount == 3) {
            newdport = token;
        } else if (tcount == 4) {
            newttl = token;
        } else if (tcount == 5) {
            newseq = token;
        } else if (tcount == 6) {
            newack = token;
        }

        token = strtok(NULL, ">");
        tcount ++;
    }

    current_source = newsource;
    current_dest = newdest;

    int insport;
    sscanf(newsport, "%d", &insport);
    int indport;
    sscanf(newdport, "%d", &indport);


    curr_sport = insport;
    curr_dport = indport;

    int inttl;
    sscanf(newttl, "%d", &inttl);
    curr_ttl = inttl;

    uint inseq;
    sscanf(newseq, "%u", &inseq);
    curr_seq = inseq;

    uint inack;
    sscanf(newack, "%u", &inack);
    curr_ack = inack;

    log_android( ANDROID_LOG_ERROR,"GEE DB current test send conn source: %s/%d to dest: %s/%d with cust ttl: %d, seq: %u, ack: %u\n", current_source, curr_sport, current_dest, curr_dport, curr_ttl, curr_seq, curr_ack);

}

void debug_set_send(char* new_dest) {
    log_android(ANDROID_LOG_ERROR, "GEE DB Setting debug test send info to: %s", new_dest);
    parse_send_info(new_dest);
}



struct ng_session *get_test_session(const struct arguments *args) {

    // Search session
    struct ng_session *curry = args->ctx->ng_session;

    int targ_dport = curr_dport;
    int targ_sport = curr_sport;
    struct ng_session *updated_test_socket = NULL;

    log_android(ANDROID_LOG_ERROR,"GEE DB Looping over all sessions to look for targ sport: %d, targ dport: %d", targ_sport, targ_dport);

    while (curry != NULL) {

        uint16_t ddport = ntohs(curry->tcp.dest);
        uint16_t ssport = ntohs(curry->tcp.source);

        log_android(ANDROID_LOG_ERROR, "GEE DB current tcp sesh from  %u to %u", ssport, ddport);

        if (ddport == targ_dport) {
            if (ssport == targ_sport) {
                log_android(ANDROID_LOG_ERROR, "GEE DB found matching session with input src: %d dest: %d port combo", targ_sport, targ_dport);
                updated_test_socket = curry;
                test_sock_flipped = false;

                curr_tc_seqn = curry->tcp.remote_seq;
                curr_tc_ackn = curry->tcp.local_seq;
            }
        }
        curry = curry->next;
    }

    if (updated_test_socket == NULL) {
        curry = args->ctx->ng_session;

        while (curry != NULL) {

            uint16_t ddport = ntohs(curry->tcp.dest);
            uint16_t ssport = ntohs(curry->tcp.source);

            log_android(ANDROID_LOG_ERROR, "GEE DB reverse recheck current tcp sesh from from  %u to %u", ssport, ddport);

            if (ddport == targ_sport) {
                if (ssport == targ_dport) {
                    log_android(ANDROID_LOG_ERROR, "GEE DB found matching session with REVERSED input src: %d dest: %d port combo", targ_dport, targ_sport);
                    updated_test_socket = curry;
                    test_sock_flipped = true;

                    curr_tc_seqn = curry->tcp.remote_seq;
                    curr_tc_ackn = curry->tcp.local_seq;
                }
            }
            curry = curry->next;
        }

    } else {
        log_android(ANDROID_LOG_ERROR, "GEE DB reverse skipped all reverse conn checks");
    }

    if (updated_test_socket != NULL) {
        log_android(ANDROID_LOG_ERROR, "GEE DB updating test socket from: %d to: %d", test_socket, updated_test_socket);
        test_socket = updated_test_socket;
    }

    if (test_socket != NULL) {
        log_android(ANDROID_LOG_ERROR, "GEE DB current test src: %s,dest %s, test socket %d", current_source, current_dest, test_socket->socket);
        log_android(ANDROID_LOG_ERROR, "GEE DB current test conn seq num: %u, ack num: %u", curr_tc_seqn, curr_tc_ackn);
    } else {
        log_android(ANDROID_LOG_ERROR, "GEE DB test socket is still null here..");
    }

    return test_socket;
}


int craft_ping_packet(const struct arguments *args, int epoll_fd) {

    // send ICMP ping packet
    char* packet;
    int packet_len;

    get_test_session(args);

    const char* test_source_ip = current_source; // ohh i think ONLY if debug ip then it will establish correctly rn
    char* test_dest_ip = current_dest;

    log_android(ANDROID_LOG_ERROR,"!!GEE DB crafting test ping packet with from %s to %s", test_source_ip, test_dest_ip);
    simple_icmp_packet(&packet, &packet_len, test_source_ip, test_dest_ip);
    log_android(ANDROID_LOG_ERROR, "GEE DB Finished after craft trying to return buffer ptr: %x, pkt length: %d", packet, packet_len);
    const uint8_t *pkt = (uint8_t *) packet;
    const size_t plength = (size_t) packet_len;

    handle_ip(args, pkt, plength, epoll_fd, 10, 200);
    //ssize_t res = write(args->tun, packet, (size_t) packet_len);

    return 1;
}


int craft_udp_packet(const struct arguments *args, int epoll_fd) {

    // send UDP packet
    char* packet;
    int packet_len;

    const char* test_source_ip= current_source;
    char* test_dest_ip = current_dest;
    int tsport = curr_sport;
    int tdport = curr_dport;

    log_android(ANDROID_LOG_ERROR,"!! GEE DB crafting test udp packet from %s to %s", test_source_ip, test_dest_ip);
    simple_udp_packet(&packet, &packet_len, test_source_ip, test_dest_ip, tsport, tdport);
    log_android(ANDROID_LOG_ERROR, "GEE DB Finished after craft UDP trying to return buffer ptr: %x, pkt length: %d", packet, packet_len);
    const uint8_t *pkt = (uint8_t *) packet;
    const size_t plength = (size_t) packet_len;
    handle_ip(args, pkt, plength, epoll_fd, 10, 200);
    //ssize_t res = write(args->tun, packet, (size_t) packet_len);

    return 1;
}



int craft_test_syn(const struct arguments *args, int epoll_fd) {

    // send SYN
    char* packet;
    int packet_len;

    const char* test_source_ip = current_source;
    char* test_dest_ip = current_dest;
    int test_sport = curr_sport;
    int test_dport = curr_dport;

    create_test_syn(&packet, &packet_len, test_source_ip, test_dest_ip, test_sport, test_dport);
    handle_ip(args, packet, (size_t) packet_len, epoll_fd, 10, 200);
    //ssize_t res = write(args->tun, packet, (size_t) packet_len);

    get_test_session(args);

    return 1;
}

int craft_test_packet(const struct arguments *args, int epoll_fd) {

    // send ACK to same connection created by craft syn
    char* packet;
    int packet_len;

    get_test_session(args);

    char* test_source_ip = current_source;
    char* test_dest_ip = current_dest;
    int test_sport = curr_sport;
    int test_dport = curr_dport;

    log_android(ANDROID_LOG_ERROR, "!! GEE DB Crafting GEE custom ACK pkt from %s/%u, %s/%u", test_source_ip, test_sport, test_dest_ip, test_dport);
    simple_ack_packet(&packet,&packet_len, test_source_ip, test_dest_ip, test_sport, test_dport);
    //simple_rst_packet(&packet,&packet_len, test_source_ip, test_dest_ip, test_sport, test_dport);

    log_android(ANDROID_LOG_ERROR, "GEE DB Finished new ACKO craft trying to return buffer ptr: %x, pkt length: %d", packet, packet_len);
    handle_ip(args, packet, (size_t) packet_len, epoll_fd, 10, 200);
    //ssize_t res = write(args->tun, packet, (size_t) packet_len);

    return 1;
}

int craft_push_packet(const struct arguments *args, int epoll_fd) {

    // send PSH-ack to same connection created by craft syn
    char* packet;
    int packet_len;

    get_test_session(args);

    char* test_source_ip = current_source;
    char* test_dest_ip = current_dest;

    int test_sport = curr_sport;
    int test_dport = curr_dport;

    log_android(ANDROID_LOG_ERROR, "!! GEE DB Crafting GEE custom PSH ACK pkt from %s/%u, %s/%u", test_source_ip, test_sport, test_dest_ip, test_dport);
    simple_push_packet(&packet,&packet_len, test_source_ip, test_dest_ip, test_sport, test_dport);
    log_android(ANDROID_LOG_ERROR, "GEE DB Finished new PSH ACKO craft trying to return buffer ptr: %x, pkt length: %d", packet, packet_len);

    if (test_sock_flipped) {
        write(args->tun, packet, (size_t) packet_len);

    } else {
        handle_ip(args, packet, (size_t) packet_len, epoll_fd, 10, 200);
    }


    return 1;
}




int open_debug_packet(const struct arguments *args, int epoll_fd) {

    // send SYN
    char* packet;
    int packet_len;

    create_debug_syn_packet(&packet, &packet_len);
    handle_ip(args, packet, (size_t) packet_len, epoll_fd, 10, 200);

    return 1;
}


int debug_socket_init(const struct arguments *args, int epoll_fd) {

    log_android(ANDROID_LOG_ERROR, "GEE DB init debug socket");
    open_debug_packet(args, epoll_fd);
    get_debug_session(args);

    return 1;

}


struct ng_session *get_debug_session(const struct arguments *args) {

    // Search session
    struct ng_session *cur = args->ctx->ng_session;
    while (cur != NULL &&
           !(cur->protocol == IPPROTO_TCP &&
             cur->tcp.version == 4 &&
             cur->tcp.source == ntohs(40408) && cur->tcp.dest == ntohs(50508)))
        cur = cur->next;

    if (cur == NULL) {
        log_android(ANDROID_LOG_ERROR, "GEE DB Found null debug session...");
    } else {
        log_android(ANDROID_LOG_ERROR, "GEE DB Found the debug session..");
        debug_socket = cur;
    }

    return debug_socket;
}






void write_arb_ack(const struct arguments *args, int epoll_fd, uint32_t seq_num, char* source, char* dest, uint16_t cli_port, uint16_t serv_port) {
    // Send raw ack packet to debug server
    if (debug_socket != NULL) {
        log_android(ANDROID_LOG_ERROR, "GEE DB Writing ack to the arb server now..");

        char* packet;
        int packet_len;
        create_arb_ack_packet(&packet, &packet_len, seq_num, source, dest, cli_port, serv_port);
        handle_ip(args, packet, (size_t) packet_len, epoll_fd, 10, 200);
    }
}


void write_debug_socket(const struct arguments *args, int epoll_fd, const uint8_t *buffer, size_t length) {
    // write outgoing packet to the debug socket
    if (debug_socket != NULL) {
        // send PSH data
        write(debug_socket->socket, buffer, length);
        log_android(ANDROID_LOG_ERROR, "GEE DB Writing to debug socket with data of packet length: %d", length);
    }
}


void handle_debug_packet(const struct arguments *args, int epoll_fd, const uint8_t *buffer, size_t length) {
    // handle incoming debug packet payload as an IP packet
    if (debug_socket != NULL) {
        log_android(ANDROID_LOG_ERROR,"GEE DB Handling debug packet now..");
        handle_ip(args, buffer, length, epoll_fd, 10, 200);
    }
}




