// File: /workspace/github_c_makefile_star2_O1/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 0x3b38(%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, 0x3f61(%rip)      # 0x6568
jne 0x262f
movq 0x3f50(%rip), %rdi      # 0x6560
callq 0x2004
testq %rax, %rax
jne 0x262f
movq 0x3f3f(%rip), %rdi      # 0x6560
callq 0x1f81
testq %rax, %rax
je 0x27ca
callq 0x2280
movl %eax, %ebp
movl %eax, %edi
callq 0x1e38
leaq 0x80(%rsp), %rbx
movq %rax, (%rbx)
movq %rdx, 0x8(%rbx)
movl %ebp, %eax
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
divsd 0xba2(%rip), %xmm0      # 0x3200
leaq 0xd44(%rip), %rdi       # 0x33a9
movb $0x1, %al
callq 0x1220
movq 0x3eed(%rip), %rdi      # 0x6560
callq 0x1ec3
movq %rax, %r14
movq 0x3ede(%rip), %rdi      # 0x6560
callq 0x1ec8
movq %rax, %r15
movq 0x3ecf(%rip), %rdi      # 0x6560
callq 0x2004
movq %rax, %r12
movq 0x3ec0(%rip), %rdi      # 0x6560
callq 0x1f81
leaq 0xcd1(%rip), %rdi       # 0x337d
movq %r14, %rsi
movq %r15, %rdx
movq %r12, %rcx
movq %rax, %r8
xorl %eax, %eax
callq 0x1220
movl 0x3a53(%rip), %edi      # 0x6118
incl %edi
movq %rsp, %rsi
xorl %edx, %edx
xorl %ecx, %ecx
movq %rbx, %r8
callq 0x1130
cmpl $-0x1, %eax
jne 0x26e7
leaq 0xcc0(%rip), %rdi       # 0x33a2
callq 0x19ea
movl 0x3a2b(%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 0x292d
leaq 0x80(%rsp), %rsi
movl $0x210, %edx            # imm = 0x210
xorl %ecx, %ecx
callq 0x1040
movq %rax, %r14
cmpl $-0x1, %r14d
jne 0x2731
leaq 0xc9e(%rip), %rdi       # 0x33ca
callq 0x19ea
xorl %eax, %eax
callq 0x14ac
movq %rax, %rbx
testq %rax, %rax
jne 0x274e
leaq 0xc88(%rip), %rdi       # 0x33cf
xorl %eax, %eax
callq 0x1948
movslq %r14d, %rsi
leaq 0x80(%rsp), %rdi
movq %rbx, %rdx
callq 0x153a
testl %eax, %eax
je 0x277b
movl %eax, %edi
callq 0x17c6
leaq 0xc77(%rip), %rdi       # 0x33ea
movq %rax, %rsi
jmp 0x28cb
movq %rbx, %rdi
callq 0x1a56
leaq 0xc86(%rip), %rdi       # 0x3410
movq %rax, %rsi
xorl %eax, %eax
callq 0x1220
movq %rbx, %rdi
callq 0x1677
cmpl $0x3, %eax
je 0x2867
cmpl $0x2, %eax
je 0x2842
cmpl $0x1, %eax
jne 0x2888
leaq 0xc58(%rip), %rdi       # 0x3416
xorl %eax, %eax
callq 0x1220
jmp 0x2af2
leaq 0xb88(%rip), %rdi       # 0x3359
xorl %eax, %eax
callq 0x1220
movq 0x3d81(%rip), %rdi      # 0x6560
callq 0x1ec3
movq %rax, %rbx
movq 0x3d72(%rip), %rdi      # 0x6560
callq 0x1ec8
movq %rax, %r14
movq 0x3d63(%rip), %rdi      # 0x6560
callq 0x2004
movq %rax, %r15
movq 0x3d54(%rip), %rdi      # 0x6560
callq 0x1f81
leaq 0xb65(%rip), %rdi       # 0x337d
movq %rbx, %rsi
movq %r14, %rdx
movq %r15, %rcx
movq %rax, %r8
xorl %eax, %eax
callq 0x1220
movl 0x38e7(%rip), %edi      # 0x6118
incl %edi
movq %rsp, %rsi
xorl %edx, %edx
xorl %ecx, %ecx
xorl %r8d, %r8d
jmp 0x26d1
movq %rbx, %rdi
callq 0x17e4
movzbl %al, %esi
decl %esi
leaq 0xbe0(%rip), %rdi       # 0x3436
xorl %eax, %eax
callq 0x1220
movq %rbx, %rdi
callq 0x22cf
jmp 0x2888
movq %rbx, %rdi
callq 0x17e4
movzbl %al, %esi
leaq 0xbd3(%rip), %rdi       # 0x344c
xorl %eax, %eax
callq 0x1220
movq %rbx, %rdi
callq 0x2446
movq 0x3cd1(%rip), %rdi      # 0x6560
callq 0x1f7c
movq %rax, %r15
movq %rbx, %rdi
callq 0x1686
movzbl %al, %r14d
cmpq %r14, %r15
cmovbq %r15, %r14
movq 0x3caf(%rip), %rdi      # 0x6560
movq %r14, %rsi
callq 0x1f6a
testl %eax, %eax
jne 0x2b02
leaq 0xbd4(%rip), %rdi       # 0x349c
movq %r14, %rsi
xorl %eax, %eax
callq 0x1220
movq %rbx, %rdi
callq 0x14bb
movq 0x3c7f(%rip), %rdi      # 0x6560
callq 0x1ec3
movq %rax, %rbx
movq 0x3c70(%rip), %rdi      # 0x6560
callq 0x1ec8
movq %rax, %r14
movq 0x3c61(%rip), %rdi      # 0x6560
callq 0x2004
movq %rax, %r15
movq 0x3c52(%rip), %rdi      # 0x6560
callq 0x1f81
leaq 0xa63(%rip), %rdi       # 0x337d
movq %rbx, %rsi
movq %r14, %rdx
movq %r15, %rcx
movq %rax, %r8
xorl %eax, %eax
callq 0x1220
callq 0x24be
movq 0x3c27(%rip), %rdi      # 0x6560
callq 0x1fe1
testb %al, %al
jne 0x2af2
cmpb $0x0, 0x3c1b(%rip)      # 0x6568
jne 0x2af2
leaq 0x80(%rsp), %rbx
movl $0x200, %edx            # imm = 0x200
movq %rbx, %rdi
xorl %esi, %esi
callq 0x10f0
movq 0x3bff(%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 0x29ba
movq 0x3bdb(%rip), %rdi      # 0x6570
callq 0x1070
testl %eax, %eax
je 0x29ac
leaq 0xb0d(%rip), %rdi       # 0x34b2
xorl %eax, %eax
callq 0x1948
leaq 0xb18(%rip), %rdi       # 0x34cb
xorl %eax, %eax
callq 0x1220
xorl %eax, %eax
callq 0x14ac
movq %rax, %r14
testq %rax, %rax
jne 0x29d7
leaq 0xb05(%rip), %rdi       # 0x34d5
xorl %eax, %eax
callq 0x1948
movq %r14, %rdi
movl $0x1, %esi
callq 0x180a
movb $0x1, %bpl
testl %eax, %eax
jne 0x2a3c
movzbl 0x3b66(%rip), %esi      # 0x6558
movq %r14, %rdi
callq 0x1859
testl %eax, %eax
jne 0x2a3c
movq %r14, %rdi
xorl %esi, %esi
callq 0x1842
testl %eax, %eax
jne 0x2a3c
callq 0x1d45
leal 0x44aa20(%rax), %esi
movq %r14, %rdi
callq 0x18a3
testl %eax, %eax
jne 0x2a3c
movzwl %bx, %edx
leaq 0x80(%rsp), %rsi
movq %r14, %rdi
callq 0x18ab
testl %eax, %eax
setne %bpl
testb %bpl, %bpl
je 0x2a53
movzbl %bpl, %esi
leaq 0xaa0(%rip), %rdi       # 0x34ec
xorl %eax, %eax
callq 0x1948
movl 0x36bf(%rip), %edi      # 0x6118
movq %r14, %rsi
callq 0x1cf1
cmpl $-0x1, %eax
jne 0x2a72
leaq 0x8dc(%rip), %rdi       # 0x3349
callq 0x19ea
movq 0x3ae7(%rip), %rdi      # 0x6560
movq %r14, %rsi
callq 0x1f86
cmpl $-0x1, %eax
jne 0x2a94
leaq 0xa7c(%rip), %rdi       # 0x3509
xorl %eax, %eax
callq 0x1948
movl 0x3abe(%rip), %eax      # 0x6558
incl %eax
movzbl %al, %eax
movq %rax, 0x3ab2(%rip)      # 0x6558
movq %r14, %rdi
callq 0x1a56
leaq 0xa74(%rip), %rdi       # 0x3529
movq %rax, %rsi
xorl %eax, %eax
callq 0x1220
movq %r14, %rdi
callq 0x17e4
movzbl %al, %esi
leaq 0xa5e(%rip), %rdi       # 0x352f
xorl %eax, %eax
callq 0x1220
testq %rbx, %rbx
jne 0x2af2
leaq 0xa67(%rip), %rdi       # 0x354b
xorl %eax, %eax
callq 0x1220
movb $0x1, 0x3a76(%rip)      # 0x6568
addq $0x290, %rsp            # imm = 0x290
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
leaq 0x95a(%rip), %rdi       # 0x3463
leaq 0x723(%rip), %rsi       # 0x3233
leaq 0x970(%rip), %rcx       # 0x3487
movl $0xd0, %edx
callq 0x10e0