// File: bummelbaerchen[P]e3dc/RscpExampleMain.cpp
// Function: receiveLoop(bool&)
static void receiveLoop(bool & bStopExecution)
{
    //--------------------------------------------------------------------------------------------------------------
    // RSCP Receive Frame Block Data
    //--------------------------------------------------------------------------------------------------------------
    // setup a static dynamic buffer which is dynamically expanded (re-allocated) on demand
    // the data inside this buffer is not released when this function is left
    static int iReceivedBytes = 0;
    static std::vector<uint8_t> vecDynamicBuffer;

    // check how many RSCP frames are received, must be at least 1
    // multiple frames can only occur in this example if one or more frames are received with a big time delay
    // this should usually not occur but handling this is shown in this example
    int iReceivedRscpFrames = 0;
    while(!bStopExecution && ((iReceivedBytes > 0) || iReceivedRscpFrames == 0))
    {
        // check and expand buffer
        if((vecDynamicBuffer.size() - iReceivedBytes) < 4096) {
            // check maximum size
            if(vecDynamicBuffer.size() > RSCP_MAX_FRAME_LENGTH) {
                // something went wrong and the size is more than possible by the RSCP protocol
                printf("Maximum buffer size exceeded %lu\n", vecDynamicBuffer.size());
                bStopExecution = true;
                break;
            }
            // increase buffer size by 4096 bytes each time the remaining size is smaller than 4096
            vecDynamicBuffer.resize(vecDynamicBuffer.size() + 4096);
        }
        // receive data
        int iResult = SocketRecvData(iSocket, &vecDynamicBuffer[0] + iReceivedBytes, vecDynamicBuffer.size() - iReceivedBytes);
        if(iResult < 0)
        {
            // check errno for the error code to detect if this is a timeout or a socket error
            if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
                // receive timed out -> continue with re-sending the initial block
                printf("Response receive timeout (retry)\n");
                break;
            }
            // socket error -> check errno for failure code if needed
            printf("Socket receive error. errno %i\n", errno);
            bStopExecution = true;
            break;
        }
        else if(iResult == 0)
        {
            // connection was closed regularly by peer
            // if this happens on startup each time the possible reason is
            // wrong AES password or wrong network subnet (adapt hosts.allow file required)
            printf("Connection closed by peer\n");
            bStopExecution = true;
            break;
        }
        // increment amount of received bytes
        iReceivedBytes += iResult;

        // process all received frames
        while (!bStopExecution)
        {
            // round down to a multiple of AES_BLOCK_SIZE
            int iLength = ROUNDDOWN(iReceivedBytes, AES_BLOCK_SIZE);
            // if not even 32 bytes were received then the frame is still incomplete
            if(iLength == 0) {
                break;
            }
            // resize temporary decryption buffer
            std::vector<uint8_t> decryptionBuffer;
            decryptionBuffer.resize(iLength);
            // initialize encryption sequence IV value with value of previous block
            aesDecrypter.SetIV(ucDecryptionIV, AES_BLOCK_SIZE);
            // decrypt data from vecDynamicBuffer to temporary decryptionBuffer
            aesDecrypter.Decrypt(&vecDynamicBuffer[0], &decryptionBuffer[0], iLength / AES_BLOCK_SIZE);

            // data was received, check if we received all data
            int iProcessedBytes = processReceiveBuffer(&decryptionBuffer[0], iLength);
            if(iProcessedBytes < 0) {
                // an error occured;
                printf("Error parsing RSCP frame: %i\n", iProcessedBytes);
                // stop execution as the data received is not RSCP data
                bStopExecution = true;
                break;

            }
            else if(iProcessedBytes > 0) {
                // round up the processed bytes as iProcessedBytes does not include the zero padding bytes
                iProcessedBytes = ROUNDUP(iProcessedBytes, AES_BLOCK_SIZE);
                // store the IV value from encrypted buffer for next block decryption
                memcpy(ucDecryptionIV, &vecDynamicBuffer[0] + iProcessedBytes - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
                // move the encrypted data behind the current frame data (if any received) to the front
                memcpy(&vecDynamicBuffer[0], &vecDynamicBuffer[0] + iProcessedBytes, vecDynamicBuffer.size() - iProcessedBytes);
                // decrement the total received bytes by the amount of processed bytes
                iReceivedBytes -= iProcessedBytes;
                // increment a counter that a valid frame was received and
                // continue parsing process in case a 2nd valid frame is in the buffer as well
                iReceivedRscpFrames++;
            }
            else {
                // iProcessedBytes is 0
                // not enough data of the next frame received, go back to receive mode if iReceivedRscpFrames == 0
                // or transmit mode if iReceivedRscpFrames > 0
                break;
            }
        }
    }
}

