From ab94a6d2b23d2839827c0d49ada251a2e9bd33d6 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Mon, 25 May 2026 01:41:18 -0400
Subject: [PATCH] haiku: Add support for network interface change
notifications.
Fixes #166.
---
CMakeLists.txt | 16 +++++----
src/SDL_net.c | 11 ++++--
src/SDL_net_haiku.cpp | 82 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 101 insertions(+), 8 deletions(-)
create mode 100644 src/SDL_net_haiku.cpp
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3ab2e73..e14eaa2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -104,6 +104,12 @@ endif()
set(PC_LIBS)
set(PC_REQUIRES)
+if(HAIKU)
+ set(HAVE_GETIFADDRS True) # Haiku always has it (but you have to -lnetwork, so check_c_source_compiles won't work as-is).
+ set(EXTRA_SOURCES "src/SDL_net_haiku.cpp")
+ enable_language(CXX)
+endif()
+
set(PLATFORM_UNSUPPORTED False)
if (DOS OR EMSCRIPTEN) # These either don't have networking at all, or have needs we don't currently meet.
set(PLATFORM_UNSUPPORTED True)
@@ -114,12 +120,10 @@ if(SDLNET_STUB_ONLY)
message(WARNING "Only building a stub library. The functions will be there but all of them will fail!")
add_library(${sdl3_net_target_name} src/SDL_net_stub_only.c)
else()
- add_library(${sdl3_net_target_name} src/SDL_net.c)
+ add_library(${sdl3_net_target_name} src/SDL_net.c ${EXTRA_SOURCES})
endif()
-if(HAIKU)
- set(HAVE_GETIFADDRS True) # Haiku always has it (but you have to -lnetwork, so check_c_source_compiles won't work as-is).
-elseif(NOT (WIN32 OR SDLNET_STUB_ONLY))
+if(NOT (HAIKU OR WIN32 OR SDLNET_STUB_ONLY))
check_c_source_compiles("
#include <ifaddrs.h>
int main(void) {
@@ -173,8 +177,8 @@ if(WIN32)
target_link_libraries(${sdl3_net_target_name} PRIVATE iphlpapi ws2_32)
list(APPEND PC_LIBS -liphlpapi -lws2_32)
endif()
-if(CMAKE_SYSTEM_NAME MATCHES "Haiku.*")
- target_link_libraries(${sdl3_net_target_name} PRIVATE network)
+if(HAIKU)
+ target_link_libraries(${sdl3_net_target_name} PRIVATE network be bnetapi)
endif()
set_target_properties(${sdl3_net_target_name} PROPERTIES
OUTPUT_NAME "SDL3_net"
diff --git a/src/SDL_net.c b/src/SDL_net.c
index 03dcd03..f52b7e6 100644
--- a/src/SDL_net.c
+++ b/src/SDL_net.c
@@ -491,13 +491,16 @@ static void RefreshInterfaces(void) // WINDOWS VERSION
// AF_NETLINK covers Linux (and by extension Android). PF_ROUTE covers the BSDs (and by extension Apple platforms).
// This doesn't cover all Unix platforms that ever existed, but this hits just about everything that is still being maintained seriously.
-#if defined(USE_NETLINK) || defined(PF_ROUTE)
+#if defined(SDL_PLATFORM_HAIKU) // haiku has its own thing for monitoring, but needs getifaddrs.
+extern bool NET_HAIKU_InitInterfaceChangeNotifications(SDL_AtomicInt *changed);
+extern void NET_HAIKU_QuitInterfaceChangeNotifications(void);
+#elif defined(USE_NETLINK) || defined(PF_ROUTE)
#define USE_NETWORK_MONITOR 1
#else
#warning unknown network monitoring system for this platform - will not report network changes
#endif
-#ifdef USE_NETWORK_MONITOR
+#if defined(USE_NETWORK_MONITOR)
static SDL_Thread *interface_change_notifications_thread = NULL;
static SDL_AtomicInt interface_change_notifications_flag; // !!! FIXME
@@ -572,6 +575,8 @@ static bool InitInterfaceChangeNotifications(void) // LINUX/BSD VERSION
#ifdef USE_NETWORK_MONITOR
interface_change_notifications_thread = SDL_CreateThread(LinuxInterfaceChangeNotificationThread, "SDLNetIfaceEnum", NULL);
return (interface_change_notifications_thread != NULL);
+#elif defined(SDL_PLATFORM_HAIKU)
+ return NET_HAIKU_InitInterfaceChangeNotifications(&interfaces_have_changed);
#else
return true;
#endif
@@ -586,6 +591,8 @@ static void QuitInterfaceChangeNotifications(void) // LINUX/BSD VERSION
SDL_SetAtomicInt(&interface_change_notifications_flag, 0);
}
interface_change_notifications_thread = NULL;
+#elif defined(SDL_PLATFORM_HAIKU)
+ NET_HAIKU_QuitInterfaceChangeNotifications();
#endif
}
diff --git a/src/SDL_net_haiku.cpp b/src/SDL_net_haiku.cpp
new file mode 100644
index 0000000..dcb3f60
--- /dev/null
+++ b/src/SDL_net_haiku.cpp
@@ -0,0 +1,82 @@
+/*
+ SDL_net: A simple networking library for use with SDL
+ Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+// we use a little bit of C++ for Haiku support, since the system frameworks
+// require it. Specifically, we need to get network interface change
+// notifications through BNetworkRoster.
+
+#include <AppKit.h>
+#include <NetworkNotifications.h>
+
+#include <SDL3/SDL.h>
+
+extern "C" {
+ extern bool NET_HAIKU_InitInterfaceChangeNotifications(SDL_AtomicInt *changed);
+ extern void NET_HAIKU_QuitInterfaceChangeNotifications(void);
+}
+
+class NET_InterfaceLooper : public BLooper
+{
+public:
+ NET_InterfaceLooper(SDL_AtomicInt *_changed);
+ virtual void MessageReceived(BMessage *message);
+ virtual ~NET_InterfaceLooper() {}
+
+private:
+ SDL_AtomicInt *changed;
+};
+
+
+NET_InterfaceLooper::NET_InterfaceLooper(SDL_AtomicInt *_changed)
+ : BLooper("NET_InterfaceLooper")
+ , changed(_changed)
+{
+}
+
+void NET_InterfaceLooper::MessageReceived(BMessage *message)
+{
+ //SDL_Log("NET_InterfaceLooper::MessageReceived %d", (int) message->what);
+ SDL_SetAtomicInt(changed, 1);
+ BLooper::MessageReceived(message);
+}
+
+
+static NET_InterfaceLooper *looper = NULL;
+
+bool NET_HAIKU_InitInterfaceChangeNotifications(SDL_AtomicInt *changed)
+{
+ SDL_assert(!looper);
+ looper = new NET_InterfaceLooper(changed);
+ looper->Run();
+ return start_watching_network(
+ B_NETWORK_INTERFACE_ADDED | B_NETWORK_INTERFACE_REMOVED |
+ B_NETWORK_INTERFACE_CHANGED | B_NETWORK_DEVICE_LINK_CHANGED, looper
+ ) == B_OK;
+}
+
+void NET_HAIKU_QuitInterfaceChangeNotifications(void)
+{
+ if (looper) {
+ looper->PostMessage(B_QUIT_REQUESTED);
+ looper = NULL;
+ }
+}
+