// File: /workspace/github_cpp_makefile_star2_O3/rellla[P]E3DC-Rscp/RscpMain.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;
    int isAuthRequest = 0;

    // 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 %i\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,
				     &isAuthRequest);
	    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++;
		if (!isAuthRequest) {
		    printf
			("Successfully received %i RscpFrames\n",
			 iReceivedRscpFrames);
		    bStopExecution = true;
		}
	    } 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:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq %rdi, %rbx
movb 0xfa4e(%rip), %al       # 0x136d0
testb %al, %al
je 0x3fa5
movl $0x0, 0x8(%rsp)
cmpb $0x0, (%rbx)
je 0x3ca6
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl 0xfa04(%rip), %eax      # 0x136b0
leaq 0x28(%rsp), %r15
leaq 0x8(%rsp), %r12
movabsq $-0x1111111111111111, %r14 # imm = 0xEEEEEEEEEEEEEEEF
movl $0x0, 0x4(%rsp)
movq 0xf9f1(%rip), %rdx      # 0x136c0
movq 0xf9e2(%rip), %rcx      # 0x136b8
subq %rcx, %rdx
movslq %eax, %rsi
movq %rdx, %rdi
subq %rsi, %rdi
cmpq $0xfff, %rdi            # imm = 0xFFF
ja 0x3d28
cmpq $0x10016, %rdx          # imm = 0x10016
jae 0x3f7c
addq $0x1000, %rdx           # imm = 0x1000
leaq 0xf9b2(%rip), %rdi      # 0x136b8
movq %rdx, %rsi
callq 0x4896
movq 0xf9a3(%rip), %rcx      # 0x136b8
movl 0xf995(%rip), %eax      # 0x136b0
movq 0xf99e(%rip), %rdx      # 0x136c0
movslq %eax, %rsi
subq %rcx, %rdx
addq %rcx, %rsi
movl 0xf42f(%rip), %edi      # 0x13160
subl %eax, %edx
callq 0xf99f
testl %eax, %eax
js 0x3f51
je 0x3f6e
addl %eax, 0xf964(%rip)      # 0x136b0
cmpb $0x0, (%rbx)
jne 0x3c97
movslq 0xf954(%rip), %rbp      # 0x136b0
movq %rbp, %r13
andq $-0x20, %r13
testl %r13d, %r13d
je 0x3f31
xorps %xmm0, %xmm0
movaps %xmm0, 0x10(%rsp)
movq $0x0, 0x20(%rsp)
leaq 0x10(%rsp), %rdi
movq %r13, %rsi
callq 0x4896
leaq 0xf6cb(%rip), %rdi      # 0x1345c
leaq 0xf8f8(%rip), %rsi      # 0x13690
movl $0x20, %edx
callq 0x5dd0
movq 0xf90f(%rip), %rsi      # 0x136b8
movq 0x10(%rsp), %rdx
sarl $0x5, %ebp
movslq %ebp, %rcx
leaq 0xf6a1(%rip), %rdi      # 0x1345c
movl $0x1, %r8d
callq 0xf068
movq 0x10(%rsp), %rbp
movq %r15, %rdi
callq 0x49e0
leaq 0x48(%rsp), %rax
xorps %xmm0, %xmm0
movups %xmm0, (%rax)
movq $0x0, 0x10(%rax)
movl %r13d, 0xc(%rsp)
movq %r15, %rdi
movq %rbp, %rsi
leaq 0xc(%rsp), %rdx
leaq 0x30(%rsp), %rcx
callq 0x50dc
movl %eax, %r13d
testl %eax, %eax
js 0x3e54
movq 0x48(%rsp), %rax
cmpq %rax, 0x50(%rsp)
je 0x3e45
xorl %ecx, %ecx
leaq (%rcx,%rcx,4), %rcx
leaq (%rcx,%rcx,2), %rsi
addq %rax, %rsi
movq %r15, %rdi
movq %r12, %rdx
callq 0x3365
movl %ebp, %ecx
movq 0x48(%rsp), %rax
movq 0x50(%rsp), %rdx
subq %rax, %rdx
imulq %r14, %rdx
incl %ebp
cmpq %rcx, %rdx
ja 0x3e15
movq %r15, %rdi
leaq 0x48(%rsp), %rsi
callq 0x52d8
jmp 0x3e61
cmpl $-0x5, %r13d
movl $0x0, %eax
cmovel %eax, %r13d
movq 0x48(%rsp), %rdi
testq %rdi, %rdi
je 0x3e78
movq 0x58(%rsp), %rsi
subq %rdi, %rsi
callq 0x2160
movq %r15, %rdi
callq 0x49ec
testl %r13d, %r13d
setns %bpl
js 0x3ee7
je 0x3ef3
addl $0x1f, %r13d
andl $0x7fffffe0, %r13d      # imm = 0x7FFFFFE0
movq 0xf81b(%rip), %rdi      # 0x136b8
leaq (%rdi,%r13), %rsi
movups -0x20(%rdi,%r13), %xmm0
movups -0x10(%rdi,%r13), %xmm1
movaps %xmm0, 0xf7dc(%rip)     # 0x13690
movaps %xmm1, 0xf7e5(%rip)     # 0x136a0
movq 0xf7fe(%rip), %rdx      # 0x136c0
subq %rsi, %rdx
callq 0x20f0
subl %r13d, 0xf7df(%rip)     # 0x136b0
movl 0x4(%rsp), %esi
incl %esi
cmpl $0x0, 0x8(%rsp)
movl %esi, 0x4(%rsp)
je 0x3ef7
movb $0x1, %bpl
jmp 0x3f08
leaq 0xc6ec(%rip), %rdi      # 0x105da
movl %r13d, %esi
jmp 0x3efe
xorl %ebp, %ebp
jmp 0x3f08
leaq 0xc6fa(%rip), %rdi      # 0x105f8
xorl %eax, %eax
callq 0x2040
movb $0x1, (%rbx)
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0x3f1f
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0x2160
testb %bpl, %bpl
jne 0x3d4c
testb $0x1, (%rbx)
jne 0x3c97
movl 0xf779(%rip), %eax      # 0x136b0
testl %eax, %eax
setg %cl
cmpl $0x0, 0x4(%rsp)
sete %dl
orb %cl, %dl
jne 0x3cc8
jmp 0x3c97
callq 0x2030
movl (%rax), %esi
cmpl $0xb, %esi
jne 0x3f8f
leaq 0xc759(%rip), %rdi      # 0x106bd
callq 0x21c0
jmp 0x3c97
leaq 0xc72e(%rip), %rdi      # 0x106a3
callq 0x21c0
jmp 0x3f9d
leaq 0xc616(%rip), %rdi      # 0x10599
movq %rdx, %rsi
xorl %eax, %eax
callq 0x2040
jmp 0x3f9d
leaq 0xc624(%rip), %rdi      # 0x105ba
xorl %eax, %eax
callq 0x2040
movb $0x1, (%rbx)
jmp 0x3c97
callq 0x2321
jmp 0x3c8a
jmp 0x3fba
jmp 0x3fba
jmp 0x3fb5
movq %rax, %rbx
jmp 0x3fde
movq %rax, %rbx
movq 0x48(%rsp), %rdi
testq %rdi, %rdi
je 0x3fd4
movq 0x58(%rsp), %rsi
subq %rdi, %rsi
callq 0x2160
leaq 0x28(%rsp), %rdi
callq 0x49ec
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0x3ff5
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0x2160
movq %rbx, %rdi
callq 0x2240