diff --git a/enet b/enet index 78cc9b4..dea6fb5 160000 --- a/enet +++ b/enet @@ -1 +1 @@ -Subproject commit 78cc9b4b03bdd4f95c277391cac6e0951407072b +Subproject commit dea6fb5414b180908b58c0293c831105b5d124dd diff --git a/src/Connection.c b/src/Connection.c index bac9a6e..d2e8292 100644 --- a/src/Connection.c +++ b/src/Connection.c @@ -377,19 +377,6 @@ int LiStartConnection(PSERVER_INFORMATION serverInfo, PSTREAM_CONFIGURATION stre ListenerCallbacks.stageFailed(STAGE_NAME_RESOLUTION, err); goto Cleanup; } - - // Resolve LocalAddr by RemoteAddr. - { - SOCKADDR_LEN localAddrLen; - err = getLocalAddressByUdpConnect(&RemoteAddr, AddrLen, RtspPortNumber, &LocalAddr, &localAddrLen); - if (err != 0) { - Limelog("failed to resolve local addr: %d\n", err); - ListenerCallbacks.stageFailed(STAGE_NAME_RESOLUTION, err); - goto Cleanup; - } - LC_ASSERT(localAddrLen == AddrLen); - } - stage++; LC_ASSERT(stage == STAGE_NAME_RESOLUTION); ListenerCallbacks.stageComplete(STAGE_NAME_RESOLUTION); diff --git a/src/ControlStream.c b/src/ControlStream.c index fd8e7a7..4280963 100644 --- a/src/ControlStream.c +++ b/src/ControlStream.c @@ -31,12 +31,11 @@ typedef struct _NVCTL_ENCRYPTED_PACKET_HEADER { // encrypted NVCTL_ENET_PACKET_HEADER_V2 and payload data follow } NVCTL_ENCRYPTED_PACKET_HEADER, *PNVCTL_ENCRYPTED_PACKET_HEADER; -typedef struct _QUEUED_REFERENCE_FRAME_CONTROL { +typedef struct _QUEUED_FRAME_INVALIDATION_TUPLE { uint32_t startFrame; uint32_t endFrame; - bool invalidate; // true: RFI(startFrame, endFrame); false: LTR_ACK(startFrame) LINKED_BLOCKING_QUEUE_ENTRY entry; -} QUEUED_REFERENCE_FRAME_CONTROL, *PQUEUED_REFERENCE_FRAME_CONTROL; +} QUEUED_FRAME_INVALIDATION_TUPLE, *PQUEUED_FRAME_INVALIDATION_TUPLE; typedef struct _QUEUED_FRAME_FEC_STATUS { SS_FRAME_FEC_STATUS fecStatus; @@ -83,12 +82,6 @@ typedef struct _QUEUED_ASYNC_CALLBACK { uint8_t left[DS_EFFECT_PAYLOAD_SIZE]; uint8_t right[DS_EFFECT_PAYLOAD_SIZE]; } dsAdaptiveTrigger; - struct { - uint8_t allowKeyboard; - uint8_t allowMouse; - uint8_t allowGamepad; - uint8_t reason; - } setInputPolicy; } data; LINKED_BLOCKING_QUEUE_ENTRY entry; } QUEUED_ASYNC_CALLBACK, *PQUEUED_ASYNC_CALLBACK; @@ -120,7 +113,7 @@ static int lastConnectionStatusUpdate; static uint32_t currentEnetSequenceNumber; static uint64_t firstFrameTimeMs; -static LINKED_BLOCKING_QUEUE referenceFrameControlQueue; +static LINKED_BLOCKING_QUEUE invalidReferenceFrameTuples; static LINKED_BLOCKING_QUEUE frameFecStatusQueue; static LINKED_BLOCKING_QUEUE asyncCallbackQueue; static PLT_EVENT idrFrameRequiredEvent; @@ -146,7 +139,6 @@ static PPLT_CRYPTO_CONTEXT decryptionCtx; #define IDX_SET_MOTION_EVENT 10 #define IDX_SET_RGB_LED 11 #define IDX_DS_ADAPTIVE_TRIGGERS 12 -#define IDX_SET_INPUT_POLICY 13 #define CONTROL_STREAM_TIMEOUT_SEC 10 #define CONTROL_STREAM_LINGER_TIMEOUT_SEC 2 @@ -164,7 +156,6 @@ static const short packetTypesGen3[] = { -1, // Rumble triggers (unused) -1, // Set motion event (unused) -1, // Set RGB LED (unused) - -1, }; static const short packetTypesGen4[] = { 0x0606, // Request IDR frame @@ -179,7 +170,6 @@ static const short packetTypesGen4[] = { -1, // Rumble triggers (unused) -1, // Set motion event (unused) -1, // Set RGB LED (unused) - -1, }; static const short packetTypesGen5[] = { 0x0305, // Start A @@ -194,7 +184,6 @@ static const short packetTypesGen5[] = { -1, // Rumble triggers (unused) -1, // Set motion event (unused) -1, // Set RGB LED (unused) - -1, }; static const short packetTypesGen7[] = { 0x0305, // Start A @@ -209,7 +198,6 @@ static const short packetTypesGen7[] = { -1, // Rumble triggers (unused) -1, // Set motion event (unused) -1, // Set RGB LED (unused) - -1, }; static const short packetTypesGen7Enc[] = { 0x0302, // Request IDR frame @@ -225,7 +213,6 @@ static const short packetTypesGen7Enc[] = { 0x5501, // Set motion event (Sunshine protocol extension) 0x5502, // Set RGB LED (Sunshine protocol extension) 0x5503, // Set Adaptive Triggers (Sunshine protocol extension) - 0x5504, }; static const char requestIdrFrameGen3[] = { 0, 0 }; @@ -313,7 +300,7 @@ static bool supportsIdrFrameRequest; int initializeControlStream(void) { stopping = false; PltCreateEvent(&idrFrameRequiredEvent); - LbqInitializeLinkedBlockingQueue(&referenceFrameControlQueue, 20); + LbqInitializeLinkedBlockingQueue(&invalidReferenceFrameTuples, 20); LbqInitializeLinkedBlockingQueue(&frameFecStatusQueue, 8); // Limits number of frame status reports per periodic ping interval LbqInitializeLinkedBlockingQueue(&asyncCallbackQueue, 30); PltCreateMutex(&enetMutex); @@ -388,7 +375,7 @@ void destroyControlStream(void) { PltDestroyCryptoContext(encryptionCtx); PltDestroyCryptoContext(decryptionCtx); PltCloseEvent(&idrFrameRequiredEvent); - freeBasicLbqList(LbqDestroyLinkedBlockingQueue(&referenceFrameControlQueue)); + freeBasicLbqList(LbqDestroyLinkedBlockingQueue(&invalidReferenceFrameTuples)); freeBasicLbqList(LbqDestroyLinkedBlockingQueue(&frameFecStatusQueue)); freeBasicLbqList(LbqDestroyLinkedBlockingQueue(&asyncCallbackQueue)); @@ -399,15 +386,12 @@ static void queueFrameInvalidationTuple(uint32_t startFrame, uint32_t endFrame) LC_ASSERT(startFrame <= endFrame); if (isReferenceFrameInvalidationEnabled()) { - PQUEUED_REFERENCE_FRAME_CONTROL qfit; + PQUEUED_FRAME_INVALIDATION_TUPLE qfit; qfit = malloc(sizeof(*qfit)); if (qfit != NULL) { - *qfit = (QUEUED_REFERENCE_FRAME_CONTROL){ - .startFrame = startFrame, - .endFrame = endFrame, - .invalidate = true, - }; - if (LbqOfferQueueItem(&referenceFrameControlQueue, qfit, &qfit->entry) == LBQ_BOUND_EXCEEDED) { + qfit->startFrame = startFrame; + qfit->endFrame = endFrame; + if (LbqOfferQueueItem(&invalidReferenceFrameTuples, qfit, &qfit->entry) == LBQ_BOUND_EXCEEDED) { // Too many invalidation tuples, so we need an IDR frame now Limelog("RFI range list reached maximum size limit\n"); free(qfit); @@ -427,7 +411,7 @@ static void queueFrameInvalidationTuple(uint32_t startFrame, uint32_t endFrame) void LiRequestIdrFrame(void) { // Any reference frame invalidation requests should be dropped now. // We require a full IDR frame to recover. - freeBasicLbqList(LbqFlushQueueItems(&referenceFrameControlQueue)); + freeBasicLbqList(LbqFlushQueueItems(&invalidReferenceFrameTuples)); // Request the IDR frame PltSetEvent(&idrFrameRequiredEvent); @@ -439,29 +423,9 @@ void connectionDetectedFrameLoss(uint32_t startFrame, uint32_t endFrame) { } // When we receive a frame, update the number of our current frame -// and send ACK control message if the frame is LTR -void connectionReceivedCompleteFrame(uint32_t frameIndex, bool frameIsLTR) { +void connectionReceivedCompleteFrame(uint32_t frameIndex) { lastGoodFrame = frameIndex; intervalGoodFrameCount++; - - if (frameIsLTR && IS_SUNSHINE() && isReferenceFrameInvalidationEnabled()) { - // Queue LTR frame ACK control message - PQUEUED_REFERENCE_FRAME_CONTROL qfit; - qfit = malloc(sizeof(*qfit)); - if (qfit != NULL) { - *qfit = (QUEUED_REFERENCE_FRAME_CONTROL){ - .startFrame = frameIndex, - .invalidate = false, - }; - if (LbqOfferQueueItem(&referenceFrameControlQueue, qfit, &qfit->entry) == LBQ_BOUND_EXCEEDED) { - // This shouldn't happen and indicates that something has gone wrong with the queue - LC_ASSERT(false); - Limelog("Couldn't queue LTR ACK because the list has reached maximum size limit\n"); - free(qfit); - LiRequestIdrFrame(); - } - } - } } void connectionSendFrameFecStatus(PSS_FRAME_FEC_STATUS fecStatus) { @@ -1022,12 +986,6 @@ static void asyncCallbackThreadFunc(void* context) { queuedCb->data.dsAdaptiveTrigger.left, queuedCb->data.dsAdaptiveTrigger.right); break; - case IDX_SET_INPUT_POLICY: - ListenerCallbacks.setInputPolicy(queuedCb->data.setInputPolicy.allowKeyboard, - queuedCb->data.setInputPolicy.allowMouse, - queuedCb->data.setInputPolicy.allowGamepad, - queuedCb->data.setInputPolicy.reason); - break; default: // Unhandled packet type from queueAsyncCallback() LC_ASSERT(false); @@ -1044,8 +1002,7 @@ static bool needsAsyncCallback(unsigned short packetType) { packetType == packetTypes[IDX_SET_MOTION_EVENT] || packetType == packetTypes[IDX_SET_RGB_LED] || packetType == packetTypes[IDX_HDR_INFO] || - packetType == packetTypes[IDX_DS_ADAPTIVE_TRIGGERS] || - packetType == packetTypes[IDX_SET_INPUT_POLICY]; + packetType == packetTypes[IDX_DS_ADAPTIVE_TRIGGERS]; } static void queueAsyncCallback(PNVCTL_ENET_PACKET_HEADER_V1 ctlHdr, int packetLength) { @@ -1106,13 +1063,6 @@ static void queueAsyncCallback(PNVCTL_ENET_PACKET_HEADER_V1 ctlHdr, int packetLe BbGetBytes(&bb, queuedCb->data.dsAdaptiveTrigger.right, DS_EFFECT_PAYLOAD_SIZE); queuedCb->typeIndex = IDX_DS_ADAPTIVE_TRIGGERS; } - else if (ctlHdr->type == packetTypes[IDX_SET_INPUT_POLICY]) { - BbGet8(&bb, &queuedCb->data.setInputPolicy.allowKeyboard); - BbGet8(&bb, &queuedCb->data.setInputPolicy.allowMouse); - BbGet8(&bb, &queuedCb->data.setInputPolicy.allowGamepad); - BbGet8(&bb, &queuedCb->data.setInputPolicy.reason); - queuedCb->typeIndex = IDX_SET_INPUT_POLICY; - } else { // Unhandled packet type from needsAsyncCallback() LC_ASSERT(false); @@ -1562,22 +1512,22 @@ static void requestIdrFrame(void) { } static void requestInvalidateReferenceFrames(uint32_t startFrame, uint32_t endFrame) { + int64_t payload[3]; + LC_ASSERT(startFrame <= endFrame); LC_ASSERT(isReferenceFrameInvalidationEnabled()); - SS_RFI_REQUEST payload = { - .firstFrameIndex = LE32(startFrame), - .lastFrameIndex = LE32(endFrame), - }; + payload[0] = LE64(startFrame); + payload[1] = LE64(endFrame); + payload[2] = 0; // Send the reference frame invalidation request and read the response if (!sendMessageAndDiscardReply(packetTypes[IDX_INVALIDATE_REF_FRAMES], sizeof(payload), - &payload, - CTRL_CHANNEL_URGENT, + payload, CTRL_CHANNEL_URGENT, ENET_PACKET_FLAG_RELIABLE, false)) { - Limelog("Request Invalidate Reference Frames: Transaction failed: %d\n", (int)LastSocketError()); + Limelog("Request Invaldiate Reference Frames: Transaction failed: %d\n", (int)LastSocketError()); ListenerCallbacks.connectionTerminated(LastSocketFail()); return; } @@ -1585,65 +1535,32 @@ static void requestInvalidateReferenceFrames(uint32_t startFrame, uint32_t endFr Limelog("Invalidate reference frame request sent (%d to %d)\n", startFrame, endFrame); } -static void confirmLongtermReferenceFrame(uint32_t frameIndex) { - LC_ASSERT(isReferenceFrameInvalidationEnabled()); - - SS_LTR_FRAME_ACK payload = { - .frameIndex = LE32(frameIndex), - }; - - // Send LTR frame ACK and don't wait for response - if (!sendMessageAndForget(SS_LTR_FRAME_ACK_PTYPE, - sizeof(payload), - &payload, - CTRL_CHANNEL_URGENT, - ENET_PACKET_FLAG_RELIABLE, - false)) { - Limelog("LTR frame ACK: Transaction failed: %d\n", (int)LastSocketError()); - ListenerCallbacks.connectionTerminated(LastSocketFail()); - return; - } -} - -static void referenceFrameControlFunc(void* context) { +static void invalidateRefFramesFunc(void* context) { LC_ASSERT(isReferenceFrameInvalidationEnabled()); while (!PltIsThreadInterrupted(&invalidateRefFramesThread)) { - PQUEUED_REFERENCE_FRAME_CONTROL qfit; - uint32_t invalidateStartFrame; - uint32_t invalidateEndFrame; - bool invalidate = false; + PQUEUED_FRAME_INVALIDATION_TUPLE qfit; + uint32_t startFrame; + uint32_t endFrame; - // Wait for a reference frame control message or a request to shutdown - if (LbqWaitForQueueElement(&referenceFrameControlQueue, (void**)&qfit) != LBQ_SUCCESS) { + // Wait for a reference frame invalidation request or a request to shutdown + if (LbqWaitForQueueElement(&invalidReferenceFrameTuples, (void**)&qfit) != LBQ_SUCCESS) { // Bail if we're stopping return; } - do { - if (qfit->invalidate) { - if (!invalidate) { - invalidateStartFrame = qfit->startFrame; - invalidateEndFrame = qfit->endFrame; - invalidate = true; - } - else { - // Aggregate all lost frames into one range - LC_ASSERT(qfit->endFrame >= invalidateEndFrame); - invalidateEndFrame = qfit->endFrame; - } - } - else { - // Send LTR frame ACK - confirmLongtermReferenceFrame(qfit->startFrame); - } - free(qfit); - } while (LbqPollQueueElement(&referenceFrameControlQueue, (void**)&qfit) == LBQ_SUCCESS); + startFrame = qfit->startFrame; + endFrame = qfit->endFrame; - if (invalidate) { - // Send the reference frame invalidation request - requestInvalidateReferenceFrames(invalidateStartFrame, invalidateEndFrame); - } + // Aggregate all lost frames into one range + do { + LC_ASSERT(qfit->endFrame >= endFrame); + endFrame = qfit->endFrame; + free(qfit); + } while (LbqPollQueueElement(&invalidReferenceFrameTuples, (void**)&qfit) == LBQ_SUCCESS); + + // Send the reference frame invalidation request + requestInvalidateReferenceFrames(startFrame, endFrame); } } @@ -1657,8 +1574,8 @@ static void requestIdrFrameFunc(void* context) { return; } - // Any pending RFI requests and LTR frame ACK messages are now redundant - freeBasicLbqList(LbqFlushQueueItems(&referenceFrameControlQueue)); + // Any pending reference frame invalidation requests are now redundant + freeBasicLbqList(LbqFlushQueueItems(&invalidReferenceFrameTuples)); // Request the IDR frame requestIdrFrame(); @@ -1668,7 +1585,7 @@ static void requestIdrFrameFunc(void* context) { // Stops the control stream int stopControlStream(void) { stopping = true; - LbqSignalQueueShutdown(&referenceFrameControlQueue); + LbqSignalQueueShutdown(&invalidReferenceFrameTuples); LbqSignalQueueShutdown(&frameFecStatusQueue); LbqSignalQueueDrain(&asyncCallbackQueue); PltSetEvent(&idrFrameRequiredEvent); @@ -1727,34 +1644,6 @@ int sendInputPacketOnControlStream(unsigned char* data, int length, uint8_t chan return 0; } -int LiSendSessionInputPolicy(bool allowKeyboard, bool allowMouse, bool allowGamepad, uint8_t reason) { - struct { - uint8_t allowKeyboard; - uint8_t allowMouse; - uint8_t allowGamepad; - uint8_t reason; - } payload; - - if (!IS_SUNSHINE() || AppVersionQuad[0] < 7) { - return LI_ERR_UNSUPPORTED; - } - - if (client == NULL || peer == NULL || stopping) { - return -2; - } - - payload.allowKeyboard = allowKeyboard ? 1 : 0; - payload.allowMouse = allowMouse ? 1 : 0; - payload.allowGamepad = allowGamepad ? 1 : 0; - payload.reason = reason; - - if (sendMessageAndForget(0x5504, sizeof(payload), &payload, CTRL_CHANNEL_GENERIC, ENET_PACKET_FLAG_RELIABLE, false) == 0) { - return -1; - } - - return 0; -} - // Called by the input stream to flush queued packets before a batching wait void flushInputOnControlStream(void) { if (AppVersionQuad[0] >= 5) { @@ -1781,10 +1670,7 @@ bool isControlDataInTransit(void) { bool LiGetEstimatedRttInfo(uint32_t* estimatedRtt, uint32_t* estimatedRttVariance) { bool ret = false; - // We do not acquire enetMutex here because we're just reading metrics - // and observing a torn write every once in a while is totally fine. - // The peer pointer points to memory reserved inside the client object, - // so it's guaranteed that it will never go away underneath us. + PltLockMutex(&enetMutex); if (peer != NULL && peer->state == ENET_PEER_STATE_CONNECTED) { if (estimatedRtt != NULL) { *estimatedRtt = peer->roundTripTime; @@ -1796,6 +1682,7 @@ bool LiGetEstimatedRttInfo(uint32_t* estimatedRtt, uint32_t* estimatedRttVarianc ret = true; } + PltUnlockMutex(&enetMutex); return ret; } @@ -2083,7 +1970,7 @@ int startControlStream(void) { // Only create the reference frame invalidation thread if RFI is enabled if (isReferenceFrameInvalidationEnabled()) { - err = PltCreateThread("InvRefFrames", referenceFrameControlFunc, NULL, &invalidateRefFramesThread); + err = PltCreateThread("InvRefFrames", invalidateRefFramesFunc, NULL, &invalidateRefFramesThread); if (err != 0) { stopping = true; PltSetEvent(&idrFrameRequiredEvent); diff --git a/src/FakeCallbacks.c b/src/FakeCallbacks.c index 50095a0..29fdf18 100644 --- a/src/FakeCallbacks.c +++ b/src/FakeCallbacks.c @@ -41,7 +41,6 @@ static void fakeClRumbleTriggers(uint16_t controllerNumber, uint16_t leftTrigger static void fakeClSetMotionEventState(uint16_t controllerNumber, uint8_t motionType, uint16_t reportRateHz) {} static void fakeClSetAdaptiveTriggers(uint16_t controllerNumber, uint8_t eventFlags, uint8_t typeLeft, uint8_t typeRight, uint8_t *left, uint8_t *right) {}; static void fakeClSetControllerLED(uint16_t controllerNumber, uint8_t r, uint8_t g, uint8_t b) {} -static void fakeClSetInputPolicy(uint8_t allowKeyboard, uint8_t allowMouse, uint8_t allowGamepad, uint8_t reason) {} static CONNECTION_LISTENER_CALLBACKS fakeClCallbacks = { .stageStarting = fakeClStageStarting, @@ -57,7 +56,6 @@ static CONNECTION_LISTENER_CALLBACKS fakeClCallbacks = { .setMotionEventState = fakeClSetMotionEventState, .setControllerLED = fakeClSetControllerLED, .setAdaptiveTriggers = fakeClSetAdaptiveTriggers, - .setInputPolicy = fakeClSetInputPolicy, }; void fixupMissingCallbacks(PDECODER_RENDERER_CALLBACKS* drCallbacks, PAUDIO_RENDERER_CALLBACKS* arCallbacks, @@ -148,8 +146,5 @@ void fixupMissingCallbacks(PDECODER_RENDERER_CALLBACKS* drCallbacks, PAUDIO_REND if ((*clCallbacks)->setAdaptiveTriggers == NULL) { (*clCallbacks)->setAdaptiveTriggers = fakeClSetAdaptiveTriggers; } - if ((*clCallbacks)->setInputPolicy == NULL) { - (*clCallbacks)->setInputPolicy = fakeClSetInputPolicy; - } } } diff --git a/src/InputStream.c b/src/InputStream.c index e8e60a4..06913ff 100644 --- a/src/InputStream.c +++ b/src/InputStream.c @@ -724,14 +724,9 @@ int LiSendMouseMoveEvent(short deltaX, short deltaY) { // Queue a packet holder if this is the only pending relative mouse event if (!currentRelativeMouseState.dirty) { - // Set the dirty flag to claim ownership of inserting the packet holder - // and unlock to allow other threads to enqueue or process input. - currentRelativeMouseState.dirty = true; - PltUnlockMutex(&batchedInputMutex); - holder = allocatePacketHolder(0); if (holder == NULL) { - currentRelativeMouseState.dirty = false; + PltUnlockMutex(&batchedInputMutex); return -1; } @@ -752,21 +747,22 @@ int LiSendMouseMoveEvent(short deltaX, short deltaY) { // Remaining fields are set in the input thread based on the latest currentRelativeMouseState values err = LbqOfferQueueItem(&packetQueue, holder, &holder->entry); - if (err != LBQ_SUCCESS) { + if (err == LBQ_SUCCESS) { + currentRelativeMouseState.dirty = true; + } + else { LC_ASSERT(err == LBQ_BOUND_EXCEEDED); Limelog("Input queue reached maximum size limit\n"); freePacketHolder(holder); - - // We weren't able to insert the entry, so let the next call try again - currentRelativeMouseState.dirty = false; } } else { // There's already a packet holder queued to send this event - PltUnlockMutex(&batchedInputMutex); err = 0; } + PltUnlockMutex(&batchedInputMutex); + return err; } @@ -789,14 +785,9 @@ int LiSendMousePositionEvent(short x, short y, short referenceWidth, short refer // Queue a packet holder if this is the only pending absolute mouse event if (!currentAbsoluteMouseState.dirty) { - // Set the dirty flag to claim ownership of inserting the packet holder - // and unlock to allow other threads to enqueue or process input. - currentAbsoluteMouseState.dirty = true; - PltUnlockMutex(&batchedInputMutex); - holder = allocatePacketHolder(0); if (holder == NULL) { - currentAbsoluteMouseState.dirty = false; + PltUnlockMutex(&batchedInputMutex); return -1; } @@ -812,21 +803,22 @@ int LiSendMousePositionEvent(short x, short y, short referenceWidth, short refer // Remaining fields are set in the input thread based on the latest currentAbsoluteMouseState values err = LbqOfferQueueItem(&packetQueue, holder, &holder->entry); - if (err != LBQ_SUCCESS) { + if (err == LBQ_SUCCESS) { + currentAbsoluteMouseState.dirty = true; + } + else { LC_ASSERT(err == LBQ_BOUND_EXCEEDED); Limelog("Input queue reached maximum size limit\n"); freePacketHolder(holder); - - // We weren't able to insert the entry, so let the next call try again - currentAbsoluteMouseState.dirty = false; } } else { // There's already a packet holder queued to send this event - PltUnlockMutex(&batchedInputMutex); err = 0; } + PltUnlockMutex(&batchedInputMutex); + // This is not thread safe, but it's not a big deal because callers that want to // use LiSendRelativeMotionAsMousePositionEvent() must not mix these function // without synchronization (otherwise the state of the cursor on the host is @@ -1544,14 +1536,9 @@ int LiSendControllerMotionEvent(uint8_t controllerNumber, uint8_t motionType, fl // Queue a packet holder if this is the only pending sensor event if (!currentGamepadSensorState[controllerNumber][motionType - 1].dirty) { - // Set the dirty flag to claim ownership of inserting the packet holder - // and unlock to allow other threads to enqueue or process input. - currentGamepadSensorState[controllerNumber][motionType - 1].dirty = true; - PltUnlockMutex(&batchedInputMutex); - holder = allocatePacketHolder(0); if (holder == NULL) { - currentGamepadSensorState[controllerNumber][motionType - 1].dirty = false; + PltUnlockMutex(&batchedInputMutex); return -1; } @@ -1567,21 +1554,22 @@ int LiSendControllerMotionEvent(uint8_t controllerNumber, uint8_t motionType, fl // Remaining fields are set in the input thread based on the latest currentGamepadSensorState values err = LbqOfferQueueItem(&packetQueue, holder, &holder->entry); - if (err != LBQ_SUCCESS) { + if (err == LBQ_SUCCESS) { + currentGamepadSensorState[controllerNumber][motionType - 1].dirty = true; + } + else { LC_ASSERT(err == LBQ_BOUND_EXCEEDED); Limelog("Input queue reached maximum size limit\n"); freePacketHolder(holder); - - // We weren't able to insert the entry, so let the next call try again - currentGamepadSensorState[controllerNumber][motionType - 1].dirty = false; } } else { // There's already a packet holder queued to send this event - PltUnlockMutex(&batchedInputMutex); err = 0; } + PltUnlockMutex(&batchedInputMutex); + return err; } diff --git a/src/Limelight-internal.h b/src/Limelight-internal.h index e1314c5..dfd4758 100644 --- a/src/Limelight-internal.h +++ b/src/Limelight-internal.h @@ -55,7 +55,7 @@ extern uint32_t EncryptionFeaturesEnabled; // ENet channel ID values #define CTRL_CHANNEL_GENERIC 0x00 -#define CTRL_CHANNEL_URGENT 0x01 // IDR, LTR ACK and RFI +#define CTRL_CHANNEL_URGENT 0x01 // IDR and reference frame invalidation requests #define CTRL_CHANNEL_KEYBOARD 0x02 #define CTRL_CHANNEL_MOUSE 0x03 #define CTRL_CHANNEL_PEN 0x04 @@ -119,7 +119,7 @@ int startControlStream(void); int stopControlStream(void); void destroyControlStream(void); void connectionDetectedFrameLoss(uint32_t startFrame, uint32_t endFrame); -void connectionReceivedCompleteFrame(uint32_t frameIndex, bool frameIsLTR); +void connectionReceivedCompleteFrame(uint32_t frameIndex); void connectionSawFrame(uint32_t frameIndex); void connectionSendFrameFecStatus(PSS_FRAME_FEC_STATUS fecStatus); int sendInputPacketOnControlStream(unsigned char* data, int length, uint8_t channelId, uint32_t flags, bool moreData); diff --git a/src/Limelight.h b/src/Limelight.h index ba4e5c5..ac87a4b 100644 --- a/src/Limelight.h +++ b/src/Limelight.h @@ -483,8 +483,6 @@ typedef void(*ConnListenerSetAdaptiveTriggers)(uint16_t controllerNumber, uint8_ // This callback is invoked to set a controller's RGB LED (if present). typedef void(*ConnListenerSetControllerLED)(uint16_t controllerNumber, uint8_t r, uint8_t g, uint8_t b); -typedef void(*ConnListenerSetInputPolicy)(uint8_t allowKeyboard, uint8_t allowMouse, uint8_t allowGamepad, uint8_t reason); - typedef struct _CONNECTION_LISTENER_CALLBACKS { ConnListenerStageStarting stageStarting; ConnListenerStageComplete stageComplete; @@ -499,7 +497,6 @@ typedef struct _CONNECTION_LISTENER_CALLBACKS { ConnListenerSetMotionEventState setMotionEventState; ConnListenerSetControllerLED setControllerLED; ConnListenerSetAdaptiveTriggers setAdaptiveTriggers; - ConnListenerSetInputPolicy setInputPolicy; } CONNECTION_LISTENER_CALLBACKS, *PCONNECTION_LISTENER_CALLBACKS; // Use this function to zero the connection callbacks when allocated on the stack or heap @@ -840,12 +837,6 @@ int LiSendHighResScrollEvent(short scrollAmount); int LiSendHScrollEvent(signed char scrollClicks); int LiSendHighResHScrollEvent(short scrollAmount); -#define LI_SESSION_INPUT_POLICY_REASON_STREAM_START 0x00 -#define LI_SESSION_INPUT_POLICY_REASON_USER_TOGGLE 0x01 -#define LI_SESSION_INPUT_POLICY_REASON_HOST_ACK 0x02 -#define LI_SESSION_INPUT_POLICY_REASON_HOST_OVERRIDE 0x03 -int LiSendSessionInputPolicy(bool allowKeyboard, bool allowMouse, bool allowGamepad, uint8_t reason); - // This function returns a time in microseconds with an implementation-defined epoch. // It should only ever be compared with the return value from a previous call to itself. uint64_t LiGetMicroseconds(void); diff --git a/src/Platform.c b/src/Platform.c index d68e692..30ae48b 100644 --- a/src/Platform.c +++ b/src/Platform.c @@ -86,7 +86,9 @@ void* ThreadProc(void* context) { ctx->entry(ctx->context); - free(ctx); +#if defined(__vita__) +free(ctx); +#endif #if defined(LC_WINDOWS) || defined(__vita__) || defined(__WIIU__) || defined(__3DS__) return 0; @@ -286,14 +288,11 @@ int PltCreateThread(const char* name, ThreadEntry entry, void* context, PLT_THRE pthread_attr_init(&attr); -#ifdef __vita__ pthread_attr_setstacksize(&attr, 0x100000); -#endif ctx->name = name; int err = pthread_create(&thread->thread, &attr, ThreadProc, ctx); - pthread_attr_destroy(&attr); if (err != 0) { free(ctx); return err; diff --git a/src/PlatformSockets.c b/src/PlatformSockets.c index 41e7dd8..56f9b9c 100644 --- a/src/PlatformSockets.c +++ b/src/PlatformSockets.c @@ -568,40 +568,6 @@ Exit: return s; } -int getLocalAddressByUdpConnect(const struct sockaddr_storage* targetAddr, SOCKADDR_LEN targetAddrLen, unsigned short targetPort, - struct sockaddr_storage* localAddr, SOCKADDR_LEN* localAddrLen) { - SOCKET udpSocket; - LC_SOCKADDR connAddr; - - LC_ASSERT(targetPort != 0); - - udpSocket = createSocket(targetAddr->ss_family, SOCK_DGRAM, IPPROTO_UDP, false); - if (udpSocket == INVALID_SOCKET) { - return LastSocketError(); - } - - memcpy(&connAddr, targetAddr, targetAddrLen); - SET_PORT(&connAddr, RtspPortNumber); - - if (connect(udpSocket, (struct sockaddr*)&connAddr, targetAddrLen) < 0) { - int err = LastSocketError(); - Limelog("UDP connect() failed: %d\n", err); - closeSocket(udpSocket); - return err; - } - - *localAddrLen = sizeof(*localAddr); - if (getsockname(udpSocket, (struct sockaddr*)localAddr, localAddrLen) < 0) { - int err = LastSocketError(); - Limelog("getsockname() failed: %d\n", err); - closeSocket(udpSocket); - return err; - } - - closeSocket(udpSocket); - return 0; -} - // See TCP_MAXSEG note in connectTcpSocket() above for more information. // TCP_NODELAY must be enabled on the socket for this function to work! int sendMtuSafe(SOCKET s, char* buffer, int size) { diff --git a/src/PlatformSockets.h b/src/PlatformSockets.h index db47d83..78ae4be 100644 --- a/src/PlatformSockets.h +++ b/src/PlatformSockets.h @@ -107,8 +107,6 @@ void addrToUrlSafeString(struct sockaddr_storage* addr, char* string, size_t str SOCKET createSocket(int addressFamily, int socketType, int protocol, bool nonBlocking); SOCKET connectTcpSocket(struct sockaddr_storage* dstaddr, SOCKADDR_LEN addrlen, unsigned short port, int timeoutSec); -int getLocalAddressByUdpConnect(const struct sockaddr_storage* targetAddr, SOCKADDR_LEN targetAddrLen, unsigned short targetPort, - struct sockaddr_storage* localAddr, SOCKADDR_LEN* localAddrLen); int sendMtuSafe(SOCKET s, char* buffer, int size); SOCKET bindUdpSocket(int addressFamily, struct sockaddr_storage* localAddr, SOCKADDR_LEN addrLen, int bufferSize, int socketQosType); int enableNoDelay(SOCKET s); diff --git a/src/RtpVideoQueue.c b/src/RtpVideoQueue.c index dfbed48..c34d2a1 100644 --- a/src/RtpVideoQueue.c +++ b/src/RtpVideoQueue.c @@ -382,9 +382,9 @@ cleanup_packets: // Check all NV_VIDEO_PACKET fields except FEC stuff which differs in the recovered packet LC_ASSERT_VT(nvPacket->flags == droppedNvPacket->flags); - LC_ASSERT_VT(nvPacket->extraFlags == droppedNvPacket->extraFlags); LC_ASSERT_VT(nvPacket->frameIndex == droppedNvPacket->frameIndex); LC_ASSERT_VT(nvPacket->streamPacketIndex == droppedNvPacket->streamPacketIndex); + LC_ASSERT_VT(nvPacket->reserved == droppedNvPacket->reserved); LC_ASSERT_VT(!queue->multiFecCapable || nvPacket->multiFecBlocks == droppedNvPacket->multiFecBlocks); // Check the data itself - use memcmp() and only loop if an error is detected diff --git a/src/RtspConnection.c b/src/RtspConnection.c index 52ce2b1..d8f1b35 100644 --- a/src/RtspConnection.c +++ b/src/RtspConnection.c @@ -477,6 +477,18 @@ static bool transactRtspMessageTcp(PRTSP_MESSAGE request, PRTSP_MESSAGE response // Decrypt (if necessary) and deserialize the RTSP response ret = unsealRtspMessage(responseBuffer, offset, response); + // Fetch the local address for this socket if it's not populated yet + if (LocalAddr.ss_family == 0) { + SOCKADDR_LEN addrLen = (SOCKADDR_LEN)sizeof(LocalAddr); + if (getsockname(sock, (struct sockaddr*)&LocalAddr, &addrLen) < 0) { + Limelog("Failed to get local address: %d\n", LastSocketError()); + memset(&LocalAddr, 0, sizeof(LocalAddr)); + } + else { + LC_ASSERT(addrLen == AddrLen); + } + } + Exit: if (serializedMessage != NULL) { free(serializedMessage); diff --git a/src/Video.h b/src/Video.h index 737d23c..3df2eae 100644 --- a/src/Video.h +++ b/src/Video.h @@ -22,13 +22,11 @@ typedef struct _ENC_VIDEO_HEADER { #define FLAG_EOF 0x2 #define FLAG_SOF 0x4 -#define NV_VIDEO_PACKET_EXTRA_FLAG_LTR_FRAME 0x1 - typedef struct _NV_VIDEO_PACKET { uint32_t streamPacketIndex; uint32_t frameIndex; uint8_t flags; - uint8_t extraFlags; + uint8_t reserved; uint8_t multiFecFlags; uint8_t multiFecBlocks; uint32_t fecInfo; @@ -69,20 +67,4 @@ typedef struct _SS_FRAME_FEC_STATUS { uint8_t multiFecBlockCount; } SS_FRAME_FEC_STATUS, *PSS_FRAME_FEC_STATUS; -// Fields are little-endian -#define SS_LTR_FRAME_ACK_PTYPE 0x0350 -typedef struct _SS_LTR_FRAME_ACK { - uint32_t frameIndex; - uint32_t reserved; -} SS_LTR_FRAME_ACK, *PSS_LTR_FRAME_ACK; - -// Fields are little-endian -#define SS_RFI_REQUEST_PTYPE 0x0301 -typedef struct _SS_RFI_REQUEST { - uint32_t firstFrameIndex; - uint32_t reserved1; - uint32_t lastFrameIndex; - uint32_t reserved2[3]; -} SS_RFI_REQUEST, *PSS_RFI_REQUEST; - #pragma pack(pop) diff --git a/src/VideoDepacketizer.c b/src/VideoDepacketizer.c index 43f2df9..364dcec 100644 --- a/src/VideoDepacketizer.c +++ b/src/VideoDepacketizer.c @@ -466,7 +466,7 @@ static bool isIdrFrameStart(PBUFFER_DESC buffer) { } // Reassemble the frame with the given frame number -static void reassembleFrame(int frameNumber, bool frameIsLTR) { +static void reassembleFrame(int frameNumber) { if (nalChainHead != NULL) { QUEUED_DECODE_UNIT qduDS; PQUEUED_DECODE_UNIT qdu; @@ -539,7 +539,7 @@ static void reassembleFrame(int frameNumber, bool frameIsLTR) { } // Notify the control connection - connectionReceivedCompleteFrame(frameNumber, frameIsLTR); + connectionReceivedCompleteFrame(frameNumber); // Clear frame drops consecutiveFrameDrops = 0; @@ -748,7 +748,6 @@ static void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length, BUFFER_DESC currentPos; uint32_t frameIndex; uint8_t flags; - uint8_t extraFlags; bool firstPacket, lastPacket; uint32_t streamPacketIndex; uint8_t fecCurrentBlockNumber; @@ -766,7 +765,6 @@ static void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length, fecLastBlockNumber = (videoPacket->multiFecBlocks >> 6) & 0x3; frameIndex = videoPacket->frameIndex; flags = videoPacket->flags; - extraFlags = videoPacket->extraFlags; firstPacket = isFirstPacket(flags, fecCurrentBlockNumber); lastPacket = (flags & FLAG_EOF) && fecCurrentBlockNumber == fecLastBlockNumber; @@ -1121,7 +1119,7 @@ static void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length, } } - reassembleFrame(frameIndex, extraFlags & NV_VIDEO_PACKET_EXTRA_FLAG_LTR_FRAME); + reassembleFrame(frameIndex); } }