Work-around some issues with gio on windows
authorJens Georg <mail@jensge.org>
Sun, 2 May 2010 15:37:06 +0000 (17:37 +0200)
committerZeeshan Ali (Khattak) <zeeshanak@gnome.org>
Sun, 10 Oct 2010 19:24:31 +0000 (22:24 +0300)
glib uses a rather strange mechanism to init the winsock library (through
usage of g_inet_addres_*), so we better do it ourselves.

glib - rightly - doesn't set SO_REUSEADDR on g_socket_bind on windows
since it has different semantics. Nevertheless we need it on windows for
multicast sockets, so we add a helper function to set this socket option.

libgssdp/gssdp-client.c
libgssdp/gssdp-socket-functions.c
libgssdp/gssdp-socket-functions.h
libgssdp/gssdp-socket-source.c

index e2bb22d..b966725 100644 (file)
@@ -144,6 +144,19 @@ gssdp_client_constructed (GObject *object)
 {
         GSSDPClient *client = GSSDP_CLIENT (object);
         GError *error = NULL;
+#ifdef G_OS_WIN32
+        WSADATA wsaData = {0};
+        if (WSAStartup (MAKEWORD (2,2), &wsaData) != 0) {
+                gchar *message;
+
+                message = g_win32_error_message (WSAGetLastError ());
+                g_set_error_literal (client->priv->error,
+                                     GSSDP_ERROR,
+                                     GSSDP_ERROR_FAILED,
+                                     message);
+                g_free (message);
+        }
+#endif
 
         /* Make sure all network info is available to us */
         if (!init_network_info (client))
@@ -295,6 +308,9 @@ gssdp_client_finalize (GObject *object)
         GSSDPClient *client;
 
         client = GSSDP_CLIENT (object);
+#ifdef G_OS_WIN32
+        WSACleanup ();
+#endif
 
         g_free (client->priv->server_id);
         g_free (client->priv->iface);
index 0fe78de..37af2ca 100644 (file)
@@ -143,6 +143,21 @@ gssdp_socket_mcast_interface_set (GSocket      *socket,
                                         error);
 }
 
+#ifdef G_OS_WIN32
+gboolean
+gssdp_socket_reuse_address (GSocket *socket,
+                            gboolean enable,
+                            GError **error) {
+        return gssdp_socket_option_set (socket,
+                                        SOL_SOCKET,
+                                        SO_REUSEADDR,
+                                        (char *) &enable,
+                                        sizeof (enable),
+                                        error);
+}
+#endif
+
+
 /*
  * Iface may be NULL if no special interface is wanted
  */
index e1cda40..99784d2 100644 (file)
@@ -45,4 +45,10 @@ gssdp_socket_mcast_group_join    (GSocket       *socket,
                                   GInetAddress  *group,
                                   GInetAddress  *iface,
                                   GError       **error);
+#ifdef G_OS_WIN32
+G_GNUC_INTERNAL gboolean
+gssdp_socket_reuse_address       (GSocket *socket,
+                                  gboolean enable,
+                                  GError **error);
+#endif
 #endif
index bf7b955..7467de0 100644 (file)
@@ -250,6 +250,23 @@ gssdp_socket_source_do_init (GInitable     *initable,
                                                           SSDP_PORT);
         }
 
+#ifdef G_OS_WIN32
+        /* normally g_socket_bind does this, but it is disabled on
+         * windows since SO_REUSEADDR has different semantics
+         * there. Nevertheless, there's no way without for
+         * multicast sockets
+         */
+        if (!gssdp_socket_reuse_address (self->priv->socket,
+                                         TRUE,
+                                         &inner_error)) {
+                g_propagate_prefixed_error (
+                                error,
+                                inner_error,
+                                "Failed to enable reuse");
+
+                goto error;
+        }
+#endif
         /* Bind to requested port and address */
         if (!g_socket_bind (self->priv->socket,
                             bind_address,