// File: qian-jiahong[P]uvncrep017-ws/repeater.cpp
// Function: nonBlockingRead(int, char*, int, int)
static int nonBlockingRead(int sock, char *buf, int len, int timeOut)
{
    int n;
    int timeOutCtr;
    int numRead = 0;
    
    debug(LEVEL_3, "nonBlockingRead(): start\n");
    timeOutCtr=0;
    while ((len > 0) && (timeOutCtr < timeOut)) {
        n = recv(sock, buf, len, MSG_DONTWAIT);

        if (n > 0) {
            buf += n;
            len -= n;
            numRead += n;
        }
        else {
            if (n == -1) {
                //recv() returned -1 to indicate some error
                //Because we use non-blocking in recv(), we have to 
                //handle EAGAIN by incrementing timeout counter
                if (errno == EAGAIN) {
                    sleep(1);
                    timeOutCtr++;
                }
            }
            else {
                debug(LEVEL_2, "nonBlockingRead(): recv() returned error, errno= %d (%s)\n", errno, strerror(errno));
                return -1;  //return value of recv() was unknown
            }
        }
    }

    if (timeOutCtr < timeOut) {
        debug(LEVEL_3, "nonBlockingRead(): returning normally\n");
        return numRead;
    }
    else {
        //In case of timeout, return number of bytes received if > 0, 
        //otherwise return -2 to indicate timeout
        if (numRead > 0) {
            debug(LEVEL_3, "nonBlockingRead(): returning %d bytes\n", numRead);
            return numRead;
        }
        else {
            debug(LEVEL_3, "nonBlockingRead(): timeout error\n");
            return -2;
        }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
movl %ecx, -0x18(%rbp)
movl $0x0, -0x24(%rbp)
movl $0x3, %edi
leaq 0x7672(%rip), %rsi      # 0xa63a
movb $0x0, %al
callq 0x2480
movl $0x0, -0x20(%rbp)
xorl %eax, %eax
cmpl $0x0, -0x14(%rbp)
movb %al, -0x25(%rbp)
jle 0x2fed
movl -0x20(%rbp), %eax
cmpl -0x18(%rbp), %eax
setl %al
movb %al, -0x25(%rbp)
movb -0x25(%rbp), %al
testb $0x1, %al
jne 0x2ff9
jmp 0x30a2
movl -0x8(%rbp), %edi
movq -0x10(%rbp), %rsi
movslq -0x14(%rbp), %rdx
movl $0x40, %ecx
callq 0x20a0
movl %eax, -0x1c(%rbp)
cmpl $0x0, -0x1c(%rbp)
jle 0x303e
movl -0x1c(%rbp), %ecx
movq -0x10(%rbp), %rax
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x10(%rbp)
movl -0x1c(%rbp), %ecx
movl -0x14(%rbp), %eax
subl %ecx, %eax
movl %eax, -0x14(%rbp)
movl -0x1c(%rbp), %eax
addl -0x24(%rbp), %eax
movl %eax, -0x24(%rbp)
jmp 0x309d
cmpl $-0x1, -0x1c(%rbp)
jne 0x3063
callq 0x2030
cmpl $0xb, (%rax)
jne 0x3061
movl $0x1, %edi
callq 0x2170
movl -0x20(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x20(%rbp)
jmp 0x309b
callq 0x2030
movl (%rax), %eax
movl %eax, -0x2c(%rbp)
callq 0x2030
movl (%rax), %edi
callq 0x20b0
movl -0x2c(%rbp), %edx
movq %rax, %rcx
movl $0x2, %edi
leaq 0x75c9(%rip), %rsi      # 0xa654
movb $0x0, %al
callq 0x2480
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x3103
jmp 0x309d
jmp 0x2fd6
movl -0x20(%rbp), %eax
cmpl -0x18(%rbp), %eax
jge 0x30c5
movl $0x3, %edi
leaq 0x75d8(%rip), %rsi      # 0xa68e
movb $0x0, %al
callq 0x2480
movl -0x24(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x3103
cmpl $0x0, -0x24(%rbp)
jle 0x30e9
movl -0x24(%rbp), %edx
movl $0x3, %edi
leaq 0x75db(%rip), %rsi      # 0xa6b5
movb $0x0, %al
callq 0x2480
movl -0x24(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x3103
movl $0x3, %edi
leaq 0x75e7(%rip), %rsi      # 0xa6dc
movb $0x0, %al
callq 0x2480
movl $0xfffffffe, -0x4(%rbp) # imm = 0xFFFFFFFE
movl -0x4(%rbp), %eax
addq $0x30, %rsp
popq %rbp
retq
nopl (%rax)