// File: /workspace/github_c_makefile_star2_O3/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 $0x78, %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
movl $0x2, %edi
movl $0x1, %esi
xorl %edx, %edx
callq 0x35d0
movl %eax, %r14d
testl %eax, %eax
jle 0x87fa
leaq -0x50(%rbp), %rcx
movl $0x1, (%rcx)
movl %r14d, %edi
movl $0x1, %esi
movl $0x2, %edx
movl $0x4, %r8d
callq 0x3100
leaq -0xa0(%rbp), %rsi
movq $0x0, 0x8(%rsi)
movw $0x2, (%rsi)
movl %r15d, %eax
rolw $0x8, %ax
movw %ax, 0x2(%rsi)
movl $0x0, 0x4(%rsi)
movl %r14d, %edi
movl $0x10, %edx
callq 0x3460
testl %eax, %eax
js 0x8801
movl %r14d, %edi
xorl %esi, %esi
callq 0x33f0
testl %eax, %eax
js 0x8808
leaq 0x329b(%rip), %rsi      # 0xb854
movl $0x4, %edi
movl %r15d, %edx
xorl %eax, %eax
callq 0x3540
movl %r14d, (%r12)
leaq 0x3076(%rip), %rdi      # 0xb649
callq 0x3590
testl %eax, %eax
jne 0x85ec
leaq 0x3073(%rip), %rsi      # 0xb656
xorl %edi, %edi
xorl %eax, %eax
callq 0x3540
leaq 0x307c(%rip), %rdi      # 0xb66f
callq 0x3590
testl %eax, %eax
jne 0x860c
leaq 0x3079(%rip), %rsi      # 0xb67c
xorl %edi, %edi
xorl %eax, %eax
callq 0x3540
xorps %xmm0, %xmm0
leaq -0xa0(%rbp), %rcx
movaps %xmm0, (%rcx)
movaps %xmm0, 0x10(%rcx)
movaps %xmm0, 0x30(%rcx)
movaps %xmm0, 0x20(%rcx)
movq $0xa, 0x8(%rcx)
movq $0x4, 0x10(%rcx)
leaq 0x300d(%rip), %rdi      # 0xb649
movl $0x41, %esi
movl $0x1a4, %edx            # imm = 0x1A4
xorl %eax, %eax
callq 0x3370
cmpl $-0x1, %eax
je 0x881f
movl %eax, %r14d
leaq -0xa0(%rbp), %rcx
xorps %xmm0, %xmm0
movaps %xmm0, (%rcx)
movaps %xmm0, 0x10(%rcx)
movaps %xmm0, 0x30(%rcx)
movaps %xmm0, 0x20(%rcx)
movq $0xa, 0x8(%rcx)
movq $0x8, 0x10(%rcx)
leaq 0x2fe6(%rip), %rdi      # 0xb66f
movl $0x41, %esi
movl $0x1a4, %edx            # imm = 0x1A4
xorl %eax, %eax
callq 0x3370
movl %eax, %r15d
cmpl $-0x1, %eax
je 0x882d
movl (%r12), %eax
leaq -0x54(%rbp), %rcx
movl %eax, (%rcx)
leaq 0x1d0(%rip), %rdx       # 0x8887
leaq -0x48(%rbp), %rdi
xorl %esi, %esi
callq 0x3470
testl %eax, %eax
jne 0x883e
leaq 0x301b(%rip), %rsi      # 0xb6ec
xorl %edi, %edi
xorl %eax, %eax
callq 0x3540
leaq 0x30c(%rip), %rdx       # 0x89ed
leaq -0x50(%rbp), %rdi
xorl %esi, %esi
xorl %ecx, %ecx
callq 0x3470
testl %eax, %eax
jne 0x8845
movl %r15d, -0x34(%rbp)
movl %r14d, -0x38(%rbp)
movq %r13, -0x40(%rbp)
movq %r12, -0x30(%rbp)
leaq 0x301a(%rip), %rsi      # 0xb727
xorl %edi, %edi
xorl %eax, %eax
callq 0x3540
cmpl $0x0, 0xc(%rbx)
jle 0x877a
leaq -0xa0(%rbp), %r13
leaq 0x3017(%rip), %r14      # 0xb741
movq -0x40(%rbp), %r15
xorl %r12d, %r12d
movq %rbx, -0xa0(%rbp)
movl %r12d, -0x98(%rbp)
movq %r15, %rdi
xorl %esi, %esi
leaq 0x2d0(%rip), %rdx       # 0x8a1b
movq %r13, %rcx
callq 0x3470
testl %eax, %eax
jne 0x8851
xorl %edi, %edi
movq %r14, %rsi
movl %r12d, %edx
xorl %eax, %eax
callq 0x3540
incq %r12
movslq 0xc(%rbx), %rax
addq $0x8, %r15
cmpq %rax, %r12
jl 0x8731
movl -0x38(%rbp), %edi
callq 0x3260
cmpl $-0x1, %eax
je 0x884c
movl -0x34(%rbp), %edi
callq 0x3260
cmpl $-0x1, %eax
movq -0x30(%rbp), %r12
je 0x8857
cmpl $0x0, 0xc(%rbx)
movq -0x40(%rbp), %r13
jle 0x87db
leaq 0x3003(%rip), %r14      # 0xb7b4
xorl %r15d, %r15d
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
movslq 0xc(%rbx), %rax
cmpq %rax, %r15
jl 0x87b4
movq -0x48(%rbp), %rdi
xorl %ebx, %ebx
xorl %esi, %esi
callq 0x35a0
leaq 0x2fdf(%rip), %rsi      # 0xb7ce
xorl %edi, %edi
xorl %eax, %eax
callq 0x3540
jmp 0x886d
callq 0x3670
jmp 0x880d
callq 0x3681
jmp 0x880d
callq 0x3698
movl %r14d, %edi
callq 0x3280
movl $0xffffffff, (%r12)     # imm = 0xFFFFFFFF
jmp 0x885c
leaq -0xa0(%rbp), %rdi
callq 0x3641
jmp 0x885c
leaq 0x3042(%rip), %rdi      # 0xb876
callq 0x34f0
jmp 0x86a6
callq 0x36f4
jmp 0x885c
callq 0x36dd
jmp 0x885c
callq 0x36c6
movq -0x30(%rbp), %r12
jmp 0x885c
callq 0x36af
leaq 0x2f84(%rip), %rdi      # 0xb7e7
callq 0x34f0
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
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