// File: /workspace/github_c_makefile_star2_O2/qpfiffer[P]38-Moths/src/server.c
// Function: m38_http_serve
int m38_http_serve(m38_app *app) {
	mqd_t po_accepted_queue = -1;
	mqd_t po_handled_queue = -1;
	/* Handlers take accepted sockets and turn them into responses: */
	pthread_t handlers[app->num_threads];
	/* The responder is responsible for sending bytes back over the wire: */
	pthread_t responder_worker;
	/* The acceptor listens and accepts new connections, and enqueues them: */
	pthread_t acceptor_enqueuer;

	int *main_sock_fd = app->main_sock_fd;
	*main_sock_fd = create_socket(app->port);
	if (*main_sock_fd < 0)
		goto error;

	/* Purge the queue if it already exists by unlinking it. Otherwise we get
	 * stale messages.
	 */
	if (mq_unlink(ACCEPTED_SOCKET_QUEUE_NAME) == 0) {
		m38_log_msg(LOG_INFO, "Purged old socket queue.");
	}

	if (mq_unlink(HANDLED_CONNECTION_QUEUE_NAME) == 0) {
		m38_log_msg(LOG_INFO, "Purged old handled queue.");
	}

	/* We precreate the queue here to guarantee that everyone else will have access to it. */
	po_accepted_queue = _open_queue(ACCEPTED_SOCKET_QUEUE_NAME, O_RDWR | O_CREAT, sizeof(int));
	if (po_accepted_queue == -1) {
		m38_log_msg(LOG_ERR, "Could not preopen accepted_socket_queue.");
		perror("Main Thread");
		goto error;
	}

	po_handled_queue = _open_queue(HANDLED_CONNECTION_QUEUE_NAME, O_RDWR | O_CREAT, sizeof(m38_handled_request *));
	if (po_accepted_queue == -1) {
		m38_log_msg(LOG_ERR, "Could not preopen handled socket queue..");
		perror("Main Thread");
		goto error;
	}

	acceptor_arg args = {
		.main_sock_fd = *main_sock_fd,
	};

	if (pthread_create(&acceptor_enqueuer, NULL, acceptor, &args) != 0) {
		m38_log_msg(LOG_ERR, "Could not start acceptor thread.");
		goto error;
	}

	m38_log_msg(LOG_INFO, "Acceptor thread started.");

	if (pthread_create(&responder_worker, NULL, responder, NULL) != 0) {
		m38_log_msg(LOG_ERR, "Could not start responder thread.");
		goto error;
	}

	m38_log_msg(LOG_INFO, "Responder thread started.");

	int i;
	for (i = 0; i < app->num_threads; i++) {
		handler_arg args = {
			.app = app,
			.worker_ident = i
		};
		if (pthread_create(&handlers[i], NULL, handler, &args) != 0) {
			goto error;
		}
		m38_log_msg(LOG_INFO, "Worker thread %i started.", i);
	}

	if (mq_close(po_accepted_queue) == -1) {
		m38_log_msg(LOG_ERR, "Main thread: Could not close accepted queue.");
		goto error;
	}

	if (mq_close(po_handled_queue) == -1) {
		m38_log_msg(LOG_ERR, "Main thread: Could not close handled queue.");
		goto error;
	}

	for (i = 0; i < app->num_threads; i++) {
		pthread_join(handlers[i], NULL);
		m38_log_msg(LOG_INFO, "Worker thread %i stopped.", i);
	}
	pthread_join(acceptor_enqueuer, NULL);
	m38_log_msg(LOG_INFO, "Acceptor thread stopped.");

	close(*main_sock_fd);
	return 0;

error:
	perror("Server error");
	close(*main_sock_fd);
	return -1;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rdi, %rbx
movl 0xc(%rdi), %eax
movq %rsp, %r13
leaq 0xf(,%rax,8), %rax
andq $-0x10, %rax
subq %rax, %r13
movq %r13, %rsp
movq (%rdi), %r12
movl 0x8(%rdi), %r15d
pushq $0x2
popq %rdi
pushq $0x1
popq %rsi
xorl %edx, %edx
callq 0x35d0
movl %eax, %r14d
testl %eax, %eax
jle 0x7ec3
leaq -0x50(%rbp), %rcx
movl $0x1, (%rcx)
pushq $0x1
popq %rsi
pushq $0x2
popq %rdx
pushq $0x4
popq %r8
movl %r14d, %edi
callq 0x3100
leaq -0x60(%rbp), %rsi
andq $0x0, 0x8(%rsi)
movw $0x2, (%rsi)
movl %r15d, %eax
rolw $0x8, %ax
movw %ax, 0x2(%rsi)
andl $0x0, 0x4(%rsi)
pushq $0x10
popq %rdx
movl %r14d, %edi
callq 0x3460
testl %eax, %eax
js 0x7ecc
movl %r14d, %edi
xorl %esi, %esi
callq 0x33f0
testl %eax, %eax
js 0x7ed5
leaq 0x2b54(%rip), %rsi      # 0xa854
pushq $0x4
popq %rdi
movl %r15d, %edx
xorl %eax, %eax
callq 0x3540
movl %r14d, (%r12)
leaq 0x2931(%rip), %rdi      # 0xa649
callq 0x3590
testl %eax, %eax
jne 0x7d31
leaq 0x292e(%rip), %rsi      # 0xa656
xorl %edi, %edi
xorl %eax, %eax
callq 0x3540
leaq 0x2937(%rip), %rdi      # 0xa66f
callq 0x3590
testl %eax, %eax
jne 0x7d51
leaq 0x2934(%rip), %rsi      # 0xa67c
xorl %edi, %edi
xorl %eax, %eax
callq 0x3540
leaq 0x28f1(%rip), %rdi      # 0xa649
pushq $0x4
popq %rsi
callq 0x7f6f
cmpl $-0x1, %eax
je 0x7ef5
movl %eax, %r14d
leaq 0x28fc(%rip), %rdi      # 0xa66f
pushq $0x8
popq %rsi
callq 0x7f6f
movl %eax, %r15d
movl (%r12), %eax
leaq -0x64(%rbp), %rcx
movl %eax, (%rcx)
leaq 0x232(%rip), %rdx       # 0x7fc1
leaq -0x48(%rbp), %rdi
xorl %esi, %esi
callq 0x3470
testl %eax, %eax
jne 0x7f14
leaq 0x2943(%rip), %rsi      # 0xa6ec
xorl %edi, %edi
xorl %eax, %eax
callq 0x3540
leaq 0x308(%rip), %rdx       # 0x80c1
leaq -0x50(%rbp), %rdi
xorl %esi, %esi
xorl %ecx, %ecx
callq 0x3470
testl %eax, %eax
jne 0x7f1d
movl %r15d, -0x2c(%rbp)
movl %r14d, -0x30(%rbp)
movq %r12, -0x38(%rbp)
leaq 0x2946(%rip), %rsi      # 0xa727
xorl %edi, %edi
xorl %eax, %eax
callq 0x3540
movq %r13, %r14
leaq -0x60(%rbp), %r13
leaq 0x2949(%rip), %r15      # 0xa741
movq %r14, -0x40(%rbp)
xorl %r12d, %r12d
movslq 0xc(%rbx), %rax
cmpq %rax, %r12
jge 0x7e44
movq %rbx, -0x60(%rbp)
movl %r12d, -0x58(%rbp)
movq %r14, %rdi
xorl %esi, %esi
leaq 0x3a7(%rip), %rdx       # 0x81c3
movq %r13, %rcx
callq 0x3470
testl %eax, %eax
jne 0x7f26
xorl %edi, %edi
movq %r15, %rsi
movl %r12d, %edx
xorl %eax, %eax
callq 0x3540
incq %r12
addq $0x8, %r14
jmp 0x7dff
movl -0x30(%rbp), %edi
callq 0x3260
cmpl $-0x1, %eax
movq -0x38(%rbp), %r12
je 0x7f2c
movl -0x2c(%rbp), %edi
callq 0x3260
cmpl $-0x1, %eax
je 0x7f35
leaq 0x2943(%rip), %r14      # 0xa7b4
xorl %r15d, %r15d
movq -0x40(%rbp), %r13
movslq 0xc(%rbx), %rax
cmpq %rax, %r15
jge 0x7ea1
movq (%r13,%r15,8), %rdi
xorl %esi, %esi
callq 0x35a0
xorl %edi, %edi
movq %r14, %rsi
movl %r15d, %edx
xorl %eax, %eax
callq 0x3540
incq %r15
jmp 0x7e78
movq -0x48(%rbp), %rdi
xorl %ebx, %ebx
xorl %esi, %esi
callq 0x35a0
leaq 0x2919(%rip), %rsi      # 0xa7ce
xorl %edi, %edi
xorl %eax, %eax
callq 0x3540
jmp 0x7f55
leaq 0x292f(%rip), %rsi      # 0xa7f9
jmp 0x7edc
leaq 0x2944(%rip), %rsi      # 0xa817
jmp 0x7edc
leaq 0x2957(%rip), %rsi      # 0xa833
pushq $0x3
popq %rdi
xorl %eax, %eax
callq 0x3540
movl %r14d, %edi
callq 0x3280
orl $-0x1, (%r12)
jmp 0x7f46
leaq 0x279a(%rip), %rsi      # 0xa696
pushq $0x3
popq %rdi
xorl %eax, %eax
callq 0x3540
leaq 0x27b2(%rip), %rdi      # 0xa6bf
callq 0x34f0
jmp 0x7f46
leaq 0x27b0(%rip), %rsi      # 0xa6cb
jmp 0x7f3c
leaq 0x27e1(%rip), %rsi      # 0xa705
jmp 0x7f3c
movq -0x38(%rbp), %r12
jmp 0x7f46
leaq 0x2828(%rip), %rsi      # 0xa75b
jmp 0x7f3c
leaq 0x284c(%rip), %rsi      # 0xa788
pushq $0x3
popq %rdi
xorl %eax, %eax
callq 0x3540
leaq 0x289a(%rip), %rdi      # 0xa7e7
callq 0x34f0
pushq $-0x1
popq %rbx
movl (%r12), %edi
callq 0x3280
movl %ebx, %eax
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq