// File: /workspace/github_c_makefile_star2_O0/sprt[P]lossless-transport/src/receiver.c
// Function: main_loop
void main_loop(void) {
	log_msg("---------- Waiting for a packet...\n");
	log_msg("Window: [%zu, %zu], buffer: %zu/%zu\n", window_start(w),
		window_end(w), window_buffer_size(w), window_get_size(w));

	/* Read the datagram received into a buffer */
	char buf[MAX_PACKET_SIZE];
	int len = recv(sockfd, buf, MAX_PACKET_SIZE, 0);
	if (len == -1) {
		exit_perror("recv");
	}

	/* Decode the datagram into a packet */
	pkt_t *pkt = pkt_new();
	if (pkt == NULL) {
		exit_msg("Could not allocate packet\n");
	}

	pkt_status_code decerr = pkt_decode(buf, len, pkt);
	if (decerr != PKT_OK) {
		log_msg("Error decoding packet (%s), ignoring\n", pkt_code_to_str(decerr));
		pkt_del(pkt);
		return;
	}

	log_msg("< %s\n", pkt_repr(pkt));

	if (!window_has(w, pkt_get_seqnum(pkt))) {
		log_msg("Out of window, ignoring\n");
		pkt_del(pkt);
		return;
	}

	/* We're gonna send a (N)ACK so let's allocate a new packet to reply */
	pkt_t *reply = pkt_new();
	if (reply == NULL) {
		exit_msg("Could not allocate reply packet\n");
	}

	if (pkt_get_tr(pkt)) {
		/* Send a NACK if we receive a truncated packet */
		pkt_status_code err = PKT_OK;
		err = err || pkt_set_type(reply, PTYPE_NACK);
		/* We don't store truncated packets so the window size doesn't change */
		err = err || pkt_set_window(reply, window_available(w));
		err = err || pkt_set_seqnum(reply, pkt_get_seqnum(pkt));

		if (err != PKT_OK) {
			exit_msg("Could not create packet: %s\n",
				pkt_code_to_str(err));
		}

		if (send_packet(sockfd, reply) == -1) {
			exit_perror("Could not send NACK: send:");
		}

		pkt_del(pkt);
		log_msg("> %s\n", pkt_repr(reply));
	} else {
		/* We're gonna send an ACK, but first we store the received
		 * packet in the buffer, and then we try to write out packets to
		 * the file, so that we can reply with an accurate window size. */

		if (window_find_seqnum(w, pkt_get_seqnum(pkt)) != NULL) {
			log_msg("Already in buffer\n");
		} else {
			if (window_push(w, pkt) == -1) {
				if (window_full(w)) {
					log_msg("Buffer full, not adding\n");
					// pkt_del(pkt);
					// pkt_del(reply);
					// return;
				} else {
					exit_msg("Could not add packet to buffer\n");
				}
			} else {
				log_msg("%d\n", pkt_get_seqnum(pkt));
			}
		}

		/* Save the timestamp of the packet we just received in case
		 * it's immediately removed from the buffer and freed. */
		uint32_t ack_timestamp = pkt_get_timestamp(pkt);

		/* Find the next in-sequence packet. If it's not in the buffer,
		 * we can't acknowledge any packet. */
		pkt_t *next_pkt = window_find_seqnum(w, window_start(w));
		while (next_pkt != NULL) {
			/* Try to write the packet to the file. Iff this succeeds,
			 * we can pop it from the buffer and slide the window. */

			const char *payload = pkt_get_payload(next_pkt);
			size_t payload_len = pkt_get_length(next_pkt);

			if (fwrite(payload, sizeof (*payload), payload_len, outfile) < payload_len) {
				exit_msg("Error writing to file\n");
			}

			log_msg("Wrote packet #%d\n", pkt_get_seqnum(next_pkt));
			assert(window_pop_timestamp(w, pkt_get_timestamp(next_pkt)) == next_pkt);

			/* We don't store truncated packets in the buffer so no
			* need to check for that */
			if (pkt_get_length(next_pkt) == 0) {
				log_msg("Received EOF packet, ready to quit\n");
			} else {
				/* Don't slide the window when we receive the
				* EOF packet. Rationale: the ACK may get lost
				* and when the sender retransmits the EOF packet,
				* it would fall outside our window. */
				window_slide(w);
			}

			pkt_del(next_pkt);
			next_pkt = window_find_seqnum(w, window_start(w));
		}

		assert(fflush(outfile) == 0);

		/* There's no duplication so we can just send an ACK */

		pkt_status_code err = PKT_OK;
		err = err || pkt_set_type(reply, PTYPE_ACK);
		err = err || pkt_set_window(reply, window_available(w));
		err = err || pkt_set_seqnum(reply, window_start(w));
		err = err || pkt_set_timestamp(reply, ack_timestamp);

		if (err != PKT_OK) {
			exit_msg("Could not create packet: %s\n",
				pkt_code_to_str(err));
		}

		if (send_packet(sockfd, reply) == -1) {
			exit_perror("Could not send ACK: send:");
		}

		log_msg("> %s\n", pkt_repr(reply));

		log_msg("Window: [%zu, %zu], buffer: %zu/%zu\n", window_start(w),
			window_end(w), window_buffer_size(w), window_get_size(w));
	}

	pkt_del(reply);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x300, %rsp            # imm = 0x300
leaq 0x1365(%rip), %rdi      # 0x41f7
movb $0x0, %al
callq 0x1cd0
movq 0x46d0(%rip), %rdi      # 0x7570
callq 0x2670
movq %rax, -0x270(%rbp)
movq 0x46bd(%rip), %rdi      # 0x7570
callq 0x2690
movq %rax, -0x268(%rbp)
movq 0x46aa(%rip), %rdi      # 0x7570
callq 0x29d0
movq %rax, -0x260(%rbp)
movq 0x4697(%rip), %rdi      # 0x7570
callq 0x2890
movq -0x270(%rbp), %rsi
movq -0x268(%rbp), %rdx
movq -0x260(%rbp), %rcx
movq %rax, %r8
leaq 0x131e(%rip), %rdi      # 0x421b
movb $0x0, %al
callq 0x1cd0
movl 0x422a(%rip), %edi      # 0x7134
leaq -0x210(%rbp), %rsi
movl $0x210, %edx            # imm = 0x210
xorl %ecx, %ecx
callq 0x1040
movl %eax, -0x214(%rbp)
cmpl $-0x1, -0x214(%rbp)
jne 0x2f38
leaq 0x130d(%rip), %rdi      # 0x4240
callq 0x1e50
movb $0x0, %al
callq 0x1340
movq %rax, -0x220(%rbp)
cmpq $0x0, -0x220(%rbp)
jne 0x2f5e
leaq 0x12ee(%rip), %rdi      # 0x4245
movb $0x0, %al
callq 0x1da0
leaq -0x210(%rbp), %rdi
movslq -0x214(%rbp), %rsi
movq -0x220(%rbp), %rdx
callq 0x14a0
movl %eax, -0x224(%rbp)
cmpl $0x0, -0x224(%rbp)
je 0x2fb4
movl -0x224(%rbp), %edi
callq 0x18d0
movq %rax, %rsi
leaq 0x12c4(%rip), %rdi      # 0x4260
movb $0x0, %al
callq 0x1cd0
movq -0x220(%rbp), %rdi
callq 0x1360
jmp 0x3644
movq -0x220(%rbp), %rdi
callq 0x1ef0
movq %rax, %rsi
leaq 0x12bc(%rip), %rdi      # 0x4286
movb $0x0, %al
callq 0x1cd0
movq 0x4598(%rip), %rax      # 0x7570
movq %rax, -0x278(%rbp)
movq -0x220(%rbp), %rdi
callq 0x19a0
movq -0x278(%rbp), %rdi
movzbl %al, %eax
movl %eax, %esi
callq 0x2750
testb $0x1, %al
jne 0x301f
leaq 0x1285(%rip), %rdi      # 0x428c
movb $0x0, %al
callq 0x1cd0
movq -0x220(%rbp), %rdi
callq 0x1360
jmp 0x3644
movb $0x0, %al
callq 0x1340
movq %rax, -0x230(%rbp)
cmpq $0x0, -0x230(%rbp)
jne 0x3045
leaq 0x1267(%rip), %rdi      # 0x42a5
movb $0x0, %al
callq 0x1da0
movq -0x220(%rbp), %rdi
callq 0x1680
cmpb $0x0, %al
je 0x31c6
movl $0x0, -0x234(%rbp)
movb $0x1, %al
cmpl $0x0, -0x234(%rbp)
movb %al, -0x279(%rbp)
jne 0x3091
movq -0x230(%rbp), %rdi
movl $0x3, %esi
callq 0x1a20
cmpl $0x0, %eax
setne %al
movb %al, -0x279(%rbp)
movb -0x279(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x234(%rbp)
movb $0x1, %al
cmpl $0x0, -0x234(%rbp)
movb %al, -0x27a(%rbp)
jne 0x30e8
movq -0x230(%rbp), %rax
movq %rax, -0x288(%rbp)
movq 0x44a8(%rip), %rdi      # 0x7570
callq 0x2990
movq -0x288(%rbp), %rdi
movzbl %al, %esi
callq 0x1ac0
cmpl $0x0, %eax
setne %al
movb %al, -0x27a(%rbp)
movb -0x27a(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x234(%rbp)
movb $0x1, %al
cmpl $0x0, -0x234(%rbp)
movb %al, -0x289(%rbp)
jne 0x313f
movq -0x230(%rbp), %rax
movq %rax, -0x298(%rbp)
movq -0x220(%rbp), %rdi
callq 0x19a0
movq -0x298(%rbp), %rdi
movzbl %al, %esi
callq 0x1b10
cmpl $0x0, %eax
setne %al
movb %al, -0x289(%rbp)
movb -0x289(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x234(%rbp)
cmpl $0x0, -0x234(%rbp)
je 0x3175
movl -0x234(%rbp), %edi
callq 0x18d0
movq %rax, %rsi
leaq 0x1158(%rip), %rdi      # 0x42c6
movb $0x0, %al
callq 0x1da0
movl 0x3fb9(%rip), %edi      # 0x7134
movq -0x230(%rbp), %rsi
callq 0x2330
cmpl $-0x1, %eax
jne 0x3198
leaq 0x1150(%rip), %rdi      # 0x42e3
callq 0x1e50
movq -0x220(%rbp), %rdi
callq 0x1360
movq -0x230(%rbp), %rdi
callq 0x1ef0
movq %rax, %rsi
leaq 0x1144(%rip), %rdi      # 0x42fe
movb $0x0, %al
callq 0x1cd0
jmp 0x3638
movq 0x43a3(%rip), %rax      # 0x7570
movq %rax, -0x2a0(%rbp)
movq -0x220(%rbp), %rdi
callq 0x19a0
movq -0x2a0(%rbp), %rdi
movzbl %al, %eax
movl %eax, %esi
callq 0x2a10
cmpq $0x0, %rax
je 0x3207
leaq 0x1106(%rip), %rdi      # 0x4304
movb $0x0, %al
callq 0x1cd0
jmp 0x3270
movq 0x4362(%rip), %rdi      # 0x7570
movq -0x220(%rbp), %rsi
callq 0x28b0
cmpl $-0x1, %eax
jne 0x3251
movq 0x434a(%rip), %rdi      # 0x7570
callq 0x2950
testb $0x1, %al
jne 0x3231
jmp 0x3241
leaq 0x10df(%rip), %rdi      # 0x4317
movb $0x0, %al
callq 0x1cd0
jmp 0x324f
leaq 0x10e8(%rip), %rdi      # 0x4330
movb $0x0, %al
callq 0x1da0
jmp 0x326e
movq -0x220(%rbp), %rdi
callq 0x19a0
movzbl %al, %esi
leaq 0xf2a(%rip), %rdi       # 0x4191
movb $0x0, %al
callq 0x1cd0
jmp 0x3270
movq -0x220(%rbp), %rdi
callq 0x19c0
movl %eax, -0x238(%rbp)
movq 0x42e7(%rip), %rax      # 0x7570
movq %rax, -0x2a8(%rbp)
movq 0x42d9(%rip), %rdi      # 0x7570
callq 0x2670
movq -0x2a8(%rbp), %rdi
movq %rax, %rsi
callq 0x2a10
movq %rax, -0x240(%rbp)
cmpq $0x0, -0x240(%rbp)
je 0x33ff
movq -0x240(%rbp), %rdi
callq 0x19e0
movq %rax, -0x248(%rbp)
movq -0x240(%rbp), %rdi
callq 0x1460
movzwl %ax, %eax
movq %rax, -0x250(%rbp)
movq -0x248(%rbp), %rdi
movq -0x250(%rbp), %rdx
movq 0x427a(%rip), %rcx      # 0x7578
movl $0x1, %esi
callq 0x11e0
cmpq -0x250(%rbp), %rax
jae 0x331f
leaq 0x1038(%rip), %rdi      # 0x4350
movb $0x0, %al
callq 0x1da0
movq -0x240(%rbp), %rdi
callq 0x19a0
movzbl %al, %esi
leaq 0x1032(%rip), %rdi      # 0x4367
movb $0x0, %al
callq 0x1cd0
movq 0x422d(%rip), %rax      # 0x7570
movq %rax, -0x2b0(%rbp)
movq -0x240(%rbp), %rdi
callq 0x19c0
movq -0x2b0(%rbp), %rdi
movl %eax, %esi
callq 0x2b70
cmpq -0x240(%rbp), %rax
jne 0x336f
jmp 0x338e
leaq 0x1003(%rip), %rdi      # 0x4379
leaq 0x103d(%rip), %rsi      # 0x43ba
movl $0x92, %edx
leaq 0x1040(%rip), %rcx      # 0x43c9
callq 0x10c0
movq -0x240(%rbp), %rdi
callq 0x1460
movzwl %ax, %eax
cmpl $0x0, %eax
jne 0x33b2
leaq 0x1035(%rip), %rdi      # 0x43de
movb $0x0, %al
callq 0x1cd0
jmp 0x33be
movq 0x41b7(%rip), %rdi      # 0x7570
callq 0x26d0
movq -0x240(%rbp), %rdi
callq 0x1360
movq 0x419f(%rip), %rax      # 0x7570
movq %rax, -0x2b8(%rbp)
movq 0x4191(%rip), %rdi      # 0x7570
callq 0x2670
movq -0x2b8(%rbp), %rdi
movq %rax, %rsi
callq 0x2a10
movq %rax, -0x240(%rbp)
jmp 0x32b2
movq 0x4172(%rip), %rdi      # 0x7578
callq 0x1120
cmpl $0x0, %eax
jne 0x3412
jmp 0x3431
leaq 0xfe9(%rip), %rdi       # 0x4402
leaq 0xf9a(%rip), %rsi       # 0x43ba
movl $0xa4, %edx
leaq 0xf9d(%rip), %rcx       # 0x43c9
callq 0x10c0
movl $0x0, -0x254(%rbp)
movb $0x1, %al
cmpl $0x0, -0x254(%rbp)
movb %al, -0x2b9(%rbp)
jne 0x3469
movq -0x230(%rbp), %rdi
movl $0x2, %esi
callq 0x1a20
cmpl $0x0, %eax
setne %al
movb %al, -0x2b9(%rbp)
movb -0x2b9(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x254(%rbp)
movb $0x1, %al
cmpl $0x0, -0x254(%rbp)
movb %al, -0x2ba(%rbp)
jne 0x34c0
movq -0x230(%rbp), %rax
movq %rax, -0x2c8(%rbp)
movq 0x40d0(%rip), %rdi      # 0x7570
callq 0x2990
movq -0x2c8(%rbp), %rdi
movzbl %al, %esi
callq 0x1ac0
cmpl $0x0, %eax
setne %al
movb %al, -0x2ba(%rbp)
movb -0x2ba(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x254(%rbp)
movb $0x1, %al
cmpl $0x0, -0x254(%rbp)
movb %al, -0x2c9(%rbp)
jne 0x3517
movq -0x230(%rbp), %rax
movq %rax, -0x2d8(%rbp)
movq 0x4079(%rip), %rdi      # 0x7570
callq 0x2670
movq -0x2d8(%rbp), %rdi
movzbl %al, %esi
callq 0x1b10
cmpl $0x0, %eax
setne %al
movb %al, -0x2c9(%rbp)
movb -0x2c9(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x254(%rbp)
movb $0x1, %al
cmpl $0x0, -0x254(%rbp)
movb %al, -0x2d9(%rbp)
jne 0x3557
movq -0x230(%rbp), %rdi
movl -0x238(%rbp), %esi
callq 0x1bb0
cmpl $0x0, %eax
setne %al
movb %al, -0x2d9(%rbp)
movb -0x2d9(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x254(%rbp)
cmpl $0x0, -0x254(%rbp)
je 0x358d
movl -0x254(%rbp), %edi
callq 0x18d0
movq %rax, %rsi
leaq 0xd40(%rip), %rdi       # 0x42c6
movb $0x0, %al
callq 0x1da0
movl 0x3ba1(%rip), %edi      # 0x7134
movq -0x230(%rbp), %rsi
callq 0x2330
cmpl $-0x1, %eax
jne 0x35b0
leaq 0xe6c(%rip), %rdi       # 0x4417
callq 0x1e50
movq -0x230(%rbp), %rdi
callq 0x1ef0
movq %rax, %rsi
leaq 0xd38(%rip), %rdi       # 0x42fe
movb $0x0, %al
callq 0x1cd0
movq 0x3f9c(%rip), %rdi      # 0x7570
callq 0x2670
movq %rax, -0x2f8(%rbp)
movq 0x3f89(%rip), %rdi      # 0x7570
callq 0x2690
movq %rax, -0x2f0(%rbp)
movq 0x3f76(%rip), %rdi      # 0x7570
callq 0x29d0
movq %rax, -0x2e8(%rbp)
movq 0x3f63(%rip), %rdi      # 0x7570
callq 0x2890
movq -0x2f8(%rbp), %rsi
movq -0x2f0(%rbp), %rdx
movq -0x2e8(%rbp), %rcx
movq %rax, %r8
leaq 0xbea(%rip), %rdi       # 0x421b
movb $0x0, %al
callq 0x1cd0
movq -0x230(%rbp), %rdi
callq 0x1360
addq $0x300, %rsp            # imm = 0x300
popq %rbp
retq
nopl (%rax)