// File: /workspace/github_cpp_makefile_star2_O3/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, %ebx
movl %edi, %r14d
cmpl %edi, %esi
movl %edi, %eax
cmovgl %esi, %eax
incl %eax
movl %eax, 0x4(%rsp)
leal 0x3f(%rbx), %eax
testl %esi, %esi
cmovnsl %esi, %eax
movl %eax, %edx
andl $-0x40, %edx
movl %esi, %ecx
subl %edx, %ecx
movl $0x1, %edx
shlq %cl, %rdx
movq %rdx, 0x10(%rsp)
movl $0x1, %r12d
sarl $0x6, %eax
cltq
movq %rax, 0x8(%rsp)
leal 0x3f(%r14), %eax
testl %edi, %edi
cmovnsl %edi, %eax
movl %eax, %edx
andl $-0x40, %edx
movl %edi, %ecx
subl %edx, %ecx
shlq %cl, %r12
sarl $0x6, %eax
cltq
movq %rax, 0x18(%rsp)
xorl %ebp, %ebp
xorl %r15d, %r15d
xorps %xmm0, %xmm0
movaps %xmm0, 0x90(%rsp)
movaps %xmm0, 0x80(%rsp)
movaps %xmm0, 0x70(%rsp)
movaps %xmm0, 0x60(%rsp)
movaps %xmm0, 0x50(%rsp)
movaps %xmm0, 0x40(%rsp)
movaps %xmm0, 0x30(%rsp)
movaps %xmm0, 0x20(%rsp)
movaps %xmm0, 0xa0(%rsp)
movaps %xmm0, 0xb0(%rsp)
movaps %xmm0, 0xc0(%rsp)
movaps %xmm0, 0xd0(%rsp)
movaps %xmm0, 0xe0(%rsp)
movaps %xmm0, 0xf0(%rsp)
movaps %xmm0, 0x100(%rsp)
movaps %xmm0, 0x110(%rsp)
cmpl $0x3ff, %r15d           # imm = 0x3FF
jg 0x548a
movq 0x10(%rsp), %rax
movq 0x8(%rsp), %rcx
orq %rax, 0x20(%rsp,%rcx,8)
cmpl $0x3ff, %ebp            # imm = 0x3FF
jg 0x549c
movq 0x18(%rsp), %rax
orq %r12, 0x20(%rsp,%rax,8)
movl 0x4(%rsp), %edi
leaq 0x20(%rsp), %rsi
leaq 0xa0(%rsp), %rdx
xorl %ecx, %ecx
xorl %r8d, %r8d
callq 0x21d0
cmpl $-0x1, %eax
je 0x567c
cmpl $0x3ff, %ebp            # imm = 0x3FF
jg 0x552d
movq 0x18(%rsp), %rax
movq 0x20(%rsp,%rax,8), %rax
andq %r12, %rax
je 0x552d
movslq %ebp, %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 0x5508
testl %eax, %eax
je 0x56fc
addl %eax, %ebp
jmp 0x552d
callq 0x2030
movl (%rax), %r13d
cmpl $0x68, %r13d
jne 0x5716
movl $0x2, %edi
leaq 0x3c64(%rip), %rsi      # 0x918a
xorl %eax, %eax
callq 0x352c
cmpl $0x3ff, %r15d           # imm = 0x3FF
jg 0x557a
movq 0x8(%rsp), %rax
movq 0x20(%rsp,%rax,8), %rax
andq 0x10(%rsp), %rax
je 0x557a
movslq %r15d, %rax
leaq (%rsp,%rax), %rsi
addq $0x520, %rsi            # imm = 0x520
movl $0x400, %edx            # imm = 0x400
subq %rax, %rdx
movl %ebx, %edi
xorl %ecx, %ecx
callq 0x2090
cmpl $-0x1, %eax
je 0x56cf
testl %eax, %eax
je 0x56b5
addl %eax, %r15d
testl %r15d, %r15d
jle 0x55fe
movl %r15d, %edx
movl %r14d, %edi
leaq 0x520(%rsp), %rsi
xorl %ecx, %ecx
callq 0x2100
cmpl $-0x1, %eax
je 0x55c4
testl %eax, %eax
jle 0x55fe
subl %eax, %r15d
jle 0x55ef
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
leaq (%rsp,%rax), %rsi
addq $0x520, %rsi            # imm = 0x520
movl %r15d, %edx
leaq 0x520(%rsp), %rdi
callq 0x21a0
jmp 0x55fe
callq 0x2030
movl (%rax), %r13d
movl %r13d, %edi
callq 0x20a0
movl $0x2, %edi
leaq 0x3c32(%rip), %rsi      # 0x9212
movl %r13d, %edx
movq %rax, %rcx
xorl %eax, %eax
callq 0x352c
jmp 0x55fe
testl %r15d, %r15d
movl $0x0, %r15d
js 0x576f
testl %ebp, %ebp
jle 0x5401
movl %ebp, %edx
movl %ebx, %edi
leaq 0x120(%rsp), %rsi
xorl %ecx, %ecx
callq 0x2100
cmpl $-0x1, %eax
je 0x564e
subl %eax, %ebp
cmpl %eax, %ebp
jle 0x5641
cltq
leaq (%rsp,%rax), %rsi
addq $0x120, %rsi            # imm = 0x120
movslq %ebp, %rdx
leaq 0x120(%rsp), %rdi
callq 0x21a0
testl %ebp, %ebp
jns 0x5401
jmp 0x5750
callq 0x2030
movl (%rax), %r13d
movl %r13d, %edi
callq 0x20a0
movl $0x2, %edi
leaq 0x3c1c(%rip), %rsi      # 0x9286
movl %r13d, %edx
movq %rax, %rcx
xorl %eax, %eax
callq 0x352c
jmp 0x5401
callq 0x2030
movl (%rax), %ebp
movl $0x1, %ebx
cmpl $0x4, %ebp
je 0x573c
movl %ebp, %edi
callq 0x20a0
leaq 0x3a5a(%rip), %rsi      # 0x90f9
movl $0x2, %edi
movl %ebp, %edx
movq %rax, %rcx
xorl %eax, %eax
callq 0x352c
jmp 0x573c
leaq 0x3af1(%rip), %rsi      # 0x91ad
movl $0x3, %ebx
movl $0x3, %edi
xorl %eax, %eax
callq 0x352c
jmp 0x573c
callq 0x2030
movl (%rax), %ebx
movl %ebx, %edi
callq 0x20a0
leaq 0x3af4(%rip), %rsi      # 0x91d8
movl $0x2, %edi
movl %ebx, %edx
movq %rax, %rcx
xorl %eax, %eax
callq 0x352c
movl $0x4, %ebx
jmp 0x573c
leaq 0x3a24(%rip), %rsi      # 0x9127
movl $0x3, %edi
xorl %eax, %eax
callq 0x352c
movl $0x2, %ebx
jmp 0x573c
movl %r13d, %edi
callq 0x20a0
leaq 0x3a2d(%rip), %rsi      # 0x9152
movl $0x2, %edi
movl %r13d, %edx
movq %rax, %rcx
xorl %eax, %eax
callq 0x352c
movl $0x5, %ebx
movl %ebx, %eax
addq $0x928, %rsp            # imm = 0x928
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x3b67(%rip), %rdi      # 0x92be
leaq 0x3afe(%rip), %rsi      # 0x925c
leaq 0x3b08(%rip), %rcx      # 0x926d
movl $0xc9, %edx
callq 0x2140
leaq 0x3ad4(%rip), %rdi      # 0x924a
leaq 0x3adf(%rip), %rsi      # 0x925c
leaq 0x3ae9(%rip), %rcx      # 0x926d
movl $0xb6, %edx
callq 0x2140
nop