summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Georg <mail@jensge.org>2022-01-05 15:25:53 +0100
committerJens Georg <mail@jensge.org>2022-01-05 15:29:24 +0100
commitd01b24e11e6ae6c80e1dbca088f00bb3fdc6a11b (patch)
treee879ce8d874b2793d86fa8d762397e29a0747ac0
parentbea40d3708adda31ef64e455c317c351ad457507 (diff)
downloadgupnp-d01b24e11e6ae6c80e1dbca088f00bb3fdc6a11b.tar.gz
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
-rw-r--r--libgupnp/gupnp-service-proxy.c22
-rw-r--r--tests/test-bugs.c159
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
@@ -721,6 +721,9 @@ update_message_after_not_allowed (SoupMessage *msg)
}
static void
+gupnp_service_proxy_action_queue_task (GTask *task);
+
+static void
action_task_got_response (SoupSession *session,
SoupMessage *msg,
gpointer user_data)
@@ -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 ();
}