// File: /workspace/github_c_makefile_star2_O3/sprt[P]lossless-transport/src/sender.c
// Function: main_loop
void main_loop(void) {
	/* Initialize the set inside the loop as it is mutated by select */
	fd_set read_fds;
	FD_ZERO(&read_fds);
	FD_SET(sockfd, &read_fds);

	if (!sent_eof && window_buffer_size(w) == 0 && window_get_size(w) == 0) {
		log_msg("---------- Waiting indefinitely...\n");
		log_msg("Window: [%zu, %zu], buffer: %zu/%zu\n", window_start(w),
			window_end(w), window_buffer_size(w), window_get_size(w));

		if (select(sockfd + 1, &read_fds, NULL, NULL, NULL) == -1) {
			exit_perror("select");
		}
	} else {
		/* Timeout will be zero unless the buffer is full or EOF was sent */
		uint32_t timeout_us = get_timeout();
		struct timeval timeout_tv = micro_to_timeval(timeout_us);

		log_msg("---------- Waiting for %.3fs...\n", (double) timeout_us / 1000000);
		log_msg("Window: [%zu, %zu], buffer: %zu/%zu\n", window_start(w),
			window_end(w), window_buffer_size(w), window_get_size(w));

		/* Wait until either we receive data on the socket
		* or the timeout expires */
		if (select(sockfd + 1, &read_fds, NULL, NULL, &timeout_tv) == -1) {
			exit_perror("select");
		}
	}

	/* Received an ACK or a NACK */
	if (FD_ISSET(sockfd, &read_fds)) {
		char buf[MAX_PACKET_SIZE];
		int len = recv(sockfd, buf, MAX_PACKET_SIZE, 0);
		if (len == -1) {
			exit_perror("recv");
		}

		pkt_t *resp = pkt_new();
		if (resp == NULL) {
			exit_msg("Could not allocate packet\n");
		}

		pkt_status_code err = pkt_decode(buf, len, resp);

		if (err != PKT_OK) {
			log_msg("Error decoding packet (%s), ignoring\n",
				pkt_code_to_str(err));
		} else {
			log_msg("< %s\n", pkt_repr(resp));

			switch (pkt_get_type(resp)) {
			case PTYPE_DATA:
				log_msg("Received DATA packet, ignoring\n");
				return;

			case PTYPE_ACK:
				log_msg("Received ACK for #%d\n", pkt_get_seqnum(resp) - 1);
				handle_ack(resp);
				break;

			case PTYPE_NACK:
				log_msg("Received NACK for #%d\n", pkt_get_seqnum(resp));
				handle_nack(resp);
				break;

			/* other cases guarded by pkt_decode above */
			}

			/* We handled an ACK or a NACK, so resize the sending
			 * window according to the receiving window so as not to
			 * overload the receiver. */
			size_t swin = window_get_max_size(w);
			size_t rwin = pkt_get_window(resp);
			size_t new_win_size = MIN(swin, rwin);
			assert(window_resize(w, new_win_size) == 0);
			log_msg("New window size: %zu\n", new_win_size);
		}

		pkt_del(resp);

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

	retransmit_packets();

	/* If the window isn't full and we still have data to read,
	 * just keep filling up the buffer */
	if (!window_full(w) && !sent_eof) {
		char buf[MAX_PAYLOAD_SIZE] = {0};
		size_t len = fread(buf, sizeof (*buf), MAX_PAYLOAD_SIZE, infile);

		if (len < MAX_PAYLOAD_SIZE) { /* either error or EOF */
			if (ferror(infile)) {
				exit_msg("Error reading from file\n");
			}
			log_msg("Read EOF\n");
		}

		pkt_t *pkt = pkt_new();
		if (pkt == NULL) {
			exit_msg("Error creating packet\n");
		}

		pkt_status_code err = PKT_OK;
		err = err || pkt_set_type(pkt, PTYPE_DATA);
		err = err || pkt_set_seqnum(pkt, next);
		/* The sender has no receiving window */
		err = err || pkt_set_window(pkt, 0);
		err = err || pkt_set_timestamp(pkt, get_monotime() + TIMER);
		err = err || pkt_set_payload(pkt, buf, len);

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

		if (send_packet(sockfd, pkt) == -1) {
			exit_perror("send");
		}

		/* Packet is in-flight and non-acknowledged,
		 * hence add it to the buffer */
		if (window_push(w, pkt) == -1) {
			exit_msg("Could not add packet to buffer\n");
		}

		next = (next + 1) % 256;

		log_msg("> %s\n", pkt_repr(pkt));
		log_msg("Added packet #%d to buffer\n", pkt_get_seqnum(pkt));

		if (len == 0) {
			log_msg("Sent EOF packet\n");
			sent_eof = true;
		}
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x290, %rsp            # imm = 0x290
xorpd %xmm0, %xmm0
movapd %xmm0, 0x70(%rsp)
movapd %xmm0, 0x60(%rsp)
movapd %xmm0, 0x50(%rsp)
movapd %xmm0, 0x40(%rsp)
movapd %xmm0, 0x30(%rsp)
movapd %xmm0, 0x20(%rsp)
movapd %xmm0, 0x10(%rsp)
movapd %xmm0, (%rsp)
movl 0x3b47(%rip), %ecx      # 0x6118
leal 0x3f(%rcx), %eax
testl %ecx, %ecx
cmovnsl %ecx, %eax
movl %eax, %edx
andl $-0x40, %edx
subl %edx, %ecx
movl $0x1, %edx
shlq %cl, %rdx
sarl $0x6, %eax
cltq
orq %rdx, (%rsp,%rax,8)
cmpb $0x0, 0x3f70(%rip)      # 0x6568
jne 0x2620
movq 0x3f5f(%rip), %rdi      # 0x6560
callq 0x2010
testq %rax, %rax
jne 0x2620
movq 0x3f4e(%rip), %rdi      # 0x6560
callq 0x1f8d
testq %rax, %rax
je 0x27bb
callq 0x2288
movl %eax, %ebp
movl %eax, %edi
callq 0x1e45
leaq 0x80(%rsp), %rbx
movq %rax, (%rbx)
movq %rdx, 0x8(%rbx)
movl %ebp, %eax
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
divsd 0xbb1(%rip), %xmm0      # 0x3200
leaq 0xd53(%rip), %rdi       # 0x33a9
movb $0x1, %al
callq 0x1220
movq 0x3efc(%rip), %rdi      # 0x6560
callq 0x1ecf
movq %rax, %r14
movq 0x3eed(%rip), %rdi      # 0x6560
callq 0x1ed4
movq %rax, %r15
movq 0x3ede(%rip), %rdi      # 0x6560
callq 0x2010
movq %rax, %r12
movq 0x3ecf(%rip), %rdi      # 0x6560
callq 0x1f8d
leaq 0xce0(%rip), %rdi       # 0x337d
movq %r14, %rsi
movq %r15, %rdx
movq %r12, %rcx
movq %rax, %r8
xorl %eax, %eax
callq 0x1220
movl 0x3a62(%rip), %edi      # 0x6118
incl %edi
movq %rsp, %rsi
xorl %edx, %edx
xorl %ecx, %ecx
movq %rbx, %r8
callq 0x1130
cmpl $-0x1, %eax
jne 0x26d8
leaq 0xccf(%rip), %rdi       # 0x33a2
callq 0x19fe
movl 0x3a3a(%rip), %edi      # 0x6118
leal 0x3f(%rdi), %eax
testl %edi, %edi
cmovnsl %edi, %eax
sarl $0x6, %eax
cltq
movq (%rsp,%rax,8), %rax
btq %rdi, %rax
jae 0x291e
leaq 0x80(%rsp), %rsi
movl $0x210, %edx            # imm = 0x210
xorl %ecx, %ecx
callq 0x1040
movq %rax, %r14
cmpl $-0x1, %r14d
jne 0x2722
leaq 0xcad(%rip), %rdi       # 0x33ca
callq 0x19fe
xorl %eax, %eax
callq 0x14ac
movq %rax, %rbx
testq %rax, %rax
jne 0x273f
leaq 0xc97(%rip), %rdi       # 0x33cf
xorl %eax, %eax
callq 0x195c
movslq %r14d, %rsi
leaq 0x80(%rsp), %rdi
movq %rbx, %rdx
callq 0x153d
testl %eax, %eax
je 0x276c
movl %eax, %edi
callq 0x17e3
leaq 0xc86(%rip), %rdi       # 0x33ea
movq %rax, %rsi
jmp 0x28bc
movq %rbx, %rdi
callq 0x1a6a
leaq 0xc95(%rip), %rdi       # 0x3410
movq %rax, %rsi
xorl %eax, %eax
callq 0x1220
movq %rbx, %rdi
callq 0x1691
cmpl $0x3, %eax
je 0x2858
cmpl $0x2, %eax
je 0x2833
cmpl $0x1, %eax
jne 0x2879
leaq 0xc67(%rip), %rdi       # 0x3416
xorl %eax, %eax
callq 0x1220
jmp 0x2ada
leaq 0xb97(%rip), %rdi       # 0x3359
xorl %eax, %eax
callq 0x1220
movq 0x3d90(%rip), %rdi      # 0x6560
callq 0x1ecf
movq %rax, %rbx
movq 0x3d81(%rip), %rdi      # 0x6560
callq 0x1ed4
movq %rax, %r14
movq 0x3d72(%rip), %rdi      # 0x6560
callq 0x2010
movq %rax, %r15
movq 0x3d63(%rip), %rdi      # 0x6560
callq 0x1f8d
leaq 0xb74(%rip), %rdi       # 0x337d
movq %rbx, %rsi
movq %r14, %rdx
movq %r15, %rcx
movq %rax, %r8
xorl %eax, %eax
callq 0x1220
movl 0x38f6(%rip), %edi      # 0x6118
incl %edi
movq %rsp, %rsi
xorl %edx, %edx
xorl %ecx, %ecx
xorl %r8d, %r8d
jmp 0x26c2
movq %rbx, %rdi
callq 0x1801
movzbl %al, %esi
decl %esi
leaq 0xbef(%rip), %rdi       # 0x3436
xorl %eax, %eax
callq 0x1220
movq %rbx, %rdi
callq 0x22d7
jmp 0x2879
movq %rbx, %rdi
callq 0x1801
movzbl %al, %esi
leaq 0xbe2(%rip), %rdi       # 0x344c
xorl %eax, %eax
callq 0x1220
movq %rbx, %rdi
callq 0x2437
movq 0x3ce0(%rip), %rdi      # 0x6560
callq 0x1f88
movq %rax, %r15
movq %rbx, %rdi
callq 0x16a0
movzbl %al, %r14d
cmpq %r14, %r15
cmovbq %r15, %r14
movq 0x3cbe(%rip), %rdi      # 0x6560
movq %r14, %rsi
callq 0x1f76
testl %eax, %eax
jne 0x2aea
leaq 0xbe3(%rip), %rdi       # 0x349c
movq %r14, %rsi
xorl %eax, %eax
callq 0x1220
movq %rbx, %rdi
callq 0x14bb
movq 0x3c8e(%rip), %rdi      # 0x6560
callq 0x1ecf
movq %rax, %rbx
movq 0x3c7f(%rip), %rdi      # 0x6560
callq 0x1ed4
movq %rax, %r14
movq 0x3c70(%rip), %rdi      # 0x6560
callq 0x2010
movq %rax, %r15
movq 0x3c61(%rip), %rdi      # 0x6560
callq 0x1f8d
leaq 0xa72(%rip), %rdi       # 0x337d
movq %rbx, %rsi
movq %r14, %rdx
movq %r15, %rcx
movq %rax, %r8
xorl %eax, %eax
callq 0x1220
callq 0x24af
movq 0x3c36(%rip), %rdi      # 0x6560
callq 0x1fed
testb %al, %al
jne 0x2ada
cmpb $0x0, 0x3c2a(%rip)      # 0x6568
jne 0x2ada
leaq 0x80(%rsp), %rbx
movl $0x200, %edx            # imm = 0x200
movq %rbx, %rdi
xorl %esi, %esi
callq 0x10f0
movq 0x3c0e(%rip), %rcx      # 0x6570
movl $0x1, %esi
movl $0x200, %edx            # imm = 0x200
movq %rbx, %rdi
callq 0x1080
movq %rax, %rbx
cmpq $0x1ff, %rax            # imm = 0x1FF
ja 0x29ab
movq 0x3bea(%rip), %rdi      # 0x6570
callq 0x1070
testl %eax, %eax
je 0x299d
leaq 0xb1c(%rip), %rdi       # 0x34b2
xorl %eax, %eax
callq 0x195c
leaq 0xb27(%rip), %rdi       # 0x34cb
xorl %eax, %eax
callq 0x1220
xorl %eax, %eax
callq 0x14ac
movq %rax, %r14
testq %rax, %rax
jne 0x29c8
leaq 0xb14(%rip), %rdi       # 0x34d5
xorl %eax, %eax
callq 0x195c
movq %r14, %rdi
movl $0x1, %esi
callq 0x1822
testl %eax, %eax
jne 0x2a28
movzbl 0x3b78(%rip), %esi      # 0x6558
movq %r14, %rdi
callq 0x1871
testl %eax, %eax
jne 0x2a28
movq %r14, %rdi
xorl %esi, %esi
callq 0x185a
testl %eax, %eax
jne 0x2a28
callq 0x1d59
leal 0x44aa20(%rax), %esi
movq %r14, %rdi
callq 0x18bb
testl %eax, %eax
jne 0x2a28
movzwl %bx, %edx
leaq 0x80(%rsp), %rsi
movq %r14, %rdi
callq 0x18c3
testl %eax, %eax
je 0x2a3b
leaq 0xabd(%rip), %rdi       # 0x34ec
movl $0x1, %esi
xorl %eax, %eax
callq 0x195c
movl 0x36d7(%rip), %edi      # 0x6118
movq %r14, %rsi
callq 0x1d05
cmpl $-0x1, %eax
jne 0x2a5a
leaq 0x8f4(%rip), %rdi       # 0x3349
callq 0x19fe
movq 0x3aff(%rip), %rdi      # 0x6560
movq %r14, %rsi
callq 0x1f92
cmpl $-0x1, %eax
jne 0x2a7c
leaq 0xa94(%rip), %rdi       # 0x3509
xorl %eax, %eax
callq 0x195c
movl 0x3ad6(%rip), %eax      # 0x6558
incl %eax
movzbl %al, %eax
movq %rax, 0x3aca(%rip)      # 0x6558
movq %r14, %rdi
callq 0x1a6a
leaq 0xa8c(%rip), %rdi       # 0x3529
movq %rax, %rsi
xorl %eax, %eax
callq 0x1220
movq %r14, %rdi
callq 0x1801
movzbl %al, %esi
leaq 0xa76(%rip), %rdi       # 0x352f
xorl %eax, %eax
callq 0x1220
testq %rbx, %rbx
jne 0x2ada
leaq 0xa7f(%rip), %rdi       # 0x354b
xorl %eax, %eax
callq 0x1220
movb $0x1, 0x3a8e(%rip)      # 0x6568
addq $0x290, %rsp            # imm = 0x290
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
leaq 0x972(%rip), %rdi       # 0x3463
leaq 0x73b(%rip), %rsi       # 0x3233
leaq 0x988(%rip), %rcx       # 0x3487
movl $0xd0, %edx
callq 0x10e0