// File: /workspace/github_cpp_makefile_star2_O2/qian-jiahong[P]uvncrep017-ws/repeaterproc.cpp
// Function: doRepeater(int, int)
int doRepeater(int server, int viewer)
{
    /** vars for viewer input data **/
    char viewerBuf[1024];           /* viewer input buffer */
    int viewerBufLen;               /* available data in viewerBuf */

    /** vars for server input data **/
    char serverBuf[1024];           /* server input buffer */
    int serverBufLen;               /* available data in serverBuf */

    /** other variables **/
    int nfds, len;
    fd_set ifds;
    fd_set ofds;
    
    /*
     * repeater between server and viewer 
     */
    nfds = ((viewer < server) ? server : viewer) + 1;
    viewerBufLen = 0;
    serverBufLen = 0;

    while (true) {
        FD_ZERO(&ifds);
        FD_ZERO(&ofds);

        /** prepare for reading viewer input **/
        if ((viewerBufLen < (int) sizeof(viewerBuf))) {
            FD_SET(viewer, &ifds);
        }

        /** prepare for reading server input **/
        if ((serverBufLen < (int) sizeof(serverBuf))) {
            FD_SET(server, &ifds);
        }

        if (select(nfds, &ifds, &ofds, NULL, NULL) == -1) {

            /* EINTR is normal if user presses ctrl+c */
            if (errno != EINTR) {
                /*
                * error in select, parent process should close both connections  
                */
                debug(LEVEL_2, "doRepeater(): select() failed, errno=%d (%s)\n", errno, strerror(errno));
            }
            return 1;
        }

        /*
         * server => viewer 
         */
        if (FD_ISSET(server, &ifds)
            && (serverBufLen < (int) sizeof(serverBuf))) {
            len = recv(server, serverBuf + serverBufLen, sizeof(serverBuf) - serverBufLen, 0);

            if (len == 0) {
                debug(LEVEL_3, "doRepeater(): connection closed by server\n");
                
                //When server closes connection, parent process should also disconnect viewer
                return 2;
            }
            else if (len == -1) {
                if (errno != ECONNRESET) {

                    /*
                     * error 
                     */
                    debug(LEVEL_2, "doRepeater(): recv() from server failed, errno=%d (%s)\n", errno, strerror(errno));
                    return 5;
                }
                else {
                    debug(LEVEL_2, "doRepeater(): ECONNRESET detected\n");
                }
            }
            else {
                serverBufLen += len;
            }
        }

        /*
         * viewer => server 
         */
        if (FD_ISSET(viewer, &ifds)
            && (viewerBufLen < (int) sizeof(viewerBuf))) {
            len = recv(viewer, viewerBuf + viewerBufLen, sizeof(viewerBuf) - viewerBufLen, 0);

            if (len == 0) {
                debug(LEVEL_3, "doRepeater(): connection closed by viewer\n");

                //When viewer closes connection,parent process should also disconnect server 
                return 3;
            }
            else if (len == -1) {

                /*
                 * error on reading from viewer 
                 */
                debug(LEVEL_2, "doRepeater(): recv() from viewer failed, errno = %d (%s)\n", errno, strerror(errno));
                return 4;
            }
            else {

                /*
                 * repeat 
                 */
                viewerBufLen += len;
            }
        }

        /*
         * flush data in viewerbuffer to server 
         */
        if (0 < viewerBufLen) {
            len = send(server, viewerBuf, viewerBufLen, 0);

            if (len == -1) {
                debug(LEVEL_2, "doRepeater(): send() (to server) failed, errno=%d (%s)\n", errno, strerror(errno));
            }
            else if (0 < len) {

                /*
                 * move data on to top of buffer 
                 */
                viewerBufLen -= len;

                if (0 < viewerBufLen)
                    memcpy(viewerBuf, viewerBuf + len, viewerBufLen);

                assert(0 <= viewerBufLen);
            }
        }

        /*
         * flush data in serverbuffer to viewer 
         */
        if (0 < serverBufLen) {
            len = send(viewer, serverBuf, serverBufLen, 0);

            if (len == -1) {
                debug(LEVEL_2, "doRepeater(): send() (to viewer) failed, errno=%d (%s)\n", errno, strerror(errno));
            }
            else {
                serverBufLen -= len;

                if (len < serverBufLen)
                    memcpy(serverBuf, serverBuf + len, serverBufLen);

                assert(0 <= serverBufLen);
            }
        }
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x928, %rsp            # imm = 0x928
movl %esi, %ecx
movl %edi, %r14d
cmpl %edi, %esi
cmovgl %esi, %edi
pushq $0x40
popq %rsi
movl %ecx, %eax
cltd
idivl %esi
movslq %eax, %rdx
movq %rdx, 0x10(%rsp)
shll $0x6, %eax
movl %ecx, 0x8(%rsp)
subl %eax, %ecx
pushq $0x1
popq %rbx
movq %rbx, %r13
shlq %cl, %r13
movl %r14d, %eax
cltd
idivl %esi
movslq %eax, %rcx
movq %rcx, 0x18(%rsp)
shll $0x6, %eax
movl %r14d, %ecx
subl %eax, %ecx
shlq %cl, %rbx
incl %edi
movl %edi, 0xc(%rsp)
xorl %r15d, %r15d
xorl %ebp, %ebp
xorl %eax, %eax
cmpq $0x10, %rax
je 0x51c8
andq $0x0, 0x20(%rsp,%rax,8)
incq %rax
jmp 0x51b7
xorl %eax, %eax
cmpq $0x10, %rax
je 0x51de
andq $0x0, 0xa0(%rsp,%rax,8)
incq %rax
jmp 0x51ca
cmpl $0x3ff, %ebp            # imm = 0x3FF
jg 0x51f0
movq 0x10(%rsp), %rax
orq %r13, 0x20(%rsp,%rax,8)
cmpl $0x3ff, %r15d           # imm = 0x3FF
jg 0x5203
movq 0x18(%rsp), %rax
orq %rbx, 0x20(%rsp,%rax,8)
movl 0xc(%rsp), %edi
leaq 0x20(%rsp), %rsi
leaq 0xa0(%rsp), %rdx
xorl %ecx, %ecx
xorl %r8d, %r8d
callq 0x21d0
cmpl $-0x1, %eax
je 0x53de
cmpl $0x3ff, %r15d           # imm = 0x3FF
jg 0x5294
movq 0x18(%rsp), %rax
movq 0x20(%rsp,%rax,8), %rax
andq %rbx, %rax
je 0x5294
movslq %r15d, %rax
leaq (%rsp,%rax), %rsi
addq $0x120, %rsi            # imm = 0x120
movl $0x400, %edx            # imm = 0x400
subq %rax, %rdx
movl %r14d, %edi
xorl %ecx, %ecx
callq 0x2090
cmpl $-0x1, %eax
je 0x5271
testl %eax, %eax
je 0x544d
addl %eax, %r15d
jmp 0x5294
callq 0x2030
movl (%rax), %r12d
cmpl $0x68, %r12d
jne 0x5462
pushq $0x2
popq %rdi
leaq 0x3efd(%rip), %rsi      # 0x918a
xorl %eax, %eax
callq 0x247c
cmpl $0x3ff, %ebp            # imm = 0x3FF
jg 0x52df
movq 0x10(%rsp), %rax
movq 0x20(%rsp,%rax,8), %rax
andq %r13, %rax
je 0x52df
movslq %ebp, %rax
leaq (%rsp,%rax), %rsi
addq $0x520, %rsi            # imm = 0x520
movl $0x400, %edx            # imm = 0x400
subq %rax, %rdx
movl 0x8(%rsp), %edi
xorl %ecx, %ecx
callq 0x2090
cmpl $-0x1, %eax
je 0x5425
testl %eax, %eax
je 0x5410
addl %eax, %ebp
testl %ebp, %ebp
jle 0x535b
movl %ebp, %edx
movl %r14d, %edi
leaq 0x520(%rsp), %rsi
xorl %ecx, %ecx
callq 0x2100
cmpl $-0x1, %eax
je 0x5325
testl %eax, %eax
jle 0x535b
subl %eax, %ebp
jle 0x534e
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
leaq (%rsp,%rax), %rsi
addq $0x520, %rsi            # imm = 0x520
movl %ebp, %edx
leaq 0x520(%rsp), %rdi
callq 0x21a0
jmp 0x535b
callq 0x2030
movl (%rax), %r12d
movl %r12d, %edi
callq 0x20a0
pushq $0x2
popq %rdi
leaq 0x3ed3(%rip), %rsi      # 0x9212
movl %r12d, %edx
movq %rax, %rcx
xorl %eax, %eax
callq 0x247c
jmp 0x535b
testl %ebp, %ebp
movl $0x0, %ebp
js 0x54b7
testl %r15d, %r15d
jle 0x51b5
movl %r15d, %edx
movl 0x8(%rsp), %edi
leaq 0x120(%rsp), %rsi
xorl %ecx, %ecx
callq 0x2100
cmpl $-0x1, %eax
je 0x53b2
subl %eax, %r15d
cmpl %eax, %r15d
jle 0x53a4
cltq
leaq (%rsp,%rax), %rsi
addq $0x120, %rsi            # imm = 0x120
movslq %r15d, %rdx
leaq 0x120(%rsp), %rdi
callq 0x21a0
testl %r15d, %r15d
jns 0x51b5
jmp 0x5498
callq 0x2030
movl (%rax), %r12d
movl %r12d, %edi
callq 0x20a0
pushq $0x2
popq %rdi
leaq 0x3eba(%rip), %rsi      # 0x9286
movl %r12d, %edx
movq %rax, %rcx
xorl %eax, %eax
callq 0x247c
jmp 0x51b5
callq 0x2030
movl (%rax), %ebp
pushq $0x1
popq %rbx
cmpl $0x4, %ebp
je 0x5484
movl %ebp, %edi
callq 0x20a0
leaq 0x3cfa(%rip), %rsi      # 0x90f9
pushq $0x2
popq %rdi
movl %ebp, %edx
movq %rax, %rcx
xorl %eax, %eax
callq 0x247c
jmp 0x5484
leaq 0x3d96(%rip), %rsi      # 0x91ad
pushq $0x3
popq %rbx
movl %ebx, %edi
xorl %eax, %eax
callq 0x247c
jmp 0x5484
callq 0x2030
movl (%rax), %ebx
movl %ebx, %edi
callq 0x20a0
leaq 0x3d9e(%rip), %rsi      # 0x91d8
pushq $0x2
popq %rdi
movl %ebx, %edx
movq %rax, %rcx
xorl %eax, %eax
callq 0x247c
pushq $0x4
jmp 0x5483
leaq 0x3cd3(%rip), %rsi      # 0x9127
pushq $0x3
popq %rdi
xorl %eax, %eax
callq 0x247c
pushq $0x2
jmp 0x5483
movl %r12d, %edi
callq 0x20a0
leaq 0x3ce1(%rip), %rsi      # 0x9152
pushq $0x2
popq %rdi
movl %r12d, %edx
movq %rax, %rcx
xorl %eax, %eax
callq 0x247c
pushq $0x5
popq %rbx
movl %ebx, %eax
addq $0x928, %rsp            # imm = 0x928
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x3e1f(%rip), %rdi      # 0x92be
leaq 0x3db6(%rip), %rsi      # 0x925c
leaq 0x3dc0(%rip), %rcx      # 0x926d
movl $0xc9, %edx
callq 0x2140
leaq 0x3d8c(%rip), %rdi      # 0x924a
leaq 0x3d97(%rip), %rsi      # 0x925c
leaq 0x3da1(%rip), %rcx      # 0x926d
movl $0xb6, %edx
callq 0x2140
nop