Use connected datagram sockets for audio and video

This ensures unwanted data from other sources is dropped and that our own source address doesn't change while streaming.
This commit is contained in:
Cameron Gutman 2023-09-12 23:29:05 -05:00
parent ec6713fd80
commit c13f4a323f
4 changed files with 38 additions and 17 deletions

View File

@ -37,12 +37,6 @@ typedef struct _QUEUED_AUDIO_PACKET {
static void AudioPingThreadProc(void* context) {
char legacyPingData[] = { 0x50, 0x49, 0x4E, 0x47 };
LC_SOCKADDR saddr;
LC_ASSERT(AudioPortNumber != 0);
memcpy(&saddr, &RemoteAddr, sizeof(saddr));
SET_PORT(&saddr, AudioPortNumber);
// We do not check for errors here. Socket errors will be handled
// on the read-side in ReceiveThreadProc(). This avoids potential
@ -54,10 +48,10 @@ static void AudioPingThreadProc(void* context) {
pingCount++;
AudioPingPayload.sequenceNumber = BE32(pingCount);
sendto(rtpSocket, (char*)&AudioPingPayload, sizeof(AudioPingPayload), 0, (struct sockaddr*)&saddr, RemoteAddrLen);
send(rtpSocket, (char*)&AudioPingPayload, sizeof(AudioPingPayload), 0);
}
else {
sendto(rtpSocket, legacyPingData, sizeof(legacyPingData), 0, (struct sockaddr*)&saddr, RemoteAddrLen);
send(rtpSocket, legacyPingData, sizeof(legacyPingData), 0);
}
PltSleepMsInterruptible(&udpPingThread, 500);
@ -98,9 +92,15 @@ int notifyAudioPortNegotiationComplete(void) {
LC_ASSERT(!pingThreadStarted);
LC_ASSERT(AudioPortNumber != 0);
// Connect our audio socket to the target address and port
int err = connectUdpSocket(rtpSocket, &RemoteAddr, RemoteAddrLen, AudioPortNumber);
if (err != 0) {
return err;
}
// We may receive audio before our threads are started, but that's okay. We'll
// drop the first 1 second of audio packets to catch up with the backlog.
int err = PltCreateThread("AudioPing", AudioPingThreadProc, NULL, &udpPingThread);
err = PltCreateThread("AudioPing", AudioPingThreadProc, NULL, &udpPingThread);
if (err != 0) {
return err;
}

View File

@ -309,6 +309,23 @@ SOCKET bindUdpSocket(int addrfamily, int bufferSize) {
return s;
}
int connectUdpSocket(SOCKET s, struct sockaddr_storage* dstaddr, SOCKADDR_LEN addrlen, unsigned short port) {
int err;
LC_SOCKADDR saddr;
LC_ASSERT(port != 0);
memcpy(&saddr, dstaddr, addrlen);
SET_PORT(&saddr, port);
err = connect(s, (struct sockaddr*)&saddr, addrlen);
if (err < 0) {
Limelog("connect() failed for UDP socket: %d\n", (int)LastSocketError());
return LastSocketFail();
}
return 0;
}
int setSocketNonBlocking(SOCKET s, bool enabled) {
#if defined(__vita__)
int val = enabled ? 1 : 0;

View File

@ -86,6 +86,7 @@ void addrToUrlSafeString(struct sockaddr_storage* addr, char* string);
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 connectUdpSocket(SOCKET s, struct sockaddr_storage* dstaddr, SOCKADDR_LEN addrlen, unsigned short port);
int sendMtuSafe(SOCKET s, char* buffer, int size);
SOCKET bindUdpSocket(int addrfamily, int bufferSize);
int enableNoDelay(SOCKET s);

View File

@ -50,12 +50,6 @@ void destroyVideoStream(void) {
// UDP Ping proc
static void VideoPingThreadProc(void* context) {
char legacyPingData[] = { 0x50, 0x49, 0x4E, 0x47 };
LC_SOCKADDR saddr;
LC_ASSERT(VideoPortNumber != 0);
memcpy(&saddr, &RemoteAddr, sizeof(saddr));
SET_PORT(&saddr, VideoPortNumber);
// We do not check for errors here. Socket errors will be handled
// on the read-side in ReceiveThreadProc(). This avoids potential
@ -67,10 +61,10 @@ static void VideoPingThreadProc(void* context) {
pingCount++;
VideoPingPayload.sequenceNumber = BE32(pingCount);
sendto(rtpSocket, (char*)&VideoPingPayload, sizeof(VideoPingPayload), 0, (struct sockaddr*)&saddr, RemoteAddrLen);
send(rtpSocket, (char*)&VideoPingPayload, sizeof(VideoPingPayload), 0);
}
else {
sendto(rtpSocket, legacyPingData, sizeof(legacyPingData), 0, (struct sockaddr*)&saddr, RemoteAddrLen);
send(rtpSocket, legacyPingData, sizeof(legacyPingData), 0);
}
PltSleepMsInterruptible(&udpPingThread, 500);
@ -271,6 +265,15 @@ int startVideoStream(void* rendererContext, int drFlags) {
return LastSocketError();
}
// Connect our video socket to the target address and port
LC_ASSERT(VideoPortNumber != 0);
err = connectUdpSocket(rtpSocket, &RemoteAddr, RemoteAddrLen, VideoPortNumber);
if (err != 0) {
VideoCallbacks.cleanup();
closeSocket(rtpSocket);
return err;
}
VideoCallbacks.start();
err = PltCreateThread("VideoRecv", VideoReceiveThreadProc, NULL, &receiveThread);