// File: 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
movq %rsp, %rbp
subq $0x980, %rsp            # imm = 0x980
movl %edi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movl -0xc(%rbp), %eax
cmpl -0x8(%rbp), %eax
jge 0x6fd4
movl -0x8(%rbp), %eax
movl %eax, -0x954(%rbp)
jmp 0x6fdd
movl -0xc(%rbp), %eax
movl %eax, -0x954(%rbp)
movl -0x954(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x828(%rbp)
movl $0x0, -0x414(%rbp)
movl $0x0, -0x824(%rbp)
jmp 0x7002
leaq -0x8b0(%rbp), %rax
movq %rax, -0x940(%rbp)
movl $0x0, -0x934(%rbp)
movl -0x934(%rbp), %eax
cmpq $0x10, %rax
jae 0x704c
movq -0x940(%rbp), %rax
movl -0x934(%rbp), %ecx
movq $0x0, (%rax,%rcx,8)
movl -0x934(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x934(%rbp)
jmp 0x701a
jmp 0x704e
jmp 0x7050
leaq -0x930(%rbp), %rax
movq %rax, -0x950(%rbp)
movl $0x0, -0x944(%rbp)
movl -0x944(%rbp), %eax
cmpq $0x10, %rax
jae 0x709a
movq -0x950(%rbp), %rax
movl -0x944(%rbp), %ecx
movq $0x0, (%rax,%rcx,8)
movl -0x944(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x944(%rbp)
jmp 0x7068
jmp 0x709c
cmpl $0x400, -0x414(%rbp)    # imm = 0x400
jge 0x70df
movl -0xc(%rbp), %eax
movl $0x40, %ecx
cltd
idivl %ecx
movl %edx, %eax
movl %eax, %ecx
movl $0x1, %eax
shlq %cl, %rax
movq %rax, %rcx
movl -0xc(%rbp), %eax
movl $0x40, %esi
cltd
idivl %esi
cltq
orq -0x8b0(%rbp,%rax,8), %rcx
movq %rcx, -0x8b0(%rbp,%rax,8)
cmpl $0x400, -0x824(%rbp)    # imm = 0x400
jge 0x7122
movl -0x8(%rbp), %eax
movl $0x40, %ecx
cltd
idivl %ecx
movl %edx, %eax
movl %eax, %ecx
movl $0x1, %eax
shlq %cl, %rax
movq %rax, %rcx
movl -0x8(%rbp), %eax
movl $0x40, %esi
cltd
idivl %esi
cltq
orq -0x8b0(%rbp,%rax,8), %rcx
movq %rcx, -0x8b0(%rbp,%rax,8)
movl -0x828(%rbp), %edi
leaq -0x8b0(%rbp), %rsi
leaq -0x930(%rbp), %rdx
xorl %eax, %eax
movl %eax, %r8d
movq %r8, %rcx
callq 0x21f0
cmpl $-0x1, %eax
jne 0x7193
callq 0x2030
cmpl $0x4, (%rax)
je 0x7187
callq 0x2030
movl (%rax), %eax
movl %eax, -0x958(%rbp)
callq 0x2030
movl (%rax), %edi
callq 0x20b0
movl -0x958(%rbp), %edx
movq %rax, %rcx
movl $0x2, %edi
leaq 0x4fab(%rip), %rsi      # 0xc12b
movb $0x0, %al
callq 0x2480
movl $0x1, -0x4(%rbp)
jmp 0x75a1
movl -0x8(%rbp), %eax
movl $0x40, %ecx
cltd
idivl %ecx
cltq
movq -0x8b0(%rbp,%rax,8), %rax
movq %rax, -0x960(%rbp)
movl -0x8(%rbp), %eax
movl $0x40, %ecx
cltd
idivl %ecx
movq -0x960(%rbp), %rax
movl %edx, %ecx
movl $0x1, %edx
shlq %cl, %rdx
movq %rdx, %rcx
andq %rcx, %rax
cmpq $0x0, %rax
je 0x72c2
cmpl $0x400, -0x824(%rbp)    # imm = 0x400
jge 0x72c2
movl -0x8(%rbp), %edi
leaq -0x820(%rbp), %rsi
movslq -0x824(%rbp), %rax
addq %rax, %rsi
movslq -0x824(%rbp), %rax
movl $0x400, %edx            # imm = 0x400
subq %rax, %rdx
xorl %ecx, %ecx
callq 0x20a0
movl %eax, -0x82c(%rbp)
cmpl $0x0, -0x82c(%rbp)
jne 0x7243
movl $0x3, %edi
leaq 0x4f29(%rip), %rsi      # 0xc159
movb $0x0, %al
callq 0x2480
movl $0x2, -0x4(%rbp)
jmp 0x75a1
cmpl $-0x1, -0x82c(%rbp)
jne 0x72ac
callq 0x2030
cmpl $0x68, (%rax)
je 0x7297
callq 0x2030
movl (%rax), %eax
movl %eax, -0x964(%rbp)
callq 0x2030
movl (%rax), %edi
callq 0x20b0
movl -0x964(%rbp), %edx
movq %rax, %rcx
movl $0x2, %edi
leaq 0x4f00(%rip), %rsi      # 0xc184
movb $0x0, %al
callq 0x2480
movl $0x5, -0x4(%rbp)
jmp 0x75a1
movl $0x2, %edi
leaq 0x4f19(%rip), %rsi      # 0xc1bc
movb $0x0, %al
callq 0x2480
jmp 0x72be
movl -0x82c(%rbp), %eax
addl -0x824(%rbp), %eax
movl %eax, -0x824(%rbp)
jmp 0x72c0
jmp 0x72c2
movl -0xc(%rbp), %eax
movl $0x40, %ecx
cltd
idivl %ecx
cltq
movq -0x8b0(%rbp,%rax,8), %rax
movq %rax, -0x970(%rbp)
movl -0xc(%rbp), %eax
movl $0x40, %ecx
cltd
idivl %ecx
movq -0x970(%rbp), %rax
movl %edx, %ecx
movl $0x1, %edx
shlq %cl, %rdx
movq %rdx, %rcx
andq %rcx, %rax
cmpq $0x0, %rax
je 0x73d2
cmpl $0x400, -0x414(%rbp)    # imm = 0x400
jge 0x73d2
movl -0xc(%rbp), %edi
leaq -0x410(%rbp), %rsi
movslq -0x414(%rbp), %rax
addq %rax, %rsi
movslq -0x414(%rbp), %rax
movl $0x400, %edx            # imm = 0x400
subq %rax, %rdx
xorl %ecx, %ecx
callq 0x20a0
movl %eax, -0x82c(%rbp)
cmpl $0x0, -0x82c(%rbp)
jne 0x7372
movl $0x3, %edi
leaq 0x4e80(%rip), %rsi      # 0xc1df
movb $0x0, %al
callq 0x2480
movl $0x3, -0x4(%rbp)
jmp 0x75a1
cmpl $-0x1, -0x82c(%rbp)
jne 0x73bc
callq 0x2030
movl (%rax), %eax
movl %eax, -0x974(%rbp)
callq 0x2030
movl (%rax), %edi
callq 0x20b0
movl -0x974(%rbp), %edx
movq %rax, %rcx
movl $0x2, %edi
leaq 0x4e61(%rip), %rsi      # 0xc20a
movb $0x0, %al
callq 0x2480
movl $0x4, -0x4(%rbp)
jmp 0x75a1
movl -0x82c(%rbp), %eax
addl -0x414(%rbp), %eax
movl %eax, -0x414(%rbp)
jmp 0x73d0
jmp 0x73d2
xorl %eax, %eax
cmpl -0x414(%rbp), %eax
jge 0x74bb
movl -0x8(%rbp), %edi
leaq -0x410(%rbp), %rsi
movslq -0x414(%rbp), %rdx
xorl %ecx, %ecx
callq 0x2110
movl %eax, -0x82c(%rbp)
cmpl $-0x1, -0x82c(%rbp)
jne 0x743e
callq 0x2030
movl (%rax), %eax
movl %eax, -0x978(%rbp)
callq 0x2030
movl (%rax), %edi
callq 0x20b0
movl -0x978(%rbp), %edx
movq %rax, %rcx
movl $0x2, %edi
leaq 0x4e0f(%rip), %rsi      # 0xc244
movb $0x0, %al
callq 0x2480
jmp 0x74b9
xorl %eax, %eax
cmpl -0x82c(%rbp), %eax
jge 0x74b7
movl -0x82c(%rbp), %ecx
movl -0x414(%rbp), %eax
subl %ecx, %eax
movl %eax, -0x414(%rbp)
xorl %eax, %eax
cmpl -0x414(%rbp), %eax
jge 0x748a
leaq -0x410(%rbp), %rdi
leaq -0x410(%rbp), %rsi
movslq -0x82c(%rbp), %rax
addq %rax, %rsi
movslq -0x414(%rbp), %rdx
callq 0x21b0
xorl %eax, %eax
cmpl -0x414(%rbp), %eax
jg 0x7496
jmp 0x74b5
leaq 0x4ddf(%rip), %rdi      # 0xc27c
leaq 0x4dea(%rip), %rsi      # 0xc28e
movl $0xb6, %edx
leaq 0x4def(%rip), %rcx      # 0xc29f
callq 0x2150
jmp 0x74b7
jmp 0x74b9
jmp 0x74bb
xorl %eax, %eax
cmpl -0x824(%rbp), %eax
jge 0x759c
movl -0xc(%rbp), %edi
leaq -0x820(%rbp), %rsi
movslq -0x824(%rbp), %rdx
xorl %ecx, %ecx
callq 0x2110
movl %eax, -0x82c(%rbp)
cmpl $-0x1, -0x82c(%rbp)
jne 0x7527
callq 0x2030
movl (%rax), %eax
movl %eax, -0x97c(%rbp)
callq 0x2030
movl (%rax), %edi
callq 0x20b0
movl -0x97c(%rbp), %edx
movq %rax, %rcx
movl $0x2, %edi
leaq 0x4d9a(%rip), %rsi      # 0xc2b8
movb $0x0, %al
callq 0x2480
jmp 0x759a
movl -0x82c(%rbp), %ecx
movl -0x824(%rbp), %eax
subl %ecx, %eax
movl %eax, -0x824(%rbp)
movl -0x82c(%rbp), %eax
cmpl -0x824(%rbp), %eax
jge 0x756d
leaq -0x820(%rbp), %rdi
leaq -0x820(%rbp), %rsi
movslq -0x82c(%rbp), %rax
addq %rax, %rsi
movslq -0x824(%rbp), %rdx
callq 0x21b0
xorl %eax, %eax
cmpl -0x824(%rbp), %eax
jg 0x7579
jmp 0x7598
leaq 0x4d70(%rip), %rdi      # 0xc2f0
leaq 0x4d07(%rip), %rsi      # 0xc28e
movl $0xc9, %edx
leaq 0x4d0c(%rip), %rcx      # 0xc29f
callq 0x2150
jmp 0x759a
jmp 0x759c
jmp 0x7000
movl -0x4(%rbp), %eax
addq $0x980, %rsp            # imm = 0x980
popq %rbp
retq
nopl (%rax)