// File: alibakhtiar[P]ExampleHTTPServer/./HttpServer.hh
// Function: SimpleHttpServer::createServer(SimpleHttpServer::Server*)
bool createServer(Server *server)
{
	int st;
	int serverFd;

	// Create new TCP socket(int family, int type, int protocol)
#ifdef __linux__
	serverFd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
#else
	WSADATA WSAData;
	WSAStartup(MAKEWORD(2,0), &WSAData);
	serverFd = socket(AF_INET, SOCK_STREAM, 0);
#endif

	if (serverFd < 0) {
		APPERROR(_STRERR, _FUNC, _LINE);
		return false;
	}

	// Socket options
#ifdef __linux__
	int optVal = 1;

	// Re use address
	st = setsockopt(serverFd, SOL_SOCKET, SO_REUSEADDR, (void *)&optVal, sizeof(int));
	if (st == -1) {
		APPERROR(_STRERR, _FUNC, _LINE);
		return false;
	}

	// No-delay
	st = setsockopt(serverFd, IPPROTO_TCP, TCP_NODELAY, (void *)&optVal, sizeof(int));
	if (st == -1) {
		APPERROR(_STRERR, _FUNC, _LINE);
		return false;
	}
#else
	bool bOptVal = true;

	// No-delay
	int iResult = setsockopt(serverFd, SOL_SOCKET, SO_REUSEADDR, (char *)&bOptVal, sizeof(bool));
	if (iResult == SOCKET_ERROR) {
		APPERROR(_STRERR, _FUNC, _LINE);
		return 1;
	}
#endif

	// Bind
	struct sockaddr_in sockAddr;
	memset(&sockAddr, 0, sizeof(struct sockaddr_in));

	sockAddr.sin_family = AF_INET;
	sockAddr.sin_addr.s_addr = inet_addr((char *)server->ip.c_str());
	sockAddr.sin_port = htons(server->port);

	st = bind(serverFd, (struct sockaddr *)&sockAddr, sizeof(struct sockaddr_in));
	if (st == -1) {
		APPERROR(_STRERR, _FUNC, _LINE);
		return false;
	}

	// Listen
	st = listen(serverFd, BACKLOG_SIZE);
	if (st < 0) {
		APPERROR(_STRERR, _FUNC, _LINE);
		return false;
	}

	// Run (main loop)
	int clientFd;
	struct sockaddr_in clientAddr;
	socklen_t clientLength;

	clientLength = (socklen_t)sizeof(struct sockaddr_in);
	memset(&clientAddr, 0, sizeof(struct sockaddr_in));

	std::cout << "http://" << 
		server->ip << ":" << server->port << std::endl;

	while (1) {
		// Accept new connection (new socket)
		clientFd = accept(serverFd, (struct sockaddr *)&clientAddr, &clientLength);
		if (clientFd <= 0) {
			continue;
		}

		// New thread per connection
#ifdef __linux__
		std::thread(serverRequestHandler, server, std::move(clientFd), std::move(clientAddr)).detach();
#else
		serverRequestHandler(server, clientFd, clientAddr);
#endif
	}

	close(serverFd);

#ifndef __linux__
	WSACleanup();
#endif

	return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x10(%rbp)
movl $0x2, %edi
movl $0x1, %esi
movl $0x6, %edx
callq 0x30b0
movl %eax, -0x18(%rbp)
cmpl $0x0, -0x18(%rbp)
jge 0x3c51
movq 0xa3bd(%rip), %rax      # 0xdfd0
movq (%rax), %rax
movq %rax, -0x68(%rbp)
callq 0x3060
movl (%rax), %edi
callq 0x3100
movq -0x68(%rbp), %rdi
movq %rax, %rdx
leaq 0x540d(%rip), %rsi      # 0x9041
leaq 0x5421(%rip), %rcx      # 0x905c
movl $0x1de, %r8d            # imm = 0x1DE
movb $0x0, %al
callq 0x33c0
movb $0x0, -0x1(%rbp)
jmp 0x3f02
movl $0x1, -0x1c(%rbp)
movl -0x18(%rbp), %edi
movl $0x1, %esi
movl $0x2, %edx
leaq -0x1c(%rbp), %rcx
movl $0x4, %r8d
callq 0x3460
movl %eax, -0x14(%rbp)
cmpl $-0x1, -0x14(%rbp)
jne 0x3cc2
movq 0xa34c(%rip), %rax      # 0xdfd0
movq (%rax), %rax
movq %rax, -0x70(%rbp)
callq 0x3060
movl (%rax), %edi
callq 0x3100
movq -0x70(%rbp), %rdi
movq %rax, %rdx
leaq 0x539c(%rip), %rsi      # 0x9041
leaq 0x53b0(%rip), %rcx      # 0x905c
movl $0x1e9, %r8d            # imm = 0x1E9
movb $0x0, %al
callq 0x33c0
movb $0x0, -0x1(%rbp)
jmp 0x3f02
movl -0x18(%rbp), %edi
movl $0x6, %esi
movl $0x1, %edx
leaq -0x1c(%rbp), %rcx
movl $0x4, %r8d
callq 0x3460
movl %eax, -0x14(%rbp)
cmpl $-0x1, -0x14(%rbp)
jne 0x3d2c
movq 0xa2e2(%rip), %rax      # 0xdfd0
movq (%rax), %rax
movq %rax, -0x78(%rbp)
callq 0x3060
movl (%rax), %edi
callq 0x3100
movq -0x78(%rbp), %rdi
movq %rax, %rdx
leaq 0x5332(%rip), %rsi      # 0x9041
leaq 0x5346(%rip), %rcx      # 0x905c
movl $0x1f0, %r8d            # imm = 0x1F0
movb $0x0, %al
callq 0x33c0
movb $0x0, -0x1(%rbp)
jmp 0x3f02
leaq -0x2c(%rbp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x3190
movw $0x2, -0x2c(%rbp)
movq -0x10(%rbp), %rdi
addq $0x8, %rdi
callq 0x3140
movq %rax, %rdi
callq 0x32b0
movl %eax, -0x28(%rbp)
movq -0x10(%rbp), %rax
movl 0x28(%rax), %eax
movzwl %ax, %edi
callq 0x3070
movw %ax, -0x2a(%rbp)
movl -0x18(%rbp), %edi
leaq -0x2c(%rbp), %rsi
movl $0x10, %edx
callq 0x3080
movl %eax, -0x14(%rbp)
cmpl $-0x1, -0x14(%rbp)
jne 0x3dcc
movq 0xa242(%rip), %rax      # 0xdfd0
movq (%rax), %rax
movq %rax, -0x80(%rbp)
callq 0x3060
movl (%rax), %edi
callq 0x3100
movq -0x80(%rbp), %rdi
movq %rax, %rdx
leaq 0x5292(%rip), %rsi      # 0x9041
leaq 0x52a6(%rip), %rcx      # 0x905c
movl $0x208, %r8d            # imm = 0x208
movb $0x0, %al
callq 0x33c0
movb $0x0, -0x1(%rbp)
jmp 0x3f02
movl -0x18(%rbp), %edi
movl $0x96, %esi
callq 0x3330
movl %eax, -0x14(%rbp)
cmpl $0x0, -0x14(%rbp)
jge 0x3e2d
movq 0xa1e7(%rip), %rax      # 0xdfd0
movq (%rax), %rax
movq %rax, -0x88(%rbp)
callq 0x3060
movl (%rax), %edi
callq 0x3100
movq -0x88(%rbp), %rdi
movq %rax, %rdx
leaq 0x5231(%rip), %rsi      # 0x9041
leaq 0x5245(%rip), %rcx      # 0x905c
movl $0x20f, %r8d            # imm = 0x20F
movb $0x0, %al
callq 0x33c0
movb $0x0, -0x1(%rbp)
jmp 0x3f02
movl $0x10, -0x44(%rbp)
leaq -0x40(%rbp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x3190
movq 0xa17d(%rip), %rdi      # 0xdfc8
leaq 0x5238(%rip), %rsi      # 0x908a
callq 0x3290
movq %rax, %rdi
movq -0x10(%rbp), %rsi
addq $0x8, %rsi
callq 0x3250
movq %rax, %rdi
leaq 0x5221(%rip), %rsi      # 0x9092
callq 0x3290
movq %rax, %rdi
movq -0x10(%rbp), %rax
movl 0x28(%rax), %esi
callq 0x3420
movq %rax, %rdi
movq 0xa121(%rip), %rsi      # 0xdfb0
callq 0x32e0
movl -0x18(%rbp), %edi
leaq -0x40(%rbp), %rsi
leaq -0x44(%rbp), %rdx
callq 0x30e0
movl %eax, -0x30(%rbp)
cmpl $0x0, -0x30(%rbp)
jg 0x3eaf
jmp 0x3e94
leaq 0x6a(%rip), %rsi        # 0x3f20
leaq -0x50(%rbp), %rdi
movq %rdi, -0x90(%rbp)
leaq -0x10(%rbp), %rdx
leaq -0x30(%rbp), %rcx
leaq -0x40(%rbp), %r8
callq 0x4f80
movq -0x90(%rbp), %rdi
callq 0x3430
jmp 0x3ee0
leaq -0x50(%rbp), %rdi
callq 0x5050
jmp 0x3e94
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x50(%rbp), %rdi
callq 0x5050
jmp 0x3f10
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x90, %rsp
popq %rbp
retq
movq -0x58(%rbp), %rdi
callq 0x3440
nopl (%rax)