Skip to content

Commit

Permalink
Merge branch 'moonlight-stream:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
Nika0000 authored Nov 2, 2023
2 parents bd9e475 + 5de4a5b commit 8083972
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 77 deletions.
28 changes: 14 additions & 14 deletions src/AudioStream.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ 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
Expand All @@ -48,10 +54,10 @@ static void AudioPingThreadProc(void* context) {
pingCount++;
AudioPingPayload.sequenceNumber = BE32(pingCount);

send(rtpSocket, (char*)&AudioPingPayload, sizeof(AudioPingPayload), 0);
sendto(rtpSocket, (char*)&AudioPingPayload, sizeof(AudioPingPayload), 0, (struct sockaddr*)&saddr, AddrLen);
}
else {
send(rtpSocket, legacyPingData, sizeof(legacyPingData), 0);
sendto(rtpSocket, legacyPingData, sizeof(legacyPingData), 0, (struct sockaddr*)&saddr, AddrLen);
}

PltSleepMsInterruptible(&udpPingThread, 500);
Expand All @@ -75,13 +81,6 @@ int initializeAudioStream(void) {
memcpy(&avRiKeyId, StreamConfig.remoteInputAesIv, sizeof(avRiKeyId));
avRiKeyId = BE32(avRiKeyId);

// For GFE 3.22 compatibility, we must start the audio ping thread before the RTSP handshake.
// It will not reply to our RTSP PLAY request until the audio ping has been received.
rtpSocket = bindUdpSocket(RemoteAddr.ss_family, 0);
if (rtpSocket == INVALID_SOCKET) {
return LastSocketFail();
}

return 0;
}

Expand All @@ -92,15 +91,16 @@ 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;
// For GFE 3.22 compatibility, we must start the audio ping thread before the RTSP handshake.
// It will not reply to our RTSP PLAY request until the audio ping has been received.
rtpSocket = bindUdpSocket(RemoteAddr.ss_family, &LocalAddr, AddrLen, 0);
if (rtpSocket == INVALID_SOCKET) {
return LastSocketFail();
}

