// File: /workspace/github_cpp_makefile_star2_O1/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 $0x58, %rsp
movq %rsi, %r15
cmpl $0x6, %edi
jne 0x27d6
movq 0x8(%r15), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2090
movq %rax, %r12
movq 0x18(%r15), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2090
movq %rax, %r13
movq 0x20(%r15), %r14
movq 0x28(%r15), %rbx
movq 0x10(%r15), %rdi
leaq -0x3c(%rbp), %rsi
callq 0x20f0
testl %eax, %eax
je 0x2812
leaq 0x1ab3(%rip), %rsi      # 0x40b1
movq %r14, %rdi
callq 0x21b0
testl %eax, %eax
jne 0x282e
movl $0x2, %edi
movl $0x2, %esi
xorl %edx, %edx
callq 0x2080
testl %eax, %eax
js 0x2870
movl %eax, %r14d
leaq -0x70(%rbp), %rcx
movq $0x0, (%rcx)
movq $0xbb8, 0x8(%rcx)       # imm = 0xBB8
movl %eax, %edi
movl $0x1, %esi
movl $0x14, %edx
movl $0x10, %r8d
callq 0x2210
leaq -0x80(%rbp), %rsi
movw $0x2, (%rsi)
movl %r12d, %eax
rolw $0x8, %ax
movw %ax, 0x2(%rsi)
movl $0x0, 0x4(%rsi)
movl %r14d, %edi
movl $0x10, %edx
callq 0x2070
cmpl $-0x1, %eax
je 0x2885
movw $0x2, -0x40(%rbp)
rolw $0x8, %r13w
movw %r13w, -0x3e(%rbp)
movq 0x392c(%rip), %r12      # 0x5fc8
leaq 0x1a69(%rip), %rsi      # 0x410c
movl $0x22, %edx
movq %r12, %rdi
callq 0x2180
movq 0x10(%r15), %r13
testq %r13, %r13
je 0x26d5
movq %r13, %rdi
callq 0x20a0
movq 0x3900(%rip), %rdi      # 0x5fc8
movq %r13, %rsi
movq %rax, %rdx
callq 0x2180
jmp 0x26ee
movq (%r12), %rax
movq -0x18(%rax), %rax
leaq (%r12,%rax), %rdi
movl 0x20(%r12,%rax), %esi
orl $0x1, %esi
callq 0x21e0
movq 0x38d3(%rip), %r12      # 0x5fc8
leaq 0x1a33(%rip), %rsi      # 0x412f
movl $0x1, %edx
movq %r12, %rdi
callq 0x2180
movq 0x18(%r15), %r15
testq %r15, %r15
je 0x272e
movq %r15, %rdi
callq 0x20a0
movq 0x38a7(%rip), %rdi      # 0x5fc8
movq %r15, %rsi
movq %rax, %rdx
callq 0x2180
jmp 0x2747
movq (%r12), %rax
movq -0x18(%rax), %rax
leaq (%r12,%rax), %rdi
movl 0x20(%r12,%rax), %esi
orl $0x1, %esi
callq 0x21e0
movq (%r12), %rax
movq -0x18(%rax), %rdi
addq %r12, %rdi
movl $0xa, %esi
callq 0x2140
movsbl %al, %esi
movq %r12, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x20d0
leaq -0x60(%rbp), %r15
leaq -0x29(%rbp), %rdx
movq %r15, %rdi
movq %rbx, %rsi
callq 0x30de
movq 0x8(%r15), %rdx
movq -0x40(%rbp), %rcx
movq -0x38(%rbp), %r8
movl %r14d, %edi
movq %rbx, %rsi
callq 0x28e2
movq -0x40(%rbp), %rdx
movq -0x38(%rbp), %rcx
movl %r14d, %edi
movq %rbx, %rsi
callq 0x294e
leaq -0x50(%rbp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x27c5
movq -0x50(%rbp), %rsi
incq %rsi
callq 0x2170
xorl %eax, %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x37eb(%rip), %rbx      # 0x5fc8
leaq 0x1830(%rip), %rsi      # 0x4014
movq %rbx, %rdi
callq 0x2150
movq (%r15), %rsi
movq %rax, %rdi
callq 0x2150
leaq 0x18a6(%rip), %rsi      # 0x40a4
movq %rax, %rdi
callq 0x2150
leaq 0x180f(%rip), %rsi      # 0x401c
movq %rbx, %rdi
jmp 0x287e
movq 0x37d7(%rip), %rdi      # 0x5ff0
leaq 0x1838(%rip), %rsi      # 0x4058
callq 0x2150
movq 0x10(%r15), %rsi
movq %rax, %rdi
jmp 0x2861
movq 0x37bb(%rip), %rbx      # 0x5ff0
leaq 0x1840(%rip), %rsi      # 0x407c
movq %rbx, %rdi
callq 0x2150
movq %rax, %rdi
movq %r14, %rsi
callq 0x2150
movq %rax, %rdi
callq 0x20b0
leaq 0x1848(%rip), %rsi      # 0x40a6
movq %rbx, %rdi
callq 0x2150
movq %rax, %rdi
callq 0x20b0
jmp 0x28b4
movq 0x3779(%rip), %rdi      # 0x5ff0
leaq 0x1837(%rip), %rsi      # 0x40b5
callq 0x2150
jmp 0x28b4
movq 0x3764(%rip), %rdi      # 0x5ff0
leaq 0x184b(%rip), %rsi      # 0x40de
callq 0x2150
movzwl %r12w, %esi
movq %rax, %rdi
callq 0x21d0
movq %rax, %rdi
callq 0x20b0
movl %r14d, %edi
callq 0x2240
movl $0x1, %edi
callq 0x21a0
movq %rax, %rbx
leaq -0x50(%rbp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x28da
movq -0x50(%rbp), %rsi
incq %rsi
callq 0x2170
movq %rbx, %rdi
callq 0x2200