GSocket – Implement multicast interface selection on Windows
authorSebastian Dröge <slomo@circular-chaos.org>
Wed, 31 Jul 2013 12:11:55 +0000 (14:11 +0200)
committerDan Winship <danw@gnome.org>
Mon, 19 Aug 2013 16:28:20 +0000 (12:28 -0400)
https://bugzilla.gnome.org/show_bug.cgi?id=697185

gio/Makefile.am
gio/gnetworking.h.in
gio/gnetworking.h.win32
gio/gsocket.c

index 33d5885..f861e8b 100644 (file)
@@ -316,7 +316,7 @@ win32_more_sources_for_vcproj = \
 
 if OS_WIN32
 appinfo_sources += gwin32appinfo.c gwin32appinfo.h
-platform_libadd += -lshlwapi -lws2_32 -ldnsapi
+platform_libadd += -lshlwapi -lws2_32 -ldnsapi -liphlpapi
 win32_sources = $(win32_actual_sources)
 
 giowin32includedir=$(includedir)/gio-win32-2.0/gio
index 99bdadd..a1d4716 100644 (file)
@@ -34,6 +34,7 @@
 #include <windns.h>
 #include <mswsock.h>
 @WSPIAPI_INCLUDE@
+#include <iphlpapi.h>
 
 #else /* !G_OS_WIN32 */
 
index c6e11a4..c5a8980 100644 (file)
@@ -34,6 +34,7 @@
 #include <windns.h>
 #include <mswsock.h>
 #include <wspiapi.h>
+#include <iphlpapi.h>
 
 #else /* !G_OS_WIN32 */
 
index a1b00a3..b606171 100644 (file)
@@ -1934,6 +1934,60 @@ g_socket_bind (GSocket         *socket,
   return TRUE;
 }
 
+#if !defined(HAVE_IF_NAMETOINDEX) && defined(G_OS_WIN32)
+static guint
+if_nametoindex (const gchar *iface)
+{
+  PIP_ADAPTER_ADDRESSES addresses = NULL, p;
+  gulong addresses_len = 0;
+  guint idx = 0;
+  DWORD res;
+
+  res = GetAdaptersAddresses (AF_UNSPEC, 0, NULL, NULL, &addresses_len);
+  if (res != NO_ERROR && res != ERROR_BUFFER_OVERFLOW)
+    {
+      if (res == ERROR_NO_DATA)
+        errno = ENXIO;
+      else
+        errno = EINVAL;
+      return 0;
+    }
+
+  addresses = g_malloc (addresses_len);
+  res = GetAdaptersAddresses (AF_UNSPEC, 0, NULL, addresses, &addresses_len);
+
+  if (res != NO_ERROR)
+    {
+      g_free (addresses);
+      if (res == ERROR_NO_DATA)
+        errno = ENXIO;
+      else
+        errno = EINVAL;
+      return 0;
+    }
+
+  p = addresses;
+  while (p)
+    {
+      if (strcmp (p->AdapterName, iface) == 0)
+        {
+          idx = p->IfIndex;
+          break;
+        }
+      p = p->Next;
+    }
+
+  if (p == NULL)
+    errno = ENXIO;
+
+  g_free (addresses);
+
+  return idx;
+}
+
+#define HAVE_IF_NAMETOINDEX 1
+#endif
+
 static gboolean
 g_socket_multicast_group_operation (GSocket       *socket,
                                    GInetAddress  *group,
@@ -1969,6 +2023,11 @@ g_socket_multicast_group_operation (GSocket       *socket,
         mc_req.imr_ifindex = if_nametoindex (iface);
       else
         mc_req.imr_ifindex = 0;  /* Pick any.  */
+#elif defined(G_OS_WIN32)
+      if (iface)
+        mc_req.imr_interface.s_addr = g_htonl (if_nametoindex (iface));
+      else
+        mc_req.imr_interface.s_addr = g_htonl (INADDR_ANY);
 #else
       mc_req.imr_interface.s_addr = g_htonl (INADDR_ANY);
 #endif