// File: /workspace/github_c_makefile_star2_O2/TeaInside[P]teavpn/src/teavpn/server/tcp.c
// Function: teavpn_tcp_server
__attribute__((force_align_arg_pointer)) uint8_t teavpn_tcp_server(server_config *config)
{
	fd_set rd_set;
	int  fd_ret, max_fd;
	ssize_t nwrite, nread;
	int16_t bufchan_index;
	pthread_t accept_worker;
	struct sockaddr_in server_addr;
	struct teavpn_tcp_queue _queues[QUEUE_AMOUNT];
	struct buffer_channel _bufchan[BUFCHAN_ALLOC];
	struct connection_entry _connections[CONNECTION_ALLOC];

	/**
	 * To store config file buffer (parsing).
	 *
	 * Avoid to use heap as long as it
	 * is still eligible to use stack.
	 *
	 * (heap is slower than stack)
	 */
	char config_buffer[4096];

	/** 
	 * Assign internal stack allocation to global vars
	 * in order to make other threads can access them.
	 */
	queues = _queues;
	bufchan = _bufchan;
	connections = _connections;

	/**
	 * Initialize TeaVPN server (vars, socket, iface, etc.)
	 */
	if (teavpn_tcp_server_init(config_buffer, config)) {
		return 1;
	}

	thread_amount = config->threads;

	/**
	 * Prepare worker threads.
	 * (Threads which transmit data to client).
	 *
	 * Use stack allocation as long as possible.
	 */
	struct worker_thread _workers[thread_amount];
	workers = _workers;

	if (thread_amount < 3) {
		debug_log(0, "Minimal threads amount is 3, but %d given", thread_amount);
		goto close_server;
	}


	/**
	 * Create the worker threads.
	 */
	for (register uint8_t i = 0; i < config->threads; ++i) {
		workers[i].busy = false;
		workers[i].num = i;
		pthread_cond_init(&(workers[i].cond), NULL);
		pthread_mutex_init(&(workers[i].mutex), NULL);
		pthread_create(
			&(workers[i].thread),
			NULL,
			(void * (*)(void *))teavpn_tcp_worker_thread,
			(void *)&(workers[i])
		);
		pthread_detach(workers[i].thread);

		#define thread_name (bufchan[0].buffer)
		sprintf(thread_name, "teavpn-worker-%d", i);
		pthread_setname_np(workers[i].thread, thread_name);
		#undef thread_name
	}
	memset(bufchan[0].buffer, 0, sizeof("teavpn-worker-xxx"));

	/**
	 * Prepare server bind address data.
	 */
	memset(&server_addr, 0, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(config->bind_port);
	server_addr.sin_addr.s_addr = inet_addr(config->bind_addr);

	/**
	 * Bind socket to address.
	 */
	if (bind(net_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
		debug_log(0, "Bind socket failed");
		perror("Bind failed");
		goto close_server;
	}

	/**
	 * Listen
	 */
	if (listen(net_fd, 3) < 0) {
		debug_log(0, "Listen socket failed");
		perror("Listen failed");
		goto close_server;
	}

	/**
	 * Ignore SIGPIPE
	 */
	signal(SIGPIPE, SIG_IGN);

	/**
	 * Create accept worker thread.
	 * (Thread which accepts new connection).
	 */
	pthread_create(
		&accept_worker,
		NULL,
		(void * (*)(void *))teavpn_tcp_accept_worker_thread,
		(void *)config
	);
	pthread_setname_np(accept_worker, "accept-worker");
	pthread_detach(accept_worker);

	debug_log(0, "Listening on %s:%d...", config->bind_addr, config->bind_port);

	/**
	 * TeaVPN server event loop.
	 */
	while (true) {

		/**
		 * Calculate maximum value between tap_fd, net_fd and m_pie_fd[0].
		 */
		max_fd = (((tap_fd > net_fd) && (tap_fd > m_pipe_fd[0])) ? tap_fd :
				(net_fd > m_pipe_fd[0]) ? net_fd : m_pipe_fd[0]);

		/**
		 * Set rd_set to zero.
		 *
		 * This is a compulsory step in using
		 * select(2) inside of an event loop.
		 */
		FD_ZERO(&rd_set);

		/**
		 * Add file descriptors to rd_set.
		 */
		FD_SET(net_fd, &rd_set);
		FD_SET(tap_fd, &rd_set);
		FD_SET(m_pipe_fd[0], &rd_set);


		/**
		 * Add all connected clients file descriptor to rd_set.
		 */
		for (register uint16_t i = 0; i < CONNECTION_ALLOC; i++) {
			if (connections[i].connected) {

				/**
				 * Recalculate max fd to make sure that max_fd
				 * has the maximum value from the entire involved
				 * file descriptors.
				 */
				if (connections[i].fd > max_fd) {
					max_fd = connections[i].fd;
				}

				/**
				 * Add file descriptors to rd_set.
				 */
				FD_SET(connections[i].fd, &rd_set);
			}
		}


		/**
		 * Get buffer channel index.
		 */
		do {
			bufchan_index = get_bufchan_index();
		} while (bufchan_index == -1);


		/**
		 * Block main process until there is one or more ready fd.
		 * Read `man 2 select_tut` for details.
		 */
		fd_ret = select(max_fd + 1, &rd_set, NULL, NULL, NULL);

		/**
		 * Got interrupt signal.
		 */
		if ((fd_ret < 0) && (errno == EINTR)) {
			debug_log(2, "select(2) got interrupt signal");
			continue;
		}

		/**
		 * Got an error.
		 */
		if (fd_ret < 0) {
			debug_log(0, "select(2) got an error");
			perror("select()");
			continue;
		}

		/**
		 * Create a macro to manage buffer channel as other data type.
		 *
		 * Don't make a new variable as long as we can use the available
		 * resources in safely way.
		 */
		#define packet ((teavpn_packet *)(bufchan[bufchan_index].buffer))


		/**
		 * Read data from server TUN/TAP.
		 */
		if (FD_ISSET(tap_fd, &rd_set)) {
			/**
			 * Read from TUN/TAP.
			 */
			nread = read(tap_fd, packet->data.data, TEAVPN_TAP_READ_SIZE);
			if (nread < 0) {
				debug_log(0, "Error read from tap_fd");
				perror("Error read from tap_fd");
				goto next_1;
			}

			packet->info.type = TEAVPN_PACKET_DATA;
			packet->info.len = TEAVPN_PACK(nread);
			for (register uint16_t i = 0; i < CONNECTION_ALLOC; i++) {
				if (connections[i].connected) {
					/**
					 * Insert write queue.
					 *
					 * Send bufchan_index to connection i.
					 */
					bufchan[bufchan_index].ref_count++;
					// printf("i = %d;  r = %d\n", bufchan_index, bufchan[bufchan_index].ref_count);
					enqueue_packet(i, bufchan_index);
					thread_job_broadcast();
				}
			}
		}


		next_1:
		/**
		 * Traverse clients fd and read data from clients.
		 */
		for (register uint16_t i = 0; i < CONNECTION_ALLOC; i++) {
			if (connections[i].connected) {
				if (FD_ISSET(connections[i].fd, &rd_set)) {

					/**
					 * Get buffer channel index.
					 */
					do {
						bufchan_index = get_bufchan_index();
					} while (bufchan_index == -1);

					nread = read(connections[i].fd, packet, TEAVPN_PACKET_BUFFER);

					/**
					 * Connection closed by client.
					 */
					if (nread == 0) {
						FD_CLR(connections[i].fd, &rd_set);
						close(connections[i].fd);
						debug_log(1, "(%s:%d) connection closed",
							inet_ntoa(connections[i].addr.sin_addr),
							ntohs(connections[i].addr.sin_port)
						);
						connection_zero(i);
						continue;
					}

					/**
					 * Error read from client fd.
					 */
					if (nread < 0) {
						char *remote_addr = inet_ntoa(connections[i].addr.sin_addr);
						uint16_t remote_port = ntohs(connections[i].addr.sin_port);

						debug_log(0, "Error read from (%s:%d)", remote_addr, remote_port);
						perror("Error read from connection fd");

						/**
						 * Increment the error counter.
						 */
						connections[i].error++;

						/**
						 * Force disconnect client if it has
						 * reached the max number of errors.
						 */
						if (connections[i].error > MAX_CLIENT_ERR) {
							debug_log(0,
								"Client %s:%d has been disconnected because it has reached the max number of errors",
								remote_port,
								remote_port
							);
							FD_CLR(connections[i].fd, &rd_set);
							close(connections[i].fd);
							connection_zero(i);
						}

						continue;
					}


					/**
					 * Write to TUN/TAP server.
					 */
					if (packet->info.type == TEAVPN_PACKET_DATA) {

						while (nread < (packet->info.len)) {
							register ssize_t tmp_nread;
							debug_log(3, "Read extra %ld/%ld bytes", nread, packet->info.len);
							tmp_nread = read(
								connections[i].fd,
								&(((char *)packet)[nread]),
								packet->info.len - nread
							);

							if (tmp_nread < 0) {
								connections[i].error++;
								perror("Error read extra");
							} else {
								nread += tmp_nread;
							}
						}

						connections[i].seq++;
						debug_log(3, "[%ld] Read from client %s:%d (server_seq: %ld) (client_seq: %ld) (seq %s)",
							connections[i].seq,
							inet_ntoa(connections[i].addr.sin_addr),
							ntohs(connections[i].addr.sin_port),
							connections[i].seq,
							packet->info.seq,
							(connections[i].seq == packet->info.seq) ? "match" : "invalid"
						);

						nwrite = write(tap_fd, &(packet->data.data), nread - TEAVPN_PACK(0));
						if (nwrite < 0) {
							connections[i].error++;
							perror("Error write to tap_fd");
							continue;
						}

						debug_log(3, "Write to tap_fd %ld bytes", nwrite);

					} else {
						connections[i].error++;
					}
				}
			}
		}


		/**
		 * Deal with new connection.
		 */
		if (FD_ISSET(m_pipe_fd[0], &rd_set)) {
			uint8_t sig_x;

			nread = read(m_pipe_fd[0], &sig_x, sizeof(sig_x));
			if (nread < 0) {
				debug_log(0, "Error read from m_pipe_fd[0]");
				perror("Error read from m_pipe_fd[0]");
			}
		}

		if (FD_ISSET(net_fd, &rd_set)) {
			pthread_cond_signal(&accept_worker_cond);
		}

		/**
		 * Since macro doesn't have scope limit, we have to undef here
		 * so that it doesn't distrub the outer scope of variable usage.
		 */
		#undef packet
	}

	close_server:
	close(m_pipe_fd[0]);
	close(m_pipe_fd[1]);
	close(net_fd);
	close(tap_fd);
	return 1;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
andq $-0x10, %rsp
subq $0x1a1a0, %rsp          # imm = 0x1A1A0
movq %rsp, %rbx
movq %rdi, %r15
movq %fs:0x28, %rax
movq %rax, 0x1a190(%rbx)
leaq 0x19c20(%rbx), %rax
movq %rax, 0x7330(%rip)      # 0xb368
leaq 0x17a0(%rbx), %rax
movq %rax, 0x732a(%rip)      # 0xb370
leaq 0x1020(%rbx), %rax
movq %rax, 0x7324(%rip)      # 0xb378
xorl %eax, %eax
cmpq $0x18480, %rax          # imm = 0x18480
je 0x406f
andw $0x0, 0x17a0(%rbx,%rax)
addq $0x1030, %rax           # imm = 0x1030
jmp 0x4056
pushq $0x12
popq %rax
cmpq $0x492, %rax            # imm = 0x492
je 0x4099
movb $0x0, 0x19c0e(%rbx,%rax)
orq $-0x1, 0x19c16(%rbx,%rax)
orl $-0x1, 0x19c1e(%rbx,%rax)
addq $0x18, %rax
jmp 0x4072
xorl %r14d, %r14d
cmpw $0x18, %r14w
je 0x40b1
movzwl %r14w, %edi
callq 0x58c5
incl %r14d
jmp 0x409c
cmpq $0x0, 0x8(%r15)
je 0x40cc
leaq 0x20(%rbx), %rdi
movq %r15, %rsi
callq 0x26a8
testb %al, %al
je 0x4230
movb 0x3c(%r15), %al
leaq 0x734d(%rip), %rcx      # 0xb424
movb %al, (%rcx)
cmpq $0x0, 0x18(%r15)
je 0x4239
leaq 0x72ad(%rip), %rdi      # 0xb398
callq 0x21b0
testl %eax, %eax
js 0x43b3
leaq 0x7325(%rip), %rax      # 0xb424
cmpb $0x2, (%rax)
jb 0x4112
leaq 0x36f1(%rip), %rdi      # 0x77fc
xorl %eax, %eax
callq 0x5aec
movq 0x20(%r15), %rdi
pushq $0x1
popq %rsi
callq 0x5c06
movl %eax, 0x7270(%rip)      # 0xb394
movq 0x20(%r15), %rsi
testl %eax, %eax
js 0x4249
leaq 0x370f(%rip), %rdi      # 0x7846
xorl %eax, %eax
callq 0x5aec
movq 0x20(%r15), %rdi
callq 0x25a0
movq %rax, %r12
movq 0x28(%r15), %rdi
callq 0x25a0
movq %r15, %r14
movq %rax, %r13
movq 0x30(%r15), %rdi
callq 0x25a0
movq %rax, %r15
movzwl 0x38(%r14), %ecx
leaq 0x37c4(%rip), %rsi      # 0x7935
leaq 0x1a0a0(%rbx), %rdi
movq %r12, %rdx
xorl %eax, %eax
callq 0x2390
leaq 0x37de(%rip), %rsi      # 0x7967
leaq 0x1a120(%rbx), %rdi
movq %r12, %rdx
movq %r13, %rcx
movq %r15, %r8
xorl %eax, %eax
callq 0x2390
movq %r12, %rdi
callq 0x2030
movq %r13, %rdi
callq 0x2030
movq %r15, %rdi
callq 0x2030
leaq 0x37d1(%rip), %rdi      # 0x7990
leaq 0x1a0a0(%rbx), %r15
movq %r15, %rsi
xorl %eax, %eax
callq 0x5aec
movq %r15, %rdi
callq 0x2140
testl %eax, %eax
jne 0x4204
leaq 0x37ad(%rip), %rdi      # 0x7990
leaq 0x1a120(%rbx), %r15
movq %r15, %rsi
xorl %eax, %eax
callq 0x5aec
movq %r15, %rdi
callq 0x2140
testl %eax, %eax
je 0x4294
leaq 0x404d(%rip), %rdi      # 0x8258
xorl %eax, %eax
callq 0x5aec
movl 0x7180(%rip), %edi      # 0xb398
callq 0x21a0
movl 0x7179(%rip), %edi      # 0xb39c
callq 0x21a0
movl 0x7166(%rip), %edi      # 0xb394
jmp 0x4268
leaq 0x3538(%rip), %rdi      # 0x776f
jmp 0x4240
leaq 0x3fb3(%rip), %rdi      # 0x81f3
xorl %eax, %eax
callq 0x5aec
jmp 0x426d
leaq 0x3fdc(%rip), %rdi      # 0x822c
xorl %eax, %eax
callq 0x5aec
movl 0x713b(%rip), %edi      # 0xb398
callq 0x21a0
movl 0x7134(%rip), %edi      # 0xb39c
callq 0x21a0
movq %fs:0x28, %rax
cmpq 0x1a190(%rbx), %rax
jne 0x4c33
movb $0x1, %al
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x7189(%rip), %rax      # 0xb424
cmpb $0x0, (%rax)
je 0x42ae
leaq 0x35ca(%rip), %rdi      # 0x7871
xorl %eax, %eax
callq 0x5aec
pushq $0x2
popq %rdi
pushq $0x1
popq %rsi
xorl %edx, %edx
callq 0x2410
movl %eax, 0x70cf(%rip)      # 0xb390
testl %eax, %eax
js 0x4b9f
movq %r14, %r15
leaq 0x7151(%rip), %rax      # 0xb424
cmpb $0x0, (%rax)
je 0x4300
leaq 0x35c0(%rip), %rdi      # 0x789f
xorl %eax, %eax
callq 0x5aec
leaq 0x7137(%rip), %rax      # 0xb424
cmpb $0x0, (%rax)
je 0x4300
leaq 0x3f8e(%rip), %rdi      # 0x8287
xorl %eax, %eax
callq 0x5aec
movl 0x708a(%rip), %edi      # 0xb390
leaq 0x1a0a0(%rbx), %rcx
movl $0x1, (%rcx)
pushq $0x1
popq %rsi
pushq $0x2
popq %rdx
pushq $0x4
popq %r8
callq 0x20b0
testl %eax, %eax
js 0x4bbe
leaq 0x70f3(%rip), %rax      # 0xb424
cmpb $0x0, (%rax)
je 0x4344
leaq 0x3f83(%rip), %rdi      # 0x82c0
xorl %eax, %eax
callq 0x5aec
movq %rsp, %r12
movzbl 0x3d(%r15), %esi
movb %sil, 0x702d(%rip)      # 0xb380
movq %rsp, %rax
imull $0x68, %esi, %ecx
addl $0xf, %ecx
andl $-0x10, %ecx
subq %rcx, %rax
movq %rax, %rsp
movq %rax, 0x701c(%rip)      # 0xb388
cmpl $0x3, %esi
jae 0x43d1
leaq 0x3718(%rip), %rdi      # 0x7a90
xorl %eax, %eax
callq 0x5aec
movl 0x7013(%rip), %edi      # 0xb398
callq 0x21a0
movl 0x700c(%rip), %edi      # 0xb39c
callq 0x21a0
movl 0x6ff5(%rip), %edi      # 0xb390
callq 0x21a0
movl 0x6fee(%rip), %edi      # 0xb394
callq 0x21a0
movq %r12, %rsp
jmp 0x426d
leaq 0x3e53(%rip), %r14      # 0x820d
movq %r14, %rdi
xorl %eax, %eax
callq 0x5aec
movq %r14, %rdi
callq 0x2350
jmp 0x426d
movq %r12, 0x8(%rbx)
leaq 0x36de(%rip), %r12      # 0x7aba
xorl %r15d, %r15d
xorl %r13d, %r13d
movzbl 0x3d(%r14), %eax
cmpq %rax, %r13
jae 0x4495
movq 0x6f91(%rip), %rax      # 0xb388
leaq (%rax,%r15), %rdi
addq $0x38, %rdi
movb $0x0, -0x38(%rdi)
movb %r13b, -0x37(%rdi)
xorl %esi, %esi
callq 0x22a0
movq 0x6f73(%rip), %rax      # 0xb388
leaq (%rax,%r15), %rdi
addq $0x10, %rdi
xorl %esi, %esi
callq 0x23d0
movq 0x6f5d(%rip), %rcx      # 0xb388
leaq (%rcx,%r15), %rdi
addq $0x8, %rdi
addq %r15, %rcx
xorl %esi, %esi
leaq 0x7f9(%rip), %rdx       # 0x4c38
callq 0x2310
movq 0x6f3d(%rip), %rax      # 0xb388
movq 0x8(%rax,%r15), %rdi
callq 0x22e0
movq 0x6f14(%rip), %rdi      # 0xb370
addq $0x10, %rdi
movq %r12, %rsi
movl %r13d, %edx
xorl %eax, %eax
callq 0x2390
movq 0x6f14(%rip), %rax      # 0xb388
movq 0x8(%rax,%r15), %rdi
movq 0x6ef0(%rip), %rsi      # 0xb370
addq $0x10, %rsi
callq 0x2170
incq %r13
addq $0x68, %r15
jmp 0x43e2
movq 0x6ed4(%rip), %rax      # 0xb370
xorps %xmm0, %xmm0
movups %xmm0, 0x10(%rax)
andw $0x0, 0x20(%rax)
leaq 0x1a120(%rbx), %r15
andq $0x0, 0x8(%r15)
movw $0x2, (%r15)
movq %r14, %r13
movzwl 0x3a(%r14), %eax
rolw $0x8, %ax
movw %ax, 0x2(%r15)
movq (%r14), %rdi
callq 0x2210
movl %eax, 0x4(%r15)
movl 0x6eb3(%rip), %edi      # 0xb390
pushq $0x10
popq %rdx
movq %r15, %rsi
callq 0x2300
testl %eax, %eax
js 0x4bf9
movl 0x6e9a(%rip), %edi      # 0xb390
pushq $0x3
popq %rsi
callq 0x22f0
testl %eax, %eax
js 0x4c10
pushq $0xd
popq %rdi
pushq $0x1
popq %r14
movq %r14, %rsi
callq 0x2230
leaq 0xa71(%rip), %rdx       # 0x4f8d
leaq 0x18(%rbx), %r12
movq %r12, %rdi
xorl %esi, %esi
movq %r13, %rcx
callq 0x2310
movq (%r12), %rdi
leaq 0x35d5(%rip), %rsi      # 0x7b0d
callq 0x2170
movq (%r12), %rdi
callq 0x22e0
movq (%r13), %rsi
movzwl 0x3a(%r13), %edx
leaq 0x35c5(%rip), %rdi      # 0x7b1b
xorl %eax, %eax
callq 0x5aec
pushq $0x40
popq %r12
movl 0x6e2d(%rip), %edi      # 0xb394
movl 0x6e23(%rip), %ecx      # 0xb390
movl 0x6e25(%rip), %esi      # 0xb398
cmpl %esi, %ecx
movl %esi, %eax
cmovgl %ecx, %eax
xorl %edx, %edx
cmpq $0x10, %rdx
je 0x4590
andq $0x0, 0x1a0a0(%rbx,%rdx,8)
incq %rdx
jmp 0x457c
cmpl %esi, %edi
movl %eax, %r13d
cmovgl %edi, %r13d
cmpl %ecx, %edi
cmovlel %eax, %r13d
movl %ecx, %eax
cltd
idivl %r12d
movslq %eax, %rdx
shll $0x6, %eax
subl %eax, %ecx
movq %r14, %rax
shlq %cl, %rax
orq %rax, 0x1a0a0(%rbx,%rdx,8)
movl %edi, %eax
cltd
idivl %r12d
movslq %eax, %rdx
shll $0x6, %eax
subl %eax, %edi
movq %r14, %rax
movl %edi, %ecx
shlq %cl, %rax
orq %rax, 0x1a0a0(%rbx,%rdx,8)
movl %esi, %eax
cltd
idivl %r12d
movslq %eax, %rdx
shll $0x6, %eax
subl %eax, %esi
movq %r14, %rax
movl %esi, %ecx
shlq %cl, %rax
orq %rax, 0x1a0a0(%rbx,%rdx,8)
movq 0x6d7a(%rip), %rsi      # 0xb378
pushq $0x4
popq %rdi
cmpq $0x784, %rdi            # imm = 0x784
je 0x463d
cmpb $0x1, (%rsi,%rdi)
jne 0x4637
movl -0x4(%rsi,%rdi), %ecx
cmpl %r13d, %ecx
cmovgl %ecx, %r13d
movl %ecx, %eax
cltd
idivl %r12d
movslq %eax, %rdx
shll $0x6, %eax
subl %eax, %ecx
movq %r14, %rax
shlq %cl, %rax
orq %rax, 0x1a0a0(%rbx,%rdx,8)
addq $0x50, %rdi
jmp 0x4601
callq 0x590b
cmpw $-0x1, %ax
je 0x463d
movl %eax, %r15d
incl %r13d
movl %r13d, %edi
leaq 0x1a0a0(%rbx), %rsi
xorl %edx, %edx
xorl %ecx, %ecx
xorl %r8d, %r8d
callq 0x2290
testl %eax, %eax
js 0x4775
movl 0x6d22(%rip), %edi      # 0xb394
movl %edi, %eax
cltd
idivl %r12d
cltq
movq 0x1a0a0(%rbx,%rax,8), %rax
btq %rdx, %rax
jae 0x47bf
movq 0x6cdd(%rip), %rax      # 0xb370
movswq %r15w, %rcx
imulq $0x1030, %rcx, %r14     # imm = 0x1030
leaq (%rax,%r14), %rsi
addq $0x20, %rsi
movl $0xbb8, %edx            # imm = 0xBB8
callq 0x21d0
testq %rax, %rax
js 0x47a6
movq 0x6cb0(%rip), %rcx      # 0xb370
movl $0x2, 0x10(%rcx,%r14)
addl $0x10, %eax
movw %ax, 0x14(%rcx,%r14)
xorl %r12d, %r12d
cmpq $0x18, %r12
je 0x47bf
movq 0x6c92(%rip), %rax      # 0xb378
imulq $0x50, %r12, %rcx
cmpb $0x1, 0x4(%rax,%rcx)
jne 0x476d
movq 0x6c78(%rip), %rax      # 0xb370
incw (%rax,%r14)
movq 0x6c64(%rip), %rax      # 0xb368
xorl %edx, %edx
leaq 0x18(%rdx), %rcx
cmpq $0x498, %rcx            # imm = 0x498
je 0x471e
cmpb $0x0, (%rax,%rdx)
movq %rcx, %rdx
jne 0x4706
jmp 0x472e
leaq 0x352c(%rip), %rdi      # 0x7c51
xorl %eax, %eax
callq 0x5aec
jmp 0x46fd
movw $0x1, -0x18(%rax,%rcx)
movw %r12w, -0x8(%rax,%rcx)
movw %r15w, -0x6(%rax,%rcx)
movzbl 0x6c38(%rip), %eax      # 0xb380
movq 0x6c39(%rip), %rcx      # 0xb388
addq $-0x30, %rcx
incq %rax
decq %rax
je 0x476d
leaq 0x68(%rcx), %rdi
cmpb $0x0, 0x30(%rcx)
movq %rdi, %rcx
jne 0x4756
callq 0x21f0
incq %r12
jmp 0x46d5
callq 0x2050
cmpl $0x4, (%rax)
jne 0x4b80
leaq 0x6c9a(%rip), %rax      # 0xb424
cmpb $0x2, (%rax)
jb 0x4561
leaq 0x2e91(%rip), %rdi      # 0x762b
xorl %eax, %eax
callq 0x5aec
jmp 0x4561
leaq 0x2ed8(%rip), %r14      # 0x7685
movq %r14, %rdi
xorl %eax, %eax
callq 0x5aec
movq %r14, %rdi
callq 0x2350
xorl %r12d, %r12d
cmpq $0x18, %r12
je 0x4b01
movq 0x6ba5(%rip), %rax      # 0xb378
imulq $0x50, %r12, %r14
cmpb $0x1, 0x4(%rax,%r14)
jne 0x4a3b
addq %r14, %rax
movl (%rax), %eax
cltd
pushq $0x40
popq %rcx
idivl %ecx
cltq
movq 0x1a0a0(%rbx,%rax,8), %rax
btq %rdx, %rax
jae 0x4a3b
callq 0x590b
cmpw $-0x1, %ax
je 0x4802
movq 0x6b64(%rip), %rcx      # 0xb378
movl (%rcx,%r14), %edi
movq 0x6b51(%rip), %rcx      # 0xb370
movswq %ax, %rax
imulq $0x1030, %rax, %r13     # imm = 0x1030
leaq (%rcx,%r13), %rsi
addq $0x10, %rsi
movl $0xfa0, %edx            # imm = 0xFA0
callq 0x21d0
testq %rax, %rax
je 0x48e4
js 0x4a43
movq %rax, %r15
movq 0x6b1b(%rip), %rax      # 0xb370
cmpl $0x2, 0x10(%rax,%r13)
jne 0x495e
movzwl 0x14(%rax,%r13), %edx
cmpq %rdx, %r15
jge 0x496f
leaq 0x6bad(%rip), %rcx      # 0xb424
cmpb $0x3, (%rcx)
jb 0x4894
leaq 0x2e55(%rip), %rdi      # 0x76d8
movq %r15, %rsi
xorl %eax, %eax
callq 0x5aec
movq 0x6adc(%rip), %rax      # 0xb370
movq 0x6add(%rip), %rcx      # 0xb378
movl (%rcx,%r14), %edi
leaq (%rax,%r13), %rcx
leaq (%r15,%rcx), %rsi
addq $0x10, %rsi
movzwl 0x14(%rax,%r13), %edx
subq %r15, %rdx
callq 0x21d0
testq %rax, %rax
js 0x48ca
addq %rax, %r15
movq 0x6aa8(%rip), %rax      # 0xb370
jmp 0x4861
movq 0x6aa7(%rip), %rax      # 0xb378
incb 0x5(%rax,%r14)
leaq 0x2e14(%rip), %rdi      # 0x76f1
callq 0x2350
jmp 0x48c1
movq 0x6a8d(%rip), %rax      # 0xb378
movl (%rax,%r14), %ecx
pushq $-0x2
popq %rsi
rolq %cl, %rsi
movl %ecx, %eax
cltd
pushq $0x40
popq %rdi
idivl %edi
cltq
andq %rsi, 0x1a0a0(%rbx,%rax,8)
movl %ecx, %edi
callq 0x21a0
leaq 0x6b0f(%rip), %rax      # 0xb424
cmpb $0x0, (%rax)
je 0x4950
movq 0x6a57(%rip), %rax      # 0xb378
movl 0x44(%rax,%r14), %edi
callq 0x20d0
movq 0x6a46(%rip), %rcx      # 0xb378
movzwl 0x42(%rcx,%r14), %ecx
rolw $0x8, %cx
movzwl %cx, %edx
leaq 0x31eb(%rip), %rdi      # 0x7b31
movq %rax, %rsi
xorl %eax, %eax
callq 0x5aec
movzwl %r12w, %edi
callq 0x58c5
jmp 0x4a3b
movq 0x6a13(%rip), %rax      # 0xb378
incb 0x5(%rax,%r14)
jmp 0x4a3b
movq 0x6a02(%rip), %rcx      # 0xb378
movq 0x8(%rcx,%r14), %rsi
incq %rsi
movq %rsi, 0x8(%rcx,%r14)
leaq 0x6a9a(%rip), %rdx      # 0xb424
cmpb $0x3, (%rdx)
jb 0x49fb
movl 0x44(%rcx,%r14), %edi
movq %rsi, 0x8(%rbx)
callq 0x20d0
movq 0x69d4(%rip), %rdx      # 0xb378
movzwl 0x42(%rdx,%r14), %ecx
rolw $0x8, %cx
movzwl %cx, %ecx
movq 0x8(%rdx,%r14), %r8
movq 0x69b3(%rip), %rdx      # 0xb370
movq 0x18(%rdx,%r13), %r9
cmpq %r9, %r8
leaq 0x2b62(%rip), %r10      # 0x752e
leaq 0x2b55(%rip), %rdx      # 0x7528
cmoveq %rdx, %r10
subq $0x8, %rsp
leaq 0x31f2(%rip), %rdi      # 0x7bd4
movq 0x8(%rbx), %rsi
movq %rax, %rdx
xorl %eax, %eax
pushq %r10
callq 0x5aec
popq %rcx
popq %rdx
movq 0x6975(%rip), %rax      # 0xb370
movl 0x6993(%rip), %edi      # 0xb394
leaq (%rax,%r13), %rsi
addq $0x20, %rsi
addq $-0x10, %r15
movq %r15, %rdx
callq 0x20c0
testq %rax, %rax
js 0x4ae4
leaq 0x69ff(%rip), %rcx      # 0xb424
cmpb $0x3, (%rcx)
jb 0x4a3b
leaq 0x2d24(%rip), %rdi      # 0x7755
movq %rax, %rsi
xorl %eax, %eax
callq 0x5aec
incq %r12
jmp 0x47c2
movq 0x692e(%rip), %rax      # 0xb378
movl 0x44(%rax,%r14), %edi
callq 0x20d0
movq 0x691d(%rip), %rcx      # 0xb378
movzwl 0x42(%rcx,%r14), %ecx
rolw $0x8, %cx
movzwl %cx, %r15d
leaq 0x30db(%rip), %rdi      # 0x7b4b
movq %rax, %rsi
movl %r15d, %edx
xorl %eax, %eax
callq 0x5aec
leaq 0x30df(%rip), %rdi      # 0x7b63
callq 0x2350
movq 0x68e8(%rip), %rax      # 0xb378
movb 0x5(%rax,%r14), %cl
incb %cl
movb %cl, 0x5(%rax,%r14)
cmpb $0x10, %cl
jb 0x4a3b
leaq 0x30d9(%rip), %rdi      # 0x7b81
movl %r15d, %esi
movl %r15d, %edx
xorl %eax, %eax
callq 0x5aec
movq 0x68bc(%rip), %rax      # 0xb378
movl (%rax,%r14), %ecx
pushq $-0x2
popq %rsi
rolq %cl, %rsi
movl %ecx, %eax
cltd
pushq $0x40
popq %rdi
idivl %edi
cltq
andq %rsi, 0x1a0a0(%rbx,%rax,8)
movl %ecx, %edi
callq 0x21a0
jmp 0x4950
movq 0x688d(%rip), %rax      # 0xb378
incb 0x5(%rax,%r14)
leaq 0x3127(%rip), %rdi      # 0x7c1e
callq 0x2350
jmp 0x4a3b
movl 0x6891(%rip), %edi      # 0xb398
movl %edi, %eax
cltd
pushq $0x40
popq %r12
idivl %r12d
cltq
movq 0x1a0a0(%rbx,%rax,8), %rax
btq %rdx, %rax
pushq $0x1
popq %r14
jae 0x4b36
leaq 0x17(%rbx), %rsi
movq %r14, %rdx
callq 0x21d0
testq %rax, %rax
js 0x4b65
movl 0x6854(%rip), %eax      # 0xb390
cltd
idivl %r12d
cltq
movq 0x1a0a0(%rbx,%rax,8), %rax
btq %rdx, %rax
jae 0x4561
leaq 0x6845(%rip), %rdi      # 0xb3a0
callq 0x21f0
jmp 0x4561
leaq 0x30c8(%rip), %r15      # 0x7c34
movq %r15, %rdi
xorl %eax, %eax
callq 0x5aec
movq %r15, %rdi
callq 0x2350
jmp 0x4b36
leaq 0x2ac3(%rip), %rdi      # 0x764a
xorl %eax, %eax
callq 0x5aec
leaq 0x2acc(%rip), %rdi      # 0x7661
callq 0x2350
jmp 0x4561
leaq 0x36c8(%rip), %rdi      # 0x826e
xorl %eax, %eax
callq 0x5aec
leaq 0x2cd4(%rip), %rdi      # 0x7888
callq 0x2350
jmp 0x4212
leaq 0x3726(%rip), %rdi      # 0x82eb
callq 0x2350
leaq 0x36db(%rip), %rdi      # 0x82ac
xorl %eax, %eax
callq 0x5aec
movl 0x67ba(%rip), %edi      # 0xb398
callq 0x21a0
movl 0x67b3(%rip), %edi      # 0xb39c
callq 0x21a0
movl 0x679c(%rip), %edi      # 0xb390
jmp 0x4223
leaq 0x2ecb(%rip), %rdi      # 0x7acb
xorl %eax, %eax
callq 0x5aec
leaq 0x2ed0(%rip), %rdi      # 0x7ade
jmp 0x4c25
leaq 0x2ed3(%rip), %rdi      # 0x7aea
xorl %eax, %eax
callq 0x5aec
leaq 0x2eda(%rip), %rdi      # 0x7aff
callq 0x2350
movq 0x8(%rbx), %r12
jmp 0x437f
callq 0x2110