// File: /workspace/github_c_makefile_star2_O0/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
subq $0x70, %rsp
movq %rdi, -0x10(%rbp)
movl $0xffffffff, -0x14(%rbp) # imm = 0xFFFFFFFF
movl $0xffffffff, -0x18(%rbp) # imm = 0xFFFFFFFF
movq -0x10(%rbp), %rax
movl 0xc(%rax), %eax
movq %rsp, %rcx
movq %rcx, -0x20(%rbp)
leaq 0xf(,%rax,8), %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x68(%rbp)
movq %rcx, %rsp
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x40(%rbp)
movq -0x10(%rbp), %rax
movl 0x8(%rax), %edi
callq 0xaf30
movl %eax, %ecx
movq -0x40(%rbp), %rax
movl %ecx, (%rax)
movq -0x40(%rbp), %rax
cmpl $0x0, (%rax)
jge 0xac62
jmp 0xaeed
leaq 0x2a10(%rip), %rdi      # 0xd679
callq 0x35d0
cmpl $0x0, %eax
jne 0xac83
xorl %edi, %edi
leaq 0x2a0a(%rip), %rsi      # 0xd686
movb $0x0, %al
callq 0x3580
leaq 0x2a15(%rip), %rdi      # 0xd69f
callq 0x35d0
cmpl $0x0, %eax
jne 0xaca4
xorl %edi, %edi
leaq 0x2a0f(%rip), %rsi      # 0xd6ac
movb $0x0, %al
callq 0x3580
leaq 0x29ce(%rip), %rdi      # 0xd679
movl $0x42, %esi
movl $0x4, %edx
callq 0xb060
movl %eax, -0x14(%rbp)
cmpl $-0x1, -0x14(%rbp)
jne 0xace7
movl $0x3, %edi
leaq 0x29f7(%rip), %rsi      # 0xd6c6
movb $0x0, %al
callq 0x3580
leaq 0x2a12(%rip), %rdi      # 0xd6ef
callq 0x3520
jmp 0xaeed
leaq 0x29b1(%rip), %rdi      # 0xd69f
movl $0x42, %esi
movl $0x8, %edx
callq 0xb060
movl %eax, -0x18(%rbp)
cmpl $-0x1, -0x14(%rbp)
jne 0xad2a
movl $0x3, %edi
leaq 0x29e9(%rip), %rsi      # 0xd6fb
movb $0x0, %al
callq 0x3580
leaq 0x29cf(%rip), %rdi      # 0xd6ef
callq 0x3520
jmp 0xaeed
movq -0x40(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x44(%rbp)
leaq -0x38(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
leaq 0x38e(%rip), %rdx       # 0xb0d0
leaq -0x44(%rbp), %rcx
callq 0x34a0
cmpl $0x0, %eax
je 0xad68
movl $0x3, %edi
leaq 0x29c8(%rip), %rsi      # 0xd724
movb $0x0, %al
callq 0x3580
jmp 0xaeed
xorl %edi, %edi
leaq 0x29d4(%rip), %rsi      # 0xd745
movb $0x0, %al
callq 0x3580
leaq -0x30(%rbp), %rdi
xorl %eax, %eax
movl %eax, %ecx
leaq 0x479(%rip), %rdx       # 0xb200
movq %rcx, %rsi
callq 0x34a0
cmpl $0x0, %eax
je 0xadac
movl $0x3, %edi
leaq 0x29be(%rip), %rsi      # 0xd75e
movb $0x0, %al
callq 0x3580
jmp 0xaeed
xorl %edi, %edi
leaq 0x29cb(%rip), %rsi      # 0xd780
movb $0x0, %al
callq 0x3580
movl $0x0, -0x48(%rbp)
movl -0x48(%rbp), %eax
movq -0x10(%rbp), %rcx
cmpl 0xc(%rcx), %eax
jge 0xae28
movq -0x68(%rbp), %rdi
movq -0x10(%rbp), %rax
movq %rax, -0x58(%rbp)
movl -0x48(%rbp), %eax
movl %eax, -0x50(%rbp)
movslq -0x48(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
leaq 0x559(%rip), %rdx       # 0xb350
leaq -0x58(%rbp), %rcx
callq 0x34a0
cmpl $0x0, %eax
je 0xae0a
jmp 0xaeed
movl -0x48(%rbp), %edx
xorl %edi, %edi
leaq 0x2984(%rip), %rsi      # 0xd79a
movb $0x0, %al
callq 0x3580
movl -0x48(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x48(%rbp)
jmp 0xadc3
movl -0x14(%rbp), %edi
callq 0x3280
cmpl $-0x1, %eax
jne 0xae4d
movl $0x3, %edi
leaq 0x2973(%rip), %rsi      # 0xd7b4
movb $0x0, %al
callq 0x3580
jmp 0xaeed
movl -0x18(%rbp), %edi
callq 0x3280
cmpl $-0x1, %eax
jne 0xae6f
movl $0x3, %edi
leaq 0x297b(%rip), %rsi      # 0xd7e1
movb $0x0, %al
callq 0x3580
jmp 0xaeed
movl $0x0, -0x48(%rbp)
movl -0x48(%rbp), %eax
movq -0x10(%rbp), %rcx
cmpl 0xc(%rcx), %eax
jge 0xaeb5
movq -0x68(%rbp), %rax
movslq -0x48(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x35e0
movl -0x48(%rbp), %edx
xorl %edi, %edi
leaq 0x296a(%rip), %rsi      # 0xd80d
movb $0x0, %al
callq 0x3580
movl -0x48(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x48(%rbp)
jmp 0xae76
movq -0x38(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x35e0
xorl %edi, %edi
leaq 0x295c(%rip), %rsi      # 0xd827
movb $0x0, %al
callq 0x3580
movq -0x40(%rbp), %rax
movl (%rax), %edi
callq 0x32a0
movl $0x0, -0x4(%rbp)
movl $0x1, -0x5c(%rbp)
jmp 0xaf12
leaq 0x294c(%rip), %rdi      # 0xd840
callq 0x3520
movq -0x40(%rbp), %rax
movl (%rax), %edi
callq 0x32a0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl $0x1, -0x5c(%rbp)
movq -0x20(%rbp), %rax
movq %rax, %rsp
movl -0x4(%rbp), %eax
movq %rbp, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)