[gssdp/gssdp_1.0] gssdp-client: Recreate socket on errors



commit 1b0fa468cb913fac9865989315586c151b4d6102
Author: Olivier Crete <olivier crete collabora com>
Date:   Tue Oct 30 19:57:00 2018 +0100

    gssdp-client: Recreate socket on errors
    
    iOS 10 and later close the UDP socket behind our backs when going
    to sleep and we need to re-create them.
    
    Reformatted/modified for applying to master
    
    https://bugzilla.gnome.org/show_bug.cgi?id=794340

 libgssdp/gssdp-client.c | 98 ++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 88 insertions(+), 10 deletions(-)
---
diff --git a/libgssdp/gssdp-client.c b/libgssdp/gssdp-client.c
index 655a713..ec2ae5f 100644
--- a/libgssdp/gssdp-client.c
+++ b/libgssdp/gssdp-client.c
@@ -1227,6 +1227,7 @@ socket_source_cb (GSSDPSocketSource *socket_source, GSSDPClient *client)
         GInputVector vector;
         GSocketControlMessage **messages;
         gint num_messages;
+        gboolean ret = TRUE;
 
         vector.buffer = buf;
         vector.size = BUF_SIZE;
@@ -1244,8 +1245,13 @@ socket_source_cb (GSSDPSocketSource *socket_source, GSSDPClient *client)
                                           &error);
 
         if (bytes == -1) {
-                g_warning ("Failed to receive from socket: %s",
-                           error->message);
+                if (!g_error_matches (error,
+                                      G_IO_ERROR,
+                                      G_IO_ERROR_WOULD_BLOCK)) {
+                        g_warning ("Failed to receive from socket: %s",
+                                   error->message);
+                        ret = FALSE;
+                }
 
                 goto out;
         }
@@ -1392,7 +1398,7 @@ out:
                 g_free (messages);
         }
 
-        return TRUE;
+        return ret;
 }
 
 static gboolean
@@ -1400,11 +1406,34 @@ request_socket_source_cb (G_GNUC_UNUSED GIOChannel  *source,
                           G_GNUC_UNUSED GIOCondition condition,
                           gpointer                   user_data)
 {
-        GSSDPClient *client;
+        GSSDPClient *client = GSSDP_CLIENT (user_data);
+        GSSDPSocketSource *request_socket = NULL;
+        GError *error = NULL;
 
-        client = GSSDP_CLIENT (user_data);
+        if (socket_source_cb (client->priv->request_socket, client))
+                return TRUE;
+
+        request_socket = gssdp_socket_source_new (
+                                        GSSDP_SOCKET_SOURCE_TYPE_REQUEST,
+                                        gssdp_client_get_host_ip (client),
+                                        client->priv->socket_ttl,
+                                        gssdp_client_get_interface (client),
+                                        &error);
+        if (request_socket != NULL) {
+                g_clear_object (&client->priv->request_socket);
+                client->priv->request_socket = request_socket;
+                gssdp_socket_source_set_callback (
+                                        client->priv->request_socket,
+                                        (GSourceFunc) request_socket_source_cb,
+                                        client);
+                gssdp_socket_source_attach (client->priv->request_socket);
+        } else {
+                g_warning ("Could not recreate request socket on error: %s",
+                           error->message);
+                g_clear_error (&error);
+        }
 
-        return socket_source_cb (client->priv->request_socket, client);
+        return TRUE;
 }
 
 static gboolean
@@ -1412,11 +1441,34 @@ multicast_socket_source_cb (G_GNUC_UNUSED GIOChannel  *source,
                             G_GNUC_UNUSED GIOCondition condition,
                             gpointer                   user_data)
 {
-        GSSDPClient *client;
+        GSSDPClient *client = GSSDP_CLIENT (user_data);
+        GSSDPSocketSource *multicast_socket = NULL;
+        GError *error = NULL;
 
-        client = GSSDP_CLIENT (user_data);
+        if (socket_source_cb (client->priv->multicast_socket, client))
+                return TRUE;
+
+        multicast_socket = gssdp_socket_source_new (
+                                        GSSDP_SOCKET_SOURCE_TYPE_REQUEST,
+                                        gssdp_client_get_host_ip (client),
+                                        client->priv->socket_ttl,
+                                        gssdp_client_get_interface (client),
+                                        &error);
+        if (multicast_socket != NULL) {
+                g_clear_object (&client->priv->multicast_socket);
+                client->priv->multicast_socket = multicast_socket;
+                gssdp_socket_source_set_callback (
+                                        client->priv->multicast_socket,
+                                        (GSourceFunc)multicast_socket_source_cb,
+                                        client);
+                gssdp_socket_source_attach (client->priv->multicast_socket);
+        } else {
+                g_warning ("Could not recreate search socket on error: %s",
+                           error->message);
+                g_clear_error (&error);
+        }
 
-        return socket_source_cb (client->priv->multicast_socket, client);
+        return TRUE;
 }
 
 static gboolean
@@ -1424,8 +1476,34 @@ search_socket_source_cb (G_GNUC_UNUSED GIOChannel  *source,
                          G_GNUC_UNUSED GIOCondition condition,
                          gpointer                   user_data)
 {
-        GSSDPClient *client;
+        GSSDPClient *client = GSSDP_CLIENT (user_data);
+        GSSDPSocketSource *search_socket = NULL;
+        GError *error = NULL;
+
+        if (socket_source_cb (client->priv->search_socket, client))
+                return TRUE;
+
+        search_socket = gssdp_socket_source_new (
+                                        GSSDP_SOCKET_SOURCE_TYPE_REQUEST,
+                                        gssdp_client_get_host_ip (client),
+                                        client->priv->socket_ttl,
+                                        gssdp_client_get_interface (client),
+                                        &error);
+        if (search_socket != NULL) {
+                g_clear_object (&client->priv->search_socket);
+                client->priv->search_socket = search_socket;
+                gssdp_socket_source_set_callback (
+                                        client->priv->search_socket,
+                                        (GSourceFunc)search_socket_source_cb,
+                                        client);
+                gssdp_socket_source_attach (client->priv->search_socket);
+        } else {
+                g_warning ("Could not recreate search socket on error: %s",
+                           error->message);
+                g_clear_error (&error);
+        }
 
+        return TRUE;
         client = GSSDP_CLIENT (user_data);
 
         return socket_source_cb (client->priv->search_socket, client);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]