From 6e9ed871bc3e013386c775b2ee7d31deb1151068 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Thu, 28 Dec 2023 16:56:06 -0600 Subject: [PATCH] Add support for X-SS-Connect-Data in RTSP SETUP for control stream This allows the host to provide a 32-bit integer that will be sent in the data of the ENet connect event, similar to X-SS-Ping-Payload for video and audio. The host can use this data to uniquely identify a client when IP addresses are not stable across the various separate connections, such as when the client is behind a Carrier-Grade NAT. --- src/Connection.c | 1 + src/ControlStream.c | 2 +- src/Limelight-internal.h | 2 ++ src/RtspConnection.c | 10 ++++++++++ src/SdpGenerator.c | 2 +- 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Connection.c b/src/Connection.c index b914827a..3cfb3523 100644 --- a/src/Connection.c +++ b/src/Connection.c @@ -31,6 +31,7 @@ uint16_t AudioPortNumber; uint16_t VideoPortNumber; SS_PING AudioPingPayload; SS_PING VideoPingPayload; +uint32_t ControlConnectData; uint32_t SunshineFeatureFlags; // Connection stages diff --git a/src/ControlStream.c b/src/ControlStream.c index a3327987..43ef1539 100644 --- a/src/ControlStream.c +++ b/src/ControlStream.c @@ -1625,7 +1625,7 @@ int startControlStream(void) { enet_socket_set_option (client->socket, ENET_SOCKOPT_QOS, 1); // Connect to the host - peer = enet_host_connect(client, &remoteAddress, CTRL_CHANNEL_COUNT, 0); + peer = enet_host_connect(client, &remoteAddress, CTRL_CHANNEL_COUNT, ControlConnectData); if (peer == NULL) { stopping = true; enet_host_destroy(client); diff --git a/src/Limelight-internal.h b/src/Limelight-internal.h index fd040839..e8a97848 100644 --- a/src/Limelight-internal.h +++ b/src/Limelight-internal.h @@ -40,6 +40,7 @@ extern uint16_t VideoPortNumber; extern SS_PING AudioPingPayload; extern SS_PING VideoPingPayload; +extern uint32_t ControlConnectData; extern uint32_t SunshineFeatureFlags; @@ -76,6 +77,7 @@ extern uint32_t SunshineFeatureFlags; // Client feature flags for x-ml-general.featureFlags SDP attribute #define ML_FF_FEC_STATUS 0x01 // Client sends SS_FRAME_FEC_STATUS for frame losses +#define ML_FF_SESSION_ID_V1 0x02 // Client supports X-SS-Ping-Payload and X-SS-Connect-Data #define UDP_RECV_POLL_TIMEOUT_MS 100 diff --git a/src/RtspConnection.c b/src/RtspConnection.c index e94bb52a..a37ce230 100644 --- a/src/RtspConnection.c +++ b/src/RtspConnection.c @@ -1067,6 +1067,7 @@ int performRtspHandshake(PSERVER_INFORMATION serverInfo) { if (AppVersionQuad[0] >= 5) { RTSP_MESSAGE response; int error = -1; + char* connectData; if (!setupStream(&response, controlStreamId, @@ -1083,6 +1084,15 @@ int performRtspHandshake(PSERVER_INFORMATION serverInfo) { goto Exit; } + // Parse the Sunshine control connect data extension if present + connectData = getOptionContent(response.options, "X-SS-Connect-Data"); + if (connectData != NULL) { + ControlConnectData = (uint32_t)strtoul(connectData, NULL, 0); + } + else { + ControlConnectData = 0; + } + // Parse the control port out of the RTSP SETUP response LC_ASSERT(ControlPortNumber == 0); if (!parseServerPortFromTransport(&response, &ControlPortNumber)) { diff --git a/src/SdpGenerator.c b/src/SdpGenerator.c index 2942a66b..c6d8d364 100644 --- a/src/SdpGenerator.c +++ b/src/SdpGenerator.c @@ -268,7 +268,7 @@ static PSDP_OPTION getAttributesList(char*urlSafeAddr) { // Send client feature flags to Sunshine hosts if (IS_SUNSHINE()) { - uint32_t moonlightFeatureFlags = ML_FF_FEC_STATUS; + uint32_t moonlightFeatureFlags = ML_FF_FEC_STATUS | ML_FF_SESSION_ID_V1; snprintf(payloadStr, sizeof(payloadStr), "%u", moonlightFeatureFlags); err |= addAttributeString(&optionHead, "x-ml-general.featureFlags", payloadStr); }