// File: /workspace/github_c_makefile_star2_O1/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 0x875c
leaq -0x50(%rbp), %rcx
movl $0x1, (%rcx)
movl %r14d, %edi
movl $0x1, %esi
movl $0x2, %edx
movl $0x4, %r8d
callq 0x3100
xorps %xmm0, %xmm0
leaq -0xa0(%rbp), %rsi
movaps %xmm0, (%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 0x8765
movl %r14d, %edi
xorl %esi, %esi
callq 0x33f0
testl %eax, %eax
js 0x876e
leaq 0x3109(%rip), %rsi      # 0xb854
movl $0x4, %edi
movl %r15d, %edx
xorl %eax, %eax
callq 0x3540
jmp 0x878f
leaq 0x3096(%rip), %rsi      # 0xb7f9
jmp 0x8775
leaq 0x30ab(%rip), %rsi      # 0xb817
jmp 0x8775
leaq 0x30be(%rip), %rsi      # 0xb833
movl $0x3, %edi
xorl %eax, %eax
callq 0x3540
movl %r14d, %edi
callq 0x3280
movl $0xffffffff, %r14d      # imm = 0xFFFFFFFF
movl %r14d, (%r12)
testl %r14d, %r14d
js 0x8a07
leaq 0x2ea6(%rip), %rdi      # 0xb649
callq 0x3590
testl %eax, %eax
jne 0x87bc
leaq 0x2ea3(%rip), %rsi      # 0xb656
xorl %edi, %edi
xorl %eax, %eax
callq 0x3540
leaq 0x2eac(%rip), %rdi      # 0xb66f
callq 0x3590
testl %eax, %eax
jne 0x87dc
leaq 0x2ea9(%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 0x2e3d(%rip), %rdi      # 0xb649
movl $0x41, %esi
movl $0x1a4, %edx            # imm = 0x1A4
xorl %eax, %eax
callq 0x3370
cmpl $-0x1, %eax
je 0x89ca
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 0x2e16(%rip), %rdi      # 0xb66f
movl $0x41, %esi
movl $0x1a4, %edx            # imm = 0x1A4
xorl %eax, %eax
callq 0x3370
movl %eax, %r15d
cmpl $-0x1, %eax
je 0x89d8
movl (%r12), %eax
leaq -0x54(%rbp), %rcx
movl %eax, (%rcx)
leaq 0x1ab(%rip), %rdx       # 0x8a32
leaq -0x48(%rbp), %rdi
xorl %esi, %esi
callq 0x3470
testl %eax, %eax
jne 0x89e9
leaq 0x2e4b(%rip), %rsi      # 0xb6ec
xorl %edi, %edi
xorl %eax, %eax
callq 0x3540
leaq 0x2ad(%rip), %rdx       # 0x8b5e
leaq -0x50(%rbp), %rdi
xorl %esi, %esi
xorl %ecx, %ecx
callq 0x3470
testl %eax, %eax
jne 0x89f0
movl %r15d, -0x34(%rbp)
movl %r14d, -0x38(%rbp)
movq %r13, -0x40(%rbp)
movq %r12, -0x30(%rbp)
leaq 0x2e4a(%rip), %rsi      # 0xb727
xorl %edi, %edi
xorl %eax, %eax
callq 0x3540
cmpl $0x0, 0xc(%rbx)
jle 0x894a
leaq -0xa0(%rbp), %r13
leaq 0x2e47(%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 0x32e(%rip), %rdx       # 0x8c49
movq %r13, %rcx
callq 0x3470
testl %eax, %eax
jne 0x89fc
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 0x8901
movl -0x38(%rbp), %edi
callq 0x3260
cmpl $-0x1, %eax
je 0x89f7
movl -0x34(%rbp), %edi
callq 0x3260
cmpl $-0x1, %eax
movq -0x30(%rbp), %r12
je 0x8a02
cmpl $0x0, 0xc(%rbx)
movq -0x40(%rbp), %r13
jle 0x89ab
leaq 0x2e33(%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 0x8984
movq -0x48(%rbp), %rdi
xorl %ebx, %ebx
xorl %esi, %esi
callq 0x35a0
leaq 0x2e0f(%rip), %rsi      # 0xb7ce
xorl %edi, %edi
xorl %eax, %eax
callq 0x3540
jmp 0x8a18
leaq -0xa0(%rbp), %rdi
callq 0x3641
jmp 0x8a07
leaq 0x2e97(%rip), %rdi      # 0xb876
callq 0x34f0
jmp 0x8876
callq 0x36b5
jmp 0x8a07
callq 0x369e
jmp 0x8a07
callq 0x3687
movq -0x30(%rbp), %r12
jmp 0x8a07
callq 0x3670
leaq 0x2dd9(%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