[gupnp] ServiceProxy: Properly re-queue if POST failed
- From: Jens Georg <jensgeorg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gupnp] ServiceProxy: Properly re-queue if POST failed
- Date: Wed, 5 Jan 2022 15:55:42 +0000 (UTC)
commit 3038b8ecd12ac803c1610d01b3d6a6c2fe06ae3a
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 | 62 ++++++++++++++--
tests/test-bugs.c | 161 ++++++++++++++++++++++++++++++++++++++++-
2 files changed, 214 insertions(+), 9 deletions(-)
---
diff --git a/libgupnp/gupnp-service-proxy.c b/libgupnp/gupnp-service-proxy.c
index 66ba886..119edf1 100644
--- a/libgupnp/gupnp-service-proxy.c
+++ b/libgupnp/gupnp-service-proxy.c
@@ -633,6 +633,7 @@ on_action_cancelled (GCancellable *cancellable, gpointer user_data)
static gboolean
prepare_action_msg (GUPnPServiceProxy *proxy,
GUPnPServiceProxyAction *action,
+ const char *method,
GError **error)
{
char *control_url, *full_action;
@@ -673,7 +674,7 @@ prepare_action_msg (GUPnPServiceProxy *proxy,
g_free (control_url);
g_clear_object (&action->msg);
- action->msg = soup_message_new (SOUP_METHOD_POST, local_control_url);
+ action->msg = soup_message_new (method, local_control_url);
g_free (local_control_url);
SoupMessageHeaders *headers =
@@ -681,7 +682,21 @@ prepare_action_msg (GUPnPServiceProxy *proxy,
/* Specify action */
full_action = g_strdup_printf ("\"%s#%s\"", service_type, action->name);
- soup_message_headers_append (headers, "SOAPAction", full_action);
+
+ // This is internal API, it should either be that constant or the string "M-POST"
+ if (method == SOUP_METHOD_POST) {
+ soup_message_headers_append (headers,
+ "SOAPAction",
+ full_action);
+ } else {
+ soup_message_headers_append (headers,
+ "s-SOAPAction",
+ full_action);
+ soup_message_headers_append (
+ headers,
+ "Man",
+ "\"http://schemas.xmlsoap.org/soap/envelope/\"; ns=s");
+ }
g_free (full_action);
/* Specify language */
@@ -724,6 +739,9 @@ update_message_after_not_allowed (SoupMessage *msg)
soup_message_headers_remove (headers, "SOAPAction");
}
+static void
+gupnp_service_proxy_action_queue_task (GTask *task);
+
static void
action_task_got_response (GObject *source,
GAsyncResult *res,
@@ -755,10 +773,40 @@ action_task_got_response (GObject *source,
switch (soup_message_get_status (action->msg)) {
case SOUP_STATUS_METHOD_NOT_ALLOWED:
- /* And re-queue */
- update_message_after_not_allowed (action->msg);
- // FIXME: soup_session_requeue_message (session, msg);
+ if (g_str_equal (soup_message_get_method (action->msg),
+ "POST")) {
+ g_debug ("POST returned with METHOD_NOT_ALLOWED, "
+ "trying with M-POST");
+ if (!prepare_action_msg (action->proxy,
+ action,
+ "M-POST",
+ &error)) {
+ 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_error (task, error);
+
+ g_object_unref (task);
+ } else {
+ 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:
@@ -2155,7 +2203,7 @@ gupnp_service_proxy_call_action_async (GUPnPServiceProxy *proxy,
gupnp_service_proxy_action_ref (action),
(GDestroyNotify) gupnp_service_proxy_action_unref);
- prepare_action_msg (proxy, action, &error);
+ prepare_action_msg (proxy, action, SOUP_METHOD_POST, &error);
if (error != NULL) {
g_task_return_error (task, error);
@@ -2232,7 +2280,7 @@ gupnp_service_proxy_call_action (GUPnPServiceProxy *proxy,
g_return_val_if_fail (GUPNP_IS_SERVICE_PROXY (proxy), NULL);
g_return_val_if_fail (!action->pending, NULL);
- if (!prepare_action_msg (proxy, action, error)) {
+ if (!prepare_action_msg (proxy, action, SOUP_METHOD_POST, error)) {
return NULL;
}
diff --git a/tests/test-bugs.c b/tests/test-bugs.c
index 563e758..28ac0e6 100644
--- a/tests/test-bugs.c
+++ b/tests/test-bugs.c
@@ -6,12 +6,14 @@
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
-#include <config.h>
-
#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,
@@ -686,6 +688,160 @@ test_ggo_42 ()
g_object_unref (info);
}
+void
+on_control (SoupServer *server,
+ SoupServerMessage *msg,
+ const char *path,
+ GHashTable *query,
+ gpointer user_data)
+{
+ SoupMessageBody *b = soup_server_message_get_response_body (msg);
+
+ g_print ("On Control\n");
+
+ soup_message_body_append (b, SOUP_MEMORY_COPY, "<html>\0", 7);
+ soup_server_message_set_status (msg, SOUP_STATUS_METHOD_NOT_ALLOWED, NULL);
+}
+
+void
+on_event (SoupServer *server,
+ SoupServerMessage *msg,
+ const char *path,
+ GHashTable *query,
+ gpointer user_data)
+{
+ soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL);
+}
+
+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)
+{
+ g_print ("On PIng\n");
+
+ 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 = g_uri_to_string (uris->data);
+ char *resource_path = g_strconcat (server_uri, "TestDevice.xml", NULL);
+ g_free (server_uri);
+ g_slist_free_full (uris, (GDestroyNotify) g_uri_unref);
+
+ 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);
@@ -697,6 +853,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]