// File: m1c0l[P]http-client-server/web-server.cpp
// Function: main
int main(int argc, char **argv) {
	if (argc > 5) {
		cerr << "usage: " << argv[0] << " [hostname] [port] [file-dir] [--sync]" << '\n';
		return 1;
	}

	string hostname, port, filedir, sync;

	// check argc and set default parameters if needed
	hostname = argc < 2 ? "localhost" : argv[1];
	port = argc < 3 ? "4000" : argv[2];
	filedir = argc < 4 ? "." : argv[3];
	sync = argc < 5 ? "" : argv[4];

	// create a socket using TCP IP
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);

	// allow others to reuse the address
	int yes = 1;
	if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
		perror("setsockopt");
		return 1;
	}

	// bind address to socket
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(stoi(port));     // short, network byte order
	addr.sin_addr.s_addr = inet_addr("127.0.0.1");
	memset(addr.sin_zero, '\0', sizeof(addr.sin_zero));

	if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
		perror("bind");
		return 2;
	}

	// set socket to listen status
	if (listen(sockfd, 1) == -1) {
		perror("listen");
		return 3;
	}

	// accept a new connection
	struct sockaddr_in clientAddr;

	//int clientSockfd;

	socklen_t clientAddrSize = sizeof(clientAddr);
	//Start Multithreading Magic
	while(true){
		int clientSockfd= accept(sockfd, (struct sockaddr*)&clientAddr, &clientAddrSize);
		if (clientSockfd == -1) {
			perror("accept");
			return 4;
		}

		if (sync == "--sync") {
			thread_func(clientAddr, filedir, clientSockfd);
		}
		else {
			thread(thread_func, clientAddr, filedir, clientSockfd).detach();
		}

	}

	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x140, %rsp            # imm = 0x140
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpl $0x5, -0x8(%rbp)
jle 0x99c9
movq 0x1366a(%rip), %rdi     # 0x1cff0
leaq 0x981d(%rip), %rsi      # 0x131aa
callq 0x53f0
movq %rax, %rdi
movq -0x10(%rbp), %rax
movq (%rax), %rsi
callq 0x53f0
movq %rax, %rdi
leaq 0x9807(%rip), %rsi      # 0x131b2
callq 0x53f0
movq %rax, %rdi
movl $0xa, %esi
callq 0x54f0
movl $0x1, -0x4(%rbp)
jmp 0x9de9
leaq -0x30(%rbp), %rdi
callq 0x55c0
leaq -0x50(%rbp), %rdi
callq 0x55c0
leaq -0x70(%rbp), %rdi
callq 0x55c0
leaq -0x90(%rbp), %rdi
callq 0x55c0
cmpl $0x2, -0x8(%rbp)
jge 0x9a06
leaq 0x97dc(%rip), %rax      # 0x131d9
movq %rax, -0x110(%rbp)
jmp 0x9a15
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x110(%rbp)
movq -0x110(%rbp), %rsi
leaq -0x30(%rbp), %rdi
callq 0x55a0
jmp 0x9a27
cmpl $0x3, -0x8(%rbp)
jge 0x9a3d
leaq 0x97af(%rip), %rax      # 0x131e3
movq %rax, -0x118(%rbp)
jmp 0x9a4c
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x118(%rbp)
movq -0x118(%rbp), %rsi
leaq -0x50(%rbp), %rdi
callq 0x55a0
jmp 0x9a5e
cmpl $0x4, -0x8(%rbp)
jge 0x9a74
leaq 0x977d(%rip), %rax      # 0x131e8
movq %rax, -0x120(%rbp)
jmp 0x9a83
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x120(%rbp)
movq -0x120(%rbp), %rsi
leaq -0x70(%rbp), %rdi
callq 0x55a0
jmp 0x9a95
cmpl $0x5, -0x8(%rbp)
jge 0x9aab
leaq 0x96d6(%rip), %rax      # 0x13178
movq %rax, -0x128(%rbp)
jmp 0x9aba
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x128(%rbp)
movq -0x128(%rbp), %rsi
leaq -0x90(%rbp), %rdi
callq 0x55a0
jmp 0x9acf
movl $0x2, %edi
movl $0x1, %esi
xorl %edx, %edx
callq 0x50f0
movl %eax, -0xa0(%rbp)
movl $0x1, -0xa4(%rbp)
movl -0xa0(%rbp), %edi
movl $0x1, %esi
movl $0x2, %edx
leaq -0xa4(%rbp), %rcx
movl $0x4, %r8d
callq 0x56a0
cmpl $-0x1, %eax
jne 0x9b52
leaq 0x96cc(%rip), %rdi      # 0x131ea
callq 0x5330
jmp 0x9b25
movl $0x1, -0x4(%rbp)
movl $0x1, -0xa8(%rbp)
jmp 0x9d97
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
jmp 0x9dc0
movw $0x2, -0xb8(%rbp)
xorl %eax, %eax
movl %eax, %esi
leaq -0x50(%rbp), %rdi
movl $0xa, %edx
callq 0xa550
movl %eax, -0x12c(%rbp)
jmp 0x9b75
movl -0x12c(%rbp), %eax
movzwl %ax, %edi
callq 0x5060
movw %ax, -0xb6(%rbp)
leaq 0x9664(%rip), %rdi      # 0x131f5
callq 0x5410
movl %eax, -0xb4(%rbp)
leaq -0xb8(%rbp), %rdi
addq $0x8, %rdi
xorl %esi, %esi
movl $0x8, %edx
callq 0x5230
movl -0xa0(%rbp), %edi
leaq -0xb8(%rbp), %rsi
movl $0x10, %edx
callq 0x5090
cmpl $-0x1, %eax
jne 0x9bf3
leaq 0x9629(%rip), %rdi      # 0x131ff
callq 0x5330
jmp 0x9bdd
movl $0x2, -0x4(%rbp)
movl $0x1, -0xa8(%rbp)
jmp 0x9d97
movl -0xa0(%rbp), %edi
movl $0x1, %esi
callq 0x54c0
cmpl $-0x1, %eax
jne 0x9c2c
leaq 0x95f5(%rip), %rdi      # 0x13204
callq 0x5330
jmp 0x9c16
movl $0x3, -0x4(%rbp)
movl $0x1, -0xa8(%rbp)
jmp 0x9d97
movl $0x10, -0xcc(%rbp)
jmp 0x9c38
movl -0xa0(%rbp), %edi
leaq -0xc8(%rbp), %rsi
leaq -0xcc(%rbp), %rdx
callq 0x5140
movl %eax, -0x130(%rbp)
jmp 0x9c59
movl -0x130(%rbp), %eax
movl %eax, -0xd0(%rbp)
cmpl $-0x1, -0xd0(%rbp)
jne 0x9c92
leaq 0x9596(%rip), %rdi      # 0x1320b
callq 0x5330
jmp 0x9c7c
movl $0x4, -0x4(%rbp)
movl $0x1, -0xa8(%rbp)
jmp 0x9d97
leaq 0x9579(%rip), %rsi      # 0x13212
leaq -0x90(%rbp), %rdi
callq 0x8650
movb %al, -0x131(%rbp)
jmp 0x9cad
movb -0x131(%rbp), %al
testb $0x1, %al
jne 0x9cb9
jmp 0x9d2f
movups -0xc8(%rbp), %xmm0
movaps %xmm0, -0xe0(%rbp)
leaq -0x100(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x51a0
jmp 0x9cd9
movl -0xd0(%rbp), %ecx
movq -0xe0(%rbp), %rdi
movq -0xd8(%rbp), %rsi
leaq -0x100(%rbp), %rdx
callq 0x8f20
jmp 0x9cfb
leaq -0x100(%rbp), %rdi
callq 0x5280
jmp 0x9d92
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x5280
jmp 0x9dc0
leaq -0xe16(%rip), %rsi      # 0x8f20
leaq -0x108(%rbp), %rdi
leaq -0xc8(%rbp), %rdx
leaq -0x70(%rbp), %rcx
leaq -0xd0(%rbp), %r8
callq 0xa590
jmp 0x9d56
leaq -0x108(%rbp), %rdi
callq 0x5670
jmp 0x9d64
leaq -0x108(%rbp), %rdi
callq 0xa660
jmp 0x9d92
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
leaq -0x108(%rbp), %rdi
callq 0xa660
jmp 0x9dc0
jmp 0x9c36
leaq -0x90(%rbp), %rdi
callq 0x5280
leaq -0x70(%rbp), %rdi
callq 0x5280
leaq -0x50(%rbp), %rdi
callq 0x5280
leaq -0x30(%rbp), %rdi
callq 0x5280
jmp 0x9de9
leaq -0x90(%rbp), %rdi
callq 0x5280
leaq -0x70(%rbp), %rdi
callq 0x5280
leaq -0x50(%rbp), %rdi
callq 0x5280
leaq -0x30(%rbp), %rdi
callq 0x5280
jmp 0x9df5
movl -0x4(%rbp), %eax
addq $0x140, %rsp            # imm = 0x140
popq %rbp
retq
movq -0x98(%rbp), %rdi
callq 0x5680
nopw %cs:(%rax,%rax)