// File: /workspace/github_cpp_makefile_star2_O1/renzibei[P]TSProxy/proxyserver.cpp
// Function: recvAndHandleClientData(int, std::unordered_map<int, ClientNode*, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<int const, ClientNode*>>>&, std::unordered_map<int, HostNode, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<int const, HostNode>>>&, fd_set&, fd_set&, int&, int&, int&)
int recvAndHandleClientData(int sockFd, ClientMap &cMap, HostMap &h2lMap, fd_set &readFdSet, fd_set &writeFdSet, int &max_read_sd, int &max_write_sd, int &max_all_sd) {
    static uint8_t buf[constants::MAX_MSG_DATA_LENGTH];
    memset(buf, 0, sizeof(buf));
    uint8_t msgType = 0;
    int recvLen = recvData(sockFd, buf, sizeof(buf), cMap, &msgType);
    if (recvLen < 0) {
        LogHelper::log(Error, "Failed to recv data from client: %d", sockFd);
        return recvLen;
    }
    LogHelper::log(Debug, "Has recv a msg from client: %d, goning to handleit", sockFd);
    using namespace constants;
    SocketMap *l2hMap = &(cMap[sockFd]->sMap);
    if (msgType == constants::SocksTcpRequestMsg) {
        LogHelper::log(Debug, "it's a tcp request msg");
        static char dstAddrBuf[SocksDomainMaxLength];
        memset(dstAddrBuf, 0, sizeof(dstAddrBuf));
        uint8_t respCode = 0x00;
        uint8_t requestCmd = buf[0], dstAddrType = buf[1];
        int localFd = -1;
        if (requestCmd == SocksConnectCmd) {
            uint16_t dstPort = 0;
            if (dstAddrType == SocksAddrIpv4Type) {
                if (recvLen < 2 + 4 + 2 + 4) {
                    LogHelper::log(Warn, "len less than ipv4 addr, recvLen: %d", recvLen);
                    respCode = 0xff;
                }
                else {
                    if (inet_ntop(AF_INET, buf + 2, dstAddrBuf, sizeof(dstAddrBuf)) == NULL) {
                        LogHelper::log(Warn, "Fail to convert ipv4 num to str, %s", strerror(errno));
                        respCode = 0xff;
                    }
                    else {
                        ntoh_copy2bytes(&dstPort, buf + 6);
                        ntoh_copy4bytes(&localFd, buf + 8);
                    }
                }
            }
            else if (dstAddrType == SocksAddrIpv6Type) {
                if (recvLen < 2 + 16 + 2 + 4) {
                    LogHelper::log(Warn, "len less than ipv6 addr, recvLen: %d", recvLen);
                    respCode = 0xff;
                }
                else {
                    if (inet_ntop(AF_INET6, buf + 2, dstAddrBuf, sizeof(dstAddrBuf)) == NULL) {
                        LogHelper::log(Warn, "Fail to convert ipv6 num to str, %s", strerror(errno));
                        respCode = 0xff;
                    }
                    else {
                        ntoh_copy2bytes(&dstPort, buf + 18);
                        ntoh_copy4bytes(&localFd, buf + 20);
                    }
                }
            }
            else if (dstAddrType == SocksAddrDomainType) {
                if (recvLen < 2 + 1) {
                    LogHelper::log(Warn, "len less than domain header, recvLen: %d", recvLen);
                    respCode = 0xff;
                }
                else {
                    uint8_t domainAddrLen = buf[2];
                    if (recvLen < 2 + 1 + domainAddrLen + 2 + 4) {
                        LogHelper::log(Warn, "len less than domain addr, recvLen: %d", recvLen);
                        respCode = 0xff;
                    }
                    else {
                        memcpy(dstAddrBuf, buf + 3, domainAddrLen);
                        ntoh_copy2bytes(&dstPort, buf + 3 + domainAddrLen);
                        ntoh_copy4bytes(&localFd, buf + 3 + domainAddrLen + 2);
                    }
                }
            }
            else {
                LogHelper::log(Warn, "Unknown addrtype, type: %d", dstAddrType);
                respCode = 0xff;
            }

            if (respCode == 0x00) {
                
                LogHelper::log(Debug, "begin to try to connect socket to host");
                
                int hostSd = tryConnectSocket(dstAddrBuf, dstPort, constants::serverNonBlocking);
                LogHelper::log(Debug, "try end");
                if (hostSd < 0) {
                    respCode = 0xff;
                }
                else {
                    time_t nowT = time(NULL);
                    (*l2hMap)[localFd] = SocketNode(hostSd, nowT);
                    h2lMap[hostSd] = HostNode(sockFd, localFd, nowT);
                    FD_SET(hostSd, &readFdSet);
                    if (hostSd > max_read_sd) {
                        max_read_sd = hostSd;
                    }
                    FD_SET(hostSd, &writeFdSet);
                    if (hostSd > max_write_sd) {
                        max_write_sd = hostSd;
                    }
                    max_all_sd = std::max(max_read_sd, max_write_sd);
                    LogHelper::log(Debug, "Add hostFd :%d", hostSd);

                }
            }


        }
        else {
            respCode = 0xff;
        }

        

        static uint8_t replyMsgBuf[MAX_MSG_DATA_LENGTH];
        memset(replyMsgBuf, 0, sizeof(replyMsgBuf));
        replyMsgBuf[0] = respCode;
        replyMsgBuf[1] = SocksAddrIpv4Type;
        memset(replyMsgBuf + 2, 0, 4);
        uint16_t fakePort = 1728;
        hton_copy2bytes(replyMsgBuf + 6 , &fakePort);
        hton_copy4bytes(replyMsgBuf + 6 + sizeof(fakePort), &localFd);
        size_t replyLen = 1 + 1 + 4 + sizeof(fakePort) + sizeof(localFd);
        int sendCode = sendData(sockFd, replyMsgBuf, replyLen, cMap, SocksTcpReplyMsg);
        if (sendCode < 0) {
            LogHelper::log(Error, "Failed to send socks forth handshake reply from server");
            return sendCode;
        }
        
        
    }
    else if (msgType == SocksTrafficRequestMsg) {
        LogHelper::log(Debug, "it's a traffic request msg");

        int localFd = -1;
        if (recvLen < sizeof(localFd)) {
            LogHelper::log(Error, "Fail to receive socks traffic request, length less than localFd");
            return -5;
        }
        ntoh_copy4bytes(&localFd, buf);
        auto l2hIt = l2hMap->find(localFd);
        if (l2hIt == l2hMap->end()) {
            LogHelper::log(Warn, "Can not find localFd %d in l2hMap", localFd);
            return 0;
        }
        int hostSd = (*l2hMap)[localFd].sockFd;
        h2lMap[hostSd].writeToBuffer(buf + sizeof(localFd), recvLen - sizeof(localFd));
        // ssize_t sendCode = writeNBytes(hostSd, buf + sizeof(localFd), recvLen - sizeof(localFd), constants::serverNonBlocking);
        // if (sendCode < 0) {
        //     LogHelper::log(Warn, "Failed to send data to host, localFd: %d, will close hostSd", localFd);
        //     close(hostSd);
        //     FD_CLR(hostSd, &readFdSet);
        //     if (hostSd == max_read_sd) {
        //         while (FD_ISSET(max_read_sd, &readFdSet) == 0)
        //             max_read_sd -= 1;
        //     }
        //     l2hMap->erase(localFd);
        //     h2lMap.erase(hostSd);
        //     return -7;
        // }
        LogHelper::log(Debug, "End Send %d bytes to host: %d",recvLen - sizeof(localFd), hostSd);
        // for (int k = 0; k < recvLen - sizeof(localFd); ++k) {
        //     fprintf(stderr, "%c", buf[sizeof(localFd) + k]);
        // }
        // fprintf(stderr, "\n");
        time_t nowT = time(NULL);
        l2hIt->second.lastTime = nowT;
        // h2lMap[hostSd].lastTime = nowT;
    }
    else if (msgType == DebugC2SMsg) {
        LogHelper::log(Debug, "Received Debug C2S msg: %s", buf);
    }
    else {
        LogHelper::log(Warn, "Received Unknown msg type from client: %d", msgType);
        return -8;
    }

    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movq %r9, %r15
movq %r8, 0x30(%rsp)
movq %rcx, %r13
movq %rdx, %r12
movq %rsi, %rbx
movl %edi, %ebp
movl %edi, 0x18(%rsp)
leaq 0x3a59b(%rip), %r14     # 0x3d210
movl $0xffec, %edx           # imm = 0xFFEC
movq %r14, %rdi
xorl %esi, %esi
callq 0x2120
leaq 0xf(%rsp), %r8
movb $0x0, (%r8)
movl $0xffec, %edx           # imm = 0xFFEC
movl %ebp, %edi
movq %r14, %rsi
movq %rbx, %rcx
callq 0x2b00
movl %eax, %ebp
movl 0x18(%rsp), %edx
testl %eax, %eax
js 0x2d75
leaq 0x5653(%rip), %rsi      # 0x8307
movl $0x3, %edi
xorl %eax, %eax
callq 0x273c
leaq 0x18(%rsp), %rsi
movq %rbx, %rdi
callq 0x4a0e
movzbl 0xf(%rsp), %edx
cmpl $0x4, %edx
je 0x2dca
movq %r12, 0x20(%rsp)
movq (%rax), %r12
leaq 0x18(%r12), %rax
cmpl $0x8, %edx
je 0x2d8a
cmpl $0x6, %edx
jne 0x2de9
movq %rax, 0x28(%rsp)
leaq 0x5634(%rip), %rsi      # 0x833a
movl $0x3, %edi
xorl %eax, %eax
callq 0x273c
leaq 0x4a4e7(%rip), %rdi     # 0x4d200
movl $0xff, %edx
xorl %esi, %esi
callq 0x2120
movb 0x3a4e5(%rip), %al      # 0x3d210
movzbl 0x3a4df(%rip), %edx     # 0x3d211
movl $0xffffffff, 0x10(%rsp) # imm = 0xFFFFFFFF
movb $-0x1, %r12b
cmpb $0x1, %al
jne 0x319b
cmpl $0x4, %edx
je 0x2e8b
cmpl $0x3, %edx
je 0x2e7d
cmpl $0x1, %edx
jne 0x2e99
cmpl $0xb, %ebp
jg 0x2f1f
leaq 0x55e1(%rip), %rsi      # 0x8351
jmp 0x2ec6
leaq 0x5567(%rip), %rsi      # 0x82e3
xorl %edi, %edi
xorl %eax, %eax
callq 0x273c
jmp 0x31fe
movq %rax, %r14
leaq 0x572f(%rip), %rsi      # 0x84c3
movl $0x3, %edi
xorl %eax, %eax
callq 0x273c
movl $0xffffffff, 0x38(%rsp) # imm = 0xFFFFFFFF
cmpl $0x3, %ebp
ja 0x2e06
leaq 0x572a(%rip), %rsi      # 0x84de
xorl %r15d, %r15d
xorl %edi, %edi
xorl %eax, %eax
callq 0x273c
movl $0xfffffffb, %ebp       # imm = 0xFFFFFFFB
jmp 0x2ff2
leaq 0x578d(%rip), %rsi      # 0x855e
leaq 0x3a438(%rip), %rdx     # 0x3d210
movl $0x3, %edi
xorl %eax, %eax
callq 0x273c
jmp 0x31fc
leaq 0x5789(%rip), %rsi      # 0x8579
movl $0x1, %edi
xorl %eax, %eax
callq 0x273c
movl $0xfffffff8, %ebp       # imm = 0xFFFFFFF8
jmp 0x31fe
movl 0x3a404(%rip), %ecx     # 0x3d210
bswapl %ecx
movl %ecx, 0x38(%rsp)
movslq %ecx, %rax
movq 0x18(%r12), %rdi
movq 0x20(%r12), %r8
xorl %r10d, %r10d
xorl %edx, %edx
divq %r8
movq (%rdi,%rdx,8), %rax
testq %rax, %rax
je 0x2f60
movq (%rax), %r9
movq %rax, %r10
cmpl 0x8(%r9), %ecx
je 0x2f60
movq %rdx, %rsi
movq %r9, %r11
movq (%r9), %r9
testq %r9, %r9
je 0x2f5d
movslq 0x8(%r9), %rdi
movq %rdi, %rax
xorl %edx, %edx
divq %r8
movl $0x0, %r10d
cmpq %rsi, %rdx
jne 0x2f60
movq %r11, %r10
cmpl %edi, %ecx
jne 0x2e47
jmp 0x2f60
cmpl $0x2, %ebp
jg 0x2eaa
leaq 0x555a(%rip), %rsi      # 0x83e3
jmp 0x2ec6
cmpl $0x17, %ebp
jg 0x2ee1
leaq 0x5503(%rip), %rsi      # 0x839a
jmp 0x2ec6
leaq 0x5593(%rip), %rsi      # 0x8433
xorl %r14d, %r14d
movl $0x1, %edi
jmp 0x2ed0
movzbl 0x3a360(%rip), %r12d    # 0x3d212
leal 0x9(%r12), %eax
cmpl %eax, %ebp
jge 0x3000
leaq 0x5546(%rip), %rsi      # 0x840c
xorl %r14d, %r14d
movl $0x1, %edi
movl %ebp, %edx
xorl %eax, %eax
callq 0x273c
movb $-0x1, %r12b
xorl %eax, %eax
jmp 0x3033
leaq 0x3a32a(%rip), %rsi     # 0x3d212
leaq 0x4a311(%rip), %rdx     # 0x4d200
movl $0xa, %edi
movl $0xff, %ecx
callq 0x21e0
testq %rax, %rax
je 0x3226
movzwl 0x3a313(%rip), %r14d    # 0x3d222
rolw $0x8, %r14w
movl 0x3a30a(%rip), %eax     # 0x3d224
jmp 0x3028
leaq 0x3a2ec(%rip), %rsi     # 0x3d212
leaq 0x4a2d3(%rip), %rdx     # 0x4d200
movl $0x2, %edi
movl $0xff, %ecx
callq 0x21e0
testq %rax, %rax
je 0x323b
movzwl 0x3a2c9(%rip), %r14d    # 0x3d216
rolw $0x8, %r14w
movl 0x3a2c0(%rip), %eax     # 0x3d218
jmp 0x3028
xorl %r10d, %r10d
testq %r10, %r10
je 0x2f6a
movq (%r10), %r12
jmp 0x2f6d
xorl %r12d, %r12d
testq %r12, %r12
setne %r15b
je 0x2fdb
movl %ebp, %ebx
leaq 0x38(%rsp), %rsi
movq %r14, %rdi
callq 0x4ce2
movl (%rax), %eax
leaq 0x10(%rsp), %r14
movl %eax, (%r14)
movq 0x20(%rsp), %rdi
movq %r14, %rsi
callq 0x4fa0
addq $-0x4, %rbx
leaq 0x3a26d(%rip), %rsi     # 0x3d214
movq %rax, %rdi
movq %rbx, %rdx
callq 0x4328
movl (%r14), %ecx
leaq 0x5584(%rip), %rsi      # 0x8540
xorl %ebp, %ebp
movl $0x3, %edi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x273c
xorl %edi, %edi
callq 0x2190
movq %rax, 0x18(%r12)
jmp 0x2ff2
leaq 0x553c(%rip), %rsi      # 0x851e
xorl %ebp, %ebp
movl $0x1, %edi
movl %ecx, %edx
xorl %eax, %eax
callq 0x273c
testb %r15b, %r15b
jne 0x31fc
jmp 0x31fe
leaq 0x4a1f9(%rip), %rdi     # 0x4d200
leaq 0x3a205(%rip), %rsi     # 0x3d213
movq %r12, %rdx
callq 0x2150
movzwl 0x3(%r12,%r14), %ecx
rolw $0x8, %cx
movl 0x5(%r12,%r14), %eax
movl %ecx, %r14d
bswapl %eax
movl %eax, 0x10(%rsp)
movb $0x1, %al
xorl %r12d, %r12d
testb %al, %al
je 0x319b
leaq 0x540c(%rip), %rsi      # 0x844e
movl $0x3, %edi
xorl %eax, %eax
callq 0x273c
movzwl %r14w, %esi
leaq 0x4a1a7(%rip), %rdi     # 0x4d200
movl $0x1, %edx
callq 0x563c
movl %eax, 0x14(%rsp)
leaq 0x5407(%rip), %rsi      # 0x8475
movl $0x3, %edi
xorl %eax, %eax
callq 0x273c
cmpl $0x0, 0x14(%rsp)
js 0x3198
movl %r12d, 0x1c(%rsp)
xorl %edi, %edi
callq 0x2190
movq %rax, %rbp
leaq 0x14(%rsp), %rax
movl (%rax), %r12d
leaq 0x10(%rsp), %r14
movq 0x28(%rsp), %rdi
movq %r14, %rsi
callq 0x4ce2
movl %r12d, (%rax)
movq %rbp, 0x8(%rax)
movl 0x18(%rsp), %eax
movl (%r14), %ecx
leaq 0x48(%rsp), %r14
movl %eax, -0x10(%r14)
movl %ecx, -0xc(%r14)
movq %rbp, -0x8(%r14)
xorps %xmm0, %xmm0
movups %xmm0, (%r14)
movups %xmm0, 0x10(%r14)
movups %xmm0, 0x20(%r14)
movups %xmm0, 0x30(%r14)
movups %xmm0, 0x40(%r14)
movq %r14, %rdi
xorl %esi, %esi
callq 0x441a
movq 0x20(%rsp), %rdi
leaq 0x14(%rsp), %rsi
callq 0x4fa0
movq 0xd0(%rsp), %rbp
movups 0x38(%rsp), %xmm0
movups %xmm0, (%rax)
addq $0x10, %rax
movq %rax, %rdi
movq %r14, %rsi
callq 0x4590
movq %r14, %rdi
callq 0x4646
movl 0x14(%rsp), %edx
leal 0x3f(%rdx), %esi
testl %edx, %edx
cmovnsl %edx, %esi
movl %esi, %eax
andl $-0x40, %eax
movl %edx, %ecx
subl %eax, %ecx
movl $0x1, %eax
shlq %cl, %rax
sarl $0x6, %esi
movslq %esi, %rcx
orq %rax, (%r13,%rcx,8)
cmpl (%r15), %edx
movl 0x1c(%rsp), %r12d
jle 0x315d
movl %edx, (%r15)
movq 0x30(%rsp), %rsi
orq %rax, (%rsi,%rcx,8)
movq 0xd8(%rsp), %rax
cmpl (%rbp), %edx
jle 0x3176
movl %edx, (%rbp)
movl (%r15), %ecx
movl (%rbp), %esi
cmpl %esi, %ecx
cmovgl %ecx, %esi
movl %esi, (%rax)
leaq 0x52f3(%rip), %rsi      # 0x847d
movl $0x3, %edi
xorl %eax, %eax
callq 0x273c
jmp 0x319b
movb $-0x1, %r12b
leaq 0x4a15e(%rip), %r14     # 0x4d300
movl $0xffec, %edx           # imm = 0xFFEC
movq %r14, %rdi
xorl %esi, %esi
callq 0x2120
movb %r12b, 0x4a148(%rip)    # 0x4d300
movb $0x1, 0x4a142(%rip)     # 0x4d301
movl $0x0, 0x4a139(%rip)     # 0x4d302
movw $0xc006, 0x4a134(%rip)  # imm = 0xC006
movl 0x10(%rsp), %eax
bswapl %eax
movl %eax, 0x4a12a(%rip)     # 0x4d308
movl 0x18(%rsp), %edi
movl $0xc, %edx
movq %r14, %rsi
movq %rbx, %rcx
movl $0x7, %r8d
callq 0x2a15
testl %eax, %eax
js 0x3212
xorl %ebp, %ebp
movl %ebp, %eax
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl %eax, %ebp
leaq 0x5271(%rip), %rsi      # 0x848c
xorl %edi, %edi
xorl %eax, %eax
callq 0x273c
jmp 0x31fe
callq 0x2040
movl (%rax), %edi
callq 0x20d0
leaq 0x5186(%rip), %rsi      # 0x83bf
jmp 0x324e
callq 0x2040
movl (%rax), %edi
callq 0x20d0
leaq 0x5128(%rip), %rsi      # 0x8376
xorl %r14d, %r14d
movl $0x1, %edi
movq %rax, %rdx
xorl %eax, %eax
callq 0x273c
jmp 0x2ed7
movq %rax, %rbx
movq %r14, %rdi
callq 0x4646
movq %rbx, %rdi
callq 0x2310