mirror of
https://github.com/moonlight-stream/moonlight-common-c.git
synced 2025-08-17 17:05:50 +00:00
Refactor input packet sending logic into a separate function
This commit is contained in:
parent
5846a9d6aa
commit
ceafe7897c
@ -3,6 +3,7 @@
|
|||||||
static SOCKET inputSock = INVALID_SOCKET;
|
static SOCKET inputSock = INVALID_SOCKET;
|
||||||
static unsigned char currentAesIv[16];
|
static unsigned char currentAesIv[16];
|
||||||
static bool initialized;
|
static bool initialized;
|
||||||
|
static bool encryptedControlStream;
|
||||||
static PPLT_CRYPTO_CONTEXT cryptoContext;
|
static PPLT_CRYPTO_CONTEXT cryptoContext;
|
||||||
|
|
||||||
static LINKED_BLOCKING_QUEUE packetQueue;
|
static LINKED_BLOCKING_QUEUE packetQueue;
|
||||||
@ -41,6 +42,7 @@ int initializeInputStream(void) {
|
|||||||
LbqInitializeLinkedBlockingQueue(&packetHolderFreeList, MAX_QUEUED_INPUT_PACKETS);
|
LbqInitializeLinkedBlockingQueue(&packetHolderFreeList, MAX_QUEUED_INPUT_PACKETS);
|
||||||
|
|
||||||
cryptoContext = PltCreateCryptoContext();
|
cryptoContext = PltCreateCryptoContext();
|
||||||
|
encryptedControlStream = APP_VERSION_AT_LEAST(7, 1, 431);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,17 +138,79 @@ static PPACKET_HOLDER allocatePacketHolder(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool sendInputPacket(PPACKET_HOLDER holder) {
|
||||||
|
SOCK_RET err;
|
||||||
|
|
||||||
|
// On GFE 3.22, the entire control stream is encrypted (and support for separate RI encrypted)
|
||||||
|
// has been removed. We send the plaintext packet through and the control stream code will do
|
||||||
|
// the encryption.
|
||||||
|
if (encryptedControlStream) {
|
||||||
|
err = (SOCK_RET)sendInputPacketOnControlStream((unsigned char*)&holder->packet, holder->packetLength);
|
||||||
|
if (err < 0) {
|
||||||
|
Limelog("Input: sendInputPacketOnControlStream() failed: %d\n", (int) err);
|
||||||
|
ListenerCallbacks.connectionTerminated(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
char encryptedBuffer[MAX_INPUT_PACKET_SIZE];
|
||||||
|
uint32_t encryptedSize;
|
||||||
|
uint32_t encryptedLengthPrefix;
|
||||||
|
|
||||||
|
// Encrypt the message into the output buffer while leaving room for the length
|
||||||
|
encryptedSize = sizeof(encryptedBuffer) - sizeof(encryptedLengthPrefix);
|
||||||
|
err = encryptData((unsigned char*)&holder->packet, holder->packetLength,
|
||||||
|
(unsigned char*)&encryptedBuffer[sizeof(encryptedLengthPrefix)], (int*)&encryptedSize);
|
||||||
|
if (err != 0) {
|
||||||
|
Limelog("Input: Encryption failed: %d\n", (int)err);
|
||||||
|
ListenerCallbacks.connectionTerminated(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepend the length to the message
|
||||||
|
encryptedLengthPrefix = BE32(encryptedSize);
|
||||||
|
memcpy(&encryptedBuffer[0], &encryptedLengthPrefix, sizeof(encryptedLengthPrefix));
|
||||||
|
|
||||||
|
if (AppVersionQuad[0] < 5) {
|
||||||
|
// Send the encrypted payload
|
||||||
|
err = send(inputSock, (const char*) encryptedBuffer,
|
||||||
|
(int) (encryptedSize + sizeof(encryptedLengthPrefix)), 0);
|
||||||
|
if (err <= 0) {
|
||||||
|
Limelog("Input: send() failed: %d\n", (int) LastSocketError());
|
||||||
|
ListenerCallbacks.connectionTerminated(LastSocketFail());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// For reasons that I can't understand, NVIDIA decides to use the last 16
|
||||||
|
// bytes of ciphertext in the most recent game controller packet as the IV for
|
||||||
|
// future encryption. I think it may be a buffer overrun on their end but we'll have
|
||||||
|
// to mimic it to work correctly.
|
||||||
|
if (AppVersionQuad[0] >= 7 && encryptedSize >= 16 + sizeof(currentAesIv)) {
|
||||||
|
memcpy(currentAesIv,
|
||||||
|
&encryptedBuffer[4 + encryptedSize - sizeof(currentAesIv)],
|
||||||
|
sizeof(currentAesIv));
|
||||||
|
}
|
||||||
|
|
||||||
|
err = (SOCK_RET)sendInputPacketOnControlStream((unsigned char*) encryptedBuffer,
|
||||||
|
(int) (encryptedSize + sizeof(encryptedLengthPrefix)));
|
||||||
|
if (err < 0) {
|
||||||
|
Limelog("Input: sendInputPacketOnControlStream() failed: %d\n", (int) err);
|
||||||
|
ListenerCallbacks.connectionTerminated(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Input thread proc
|
// Input thread proc
|
||||||
static void inputSendThreadProc(void* context) {
|
static void inputSendThreadProc(void* context) {
|
||||||
SOCK_RET err;
|
SOCK_RET err;
|
||||||
PPACKET_HOLDER holder;
|
PPACKET_HOLDER holder;
|
||||||
char encryptedBuffer[MAX_INPUT_PACKET_SIZE];
|
|
||||||
uint32_t encryptedSize;
|
|
||||||
bool encryptedControlStream = APP_VERSION_AT_LEAST(7, 1, 431);
|
|
||||||
|
|
||||||
while (!PltIsThreadInterrupted(&inputSendThread)) {
|
while (!PltIsThreadInterrupted(&inputSendThread)) {
|
||||||
int encryptedLengthPrefix;
|
|
||||||
|
|
||||||
err = LbqWaitForQueueElement(&packetQueue, (void**)&holder);
|
err = LbqWaitForQueueElement(&packetQueue, (void**)&holder);
|
||||||
if (err != LBQ_SUCCESS) {
|
if (err != LBQ_SUCCESS) {
|
||||||
return;
|
return;
|
||||||
@ -275,64 +339,13 @@ static void inputSendThreadProc(void* context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// On GFE 3.22, the entire control stream is encrypted (and support for separate RI encrypted)
|
// Encrypt and send the input packet
|
||||||
// has been removed. We send the plaintext packet through and the control stream code will do
|
if (!sendInputPacket(holder)) {
|
||||||
// the encryption.
|
|
||||||
if (encryptedControlStream) {
|
|
||||||
err = (SOCK_RET)sendInputPacketOnControlStream((unsigned char*)&holder->packet, holder->packetLength);
|
|
||||||
freePacketHolder(holder);
|
freePacketHolder(holder);
|
||||||
if (err < 0) {
|
return;
|
||||||
Limelog("Input: sendInputPacketOnControlStream() failed: %d\n", (int) err);
|
|
||||||
ListenerCallbacks.connectionTerminated(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
// Encrypt the message into the output buffer while leaving room for the length
|
|
||||||
encryptedSize = sizeof(encryptedBuffer) - 4;
|
|
||||||
err = encryptData((unsigned char*)&holder->packet, holder->packetLength,
|
|
||||||
(unsigned char*)&encryptedBuffer[4], (int*)&encryptedSize);
|
|
||||||
freePacketHolder(holder);
|
|
||||||
if (err != 0) {
|
|
||||||
Limelog("Input: Encryption failed: %d\n", (int)err);
|
|
||||||
ListenerCallbacks.connectionTerminated(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepend the length to the message
|
freePacketHolder(holder);
|
||||||
encryptedLengthPrefix = BE32(encryptedSize);
|
|
||||||
memcpy(&encryptedBuffer[0], &encryptedLengthPrefix, 4);
|
|
||||||
|
|
||||||
if (AppVersionQuad[0] < 5) {
|
|
||||||
// Send the encrypted payload
|
|
||||||
err = send(inputSock, (const char*) encryptedBuffer,
|
|
||||||
(int) (encryptedSize + sizeof(encryptedLengthPrefix)), 0);
|
|
||||||
if (err <= 0) {
|
|
||||||
Limelog("Input: send() failed: %d\n", (int) LastSocketError());
|
|
||||||
ListenerCallbacks.connectionTerminated(LastSocketFail());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// For reasons that I can't understand, NVIDIA decides to use the last 16
|
|
||||||
// bytes of ciphertext in the most recent game controller packet as the IV for
|
|
||||||
// future encryption. I think it may be a buffer overrun on their end but we'll have
|
|
||||||
// to mimic it to work correctly.
|
|
||||||
if (AppVersionQuad[0] >= 7 && encryptedSize >= 16 + sizeof(currentAesIv)) {
|
|
||||||
memcpy(currentAesIv,
|
|
||||||
&encryptedBuffer[4 + encryptedSize - sizeof(currentAesIv)],
|
|
||||||
sizeof(currentAesIv));
|
|
||||||
}
|
|
||||||
|
|
||||||
err = (SOCK_RET)sendInputPacketOnControlStream((unsigned char*) encryptedBuffer,
|
|
||||||
(int) (encryptedSize + sizeof(encryptedLengthPrefix)));
|
|
||||||
if (err < 0) {
|
|
||||||
Limelog("Input: sendInputPacketOnControlStream() failed: %d\n", (int) err);
|
|
||||||
ListenerCallbacks.connectionTerminated(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user