From 5ddd53e17f9cae24604d2fe5289ddfdde05862ca Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Tue, 11 Aug 2020 22:10:42 -0700 Subject: [PATCH] Enable media streaming mode for 802.11 WLAN interfaces on Windows --- src/Platform.c | 4 +++ src/PlatformSockets.c | 64 +++++++++++++++++++++++++++++++++++++++++++ src/PlatformSockets.h | 5 ++++ 3 files changed, 73 insertions(+) diff --git a/src/Platform.c b/src/Platform.c index 71320cb..555ba88 100644 --- a/src/Platform.c +++ b/src/Platform.c @@ -386,10 +386,14 @@ int initializePlatform(void) { return err; } + enterLowLatencyMode(); + return 0; } void cleanupPlatform(void) { + exitLowLatencyMode(); + cleanupPlatformSockets(); enet_deinitialize(); diff --git a/src/PlatformSockets.c b/src/PlatformSockets.c index 8c59196..bb2ca0c 100644 --- a/src/PlatformSockets.c +++ b/src/PlatformSockets.c @@ -9,6 +9,10 @@ #define TCPv4_MSS 536 #define TCPv6_MSS 1220 +#if defined(LC_WINDOWS) +static HANDLE WlanHandle; +#endif + void addrToUrlSafeString(struct sockaddr_storage* addr, char* string) { char addrstr[INET6_ADDRSTRLEN]; @@ -508,6 +512,66 @@ int isPrivateNetworkAddress(struct sockaddr_storage* address) { return 0; } +// Enable platform-specific low latency options (best-effort) +void enterLowLatencyMode(void) { +#if defined(LC_WINDOWS) + DWORD negotiatedVersion; + PWLAN_INTERFACE_INFO_LIST wlanInterfaceList; + DWORD i; + + // Reduce timer period to increase wait precision + timeBeginPeriod(1); + + // Use the Vista+ WLAN API version + LC_ASSERT(WlanHandle == NULL); + if (WlanOpenHandle(WLAN_API_MAKE_VERSION(2, 0), NULL, &negotiatedVersion, &WlanHandle) != ERROR_SUCCESS) { + return; + } + + if (WlanEnumInterfaces(WlanHandle, NULL, &wlanInterfaceList) != ERROR_SUCCESS) { + WlanCloseHandle(WlanHandle, NULL); + WlanHandle = NULL; + return; + } + + for (i = 0; i < wlanInterfaceList->dwNumberOfItems; i++) { + if (wlanInterfaceList->InterfaceInfo[i].isState == wlan_interface_state_connected) { + DWORD error; + BOOL value; + + // Enable media streaming mode for 802.11 wireless interfaces to reduce latency and + // unneccessary background scanning operations that cause packet loss and jitter. + // + // https://docs.microsoft.com/en-us/windows-hardware/drivers/network/oid-wdi-set-connection-quality + // https://docs.microsoft.com/en-us/previous-versions/windows/hardware/wireless/native-802-11-media-streaming + value = TRUE; + error = WlanSetInterface(WlanHandle, &wlanInterfaceList->InterfaceInfo[i].InterfaceGuid, + wlan_intf_opcode_media_streaming_mode, sizeof(value), &value, NULL); + if (error == ERROR_SUCCESS) { + Limelog("WLAN interface %d is now in low latency mode\n", i); + } + } + } + + WlanFreeMemory(wlanInterfaceList); +#else +#endif +} + +void exitLowLatencyMode(void) { +#if defined(LC_WINDOWS) + // Closing our WLAN client handle will undo our optimizations + if (WlanHandle != NULL) { + WlanCloseHandle(WlanHandle, NULL); + WlanHandle = NULL; + } + + // Restore original timer period + timeEndPeriod(1); +#else +#endif +} + int initializePlatformSockets(void) { #if defined(LC_WINDOWS) WSADATA data; diff --git a/src/PlatformSockets.h b/src/PlatformSockets.h index 2d332ce..5bb106c 100644 --- a/src/PlatformSockets.h +++ b/src/PlatformSockets.h @@ -6,6 +6,8 @@ #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include +#include +#include #define SetLastSocketError(x) WSASetLastError(x) #define LastSocketError() WSAGetLastError() @@ -63,5 +65,8 @@ void closeSocket(SOCKET s); int isPrivateNetworkAddress(struct sockaddr_storage* address); int pollSockets(struct pollfd* pollFds, int pollFdsCount, int timeoutMs); +void enterLowLatencyMode(void); +void exitLowLatencyMode(void); + int initializePlatformSockets(void); void cleanupPlatformSockets(void);