// File: maclellant[P]ReliableGoBackN/server.cpp
// Function: main
int main(int argc, char** argv)
{
	if (argc != 5)
    {
        std::cout << "Usage: " << argv[0] << " ";
        std::cout << "<corrupt %%> <loss %%> <delay %%> <delay-amount-ms>" << std::endl;
        exit(EXIT_FAILURE);
    }

    GremlinInfo gremlin_info;

    gremlin_info.corrupt_chance = atoi(argv[1]);
    gremlin_info.loss_chance = atoi(argv[2]);
    gremlin_info.delay_chance = atoi(argv[3]);
    gremlin_info.delay_amount_ms = atoi(argv[4]);

	struct sockaddr_in server_addr;
	struct sockaddr_in client_addr;
    int sockfd = -1; 

    socklen_t slen = sizeof(client_addr);

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1)
    {
    	perror("Error: Could not create socket\n");
    	exit(EXIT_FAILURE);
    }

    // Set the receiving function to non-blocking
    int flags = fcntl(sockfd, F_GETFL);
    flags |= O_NONBLOCK;
    fcntl(sockfd, F_SETFL, flags);

    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(sockfd, (struct sockaddr*) &server_addr, sizeof(server_addr)) == -1)
    {
    	fprintf(stderr, "Error: Could not bind to port\n");
    	close(sockfd);
    	exit(EXIT_FAILURE);
    }

    printf("Successfully bound server to port %d and listening for clients...\n\n", SERVER_PORT);
	
	receive_commands(sockfd, gremlin_info); // include params for gremlin?
 
    close(sockfd);
    exit(EXIT_SUCCESS);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpl $0x5, -0x8(%rbp)
je 0x3ae9
movq 0x7535(%rip), %rdi      # 0xafc8
leaq 0x37be(%rip), %rsi      # 0x7258
callq 0x2220
movq %rax, %rdi
movq -0x10(%rbp), %rax
movq (%rax), %rsi
callq 0x2220
movq %rax, %rdi
leaq 0x37a6(%rip), %rsi      # 0x725e
callq 0x2220
movq 0x7504(%rip), %rdi      # 0xafc8
leaq 0x3795(%rip), %rsi      # 0x7260
callq 0x2220
movq %rax, %rdi
movq 0x74de(%rip), %rsi      # 0xafb8
callq 0x2260
movl $0x1, %edi
callq 0x22c0
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0x2330
movl %eax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0x2330
movl %eax, -0x1c(%rbp)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0x2330
movl %eax, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rdi
callq 0x2330
movl %eax, -0x14(%rbp)
movl $0xffffffff, -0x44(%rbp) # imm = 0xFFFFFFFF
movl $0x10, -0x48(%rbp)
movl $0x2, %esi
xorl %edx, %edx
movl %esi, %edi
callq 0x2090
movl %eax, -0x44(%rbp)
cmpl $-0x1, -0x44(%rbp)
jne 0x3b64
leaq 0x373f(%rip), %rdi      # 0x7294
callq 0x21d0
movl $0x1, %edi
callq 0x22c0
movl -0x44(%rbp), %edi
movl $0x3, %esi
movb $0x0, %al
callq 0x2140
movl %eax, -0x4c(%rbp)
movl -0x4c(%rbp), %eax
orl $0x800, %eax            # imm = 0x800
movl %eax, -0x4c(%rbp)
movl -0x44(%rbp), %edi
movl -0x4c(%rbp), %edx
movl $0x4, %esi
movb $0x0, %al
callq 0x2140
leaq -0x30(%rbp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x2130
movw $0x2, -0x30(%rbp)
movl $0x2742, %edi           # imm = 0x2742
callq 0x2050
movw %ax, -0x2e(%rbp)
xorl %edi, %edi
callq 0x2180
movl %eax, -0x2c(%rbp)
movl -0x44(%rbp), %edi
leaq -0x30(%rbp), %rsi
movl $0x10, %edx
callq 0x2070
cmpl $-0x1, %eax
jne 0x3c01
movq 0x73f2(%rip), %rax      # 0xafd0
movq (%rax), %rdi
leaq 0x36cc(%rip), %rsi      # 0x72b4
movb $0x0, %al
callq 0x22e0
movl -0x44(%rbp), %edi
callq 0x23b0
movl $0x1, %edi
callq 0x22c0
leaq 0x36cb(%rip), %rdi      # 0x72d3
movl $0x2742, %esi           # imm = 0x2742
movb $0x0, %al
callq 0x2040
movl -0x44(%rbp), %edi
leaq -0x20(%rbp), %rsi
callq 0x2800
movl -0x44(%rbp), %edi
callq 0x23b0
xorl %edi, %edi
callq 0x22c0
nop