Maelstrom: Updated to SDL_net 3.1.0 prerelease

From 8c5feb3cac6ee8fe2e160f7073450ed49235ea11 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 18 May 2026 22:34:25 -0700
Subject: [PATCH] Updated to SDL_net 3.1.0 prerelease

---
 external/SDL_net |   2 +-
 game/lobby.cpp   | 189 +----------------------------------------------
 game/netplay.cpp |   8 +-
 3 files changed, 8 insertions(+), 191 deletions(-)

diff --git a/external/SDL_net b/external/SDL_net
index 5af3b068..27dc45ae 160000
--- a/external/SDL_net
+++ b/external/SDL_net
@@ -1 +1 @@
-Subproject commit 5af3b068ea13f888be954801c0b8c17993811850
+Subproject commit 27dc45ae6e1f938bd31a76d23489c4f96f15ae28
diff --git a/game/lobby.cpp b/game/lobby.cpp
index 656a9e38..d04d2721 100644
--- a/game/lobby.cpp
+++ b/game/lobby.cpp
@@ -618,193 +618,6 @@ LobbyDialogDelegate::CheckPings()
 	}
 }
 
-#ifdef HAVE_GETIFADDRS
-static Uint32 SockAddrToUint32(struct sockaddr* a)
-{
-	return ((a) && (a->sa_family == AF_INET)) ? SDL_Swap32BE(((struct sockaddr_in*)a)->sin_addr.s_addr) : 0;
-}
-#endif
-
-#if defined(SDL_PLATFORM_WIN32) || defined(HAVE_GETIFADDRS)
-// convert a numeric IP address into its string representation
-static void Inet_NtoA(Uint32 addr, char *ipbuf, size_t maxlen)
-{
-	SDL_snprintf(ipbuf, maxlen, "%u.%u.%u.%u", (addr >> 24) & 0xFF, (addr >> 16) & 0xFF, (addr >> 8) & 0xFF, (addr >> 0) & 0xFF);
-}
-
-// convert a string representation of an IP address into its numeric equivalent
-static Uint32 Inet_AtoN(const char* buf)
-{
-	// net_server inexplicably doesn't have this function; so I'll just fake it
-	Uint32 ret = 0;
-	int shift = 24;  // fill out the MSB first
-	bool startQuad = true;
-	while ((shift >= 0) && (*buf))
-	{
-		if (startQuad)
-		{
-			unsigned char quad = (unsigned char)atoi(buf);
-			ret |= (((Uint32)quad) << shift);
-			shift -= 8;
-		}
-		startQuad = (*buf == '.');
-		buf++;
-	}
-	return ret;
-}
-#endif // SDL_PLATFORM_WIN32 || HAVE_GETIFADDRS
-
-static bool NET_SendDatagramBroadcast(NET_DatagramSocket *sock, Uint16 port, const void* buf, int buflen)
-{
-#ifdef SDL_PLATFORM_WIN32
-	// Windows XP style implementation
-	HMODULE hiphlpapi = LoadLibraryA("Iphlpapi.dll");
-	typedef DWORD (WINAPI *GetIpAddrTable_t)(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, BOOL bOrder);
-	GetIpAddrTable_t GetIpAddrTableFunc = (GetIpAddrTable_t)GetProcAddress(hiphlpapi, "GetIpAddrTable");
-	typedef ULONG (WINAPI *GetAdaptersInfo_t)(PIP_ADAPTER_INFO AdapterInfo, PULONG SizePointer);
-	GetAdaptersInfo_t GetAdaptersInfoFunc = (GetAdaptersInfo_t)GetProcAddress(hiphlpapi, "GetAdaptersInfo");
-
-	// Adapted from example code at http://msdn2.microsoft.com/en-us/library/aa365917.aspx
-	// Now get Windows' IPv4 addresses table.  Once again, we gotta call GetIpAddrTable()
-	// multiple times in order to deal with potential race conditions properly.
-	MIB_IPADDRTABLE* ipTable = NULL;
-	{
-		ULONG iptablelen = 0;
-		for (int i = 0; i < 5; i++)
-		{
-			DWORD ipRet = GetIpAddrTableFunc(ipTable, &iptablelen, false);
-			if (ipRet == ERROR_INSUFFICIENT_BUFFER)
-			{
-				free(ipTable);  // in case we had previously allocated it
-				ipTable = (MIB_IPADDRTABLE*)malloc(iptablelen);
-			}
-			else if (ipRet == NO_ERROR) break;
-			else
-			{
-				free(ipTable);
-				ipTable = NULL;
-				break;
-			}
-		}
-	}
-
-	if (ipTable)
-	{
-		// Try to get the Adapters-info table, so we can given useful names to the IP
-		// addresses we are returning.  Gotta call GetAdaptersInfo() up to 5 times to handle
-		// the potential race condition between the size-query call and the get-data call.
-		// I love a well-designed API :^P
-		IP_ADAPTER_INFO* pAdapterInfo = NULL;
-		{
-			ULONG bufLen = 0;
-			for (int i = 0; i < 5; i++)
-			{
-				DWORD apRet = GetAdaptersInfoFunc(pAdapterInfo, &bufLen);
-				if (apRet == ERROR_BUFFER_OVERFLOW)
-				{
-					free(pAdapterInfo);  // in case we had previously allocated it
-					pAdapterInfo = (IP_ADAPTER_INFO*)malloc(bufLen);
-				}
-				else if (apRet == ERROR_SUCCESS) break;
-				else
-				{
-					free(pAdapterInfo);
-					pAdapterInfo = NULL;
-					break;
-				}
-			}
-		}
-
-		for (DWORD i = 0; i < ipTable->dwNumEntries; i++)
-		{
-			const MIB_IPADDRROW& row = ipTable->table[i];
-
-			// Now lookup the appropriate adaptor-name in the pAdaptorInfos, if we can find it
-			const char* name = NULL;
-			const char* desc = NULL;
-			if (pAdapterInfo)
-			{
-				IP_ADAPTER_INFO* next = pAdapterInfo;
-				while ((next) && (name == NULL))
-				{
-					IP_ADDR_STRING* ipAddr = &next->IpAddressList;
-					while (ipAddr)
-					{
-						if (Inet_AtoN(ipAddr->IpAddress.String) == SDL_Swap32BE(row.dwAddr))
-						{
-							name = next->AdapterName;
-							desc = next->Description;
-							break;
-						}
-						ipAddr = ipAddr->Next;
-					}
-					next = next->Next;
-				}
-			}
-			char namebuf[128];
-			if (name == NULL)
-			{
-				SDL_snprintf(namebuf, sizeof(namebuf), "unnamed-%i", i);
-				name = namebuf;
-			}
-
-			Uint32 ipAddr = SDL_Swap32BE(row.dwAddr);
-			Uint32 netmask = SDL_Swap32BE(row.dwMask);
-			Uint32 baddr = ipAddr & netmask;
-			if (row.dwBCastAddr) baddr |= ~netmask;
-
-			char ifaAddrStr[32];  Inet_NtoA(ipAddr, ifaAddrStr, sizeof(ifaAddrStr));
-			char maskAddrStr[32]; Inet_NtoA(netmask, maskAddrStr, sizeof(maskAddrStr));
-			char dstAddrStr[32];  Inet_NtoA(baddr, dstAddrStr, sizeof(dstAddrStr));
-			//SDL_Log("  Found interface:  name=[%s] desc=[%s] address=[%s] netmask=[%s] broadcastAddr=[%s]\n", name, desc ? desc : "unavailable", ifaAddrStr, maskAddrStr, dstAddrStr);
-
-			NET_Address *address = NET_ResolveHostname(dstAddrStr);
-			NET_WaitUntilResolved(address, -1);
-			NET_SendDatagram(sock, address, port, buf, buflen);
-			NET_UnrefAddress(address);
-		}
-
-		free(pAdapterInfo);
-		free(ipTable);
-	}
-	return true;
-#elif defined(HAVE_GETIFADDRS)
-	// BSD-style implementation
-	struct ifaddrs* ifap;
-	if (getifaddrs(&ifap) == 0)
-	{
-		struct ifaddrs* p = ifap;
-		while (p)
-		{
-			Uint32 ifaAddr = SockAddrToUint32(p->ifa_addr);
-			Uint32 maskAddr = SockAddrToUint32(p->ifa_netmask);
-			Uint32 dstAddr = SockAddrToUint32(p->ifa_dstaddr);
-			if (ifaAddr > 0)
-			{
-				char ifaAddrStr[32];  Inet_NtoA(ifaAddr, ifaAddrStr, sizeof(ifaAddrStr));
-				char maskAddrStr[32]; Inet_NtoA(maskAddr, maskAddrStr, sizeof(maskAddrStr));
-				char dstAddrStr[32];  Inet_NtoA(dstAddr, dstAddrStr, sizeof(dstAddrStr));
-				//SDL_Log("  Found interface:  name=[%s] desc=[%s] address=[%s] netmask=[%s] broadcastAddr=[%s]\n", p->ifa_name, "unavailable", ifaAddrStr, maskAddrStr, dstAddrStr);
-
-				NET_Address* address = NET_ResolveHostname(dstAddrStr);
-				NET_WaitUntilResolved(address, -1);
-				NET_SendDatagram(sock, address, port, buf, buflen);
-				NET_UnrefAddress(address);
-			}
-			p = p->ifa_next;
-		}
-		freeifaddrs(ifap);
-	}
-	return true;
-#else
-	NET_Address *address = NET_ResolveHostname("255.255.255.255");
-	NET_WaitUntilResolved(address, -1);
-	bool result = NET_SendDatagram(sock, address, port, buf, buflen);
-	NET_UnrefAddress(address);
-	return result;
-#endif
-}
-
 void
 LobbyDialogDelegate::GetGameList()
 {
@@ -812,7 +625,7 @@ LobbyDialogDelegate::GetGameList()
 	m_packet.StartLobbyMessage(LOBBY_REQUEST_GAME_INFO);
 	m_packet.Write((Uint32)SDL_GetTicks());
 
-	NET_SendDatagramBroadcast(gSocket, NETPLAY_PORT, m_packet.data, m_packet.len);
+	NET_SendDatagram(gSocket, NULL, NETPLAY_PORT, m_packet.data, m_packet.len);
 }
 
 void
diff --git a/game/netplay.cpp b/game/netplay.cpp
index 612d413a..7abb466f 100644
--- a/game/netplay.cpp
+++ b/game/netplay.cpp
@@ -70,8 +70,12 @@ int CreateSocket(bool hosting)
 	} else {
 		port = 0;
 	}
-	gSocket = NET_CreateDatagramSocket(NULL, port);
-	if ( gSocket == NULL ) {
+
+	SDL_PropertiesID props = SDL_CreateProperties();
+	SDL_SetBooleanProperty(props, NET_PROP_DATAGRAM_SOCKET_ALLOW_BROADCAST_BOOLEAN, true);
+	gSocket = NET_CreateDatagramSocket(NULL, port, props);
+	SDL_DestroyProperties(props);
+	if (!gSocket) {
 		error("Couldn't create socket bound to port %d: %s\n", port, SDL_GetError());
 		return(-1);
 	}