[gupnp/gupnp-1.4] ServiceProxy: Properly re-queue if POST failed



commit d01b24e11e6ae6c80e1dbca088f00bb3fdc6a11b
Author: Jens Georg <mail jensge org>
Date:   Wed Jan 5 15:25:53 2022 +0100

    ServiceProxy: Properly re-queue if POST failed
    
    The re-queue of message after POST was returned with METHOD_NOT ALLOWED
    never worked. Just re-send the message after changing the method to
    M-POST
    
    Fixes #63

 libgupnp/gupnp-service-proxy.c |  22 +++++-
 tests/test-bugs.c              | 159 +++++++++++++++++++++++++++++++++++++++--
 2 files changed, 174 insertions(+), 7 deletions(-)
---
diff --git a/libgupnp/gupnp-service-proxy.c b/libgupnp/gupnp-service-proxy.c
index 25d5ef6..5e78ebf 100644
--- a/libgupnp/gupnp-service-proxy.c
+++ b/libgupnp/gupnp-service-proxy.c
@@ -720,6 +720,9 @@ update_message_after_not_allowed (SoupMessage *msg)
                                      "SOAPAction");
 }
 
+static void
+gupnp_service_proxy_action_queue_task (GTask *task);
+
 static void
 action_task_got_response (SoupSession *session,
                           SoupMessage *msg,
@@ -744,10 +747,23 @@ action_task_got_response (SoupSession *session,
                 break;
 
         case SOUP_STATUS_METHOD_NOT_ALLOWED:
-                /* And re-queue */
-                update_message_after_not_allowed (msg);
-                soup_session_requeue_message (session, msg);
+                if (g_str_equal (msg->method, "POST")) {
+                        update_message_after_not_allowed (msg);
+                        gupnp_service_proxy_action_queue_task (task);
+
+                } else {
+                        if (action->cancellable != NULL && action->cancellable_connection_id != 0) {
+                                g_cancellable_disconnect (action->cancellable,
+                                                          action->cancellable_connection_id);
+                                action->cancellable_connection_id = 0;
+                        }
 
+                        g_task_return_new_error (task,
+                                                 GUPNP_SERVER_ERROR,
+                                                 GUPNP_SERVER_ERROR_OTHER,
+                                                 "Server does not allow any POST messages");
+                        g_object_unref (task);
+                }
                 break;
 
         default:
diff --git a/tests/test-bugs.c b/tests/test-bugs.c
index 03d4e48..df1a29e 100644
--- a/tests/test-bugs.c
+++ b/tests/test-bugs.c
@@ -6,14 +6,14 @@
  * SPDX-License-Identifier: LGPL-2.1-or-later
  */
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
 #include <libgupnp/gupnp.h>
 #include <libgupnp/gupnp-service-private.h>
 #include <libgupnp/gupnp-context-private.h>
 
+#include <libgssdp/gssdp-resource-group.h>
+#include <libsoup/soup.h>
+
+
 static GUPnPContext *
 create_context (guint16 port, GError **error) {
         return GUPNP_CONTEXT (g_initable_new (GUPNP_TYPE_CONTEXT,
@@ -687,6 +687,156 @@ test_ggo_42 ()
         g_object_unref (info);
 }
 
+void
+on_control (SoupServer *server,
+            SoupMessage *msg,
+            const char *path,
+            GHashTable *query,
+            SoupClientContext *ctx,
+            gpointer user_data)
+{
+        g_print ("Method: %s\n", msg->method);
+        soup_message_set_status (msg, SOUP_STATUS_METHOD_NOT_ALLOWED);
+}
+
+void
+on_event (SoupServer *server,
+          SoupMessage *msg,
+          const char *path,
+          GHashTable *query,
+          SoupClientContext *ctx,
+          gpointer user_data)
+{
+        soup_message_set_status (msg, SOUP_STATUS_OK);
+}
+
+typedef struct {
+        GUPnPServiceProxy *p;
+        GMainLoop *loop;
+} TestGGO63Data;
+
+void
+on_proxy (GUPnPControlPoint *cp, GUPnPServiceProxy *p, gpointer user_data)
+{
+        g_print ("Got proxy....\n");
+        TestGGO63Data *d = (TestGGO63Data *) user_data;
+        d->p = g_object_ref (p);
+
+        g_main_loop_quit (d->loop);
+}
+
+void
+on_ping (GObject *object, GAsyncResult *res, gpointer user_data)
+{
+        TestGGO63Data *d = (TestGGO63Data *) user_data;
+        GError *error = NULL;
+
+        GUPnPServiceProxyAction *action =
+                gupnp_service_proxy_call_action_finish (
+                        GUPNP_SERVICE_PROXY (object),
+                        res,
+                        &error);
+
+        g_assert_null (action);
+        g_assert_error (error, GUPNP_SERVER_ERROR, GUPNP_SERVER_ERROR_OTHER);
+
+        g_error_free (error);
+
+        g_main_loop_quit (d->loop);
+}
+
+void
+test_ggo_63 ()
+{
+        GUPnPContext *context = NULL;
+        GError *error = NULL;
+
+        context = create_context (0, &error);
+        g_assert_no_error (error);
+        g_assert (context != NULL);
+
+        SoupServer *server = gupnp_context_get_server (context);
+        GSList *uris = soup_server_get_uris (server);
+        GSSDPResourceGroup *rg =
+                gssdp_resource_group_new (GSSDP_CLIENT (context));
+
+        char *server_uri = soup_uri_to_string (uris->data, FALSE);
+        char *resource_path = g_strconcat (server_uri, "TestDevice.xml", NULL);
+        g_free (server_uri);
+        g_slist_free_full (uris, (GDestroyNotify) soup_uri_free);
+
+        gssdp_resource_group_add_resource_simple (rg,
+                                                  "upnp:rootdevice",
+                                                  "uuid:1234::upnp:rootdevice",
+                                                  resource_path);
+
+        gssdp_resource_group_add_resource_simple (rg,
+                                                  "uuid:1234",
+                                                  "uuid:1234",
+                                                  resource_path);
+
+        gssdp_resource_group_add_resource_simple (
+                rg,
+                "urn:test-gupnp-org:device:TestDevice:1",
+                "uuid:1234::urn:test-gupnp-org:device:TestDevice:1",
+                resource_path);
+
+        gssdp_resource_group_add_resource_simple (
+                rg,
+                "urn:test-gupnp-org:service:TestService:1",
+                "uuid:1234::urn:test-gupnp-org:service:TestService:1",
+                resource_path);
+
+        g_free (resource_path);
+
+        gupnp_context_host_path (context,
+                                 DATA_PATH "/TestDevice.xml",
+                                 "/TestDevice.xml");
+
+        soup_server_add_handler (server,
+                                 "/TestService/Control",
+                                 on_control,
+                                 NULL,
+                                 NULL);
+
+        soup_server_add_handler (server,
+                                 "/TestService/Event",
+                                 on_event,
+                                 NULL,
+                                 NULL);
+
+        gssdp_resource_group_set_available (rg, TRUE);
+
+
+        GUPnPControlPoint *cp = gupnp_control_point_new (
+                context,
+                "urn:test-gupnp-org:service:TestService:1");
+
+        TestGGO63Data d = { .loop = g_main_loop_new (NULL, FALSE), .p = NULL };
+        g_signal_connect (G_OBJECT (cp),
+                          "service-proxy-available",
+                          G_CALLBACK (on_proxy),
+                          &d);
+
+        gssdp_resource_browser_set_active (GSSDP_RESOURCE_BROWSER (cp), TRUE);
+
+        g_main_loop_run (d.loop);
+
+        GUPnPServiceProxyAction *a =
+                gupnp_service_proxy_action_new ("Ping", NULL);
+
+        gupnp_service_proxy_call_action_async (d.p, a, NULL, on_ping, &d);
+
+        g_main_loop_run (d.loop);
+        gupnp_service_proxy_action_unref (a);
+
+        g_object_unref (d.p);
+        g_object_unref (cp);
+        g_object_unref (rg);
+        g_object_unref (context);
+        g_main_loop_unref (d.loop);
+}
+
 int
 main (int argc, char *argv[]) {
     g_test_init (&argc, &argv, NULL);
@@ -698,6 +848,7 @@ main (int argc, char *argv[]) {
     g_test_add_func ("/bugs/ggo/24", test_ggo_24);
     g_test_add_func ("/bugs/ggo/58", test_ggo_58);
     g_test_add_func ("/bugs/ggo/42", test_ggo_42);
+    g_test_add_func ("/bugs/ggo/63", test_ggo_63);
 
     return g_test_run ();
 }


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