// File: /workspace/github_c_makefile_star2_O1/sharpyfox[P]citrusleaf-client/src/cf_socket.c
// Function: cf_socket_read_timeout
int
cf_socket_read_timeout(int fd, uint8_t *buf, size_t buf_len, uint64_t trans_deadline, int attempt_ms)
{
	if (!buf_len) {
		return 0;
	}

	char *ctx = "cf_socket_read_timeout()";
	int errbuf_len = 64;
	char errbuf[errbuf_len];

	int flags;
	if (-1 == (flags = fcntl(fd, F_GETFL, 0))) {
		flags = 0;
	}
	if (!(flags & O_NONBLOCK)) {
		if (-1 == fcntl(fd, F_SETFL, flags | O_NONBLOCK)) {
			return(ENOENT);
		}
	}

	// between the transaction deadline and the attempt_ms, find the lesser
	// and create a deadline for this attempt
	uint64_t deadline = attempt_ms + cf_getms();
	if ((trans_deadline != 0) && (trans_deadline < deadline)) {
		deadline = trans_deadline;
	}

	int rv = 0, epoll_fd = -1, busy = 0, try = 0;
	size_t pos = 0;
	uint64_t start = cf_getms();

	if (0 > (epoll_fd = epoll_create(1))) {
		rv = errno;
		cf_warn("%s: epoll_create() failed (errno %d: \"%s\") ~~ Failing!", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len));
		goto Fail;
	}

	struct epoll_event event;
	memset(&event, 0, sizeof(struct epoll_event));
	event.data.fd = fd;
	event.events = EPOLLIN;

	if (0 > epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &event)) {
		rv = errno;
		cf_warn("%s: epoll_ctl(ADD) of socket failed (errno %d: \"%s\") ~~ Failing!", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len));
		goto Fail;
	}

	do {
		uint64_t now = cf_getms();
		if (now > deadline) {
#ifdef DEBUG_TIME
			debug_time_printf("socket read timeout 1", try, busy, start, now, deadline);
#endif
			rv = ETIMEDOUT;
			goto Fail;
		}

		uint64_t ms_left = deadline - now;

		int nevents = 0;
		int max_events = 1;
		int wait_ms = 1;
		struct epoll_event events[max_events];

		if (0 > (nevents = epoll_wait(epoll_fd, events, max_events, wait_ms))) {
			if ((rv = errno) == EINTR) {
				cf_debug("%s: epoll_wait() on socket encountered EINTR ~~ Retrying!", ctx);
				busy++;
				goto Retry;
			} else {
				cf_warn("%s: epoll_wait() on socket failed (errno %d: \"%s\") ~~ Failing!", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len));
			}
			goto Fail;
		} else {
			if (nevents == 0) {
				cf_debug("%s: epoll_wait() returned no events ~~ Retrying!", ctx);
				busy++;
				goto Retry;
			}
			if (nevents != 1) {
				cf_warn("%s: epoll_wait() returned %d events ~~ only 1 expected, so ignoring others!", ctx, nevents);
			}
			if (events[0].data.fd == fd) {
				if (events[0].events & EPOLLIN) {
					cf_debug("%s: epoll_wait() on socket ready for read detected ~~ Succeeding!", ctx);
				} else {
					// (Note:  ERR and HUP events are automatically waited for as well.)
					if (events[0].events & (EPOLLERR | EPOLLHUP)) {
						cf_debug("%s: epoll_wait() on socket detected failure event 0x%x ~~ Failing!", ctx, events[0].events);
					} else {
						cf_warn("%s: epoll_wait() on socket detected non-read events 0x%x ~~ Failing!", ctx, events[0].events);
					}
					rv = EBADF;
					goto Fail;
				}
			} else {
				cf_warn("%s: epoll_wait() on socket returned event on unknown socket %d ~~ Retrying!", ctx, events[0].data.fd);
				goto Retry;
			}

			int r_bytes = read(fd, buf + pos, buf_len - pos);

			if (r_bytes > 0) {
				pos += r_bytes;
				if (pos >= buf_len)	{
					goto Success;
				}
			} else if (r_bytes == 0) {
				// It's likely the socket has been closed on the remote side.
				rv = EBADF;
				goto Fail;
			} else if ((errno != ETIMEDOUT) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS) && (errno != EAGAIN)) {
#ifdef DEBUG_TIME
				debug_time_printf("socket read timeout 2", try, busy, start, now, deadline);
#endif
				rv = errno;
				goto Fail;
			}
		}

Retry:
		try++;

	} while (pos < buf_len);

