From: Jens Georg Date: Sun, 2 May 2010 15:37:06 +0000 (+0200) Subject: Work-around some issues with gio on windows X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ff9c787e0de55008745c38e862e5cdfb38ee41d2;p=profile%2Fivi%2FGSSDP.git Work-around some issues with gio on windows 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. --- diff --git a/libgssdp/gssdp-client.c b/libgssdp/gssdp-client.c index e2bb22d..b966725 100644 --- a/libgssdp/gssdp-client.c +++ b/libgssdp/gssdp-client.c @@ -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); diff --git a/libgssdp/gssdp-socket-functions.c b/libgssdp/gssdp-socket-functions.c index 0fe78de..37af2ca 100644 --- a/libgssdp/gssdp-socket-functions.c +++ b/libgssdp/gssdp-socket-functions.c @@ -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 */ diff --git a/libgssdp/gssdp-socket-functions.h b/libgssdp/gssdp-socket-functions.h index e1cda40..99784d2 100644 --- a/libgssdp/gssdp-socket-functions.h +++ b/libgssdp/gssdp-socket-functions.h @@ -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 diff --git a/libgssdp/gssdp-socket-source.c b/libgssdp/gssdp-socket-source.c index bf7b955..7467de0 100644 --- a/libgssdp/gssdp-socket-source.c +++ b/libgssdp/gssdp-socket-source.c @@ -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,