// 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.
err = PltCreateThread("AudioPing", AudioPingThreadProc, NULL, &udpPingThread);
int err = PltCreateThread("AudioPing", AudioPingThreadProc, NULL, &udpPingThread);
if (err != 0) {
return err;
}
Expand Down
14 changes: 8 additions & 6 deletions src/Connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ static int terminationCallbackErrorCode;
// Common globals
char* RemoteAddrString;
struct sockaddr_storage RemoteAddr;
SOCKADDR_LEN RemoteAddrLen;
struct sockaddr_storage LocalAddr;
SOCKADDR_LEN AddrLen;
int AppVersionQuad[4];
STREAM_CONFIGURATION StreamConfig;
CONNECTION_LISTENER_CALLBACKS ListenerCallbacks;
Expand Down Expand Up @@ -254,6 +255,7 @@ int LiStartConnection(PSERVER_INFORMATION serverInfo, PSTREAM_CONFIGURATION stre
memcpy(&ListenerCallbacks, clCallbacks, sizeof(ListenerCallbacks));
ListenerCallbacks.connectionTerminated = ClInternalConnectionTerminated;

memset(&LocalAddr, 0, sizeof(LocalAddr));
NegotiatedVideoFormat = 0;
memcpy(&StreamConfig, streamConfig, sizeof(StreamConfig));
OriginalVideoBitrate = streamConfig->bitrate;
Expand Down Expand Up @@ -344,13 +346,13 @@ int LiStartConnection(PSERVER_INFORMATION serverInfo, PSTREAM_CONFIGURATION stre
if (RtspPortNumber != 48010) {
// If we have an alternate RTSP port, use that as our test port. The host probably
// isn't listening on 47989 or 47984 anyway, since they're using alternate ports.
err = resolveHostName(serverInfo->address, AF_UNSPEC, RtspPortNumber, &RemoteAddr, &RemoteAddrLen);
err = resolveHostName(serverInfo->address, AF_UNSPEC, RtspPortNumber, &RemoteAddr, &AddrLen);
if (err != 0) {
// Sleep for a second and try again. It's possible that we've attempt to connect
// before the host has gotten around to listening on the RTSP port. Give it some
// time before retrying.
PltSleepMs(1000);
err = resolveHostName(serverInfo->address, AF_UNSPEC, RtspPortNumber, &RemoteAddr, &RemoteAddrLen);
err = resolveHostName(serverInfo->address, AF_UNSPEC, RtspPortNumber, &RemoteAddr, &AddrLen);
}
}
else {
Expand All @@ -360,12 +362,12 @@ int LiStartConnection(PSERVER_INFORMATION serverInfo, PSTREAM_CONFIGURATION stre
// TCP 48010 is a last resort because:
// a) it's not always listening and there's a race between listen() on the host and our connect()
// b) it's not used at all by certain host versions which perform RTSP over ENet
err = resolveHostName(serverInfo->address, AF_UNSPEC, 47984, &RemoteAddr, &RemoteAddrLen);
err = resolveHostName(serverInfo->address, AF_UNSPEC, 47984, &RemoteAddr, &AddrLen);
if (err != 0) {
err = resolveHostName(serverInfo->address, AF_UNSPEC, 47989, &RemoteAddr, &RemoteAddrLen);
err = resolveHostName(serverInfo->address, AF_UNSPEC, 47989, &RemoteAddr, &AddrLen);
}
if (err != 0) {
err = resolveHostName(serverInfo->address, AF_UNSPEC, 48010, &RemoteAddr, &RemoteAddrLen);
err = resolveHostName(serverInfo->address, AF_UNSPEC, 48010, &RemoteAddr, &AddrLen);
}
}
if (err != 0) {
Expand Down
17 changes: 11 additions & 6 deletions src/ControlStream.c
Original file line number Diff line number Diff line change
Expand Up @@ -1592,16 +1592,21 @@ int startControlStream(void) {
int err;

if (AppVersionQuad[0] >= 5) {
ENetAddress address;
ENetAddress remoteAddress, localAddress;
ENetEvent event;

LC_ASSERT(ControlPortNumber != 0);

enet_address_set_address(&address, (struct sockaddr *)&RemoteAddr, RemoteAddrLen);
enet_address_set_port(&address, ControlPortNumber);
enet_address_set_address(&localAddress, (struct sockaddr *)&LocalAddr, AddrLen);
enet_address_set_port(&localAddress, 0); // Wildcard port

enet_address_set_address(&remoteAddress, (struct sockaddr *)&RemoteAddr, AddrLen);
enet_address_set_port(&remoteAddress, ControlPortNumber);

// Create a client
client = enet_host_create(address.address.ss_family, NULL, 1, CTRL_CHANNEL_COUNT, 0, 0);
client = enet_host_create(RemoteAddr.ss_family,
LocalAddr.ss_family != 0 ? &localAddress : NULL,
1, CTRL_CHANNEL_COUNT, 0, 0);
if (client == NULL) {
stopping = true;
return -1;
Expand All @@ -1616,7 +1621,7 @@ int startControlStream(void) {
enet_socket_set_option (client->socket, ENET_SOCKOPT_QOS, 1);

// Connect to the host
peer = enet_host_connect(client, &address, CTRL_CHANNEL_COUNT, 0);
peer = enet_host_connect(client, &remoteAddress, CTRL_CHANNEL_COUNT, 0);
if (peer == NULL) {
stopping = true;
enet_host_destroy(client);
Expand Down Expand Up @@ -1665,7 +1670,7 @@ int startControlStream(void) {
else {
// NB: Do NOT use ControlPortNumber here. 47995 is correct for these old versions.
LC_ASSERT(ControlPortNumber == 0);
ctlSock = connectTcpSocket(&RemoteAddr, RemoteAddrLen,
ctlSock = connectTcpSocket(&RemoteAddr, AddrLen,
47995, CONTROL_STREAM_TIMEOUT_SEC);
if (ctlSock == INVALID_SOCKET) {
stopping = true;
Expand Down
2 changes: 1 addition & 1 deletion src/InputStream.c
Original file line number Diff line number Diff line change
Expand Up @@ -699,7 +699,7 @@ int startInputStream(void) {

// After Gen 5, we send input on the control stream
if (AppVersionQuad[0] < 5) {
inputSock = connectTcpSocket(&RemoteAddr, RemoteAddrLen,
inputSock = connectTcpSocket(&RemoteAddr, AddrLen,
35043, INPUT_STREAM_TIMEOUT_SEC);
if (inputSock == INVALID_SOCKET) {
return LastSocketFail();
Expand Down
3 changes: 2 additions & 1 deletion src/Limelight-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
// Common globals
extern char* RemoteAddrString;
extern struct sockaddr_storage RemoteAddr;
extern SOCKADDR_LEN RemoteAddrLen;
extern struct sockaddr_storage LocalAddr;
extern SOCKADDR_LEN AddrLen;
extern int AppVersionQuad[4];
extern STREAM_CONFIGURATION StreamConfig;
extern CONNECTION_LISTENER_CALLBACKS ListenerCallbacks;
Expand Down
53 changes: 22 additions & 31 deletions src/PlatformSockets.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,28 +220,36 @@ void closeSocket(SOCKET s) {
#endif
}

SOCKET bindUdpSocket(int addrfamily, int bufferSize) {
SOCKET bindUdpSocket(int addressFamily, struct sockaddr_storage* localAddr, SOCKADDR_LEN addrLen, int bufferSize) {
SOCKET s;
struct sockaddr_storage addr;
LC_SOCKADDR bindAddr;
int err;
SOCKADDR_LEN addrLen;

s = createSocket(addressFamily, SOCK_DGRAM, IPPROTO_UDP, false);
if (s == INVALID_SOCKET) {
return INVALID_SOCKET;
}

// Use localAddr to bind if it was provided
if (localAddr && localAddr->ss_family != 0) {
memcpy(&bindAddr, localAddr, addrLen);
SET_PORT(&bindAddr, 0);
}
else {
// Otherwise wildcard bind to the specified address family
memset(&bindAddr, 0, sizeof(bindAddr));
SET_FAMILY(&bindAddr, addressFamily);

#ifdef AF_INET6
LC_ASSERT(addrfamily == AF_INET || addrfamily == AF_INET6);
addrLen = (addrfamily == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6));
LC_ASSERT(addressFamily == AF_INET || addressFamily == AF_INET6);
addrLen = (addressFamily == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6));
#else
LC_ASSERT(addrfamily == AF_INET);
addrLen = sizeof(struct sockaddr_in);
LC_ASSERT(addressFamily == AF_INET);
addrLen = sizeof(struct sockaddr_in);
#endif

s = createSocket(addrfamily, SOCK_DGRAM, IPPROTO_UDP, false);
if (s == INVALID_SOCKET) {
return INVALID_SOCKET;
}

memset(&addr, 0, sizeof(addr));
addr.ss_family = addrfamily;
if (bind(s, (struct sockaddr*) &addr, addrLen) == SOCKET_ERROR) {
if (bind(s, (struct sockaddr*) &bindAddr, addrLen) == SOCKET_ERROR) {
err = LastSocketError();
Limelog("bind() failed: %d\n", err);
closeSocket(s);
Expand Down Expand Up @@ -309,23 +317,6 @@ 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;
Expand Down
5 changes: 3 additions & 2 deletions src/PlatformSockets.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,11 @@ typedef socklen_t SOCKADDR_LEN;

#ifdef AF_INET6
typedef struct sockaddr_in6 LC_SOCKADDR;
#define SET_FAMILY(addr, family) ((addr)->sin6_family = (family))
#define SET_PORT(addr, port) ((addr)->sin6_port = htons(port))
#else
typedef struct sockaddr_in LC_SOCKADDR;
#define SET_FAMILY(addr, family) ((addr)->sin_family = (family))
#define SET_PORT(addr, port) ((addr)->sin_port = htons(port))
#endif

Expand All @@ -86,9 +88,8 @@ 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 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);
SOCKET bindUdpSocket(int addressFamily, struct sockaddr_storage* localAddr, SOCKADDR_LEN addrLen, int bufferSize);
int enableNoDelay(SOCKET s);
int setSocketNonBlocking(SOCKET s, bool enabled);
int recvUdpSocket(SOCKET s, char* buffer, int size, bool useSelect);
Expand Down
16 changes: 14 additions & 2 deletions src/RtspConnection.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ static bool transactRtspMessageTcp(PRTSP_MESSAGE request, PRTSP_MESSAGE response
// returns HTTP 200 OK for the /launch request before the RTSP handshake port
// is listening.
do {
sock = connectTcpSocket(&RemoteAddr, RemoteAddrLen, RtspPortNumber, RTSP_CONNECT_TIMEOUT_SEC);
sock = connectTcpSocket(&RemoteAddr, AddrLen, RtspPortNumber, RTSP_CONNECT_TIMEOUT_SEC);
if (sock == INVALID_SOCKET) {
*error = LastSocketError();
if (*error == ECONNREFUSED) {
Expand Down Expand Up @@ -320,6 +320,18 @@ static bool transactRtspMessageTcp(PRTSP_MESSAGE request, PRTSP_MESSAGE response
Limelog("Failed to parse RTSP response\n");
}

// 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);
Expand Down Expand Up @@ -819,7 +831,7 @@ int performRtspHandshake(PSERVER_INFORMATION serverInfo) {
ENetAddress address;
ENetEvent event;

enet_address_set_address(&address, (struct sockaddr *)&RemoteAddr, RemoteAddrLen);
enet_address_set_address(&address, (struct sockaddr *)&RemoteAddr, AddrLen);
enet_address_set_port(&address, RtspPortNumber);

// Create a client that can use 1 outgoing connection and 1 channel
Expand Down
2 changes: 1 addition & 1 deletion src/SimpleStun.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ int LiFindExternalAddressIP4(const char* stunServer, unsigned short stunPort, un
goto Exit;
}

sock = bindUdpSocket(hints.ai_family, 0);
sock = bindUdpSocket(hints.ai_family, NULL, 0, 0);
if (sock == INVALID_SOCKET) {
err = LastSocketFail();
Limelog("Failed to connect to STUN server: %d\n", err);
Expand Down
24 changes: 11 additions & 13 deletions src/VideoStream.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ 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
Expand All @@ -61,10 +67,10 @@ static void VideoPingThreadProc(void* context) {
pingCount++;
VideoPingPayload.sequenceNumber = BE32(pingCount);

send(rtpSocket, (char*)&VideoPingPayload, sizeof(VideoPingPayload), 0);
sendto(rtpSocket, (char*)&VideoPingPayload, sizeof(VideoPingPayload), 0, (struct sockaddr*)&saddr, AddrLen);
}
else {
send(rtpSocket, legacyPingData, sizeof(legacyPingData), 0);
sendto(rtpSocket, legacyPingData, sizeof(legacyPingData), 0, (struct sockaddr*)&saddr, AddrLen);
}

PltSleepMsInterruptible(&udpPingThread, 500);
Expand Down Expand Up @@ -261,21 +267,13 @@ int startVideoStream(void* rendererContext, int drFlags) {
return err;
}

rtpSocket = bindUdpSocket(RemoteAddr.ss_family, RTP_RECV_PACKETS_BUFFERED * (StreamConfig.packetSize + MAX_RTP_HEADER_SIZE));
rtpSocket = bindUdpSocket(RemoteAddr.ss_family, &LocalAddr, AddrLen,
RTP_RECV_PACKETS_BUFFERED * (StreamConfig.packetSize + MAX_RTP_HEADER_SIZE));
if (rtpSocket == INVALID_SOCKET) {
VideoCallbacks.cleanup();
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);
Expand All @@ -301,7 +299,7 @@ int startVideoStream(void* rendererContext, int drFlags) {

if (AppVersionQuad[0] == 3) {
// Connect this socket to open port 47998 for our ping thread
firstFrameSocket = connectTcpSocket(&RemoteAddr, RemoteAddrLen,
firstFrameSocket = connectTcpSocket(&RemoteAddr, AddrLen,
FIRST_FRAME_PORT, FIRST_FRAME_TIMEOUT_SEC);
if (firstFrameSocket == INVALID_SOCKET) {
VideoCallbacks.stop();
Expand Down

0 comments on commit 8083972

Please sign in to comment.