Success:
	if (0 > epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &event)) {
		cf_warn("%s: epoll_ctl(DEL) on socket failed (errno %d: \"%s\")", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len));
	}
	close(epoll_fd);

	rv = 0;
	goto Done;

Fail:
	cf_debug("%s: socket read timeout fail: %d (%s)", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len));

	if (epoll_fd > 0) {
		if (0 > epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &event)) {
			cf_warn("%s: epoll_ctl(DEL) on socket failed (errno %d: \"%s\")", ctx, errno, my_strerror_r(errno, errbuf, errbuf_len));
		}
		close(epoll_fd);
	}

Done:
	return(rv);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
testq %rdx, %rdx
je 0xdd05
movl %r8d, %r13d
movq %rcx, %r14
movq %rdx, %r12
movl %edi, %r15d
movq %rsi, -0x70(%rbp)
movq %rsp, -0x78(%rbp)
movq %rsp, %rax
addq $-0x40, %rax
movq %rax, -0x48(%rbp)
movq %rax, %rsp
xorl %ebx, %ebx
movl $0x3, %esi
xorl %edx, %edx
xorl %eax, %eax
callq 0x2450
cmpl $-0x1, %eax
cmovel %ebx, %eax
btl $0xb, %eax
jb 0xd933
orl $0x800, %eax            # imm = 0x800
movl %r15d, %edi
movl $0x4, %esi
movl %eax, %edx
xorl %eax, %eax
callq 0x2450
cmpl $-0x1, %eax
je 0xdef6
movl %r15d, -0x2c(%rbp)
movslq %r13d, %rbx
leaq -0x60(%rbp), %r13
movl $0x1, %edi
movq %r13, %rsi
callq 0x2230
movabsq $0x431bde82d7b634db, %rax # imm = 0x431BDE82D7B634DB
mulq 0x8(%r13)
shrq $0x12, %rdx
imulq $0x3e8, (%r13), %rax    # imm = 0x3E8
addq %rbx, %rax
addq %rdx, %rax
cmpq %r14, %rax
movq %r14, %r15
cmovbq %rax, %r15
testq %r14, %r14
cmoveq %rax, %r15
leaq -0x60(%rbp), %rsi
movl $0x1, %edi
callq 0x2230
movl $0x1, %edi
callq 0x2520
testl %eax, %eax
movl %eax, -0x3c(%rbp)
js 0xdd0d
leaq -0x88(%rbp), %rcx
movq $0x0, (%rcx)
movl $0x0, 0x8(%rcx)
movl -0x2c(%rbp), %edx
movl %edx, 0x4(%rcx)
movl $0x1, (%rcx)
movl %eax, %edi
movl $0x1, %esi
callq 0x2320
testl %eax, %eax
js 0xddd6
movq %r12, -0x50(%rbp)
xorl %r12d, %r12d
xorl %r14d, %r14d
movl $0x1, %edi
movq %r13, %rsi
callq 0x2230
movabsq $0x431bde82d7b634db, %rax # imm = 0x431BDE82D7B634DB
mulq -0x58(%rbp)
shrq $0x12, %rdx
imulq $0x3e8, -0x60(%rbp), %rax # imm = 0x3E8
addq %rdx, %rax
cmpq %r15, %rax
jbe 0xda1d
movl $0x2, %ebx
movl $0x6e, %r14d
jmp 0xdbfb
movq %rsp, -0x38(%rbp)
movq %rsp, %r13
addq $-0x10, %r13
movq %r13, %rsp
movl -0x3c(%rbp), %edi
movq %r13, %rsi
movl $0x1, %edx
movl $0x1, %ecx
callq 0x2110
testl %eax, %eax
js 0xda8f
cmpl $0x1, %eax
je 0xdb11
testl %eax, %eax
jne 0xdae1
leaq 0x986c(%rip), %rax      # 0x172c8
movl (%rax), %eax
cmpl $0x3, %eax
jl 0xdbe8
leaq 0x9862(%rip), %rax      # 0x172d0
movq (%rax), %rcx
xorl %ebx, %ebx
movl $0x3, %edi
leaq 0x3eab(%rip), %rsi      # 0x1192a
leaq 0x3d9a(%rip), %rdx      # 0x11820
xorl %eax, %eax
callq *%rcx
jmp 0xdbea
callq 0x2040
movl (%rax), %r13d
cmpl $0x4, %r13d
leaq 0x9826(%rip), %rcx      # 0x172c8
movl (%rcx), %ecx
jne 0xdb9a
movl $0x4, %r13d
cmpl $0x3, %ecx
jl 0xdc82
leaq 0x9810(%rip), %rax      # 0x172d0
movq (%rax), %rcx
xorl %ebx, %ebx
movl $0x3, %edi
leaq 0x3de0(%rip), %rsi      # 0x118b1
leaq 0x3d48(%rip), %rdx      # 0x11820
xorl %eax, %eax
callq *%rcx
jmp 0xdbed
leaq 0x97e0(%rip), %rcx      # 0x172c8
cmpl $0x0, (%rcx)
jle 0xdb11
leaq 0x97dc(%rip), %rcx      # 0x172d0
movq (%rcx), %r8
movl $0x1, %edi
leaq 0x3e58(%rip), %rsi      # 0x1195b
leaq 0x3d16(%rip), %rdx      # 0x11820
movl %eax, %ecx
xorl %eax, %eax
callq *%r8
movl 0x4(%r13), %ecx
cmpl -0x2c(%rbp), %ecx
jne 0xdb68
movl (%r13), %ecx
testb $0x1, %cl
jne 0xdc12
testb $0x18, %cl
leaq 0x9797(%rip), %rax      # 0x172c8
movl (%rax), %eax
movl $0x2, %ebx
movl $0x9, %r13d
je 0xdc89
cmpl $0x3, %eax
jl 0xdbed
leaq 0x977c(%rip), %rax      # 0x172d0
movq (%rax), %r8
movl $0x3, %edi
leaq 0x3e86(%rip), %rsi      # 0x119e9
jmp 0xdca7
leaq 0x9759(%rip), %rax      # 0x172c8
cmpl $0x0, (%rax)
jle 0xdbe8
leaq 0x9755(%rip), %rax      # 0x172d0
movq (%rax), %r8
xorl %ebx, %ebx
movl $0x1, %edi
leaq 0x3ee5(%rip), %rsi      # 0x11a71
leaq 0x3c8d(%rip), %rdx      # 0x11820
xorl %eax, %eax
callq *%r8
jmp 0xdbea
movl $0x2, %ebx
testl %ecx, %ecx
jle 0xdbed
leaq 0x9726(%rip), %rcx      # 0x172d0
movq (%rcx), %rcx
movq %rcx, -0x68(%rbp)
movq -0x48(%rbp), %r14
movb $0x0, (%r14)
movl (%rax), %edi
movl $0x40, %edx
movq %r14, %rsi
callq 0x2100
movl $0x1, %edi
leaq 0x3d17(%rip), %rsi      # 0x118eb
leaq 0x3c45(%rip), %rdx      # 0x11820
movl %r13d, %ecx
movq %r14, %r8
xorl %eax, %eax
callq *-0x68(%rbp)
jmp 0xdbed
xorl %ebx, %ebx
movl %r14d, %r13d
movq -0x38(%rbp), %rcx
movq %rcx, %rsp
movl %r13d, %r14d
leaq -0x60(%rbp), %r13
testl %ebx, %ebx
jne 0xdd52
cmpq -0x50(%rbp), %r12
jb 0xd9de
jmp 0xdd64
leaq 0x96af(%rip), %rax      # 0x172c8
movl (%rax), %eax
cmpl $0x3, %eax
jl 0xdc41
leaq 0x96a9(%rip), %rax      # 0x172d0
movq (%rax), %rcx
movl $0x3, %edi
leaq 0x3d71(%rip), %rsi      # 0x119a7
leaq 0x3be3(%rip), %rdx      # 0x11820
xorl %eax, %eax
callq *%rcx
movq -0x70(%rbp), %rax
leaq (%rax,%r12), %rsi
movq -0x50(%rbp), %r13
movq %r13, %rdx
subq %r12, %rdx
movl -0x2c(%rbp), %edi
callq 0x2390
testl %eax, %eax
jle 0xdcb8
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
addq %r12, %rax
movl $0x6, %ebx
cmpq %r13, %rax
movq -0x38(%rbp), %rcx
jae 0xdc77
xorl %ebx, %ebx
movq %rax, %r12
movl %r14d, %r13d
jmp 0xdbf1
xorl %ebx, %ebx
jmp 0xdbed
testl %eax, %eax
jle 0xdbed
leaq 0x9638(%rip), %rax      # 0x172d0
movq (%rax), %r8
movl $0x1, %edi
leaq 0x3d85(%rip), %rsi      # 0x11a2c
leaq 0x3b72(%rip), %rdx      # 0x11820
xorl %eax, %eax
callq *%r8
jmp 0xdbed
movl $0x2, %ebx
je 0xdce6
callq 0x2040
movl (%rax), %r13d
cmpl $0xb, %r13d
je 0xdcf9
cmpl $0x73, %r13d
movq -0x38(%rbp), %rcx
je 0xdcf1
cmpl $0x6e, %r13d
movq %r12, %rax
jne 0xdbf1
jmp 0xdc75
movl $0x9, %r13d
jmp 0xdbed
movq %r12, %rax
jmp 0xdc75
movq %r12, %rax
movq -0x38(%rbp), %rcx
jmp 0xdc75
xorl %r14d, %r14d
jmp 0xdf02
callq 0x2040
movl (%rax), %r14d
leaq 0x95ac(%rip), %rcx      # 0x172c8
cmpl $0x0, (%rcx)
jle 0xde28
leaq 0x95a4(%rip), %rcx      # 0x172d0
movq (%rcx), %rbx
movq -0x48(%rbp), %r15
movb $0x0, (%r15)
movl (%rax), %edi
movl $0x40, %edx
movq %r15, %rsi
callq 0x2100
leaq 0x3aec(%rip), %rsi      # 0x11839
jmp 0xde12
cmpl $0x2, %ebx
je 0xde28
cmpl $0x6, %ebx
jne 0xdefe
leaq -0x88(%rbp), %rcx
movl -0x3c(%rbp), %edi
movl $0x2, %esi
movl -0x2c(%rbp), %edx
callq 0x2320
xorl %r14d, %r14d
testl %eax, %eax
jns 0xdeec
leaq 0x953b(%rip), %rax      # 0x172c8
cmpl $0x0, (%rax)
jle 0xdeec
leaq 0x9533(%rip), %rax      # 0x172d0
movq (%rax), %rbx
callq 0x2040
movl (%rax), %r15d
movq -0x48(%rbp), %r12
movb $0x0, (%r12)
movl (%rax), %edi
movl $0x40, %edx
movq %r12, %rsi
callq 0x2100
leaq 0x3cf6(%rip), %rsi      # 0x11abd
leaq 0x3a52(%rip), %rdx      # 0x11820
xorl %r14d, %r14d
jmp 0xdedd
callq 0x2040
movl (%rax), %r14d
leaq 0x94e3(%rip), %rcx      # 0x172c8
cmpl $0x0, (%rcx)
jle 0xde28
leaq 0x94df(%rip), %rcx      # 0x172d0
movq (%rcx), %rbx
movq -0x48(%rbp), %r15
movb $0x0, (%r15)
movl (%rax), %edi
movl $0x40, %edx
movq %r15, %rsi
callq 0x2100
leaq 0x3a5e(%rip), %rsi      # 0x11870
leaq 0x3a07(%rip), %rdx      # 0x11820
movl $0x1, %edi
movl %r14d, %ecx
movq %r15, %r8
xorl %eax, %eax
callq *%rbx
movl -0x2c(%rbp), %edx
leaq 0x9496(%rip), %rbx      # 0x172c8
movl (%rbx), %eax
cmpl $0x3, %eax
jl 0xde84
leaq 0x9490(%rip), %rax      # 0x172d0
movq (%rax), %r15
callq 0x2040
movl (%rax), %r12d
movq -0x48(%rbp), %r13
movb $0x0, (%r13)
movl (%rax), %edi
movl $0x40, %edx
movq %r13, %rsi
callq 0x2100
leaq 0x3c88(%rip), %rsi      # 0x11af2
leaq 0x39af(%rip), %rdx      # 0x11820
movl $0x3, %edi
movl %r12d, %ecx
movq %r13, %r8
xorl %eax, %eax
callq *%r15
movl -0x2c(%rbp), %edx
movl -0x3c(%rbp), %edi
testl %edi, %edi
jle 0xdefe
leaq -0x88(%rbp), %rcx
movl $0x2, %esi
callq 0x2320
testl %eax, %eax
jns 0xdeec
cmpl $0x0, (%rbx)
jle 0xdeec
leaq 0x9424(%rip), %rax      # 0x172d0
movq (%rax), %rbx
callq 0x2040
movl (%rax), %r15d
movq -0x48(%rbp), %r12
movb $0x0, (%r12)
movl (%rax), %edi
movl $0x40, %edx
movq %r12, %rsi
callq 0x2100
leaq 0x3be7(%rip), %rsi      # 0x11abd
leaq 0x3943(%rip), %rdx      # 0x11820
movl $0x1, %edi
movl %r15d, %ecx
movq %r12, %r8
xorl %eax, %eax
callq *%rbx
movl -0x3c(%rbp), %edi
callq 0x2550
jmp 0xdefe
movl $0x2, %r14d
jmp 0xdefe
movq -0x78(%rbp), %rsp
movl %r14d, %eax
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq