// File: 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:
subq $0x88, %rsp
movq %rdi, 0x80(%rsp)
cmpb $0x0, 0x1fbda(%rip)     # 0x24700
jne 0x4b6b
leaq 0x1fbd1(%rip), %rdi     # 0x24700
callq 0x22c0
cmpl $0x0, %eax
je 0x4b6b
leaq 0x1fba8(%rip), %rdi     # 0x246e8
callq 0x5fe0
leaq 0x1584(%rip), %rdi      # 0x60d0
leaq 0x1fb95(%rip), %rsi     # 0x246e8
leaq 0x1f62e(%rip), %rdx     # 0x24188
callq 0x2150
leaq 0x1fb9a(%rip), %rdi     # 0x24700
callq 0x2100
movl $0x0, 0x7c(%rsp)
movl $0x0, 0x78(%rsp)
movq 0x80(%rsp), %rcx
xorl %eax, %eax
testb $0x1, (%rcx)
movb %al, 0x43(%rsp)
jne 0x4bb1
movb $0x1, %al
cmpl $0x0, 0x1fb49(%rip)     # 0x246e0
movb %al, 0x42(%rsp)
jg 0x4ba9
cmpl $0x0, 0x78(%rsp)
sete %al
movb %al, 0x42(%rsp)
movb 0x42(%rsp), %al
movb %al, 0x43(%rsp)
movb 0x43(%rsp), %al
testb $0x1, %al
jne 0x4bbe
jmp 0x4f87
leaq 0x1fb23(%rip), %rdi     # 0x246e8
callq 0x60b0
movslq 0x1fb0f(%rip), %rcx     # 0x246e0
subq %rcx, %rax
cmpq $0x1000, %rax           # imm = 0x1000
jae 0x4c3f
leaq 0x1fb05(%rip), %rdi     # 0x246e8
callq 0x60b0
cmpq $0x10015, %rax          # imm = 0x10015
jbe 0x4c1d
leaq 0x1faf1(%rip), %rdi     # 0x246e8
callq 0x60b0
movq %rax, %rsi
leaq 0x1bc3a(%rip), %rdi     # 0x20840
movb $0x0, %al
callq 0x2040
movq 0x80(%rsp), %rax
movb $0x1, (%rax)
jmp 0x4f87
leaq 0x1fac4(%rip), %rdi     # 0x246e8
callq 0x60b0
movq %rax, %rsi
addq $0x1000, %rsi           # imm = 0x1000
leaq 0x1faae(%rip), %rdi     # 0x246e8
callq 0x5ff0
movl 0x1f54b(%rip), %eax     # 0x24190
movl %eax, 0x34(%rsp)
leaq 0x1fa98(%rip), %rdi     # 0x246e8
xorl %eax, %eax
movl %eax, %esi
callq 0x6090
movslq 0x1fa80(%rip), %rcx     # 0x246e0
addq %rcx, %rax
movq %rax, 0x38(%rsp)
leaq 0x1fa79(%rip), %rdi     # 0x246e8
callq 0x60b0
movl 0x34(%rsp), %edi
movq 0x38(%rsp), %rsi
movslq 0x1fa5c(%rip), %rcx     # 0x246e0
subq %rcx, %rax
movl %eax, %edx
callq 0x1f750
movl %eax, 0x74(%rsp)
cmpl $0x0, 0x74(%rsp)
jge 0x4ce5
callq 0x2030
cmpl $0xb, (%rax)
je 0x4cad
callq 0x2030
cmpl $0xb, (%rax)
jne 0x4cc0
leaq 0x1bbad(%rip), %rdi     # 0x20861
movb $0x0, %al
callq 0x2040
jmp 0x4f87
callq 0x2030
movl (%rax), %esi
leaq 0x1bbb5(%rip), %rdi     # 0x20883
movb $0x0, %al
callq 0x2040
movq 0x80(%rsp), %rax
movb $0x1, (%rax)
jmp 0x4f87
cmpl $0x0, 0x74(%rsp)
jne 0x4d0a
leaq 0x1bbb0(%rip), %rdi     # 0x208a3
movb $0x0, %al
callq 0x2040
movq 0x80(%rsp), %rax
movb $0x1, (%rax)
jmp 0x4f87
jmp 0x4d0c
movl 0x74(%rsp), %eax
addl 0x1f9ca(%rip), %eax     # 0x246e0
movl %eax, 0x1f9c4(%rip)     # 0x246e0
movq 0x80(%rsp), %rax
movb (%rax), %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x4d31
jmp 0x4f82
movl 0x1f9a9(%rip), %eax     # 0x246e0
andl $-0x20, %eax
movl %eax, 0x70(%rsp)
cmpl $0x0, 0x70(%rsp)
jne 0x4d4a
jmp 0x4f82
leaq 0x58(%rsp), %rdi
movq %rdi, 0x28(%rsp)
callq 0x5fe0
movq 0x28(%rsp), %rdi
movslq 0x70(%rsp), %rsi
callq 0x5ff0
jmp 0x4d6a
leaq 0x1f71b(%rip), %rdi     # 0x2448c
leaq 0x1f948(%rip), %rsi     # 0x246c0
movl $0x20, %edx
callq 0xac30
jmp 0x4d84
leaq 0x1f95d(%rip), %rdi     # 0x246e8
xorl %eax, %eax
movl %eax, %esi
movq %rsi, 0x18(%rsp)
callq 0x6090
movq 0x18(%rsp), %rsi
movq %rax, 0x20(%rsp)
leaq 0x58(%rsp), %rdi
callq 0x6090
movq 0x20(%rsp), %rsi
movq %rax, %rdx
movl 0x70(%rsp), %eax
movl %eax, %ecx
addl $0x1f, %ecx
testl %eax, %eax
cmovsl %ecx, %eax
sarl $0x5, %eax
movslq %eax, %rcx
leaq 0x1f6bc(%rip), %rdi     # 0x2448c
movl $0x1, %r8d
callq 0x1e2f0
jmp 0x4ddd
xorl %eax, %eax
movl %eax, %esi
leaq 0x58(%rsp), %rdi
callq 0x6090
movq %rax, %rdi
movl 0x70(%rsp), %esi
leaq 0x7c(%rsp), %rdx
callq 0x5990
movl %eax, 0x14(%rsp)
jmp 0x4e02
movl 0x14(%rsp), %eax
movl %eax, 0x48(%rsp)
cmpl $0x0, 0x48(%rsp)
jge 0x4e5a
movl 0x48(%rsp), %esi
leaq 0x1baa2(%rip), %rdi     # 0x208be
xorl %eax, %eax
callq 0x2040
jmp 0x4e25
movq 0x80(%rsp), %rax
movb $0x1, (%rax)
movl $0x5, 0x44(%rsp)
jmp 0x4f67
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x50(%rsp)
movl %eax, 0x4c(%rsp)
leaq 0x58(%rsp), %rdi
callq 0x60d0
jmp 0x4f8f
cmpl $0x0, 0x48(%rsp)
jle 0x4f53
movl 0x48(%rsp), %eax
addl $0x1f, %eax
andl $-0x20, %eax
movl %eax, 0x48(%rsp)
leaq 0x1f86e(%rip), %rdi     # 0x246e8
xorl %eax, %eax
movl %eax, %esi
callq 0x6090
movslq 0x48(%rsp), %rcx
movq -0x20(%rax,%rcx), %rdx
movq %rdx, 0x1f82c(%rip)     # 0x246c0
movq -0x18(%rax,%rcx), %rdx
movq %rdx, 0x1f828(%rip)     # 0x246c8
movq -0x10(%rax,%rcx), %rdx
movq %rdx, 0x1f824(%rip)     # 0x246d0
movq -0x8(%rax,%rcx), %rax
movq %rax, 0x1f820(%rip)     # 0x246d8
leaq 0x1f829(%rip), %rdi     # 0x246e8
xorl %eax, %eax
movl %eax, %esi
callq 0x6090
movq %rax, (%rsp)
leaq 0x1f815(%rip), %rdi     # 0x246e8
xorl %eax, %eax
movl %eax, %esi
callq 0x6090
movslq 0x48(%rsp), %rcx
addq %rcx, %rax
movq %rax, 0x8(%rsp)
leaq 0x1f7f8(%rip), %rdi     # 0x246e8
callq 0x60b0
movq (%rsp), %rdi
movq 0x8(%rsp), %rsi
movq %rax, %rdx
movslq 0x48(%rsp), %rax
subq %rax, %rdx
callq 0x2130
movl 0x48(%rsp), %ecx
movl 0x1f7c8(%rip), %eax     # 0x246e0
subl %ecx, %eax
movl %eax, 0x1f7c0(%rip)     # 0x246e0
movl 0x78(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x78(%rsp)
cmpl $0x0, 0x7c(%rsp)
jne 0x4f51
movl 0x78(%rsp), %esi
leaq 0x1b99f(%rip), %rdi     # 0x208dc
xorl %eax, %eax
callq 0x2040
jmp 0x4f46
movq 0x80(%rsp), %rax
movb $0x1, (%rax)
jmp 0x4f5d
movl $0x5, 0x44(%rsp)
jmp 0x4f67
jmp 0x4f5f
movl $0x0, 0x44(%rsp)
leaq 0x58(%rsp), %rdi
callq 0x60d0
movl 0x44(%rsp), %eax
testl %eax, %eax
je 0x4f7d
jmp 0x4f7b
jmp 0x4f82
jmp 0x4d1c
jmp 0x4b7b
addq $0x88, %rsp
retq
movq 0x50(%rsp), %rdi
callq 0x22a0
nopl (%rax)