Skip to content

Commit

Permalink
Enable ECN/L4S on Windows 10
Browse files Browse the repository at this point in the history
  • Loading branch information
cgutman committed Feb 3, 2024
1 parent a754295 commit 04e2759
Showing 1 changed file with 54 additions and 17 deletions.
71 changes: 54 additions & 17 deletions win32.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "enet/enet.h"
#include <windows.h>
#include <Mswsock.h>
#include <VersionHelpers.h>
#ifndef HAS_QOS_FLOWID
typedef UINT32 QOS_FLOWID;
#endif
Expand All @@ -19,14 +20,6 @@ typedef UINT32 *PQOS_FLOWID;
#define QOS_NON_ADAPTIVE_FLOW 0x00000002
#endif

// This is missing from MinGW headers
#ifndef IN6ADDR_V4MAPPEDPREFIX_INIT
#define IN6ADDR_V4MAPPEDPREFIX_INIT { \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0xff, 0xff, \
}
#endif

static enet_uint32 timeBase = 0;

#if !(defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP)
Expand All @@ -38,6 +31,7 @@ static enet_uint32 timeBase = 0;
static HANDLE qosHandle = INVALID_HANDLE_VALUE;
static QOS_FLOWID qosFlowId;
static BOOL qosAddedFlow;
static BOOL enableEcn;

static HMODULE QwaveLibraryHandle;

Expand Down Expand Up @@ -93,6 +87,7 @@ enet_deinitialize (void)
#ifdef HAS_QWAVE
qosAddedFlow = FALSE;
qosFlowId = 0;
enableEcn = FALSE;

if (qosHandle != INVALID_HANDLE_VALUE)
{
Expand Down Expand Up @@ -330,6 +325,9 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)

case ENET_SOCKOPT_QOS:
{
// Enable ECN marking on Windows 10 if QOS is enabled
enableEcn = value != 0 && IsWindows10OrGreater();

#ifdef HAS_QWAVE
if (value)
{
Expand Down Expand Up @@ -440,14 +438,14 @@ enet_socket_send (ENetSocket socket,
DWORD sentLength;
WSAMSG msg = { 0 };
char controlBufData[1024];
PWSACMSGHDR chdr = NULL;

#ifdef HAS_QWAVE
if (!qosAddedFlow && qosHandle != INVALID_HANDLE_VALUE)
{
static const char V4_MAPPED_V6_PREFIX[] = IN6ADDR_V4MAPPEDPREFIX_INIT;

BOOL isV4MappedV6Addr =
peerAddress->address.ss_family == AF_INET6 &&
!memcmp(&((PSOCKADDR_IN6)&peerAddress->address)->sin6_addr, V4_MAPPED_V6_PREFIX, sizeof(V4_MAPPED_V6_PREFIX));
IN6_IS_ADDR_V4MAPPED(&((PSOCKADDR_IN6)&peerAddress->address)->sin6_addr);

// qWAVE doesn't properly support IPv4-mapped IPv6 addresses, nor does it
// correctly support IPv4 addresses on a dual-stack socket (despite MSDN's
Expand Down Expand Up @@ -478,8 +476,8 @@ enet_socket_send (ENetSocket socket,
}
#endif

msg.name = peerAddress != NULL ? (struct sockaddr *) & peerAddress -> address : NULL;
msg.namelen = peerAddress != NULL ? peerAddress -> addressLength : 0;
msg.name = (struct sockaddr *) & peerAddress -> address;
msg.namelen = peerAddress -> addressLength;
msg.lpBuffers = (LPWSABUF) buffers;
msg.dwBufferCount = (DWORD) bufferCount;

Expand All @@ -494,9 +492,14 @@ enet_socket_send (ENetSocket socket,
pktInfo.ipi_ifindex = 0; // Unspecified

msg.Control.buf = controlBufData;
msg.Control.len = WSA_CMSG_SPACE(sizeof(pktInfo));
msg.Control.len += WSA_CMSG_SPACE(sizeof(pktInfo));
if (chdr == NULL) {
chdr = WSA_CMSG_FIRSTHDR(&msg);
}
else {
chdr = WSA_CMSG_NXTHDR(&msg, chdr);
}

PWSACMSGHDR chdr = WSA_CMSG_FIRSTHDR(&msg);
chdr->cmsg_level = IPPROTO_IP;
chdr->cmsg_type = IP_PKTINFO;
chdr->cmsg_len = WSA_CMSG_LEN(sizeof(pktInfo));
Expand All @@ -509,16 +512,50 @@ enet_socket_send (ENetSocket socket,
pktInfo.ipi6_ifindex = 0; // Unspecified

msg.Control.buf = controlBufData;
msg.Control.len = WSA_CMSG_SPACE(sizeof(pktInfo));
msg.Control.len += WSA_CMSG_SPACE(sizeof(pktInfo));
if (chdr == NULL) {
chdr = WSA_CMSG_FIRSTHDR(&msg);
}
else {
chdr = WSA_CMSG_NXTHDR(&msg, chdr);
}

PWSACMSGHDR chdr = WSA_CMSG_FIRSTHDR(&msg);
chdr->cmsg_level = IPPROTO_IPV6;
chdr->cmsg_type = IPV6_PKTINFO;
chdr->cmsg_len = WSA_CMSG_LEN(sizeof(pktInfo));
memcpy(WSA_CMSG_DATA(chdr), &pktInfo, sizeof(pktInfo));
}
}

// This is a bit of a hack because it's not really per-socket or
// per-destination, but it is fine for our current usage of ENet
// in Moonlight and Sunshine where only a single socket is used.
if (enableEcn) {
BOOL isV4MappedV6Addr =
peerAddress->address.ss_family == AF_INET6 &&
IN6_IS_ADDR_V4MAPPED(&((PSOCKADDR_IN6)&peerAddress->address)->sin6_addr);

msg.Control.buf = controlBufData;
msg.Control.len += WSA_CMSG_SPACE(sizeof(INT));
if (chdr == NULL) {
chdr = WSA_CMSG_FIRSTHDR(&msg);
}
else {
chdr = WSA_CMSG_NXTHDR(&msg, chdr);
}

if (peerAddress->address.ss_family == AF_INET || isV4MappedV6Addr) {
chdr->cmsg_level = IPPROTO_IP;
chdr->cmsg_type = IP_ECN;
}
else {
chdr->cmsg_level = IPPROTO_IPV6;
chdr->cmsg_type = IPV6_ECN;
}
chdr->cmsg_len = WSA_CMSG_LEN(sizeof(INT));
*(PINT)WSA_CMSG_DATA(chdr) = 0x01; // ECT(1) (L4S)
}

if (WSASendMsg (socket,
& msg,
0,
Expand Down

0 comments on commit 04e2759

Please sign in to comment.