mirror of
https://github.com/moonlight-stream/moonlight-common-c.git
synced 2025-07-01 15:25:43 +00:00
Add basic QoS attributes to our A/V sockets
This commit is contained in:
parent
68153174bc
commit
c0e3dc64a4
@ -93,7 +93,7 @@ int notifyAudioPortNegotiationComplete(void) {
|
|||||||
|
|
||||||
// For GFE 3.22 compatibility, we must start the audio ping thread before the RTSP handshake.
|
// 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.
|
// It will not reply to our RTSP PLAY request until the audio ping has been received.
|
||||||
rtpSocket = bindUdpSocket(RemoteAddr.ss_family, &LocalAddr, AddrLen, 0);
|
rtpSocket = bindUdpSocket(RemoteAddr.ss_family, &LocalAddr, AddrLen, 0, SOCK_QOS_TYPE_AUDIO);
|
||||||
if (rtpSocket == INVALID_SOCKET) {
|
if (rtpSocket == INVALID_SOCKET) {
|
||||||
return LastSocketFail();
|
return LastSocketFail();
|
||||||
}
|
}
|
||||||
|
@ -235,7 +235,56 @@ void closeSocket(SOCKET s) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SOCKET bindUdpSocket(int addressFamily, struct sockaddr_storage* localAddr, SOCKADDR_LEN addrLen, int bufferSize) {
|
// These set "safe" host or link-local QoS options that we can unconditionally
|
||||||
|
// set without having to worry about routers blockholing the traffic.
|
||||||
|
static void setSocketQos(SOCKET s, int socketQosType) {
|
||||||
|
#ifdef SO_NET_SERVICE_TYPE
|
||||||
|
int value;
|
||||||
|
switch (socketQosType) {
|
||||||
|
case SOCK_QOS_TYPE_BEST_EFFORT:
|
||||||
|
value = NET_SERVICE_TYPE_BE;
|
||||||
|
break;
|
||||||
|
case SOCK_QOS_TYPE_AUDIO:
|
||||||
|
value = NET_SERVICE_TYPE_VO;
|
||||||
|
break;
|
||||||
|
case SOCK_QOS_TYPE_VIDEO:
|
||||||
|
value = NET_SERVICE_TYPE_VI;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Limelog("Unknown QoS type: %d\n", socketQosType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// iOS/macOS
|
||||||
|
if (setsockopt(s, SOL_SOCKET, SO_NET_SERVICE_TYPE, (char*)&value, sizeof(value)) < 0) {
|
||||||
|
Limelog("setsockopt(SO_NET_SERVICE_TYPE, %d) failed: %d\n", value, (int)LastSocketError());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef SO_PRIORITY
|
||||||
|
int value;
|
||||||
|
switch (socketQosType) {
|
||||||
|
case SOCK_QOS_TYPE_BEST_EFFORT:
|
||||||
|
value = 0;
|
||||||
|
break;
|
||||||
|
case SOCK_QOS_TYPE_AUDIO:
|
||||||
|
value = 6;
|
||||||
|
break;
|
||||||
|
case SOCK_QOS_TYPE_VIDEO:
|
||||||
|
value = 5;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Limelog("Unknown QoS type: %d\n", socketQosType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Linux
|
||||||
|
if (setsockopt(s, SOL_SOCKET, SO_PRIORITY, (char*)&value, sizeof(value)) < 0) {
|
||||||
|
Limelog("setsockopt(SO_PRIORITY, %d) failed: %d\n", value, (int)LastSocketError());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
SOCKET bindUdpSocket(int addressFamily, struct sockaddr_storage* localAddr, SOCKADDR_LEN addrLen, int bufferSize, int socketQosType) {
|
||||||
SOCKET s;
|
SOCKET s;
|
||||||
LC_SOCKADDR bindAddr;
|
LC_SOCKADDR bindAddr;
|
||||||
int err;
|
int err;
|
||||||
@ -294,6 +343,11 @@ SOCKET bindUdpSocket(int addressFamily, struct sockaddr_storage* localAddr, SOCK
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Enable QOS for the socket (best effort)
|
||||||
|
if (socketQosType != SOCK_QOS_TYPE_BEST_EFFORT) {
|
||||||
|
setSocketQos(s, socketQosType);
|
||||||
|
}
|
||||||
|
|
||||||
if (bufferSize != 0) {
|
if (bufferSize != 0) {
|
||||||
// We start at the requested recv buffer value and step down until we find
|
// We start at the requested recv buffer value and step down until we find
|
||||||
// a value that the OS will accept.
|
// a value that the OS will accept.
|
||||||
|
@ -95,10 +95,14 @@ typedef struct sockaddr_in LC_SOCKADDR;
|
|||||||
#endif
|
#endif
|
||||||
void addrToUrlSafeString(struct sockaddr_storage* addr, char* string, size_t stringLength);
|
void addrToUrlSafeString(struct sockaddr_storage* addr, char* string, size_t stringLength);
|
||||||
|
|
||||||
|
#define SOCK_QOS_TYPE_BEST_EFFORT 0
|
||||||
|
#define SOCK_QOS_TYPE_AUDIO 1
|
||||||
|
#define SOCK_QOS_TYPE_VIDEO 2
|
||||||
|
|
||||||
SOCKET createSocket(int addressFamily, int socketType, int protocol, bool nonBlocking);
|
SOCKET createSocket(int addressFamily, int socketType, int protocol, bool nonBlocking);
|
||||||
SOCKET connectTcpSocket(struct sockaddr_storage* dstaddr, SOCKADDR_LEN addrlen, unsigned short port, int timeoutSec);
|
SOCKET connectTcpSocket(struct sockaddr_storage* dstaddr, SOCKADDR_LEN addrlen, unsigned short port, int timeoutSec);
|
||||||
int sendMtuSafe(SOCKET s, char* buffer, int size);
|
int sendMtuSafe(SOCKET s, char* buffer, int size);
|
||||||
SOCKET bindUdpSocket(int addressFamily, struct sockaddr_storage* localAddr, SOCKADDR_LEN addrLen, int bufferSize);
|
SOCKET bindUdpSocket(int addressFamily, struct sockaddr_storage* localAddr, SOCKADDR_LEN addrLen, int bufferSize, int socketQosType);
|
||||||
int enableNoDelay(SOCKET s);
|
int enableNoDelay(SOCKET s);
|
||||||
int setSocketNonBlocking(SOCKET s, bool enabled);
|
int setSocketNonBlocking(SOCKET s, bool enabled);
|
||||||
int recvUdpSocket(SOCKET s, char* buffer, int size, bool useSelect);
|
int recvUdpSocket(SOCKET s, char* buffer, int size, bool useSelect);
|
||||||
|
@ -73,7 +73,7 @@ int LiFindExternalAddressIP4(const char* stunServer, unsigned short stunPort, un
|
|||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
sock = bindUdpSocket(hints.ai_family, NULL, 0, 0);
|
sock = bindUdpSocket(hints.ai_family, NULL, 0, 0, SOCK_QOS_TYPE_BEST_EFFORT);
|
||||||
if (sock == INVALID_SOCKET) {
|
if (sock == INVALID_SOCKET) {
|
||||||
err = LastSocketFail();
|
err = LastSocketFail();
|
||||||
Limelog("Failed to connect to STUN server: %d\n", err);
|
Limelog("Failed to connect to STUN server: %d\n", err);
|
||||||
|
@ -337,7 +337,8 @@ int startVideoStream(void* rendererContext, int drFlags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rtpSocket = bindUdpSocket(RemoteAddr.ss_family, &LocalAddr, AddrLen,
|
rtpSocket = bindUdpSocket(RemoteAddr.ss_family, &LocalAddr, AddrLen,
|
||||||
RTP_RECV_PACKETS_BUFFERED * (StreamConfig.packetSize + MAX_RTP_HEADER_SIZE));
|
RTP_RECV_PACKETS_BUFFERED * (StreamConfig.packetSize + MAX_RTP_HEADER_SIZE),
|
||||||
|
SOCK_QOS_TYPE_VIDEO);
|
||||||
if (rtpSocket == INVALID_SOCKET) {
|
if (rtpSocket == INVALID_SOCKET) {
|
||||||
VideoCallbacks.cleanup();
|
VideoCallbacks.cleanup();
|
||||||
return LastSocketError();
|
return LastSocketError();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user