mirror of
https://github.com/moonlight-stream/moonlight-common-c.git
synced 2026-04-03 06:16:04 +00:00
Use modern string parsing functions in SdpGenerator
This commit is contained in:
@@ -35,21 +35,50 @@ static int getSerializedAttributeListSize(PSDP_OPTION head) {
|
||||
|
||||
currentEntry = currentEntry->next;
|
||||
}
|
||||
return (int)size;
|
||||
// Add one for the null terminator
|
||||
return (int)size + 1;
|
||||
}
|
||||
|
||||
// Populate the serialized attribute list into a string
|
||||
static int fillSerializedAttributeList(char* buffer, PSDP_OPTION head) {
|
||||
static int fillSerializedAttributeList(char* buffer, size_t length, PSDP_OPTION head) {
|
||||
PSDP_OPTION currentEntry = head;
|
||||
int offset = 0;
|
||||
while (currentEntry != NULL) {
|
||||
offset += sprintf(&buffer[offset], "a=%s:", currentEntry->name);
|
||||
memcpy(&buffer[offset], currentEntry->payload, currentEntry->payloadLen);
|
||||
offset += currentEntry->payloadLen;
|
||||
offset += sprintf(&buffer[offset], " \r\n");
|
||||
int ret = snprintf(&buffer[offset], length, "a=%s:", currentEntry->name);
|
||||
if (ret > 0 && (size_t)ret < length) {
|
||||
offset += ret;
|
||||
length -= ret;
|
||||
}
|
||||
else {
|
||||
LC_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((size_t)currentEntry->payloadLen < length) {
|
||||
memcpy(&buffer[offset], currentEntry->payload, currentEntry->payloadLen);
|
||||
offset += currentEntry->payloadLen;
|
||||
length -= currentEntry->payloadLen;
|
||||
}
|
||||
else {
|
||||
LC_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = snprintf(&buffer[offset], length, " \r\n");
|
||||
if (ret > 0 && (size_t)ret < length) {
|
||||
offset += ret;
|
||||
length -= ret;
|
||||
}
|
||||
else {
|
||||
LC_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
|
||||
currentEntry = currentEntry->next;
|
||||
}
|
||||
|
||||
// We should have only space for the null terminator left over
|
||||
LC_ASSERT(length == 1);
|
||||
return offset;
|
||||
}
|
||||
|
||||
@@ -64,7 +93,8 @@ static int addAttributeBinary(PSDP_OPTION* head, char* name, const void* payload
|
||||
|
||||
option->next = NULL;
|
||||
option->payloadLen = payloadLen;
|
||||
strcpy(option->name, name);
|
||||
strncpy(option->name, name, sizeof(option->name));
|
||||
option->name[sizeof(option->name) - 1] = '\0';
|
||||
option->payload = (void*)(option + 1);
|
||||
memcpy(option->payload, payload, payloadLen);
|
||||
|
||||
@@ -134,7 +164,7 @@ static int addGen4Options(PSDP_OPTION* head, char* addrStr) {
|
||||
int err = 0;
|
||||
|
||||
LC_ASSERT(RtspPortNumber != 0);
|
||||
sprintf(payloadStr, "rtsp://%s:%u", addrStr, RtspPortNumber);
|
||||
snprintf(payloadStr, sizeof(payloadStr), "rtsp://%s:%u", addrStr, RtspPortNumber);
|
||||
err |= addAttributeString(head, "x-nv-general.serverAddress", payloadStr);
|
||||
|
||||
return err;
|
||||
@@ -163,7 +193,7 @@ static int addGen5Options(PSDP_OPTION* head) {
|
||||
AudioEncryptionEnabled = true;
|
||||
}
|
||||
|
||||
sprintf(payloadStr, "%u", featureFlags);
|
||||
snprintf(payloadStr, sizeof(payloadStr), "%u", featureFlags);
|
||||
err |= addAttributeString(head, "x-nv-general.featureFlags", payloadStr);
|
||||
|
||||
// Ask for the encrypted control protocol to ensure remote input will be encrypted.
|
||||
@@ -236,19 +266,19 @@ static PSDP_OPTION getAttributesList(char*urlSafeAddr) {
|
||||
// Send client feature flags to Sunshine hosts
|
||||
if (IS_SUNSHINE()) {
|
||||
uint32_t moonlightFeatureFlags = ML_FF_FEC_STATUS;
|
||||
sprintf(payloadStr, "%u", moonlightFeatureFlags);
|
||||
snprintf(payloadStr, sizeof(payloadStr), "%u", moonlightFeatureFlags);
|
||||
err |= addAttributeString(&optionHead, "x-ml-general.featureFlags", payloadStr);
|
||||
}
|
||||
|
||||
sprintf(payloadStr, "%d", StreamConfig.width);
|
||||
snprintf(payloadStr, sizeof(payloadStr), "%d", StreamConfig.width);
|
||||
err |= addAttributeString(&optionHead, "x-nv-video[0].clientViewportWd", payloadStr);
|
||||
sprintf(payloadStr, "%d", StreamConfig.height);
|
||||
snprintf(payloadStr, sizeof(payloadStr), "%d", StreamConfig.height);
|
||||
err |= addAttributeString(&optionHead, "x-nv-video[0].clientViewportHt", payloadStr);
|
||||
|
||||
sprintf(payloadStr, "%d", StreamConfig.fps);
|
||||
snprintf(payloadStr, sizeof(payloadStr), "%d", StreamConfig.fps);
|
||||
err |= addAttributeString(&optionHead, "x-nv-video[0].maxFPS", payloadStr);
|
||||
|
||||
sprintf(payloadStr, "%d", StreamConfig.packetSize);
|
||||
snprintf(payloadStr, sizeof(payloadStr), "%d", StreamConfig.packetSize);
|
||||
err |= addAttributeString(&optionHead, "x-nv-video[0].packetSize", payloadStr);
|
||||
|
||||
err |= addAttributeString(&optionHead, "x-nv-video[0].rateControlMode", "4");
|
||||
@@ -287,7 +317,7 @@ static PSDP_OPTION getAttributesList(char*urlSafeAddr) {
|
||||
// settle on the optimal bitrate if it's somewhere in the middle), so we'll just latch the bitrate
|
||||
// to the requested value.
|
||||
if (AppVersionQuad[0] >= 5) {
|
||||
sprintf(payloadStr, "%d", bitrate);
|
||||
snprintf(payloadStr, sizeof(payloadStr), "%d", bitrate);
|
||||
|
||||
err |= addAttributeString(&optionHead, "x-nv-video[0].initialBitrateKbps", payloadStr);
|
||||
err |= addAttributeString(&optionHead, "x-nv-video[0].initialPeakBitrateKbps", payloadStr);
|
||||
@@ -301,7 +331,7 @@ static PSDP_OPTION getAttributesList(char*urlSafeAddr) {
|
||||
err |= addAttributeString(&optionHead, "x-nv-video[0].peakBitrate", "4");
|
||||
}
|
||||
|
||||
sprintf(payloadStr, "%d", bitrate);
|
||||
snprintf(payloadStr, sizeof(payloadStr), "%d", bitrate);
|
||||
err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.minimumBitrate", payloadStr);
|
||||
err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.maximumBitrate", payloadStr);
|
||||
}
|
||||
@@ -351,7 +381,7 @@ static PSDP_OPTION getAttributesList(char*urlSafeAddr) {
|
||||
// If not using slicing, we request 1 slice per frame
|
||||
slicesPerFrame = 1;
|
||||
}
|
||||
sprintf(payloadStr, "%d", slicesPerFrame);
|
||||
snprintf(payloadStr, sizeof(payloadStr), "%d", slicesPerFrame);
|
||||
err |= addAttributeString(&optionHead, "x-nv-video[0].videoEncoderSlicesPerFrame", payloadStr);
|
||||
|
||||
if (NegotiatedVideoFormat & VIDEO_FORMAT_MASK_AV1) {
|
||||
@@ -397,13 +427,13 @@ static PSDP_OPTION getAttributesList(char*urlSafeAddr) {
|
||||
err |= addAttributeString(&optionHead, "x-nv-video[0].maxNumReferenceFrames", "1");
|
||||
}
|
||||
|
||||
sprintf(payloadStr, "%d", StreamConfig.clientRefreshRateX100);
|
||||
snprintf(payloadStr, sizeof(payloadStr), "%d", StreamConfig.clientRefreshRateX100);
|
||||
err |= addAttributeString(&optionHead, "x-nv-video[0].clientRefreshRateX100", payloadStr);
|
||||
}
|
||||
|
||||
sprintf(payloadStr, "%d", audioChannelCount);
|
||||
snprintf(payloadStr, sizeof(payloadStr), "%d", audioChannelCount);
|
||||
err |= addAttributeString(&optionHead, "x-nv-audio.surround.numChannels", payloadStr);
|
||||
sprintf(payloadStr, "%d", audioChannelMask);
|
||||
snprintf(payloadStr, sizeof(payloadStr), "%d", audioChannelMask);
|
||||
err |= addAttributeString(&optionHead, "x-nv-audio.surround.channelMask", payloadStr);
|
||||
if (audioChannelCount > 2) {
|
||||
err |= addAttributeString(&optionHead, "x-nv-audio.surround.enable", "1");
|
||||
@@ -443,7 +473,7 @@ static PSDP_OPTION getAttributesList(char*urlSafeAddr) {
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(payloadStr, "%d", AudioPacketDuration);
|
||||
snprintf(payloadStr, sizeof(payloadStr), "%d", AudioPacketDuration);
|
||||
err |= addAttributeString(&optionHead, "x-nv-aqos.packetDuration", payloadStr);
|
||||
}
|
||||
else {
|
||||
@@ -455,7 +485,7 @@ static PSDP_OPTION getAttributesList(char*urlSafeAddr) {
|
||||
}
|
||||
|
||||
if (AppVersionQuad[0] >= 7) {
|
||||
sprintf(payloadStr, "%d", (StreamConfig.colorSpace << 1) | StreamConfig.colorRange);
|
||||
snprintf(payloadStr, sizeof(payloadStr), "%d", (StreamConfig.colorSpace << 1) | StreamConfig.colorRange);
|
||||
err |= addAttributeString(&optionHead, "x-nv-video[0].encoderCscMode", payloadStr);
|
||||
}
|
||||
|
||||
@@ -468,8 +498,8 @@ static PSDP_OPTION getAttributesList(char*urlSafeAddr) {
|
||||
}
|
||||
|
||||
// Populate the SDP header with required information
|
||||
static int fillSdpHeader(char* buffer, int rtspClientVersion, char*urlSafeAddr) {
|
||||
return sprintf(buffer,
|
||||
static int fillSdpHeader(char* buffer, size_t length, int rtspClientVersion, char*urlSafeAddr) {
|
||||
return snprintf(buffer, length,
|
||||
"v=0\r\n"
|
||||
"o=android 0 %d IN %s %s\r\n"
|
||||
"s=NVIDIA Streaming Client\r\n",
|
||||
@@ -479,9 +509,9 @@ static int fillSdpHeader(char* buffer, int rtspClientVersion, char*urlSafeAddr)
|
||||
}
|
||||
|
||||
// Populate the SDP tail with required information
|
||||
static int fillSdpTail(char* buffer) {
|
||||
static int fillSdpTail(char* buffer, size_t length) {
|
||||
LC_ASSERT(VideoPortNumber != 0);
|
||||
return sprintf(buffer,
|
||||
return snprintf(buffer, length,
|
||||
"t=0 0\r\n"
|
||||
"m=video %d \r\n",
|
||||
AppVersionQuad[0] < 4 ? 47996 : VideoPortNumber);
|
||||
@@ -490,7 +520,8 @@ static int fillSdpTail(char* buffer) {
|
||||
// Get the SDP attributes for the stream config
|
||||
char* getSdpPayloadForStreamConfig(int rtspClientVersion, int* length) {
|
||||
PSDP_OPTION attributeList;
|
||||
int offset;
|
||||
int attributeListSize;
|
||||
int offset, written;
|
||||
char* payload;
|
||||
char urlSafeAddr[URLSAFESTRING_LEN];
|
||||
|
||||
@@ -501,16 +532,41 @@ char* getSdpPayloadForStreamConfig(int rtspClientVersion, int* length) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
payload = malloc(MAX_SDP_HEADER_LEN + MAX_SDP_TAIL_LEN +
|
||||
getSerializedAttributeListSize(attributeList));
|
||||
attributeListSize = getSerializedAttributeListSize(attributeList);
|
||||
payload = malloc(MAX_SDP_HEADER_LEN + MAX_SDP_TAIL_LEN + attributeListSize);
|
||||
if (payload == NULL) {
|
||||
freeAttributeList(attributeList);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
offset = fillSdpHeader(payload, rtspClientVersion, urlSafeAddr);
|
||||
offset += fillSerializedAttributeList(&payload[offset], attributeList);
|
||||
offset += fillSdpTail(&payload[offset]);
|
||||
offset = 0;
|
||||
written = fillSdpHeader(payload, MAX_SDP_HEADER_LEN, rtspClientVersion, urlSafeAddr);
|
||||
if (written < 0 || written >= MAX_SDP_HEADER_LEN) {
|
||||
LC_ASSERT(false);
|
||||
freeAttributeList(attributeList);
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
offset += written;
|
||||
}
|
||||
written = fillSerializedAttributeList(&payload[offset], attributeListSize, attributeList);
|
||||
if (written < 0 || written >= attributeListSize) {
|
||||
LC_ASSERT(false);
|
||||
freeAttributeList(attributeList);
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
offset += written;
|
||||
}
|
||||
written = fillSdpTail(&payload[offset], MAX_SDP_TAIL_LEN);
|
||||
if (written < 0 || written >= MAX_SDP_TAIL_LEN) {
|
||||
LC_ASSERT(false);
|
||||
freeAttributeList(attributeList);
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
offset += written;
|
||||
}
|
||||
|
||||
freeAttributeList(attributeList);
|
||||
*length = offset;
|
||||
|
||||
Reference in New Issue
Block a user