// File: /workspace/github_cpp_makefile_star2_O2/maclellant[P]ReliableGoBackN/client.cpp
// Function: main
int main(int argc, char** argv)
{
    if(argc != 6) {
        std::cout << "Usage: " << argv[0] << " ";
        std::cout << "<client-port> <server-IP> <server-port> <func> <filename> \n";
        exit(EXIT_FAILURE);
    }

    unsigned short client_port = (unsigned short) strtoul(argv[1], NULL, 0);
    unsigned short server_port = (unsigned short) strtoul(argv[3], NULL, 0);
    char* type = argv[4];
    char* filename = argv[5];

    int sockfd;
    uint8_t packet_type = 255;
    struct sockaddr_in server;
    struct sockaddr_in client;
    socklen_t slen = sizeof(server);

    // Parse the given server IP address
    if(inet_aton(argv[2], &server.sin_addr) == 0)
    {
        std::cerr << "Error: Given IP address not valid: " << argv[2] << std::endl;
        exit(EXIT_FAILURE);
    }

    // Parse the function code
    else if (!strcmp(type, "GET"))
        packet_type = GET;

    if (packet_type == 255)
    {
        std::cerr << "Error: Given function command not valid: " << type << std::endl;
        std::cerr << "Please use GET" << std::endl;
        exit(EXIT_FAILURE);
    }

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        std::cerr << "Error: Could not create client socket.\n\n";
        exit(EXIT_FAILURE);
    }

    // Set the timeout
    struct timeval tv;
    tv.tv_sec = TIMEOUT_SEC;
    tv.tv_usec = TIMEOUT_USEC;
    setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(struct timeval));

    // Set all the information on the client address struct
    client.sin_family = AF_INET;
    client.sin_port = htons(client_port);
    client.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(sockfd, (struct sockaddr*) &client, sizeof(client)) == -1)
    {
        std::cerr << "Error: Could not bind client process to port " << client_port << std::endl;
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    server.sin_family = AF_INET;
    server.sin_port = htons(server_port);

    std::cout << "Attempting to talk with server at " << argv[2] << ":" << argv[3] << std::endl;
    std::string str_filename(filename);

    request_func(sockfd, filename, str_filename.size(), server);
    //COMMENCE LISTENING
    receive_func(sockfd, filename, server);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq %rsi, %rbx
cmpl $0x6, %edi
jne 0x25ec
movq 0x8(%rbx), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2080
movq %rax, %r12
movq 0x18(%rbx), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2080
movq %rax, %r13
movq 0x20(%rbx), %r15
movq 0x28(%rbx), %r14
movq 0x10(%rbx), %rdi
leaq -0x3c(%rbp), %rsi
callq 0x20e0
testl %eax, %eax
je 0x2628
leaq 0xbf0(%rip), %rsi       # 0x30b1
movq %r15, %rdi
callq 0x2180
testl %eax, %eax
jne 0x2644
movq %r14, -0x48(%rbp)
pushq $0x2
popq %rdi
movl %edi, %esi
xorl %edx, %edx
callq 0x2070
testl %eax, %eax
js 0x2686
movl %eax, %r15d
leaq -0x78(%rbp), %rcx
andq $0x0, (%rcx)
movq $0xbb8, 0x8(%rcx)       # imm = 0xBB8
pushq $0x1
popq %rsi
pushq $0x14
popq %rdx
pushq $0x10
popq %r14
movl %eax, %edi
movl %r14d, %r8d
callq 0x21d0
leaq -0x88(%rbp), %rsi
movw $0x2, (%rsi)
movl %r12d, %eax
rolw $0x8, %ax
movw %ax, 0x2(%rsi)
andl $0x0, 0x4(%rsi)
movl %r15d, %edi
movl %r14d, %edx
callq 0x2060
cmpl $-0x1, %eax
je 0x269b
movw $0x2, -0x40(%rbp)
rolw $0x8, %r13w
movw %r13w, -0x3e(%rbp)
movq 0x2a72(%rip), %rdi      # 0x4fc8
leaq 0xbaf(%rip), %rsi       # 0x310c
callq 0x2140
movq 0x10(%rbx), %rsi
movq %rax, %rdi
callq 0x2140
leaq 0xbba(%rip), %rsi       # 0x312f
movq %rax, %rdi
callq 0x2140
movq 0x18(%rbx), %rsi
movq %rax, %rdi
callq 0x2140
movq %rax, %rdi
callq 0x20b0
leaq -0x68(%rbp), %rbx
leaq -0x29(%rbp), %rdx
movq %rbx, %rdi
movq -0x48(%rbp), %r14
movq %r14, %rsi
callq 0x2c4e
movq 0x8(%rbx), %rdx
movq -0x40(%rbp), %rcx
movq -0x38(%rbp), %r8
movl %r15d, %edi
movq %r14, %rsi
callq 0x26e6
movq -0x40(%rbp), %rdx
movq -0x38(%rbp), %rcx
movl %r15d, %edi
movq %r14, %rsi
callq 0x2762
leaq -0x68(%rbp), %rdi
callq 0x20a0
xorl %eax, %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x29d5(%rip), %r14      # 0x4fc8
leaq 0xa1a(%rip), %rsi       # 0x3014
movq %r14, %rdi
callq 0x2140
movq (%rbx), %rsi
movq %rax, %rdi
callq 0x2140
leaq 0xa90(%rip), %rsi       # 0x30a4
movq %rax, %rdi
callq 0x2140
leaq 0x9f9(%rip), %rsi       # 0x301c
movq %r14, %rdi
jmp 0x2694
movq 0x29c1(%rip), %rdi      # 0x4ff0
leaq 0xa22(%rip), %rsi       # 0x3058
callq 0x2140
movq 0x10(%rbx), %rsi
movq %rax, %rdi
jmp 0x2677
movq 0x29a5(%rip), %rbx      # 0x4ff0
leaq 0xa2a(%rip), %rsi       # 0x307c
movq %rbx, %rdi
callq 0x2140
movq %rax, %rdi
movq %r15, %rsi
callq 0x2140
movq %rax, %rdi
callq 0x20b0
leaq 0xa32(%rip), %rsi       # 0x30a6
movq %rbx, %rdi
callq 0x2140
movq %rax, %rdi
callq 0x20b0
jmp 0x26ca
movq 0x2963(%rip), %rdi      # 0x4ff0
leaq 0xa21(%rip), %rsi       # 0x30b5
callq 0x2140
jmp 0x26ca
movq 0x294e(%rip), %rdi      # 0x4ff0
leaq 0xa35(%rip), %rsi       # 0x30de
callq 0x2140
movzwl %r12w, %esi
movq %rax, %rdi
callq 0x21a0
movq %rax, %rdi
callq 0x20b0
movl %r15d, %edi
callq 0x2200
pushq $0x1
popq %rdi
callq 0x2170
movq %rax, %rbx
leaq -0x68(%rbp), %rdi
callq 0x20a0
movq %rbx, %rdi
callq 0x21c0