// Assembly:
subq $0x88, %rsp
movq %rdi, 0x80(%rsp)
cmpb $0x0, 0x1e33a(%rip)     # 0x26ab0
jne 0x87bb
leaq 0x1e331(%rip), %rdi     # 0x26ab0
callq 0x2320
cmpl $0x0, %eax
je 0x87bb
leaq 0x1e308(%rip), %rdi     # 0x26a98
callq 0xa090
leaq 0x19e4(%rip), %rdi      # 0xa180
leaq 0x1e2f5(%rip), %rsi     # 0x26a98
leaq 0x1da0e(%rip), %rdx     # 0x261b8
callq 0x21a0
leaq 0x1e2fa(%rip), %rdi     # 0x26ab0
callq 0x2130
movl $0x0, 0x7c(%rsp)
movq 0x80(%rsp), %rcx
xorl %eax, %eax
testb $0x1, (%rcx)
movb %al, 0x43(%rsp)
jne 0x87f9
movb $0x1, %al
cmpl $0x0, 0x1e2b1(%rip)     # 0x26a90
movb %al, 0x42(%rsp)
jg 0x87f1
cmpl $0x0, 0x7c(%rsp)
sete %al
movb %al, 0x42(%rsp)
movb 0x42(%rsp), %al
movb %al, 0x43(%rsp)
movb 0x43(%rsp), %al
testb $0x1, %al
jne 0x8806
jmp 0x8ba1
leaq 0x1e28b(%rip), %rdi     # 0x26a98
callq 0xa160
movslq 0x1e277(%rip), %rcx     # 0x26a90
subq %rcx, %rax
cmpq $0x1000, %rax           # imm = 0x1000
jae 0x8887
leaq 0x1e26d(%rip), %rdi     # 0x26a98
callq 0xa160
cmpq $0x10015, %rax          # imm = 0x10015
jbe 0x8865
leaq 0x1e259(%rip), %rdi     # 0x26a98
callq 0xa160
movq %rax, %rsi
leaq 0x19156(%rip), %rdi     # 0x219a4
movb $0x0, %al
callq 0x2040
movq 0x80(%rsp), %rax
movb $0x1, (%rax)
jmp 0x8ba1
leaq 0x1e22c(%rip), %rdi     # 0x26a98
callq 0xa160
movq %rax, %rsi
addq $0x1000, %rsi           # imm = 0x1000
leaq 0x1e216(%rip), %rdi     # 0x26a98
callq 0xa0a0
movl 0x1d93b(%rip), %eax     # 0x261c8
movl %eax, 0x34(%rsp)
leaq 0x1e200(%rip), %rdi     # 0x26a98
xorl %eax, %eax
movl %eax, %esi
callq 0xa140
movslq 0x1e1e8(%rip), %rcx     # 0x26a90
addq %rcx, %rax
movq %rax, 0x38(%rsp)
leaq 0x1e1e1(%rip), %rdi     # 0x26a98
callq 0xa160
movl 0x34(%rsp), %edi
movq 0x38(%rsp), %rsi
movslq 0x1e1c4(%rip), %rcx     # 0x26a90
subq %rcx, %rax
movl %eax, %edx
callq 0x20eb0
movl %eax, 0x78(%rsp)
cmpl $0x0, 0x78(%rsp)
jge 0x892d
callq 0x2030
cmpl $0xb, (%rax)
je 0x88f5
callq 0x2030
cmpl $0xb, (%rax)
jne 0x8908
leaq 0x190ca(%rip), %rdi     # 0x219c6
movb $0x0, %al
callq 0x2040
jmp 0x8ba1
callq 0x2030
movl (%rax), %esi
leaq 0x190d2(%rip), %rdi     # 0x219e8
movb $0x0, %al
callq 0x2040
movq 0x80(%rsp), %rax
movb $0x1, (%rax)
jmp 0x8ba1
cmpl $0x0, 0x78(%rsp)
jne 0x8952
leaq 0x190cd(%rip), %rdi     # 0x21a08
movb $0x0, %al
callq 0x2040
movq 0x80(%rsp), %rax
movb $0x1, (%rax)
jmp 0x8ba1
jmp 0x8954
movl 0x78(%rsp), %eax
addl 0x1e132(%rip), %eax     # 0x26a90
movl %eax, 0x1e12c(%rip)     # 0x26a90
movq 0x80(%rsp), %rax
movb (%rax), %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x8979
jmp 0x8b9c
movl 0x1e111(%rip), %eax     # 0x26a90
andl $-0x20, %eax
movl %eax, 0x74(%rsp)
cmpl $0x0, 0x74(%rsp)
jne 0x8992
jmp 0x8b9c
leaq 0x58(%rsp), %rdi
movq %rdi, 0x28(%rsp)
callq 0xa090
movq 0x28(%rsp), %rdi
movslq 0x74(%rsp), %rsi
callq 0xa0a0
jmp 0x89b2
leaq 0x1da43(%rip), %rdi     # 0x263fc
leaq 0x1e090(%rip), %rsi     # 0x26a50
movl $0x20, %edx
callq 0xe1d0
jmp 0x89cc
leaq 0x1e0c5(%rip), %rdi     # 0x26a98
xorl %eax, %eax
movl %eax, %esi
movq %rsi, 0x18(%rsp)
callq 0xa140
movq 0x18(%rsp), %rsi
movq %rax, 0x20(%rsp)
leaq 0x58(%rsp), %rdi
callq 0xa140
movq 0x20(%rsp), %rsi
movq %rax, %rdx
movl 0x74(%rsp), %ecx
movl %ecx, %eax
addl $0x1f, %eax
testl %ecx, %ecx
cmovsl %eax, %ecx
sarl $0x5, %ecx
leaq 0x1d9e7(%rip), %rdi     # 0x263fc
movl $0x1, %r8d
callq 0x1fb80
jmp 0x8a22
xorl %eax, %eax
movl %eax, %esi
leaq 0x58(%rsp), %rdi
callq 0xa140
movq %rax, %rdi
movl 0x74(%rsp), %esi
callq 0x8bc0
movl %eax, 0x14(%rsp)
jmp 0x8a42
movl 0x14(%rsp), %eax
movl %eax, 0x48(%rsp)
cmpl $0x0, 0x48(%rsp)
jge 0x8a9a
movl 0x48(%rsp), %esi
leaq 0x18fc7(%rip), %rdi     # 0x21a23
xorl %eax, %eax
callq 0x2040
jmp 0x8a65
movq 0x80(%rsp), %rax
movb $0x1, (%rax)
movl $0x5, 0x44(%rsp)
jmp 0x8b81
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x50(%rsp)
movl %eax, 0x4c(%rsp)
leaq 0x58(%rsp), %rdi
callq 0xa180
jmp 0x8ba9
cmpl $0x0, 0x48(%rsp)
jle 0x8b6d
movl 0x48(%rsp), %eax
addl $0x1f, %eax
andl $-0x20, %eax
movl %eax, 0x48(%rsp)
leaq 0x1dfde(%rip), %rdi     # 0x26a98
xorl %eax, %eax
movl %eax, %esi
callq 0xa140
movslq 0x48(%rsp), %rcx
movq -0x20(%rax,%rcx), %rdx
movq %rdx, 0x1df7c(%rip)     # 0x26a50
movq -0x18(%rax,%rcx), %rdx
movq %rdx, 0x1df78(%rip)     # 0x26a58
movq -0x10(%rax,%rcx), %rdx
movq %rdx, 0x1df74(%rip)     # 0x26a60
movq -0x8(%rax,%rcx), %rax
movq %rax, 0x1df70(%rip)     # 0x26a68
leaq 0x1df99(%rip), %rdi     # 0x26a98
xorl %eax, %eax
movl %eax, %esi
callq 0xa140
movq %rax, (%rsp)
leaq 0x1df85(%rip), %rdi     # 0x26a98
xorl %eax, %eax
movl %eax, %esi
callq 0xa140
movslq 0x48(%rsp), %rcx
addq %rcx, %rax
movq %rax, 0x8(%rsp)
leaq 0x1df68(%rip), %rdi     # 0x26a98
callq 0xa160
movq (%rsp), %rdi
movq 0x8(%rsp), %rsi
movq %rax, %rdx
movslq 0x48(%rsp), %rax
subq %rax, %rdx
callq 0x2160
movl 0x48(%rsp), %ecx
movl 0x1df38(%rip), %eax     # 0x26a90
subl %ecx, %eax
movl %eax, 0x1df30(%rip)     # 0x26a90
movl 0x7c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x7c(%rsp)
jmp 0x8b77
movl $0x5, 0x44(%rsp)
jmp 0x8b81
jmp 0x8b79
movl $0x0, 0x44(%rsp)
leaq 0x58(%rsp), %rdi
callq 0xa180
movl 0x44(%rsp), %eax
testl %eax, %eax
je 0x8b97
jmp 0x8b95
jmp 0x8b9c
jmp 0x8964
jmp 0x87c3
addq $0x88, %rsp
retq
movq 0x50(%rsp), %rdi
callq 0x2300
nopw %cs:(%rax,%rax)