[gupnp/wip/phako/libsoup3: 6/6] wip: More libsoup3 fixes
- From: Jens Georg <jensgeorg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gupnp/wip/phako/libsoup3: 6/6] wip: More libsoup3 fixes
- Date: Sat, 7 Aug 2021 08:01:25 +0000 (UTC)
commit b0dfb4b7c4106c3e2e1af2dbc30ef6b51ff666af
Author: Jens Georg <mail jensge org>
Date: Sat Aug 7 09:46:54 2021 +0200
wip: More libsoup3 fixes
.gitlab-ci.yml | 3 +-
build-aux/org.gnome.GUPnP.json | 59 ++++++++++++++
libgupnp/gupnp-context.c | 4 +-
libgupnp/gupnp-resource-factory.c | 3 +-
libgupnp/gupnp-root-device.c | 5 +-
libgupnp/gupnp-service-info.c | 18 ++---
libgupnp/gupnp-service.c | 51 ++++++-------
libgupnp/meson.build | 2 +-
tests/meson.build | 5 +-
tests/test-bugs.c | 2 -
tests/test-service.c | 156 ++++++++++++++++++++++++++++++++++++++
vala/gupnp-1.2.deps | 2 +-
vala/meson.build | 2 +-
13 files changed, 257 insertions(+), 55 deletions(-)
---
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 6f36e91..0670d37 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -4,8 +4,7 @@ flatpak:
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master
stage: build
script:
- - curl https://gitlab.gnome.org/GNOME/rygel/-/raw/master/build-aux/org.gnome.Rygel.json | sed
's/40/master/' >org.gnome.Rygel.json
- - flatpak-builder build-dir org.gnome.Rygel.json --stop-at=gupnp --user --disable-rofiles-fuse
+ - flatpak-builder build-dir build-aux/org.gnome.GUPnP.json --stop-at=gupnp --user --disable-rofiles-fuse
- flatpak build build-dir meson _build
- flatpak build build-dir ninja -C _build
- flatpak build build-dir meson test -C _build --gdb
diff --git a/build-aux/org.gnome.GUPnP.json b/build-aux/org.gnome.GUPnP.json
new file mode 100644
index 0000000..b7967d3
--- /dev/null
+++ b/build-aux/org.gnome.GUPnP.json
@@ -0,0 +1,59 @@
+{
+ "app-id" : "org.gnome.GUPnP",
+ "runtime" : "org.gnome.Platform",
+ "runtime-version" : "master",
+ "sdk" : "org.gnome.Sdk",
+ "command" : "light-server",
+ "finish-args" : [
+ "--share=network",
+ "--share=ipc",
+ "--talk-name=org.gtk.vfs",
+ "--talk-name=org.gtk.vfs.*",
+ "--filesystem=xdg-pictures",
+ "--filesystem=xdg-videos",
+ "--filesystem=xdg-music",
+ "--own-name=org.gnome.Rygel1"
+ ],
+ "build-options" : {
+ "cflags" : "-O2 -g",
+ "cxxflags" : "-O2 -g",
+ "env" : {
+ "V" : "1"
+ }
+ },
+ "cleanup" : [
+ "/include",
+ "/lib/pkgconfig",
+ "/man",
+ "/share/doc",
+ "/share/gtk-doc",
+ "/share/man",
+ "/share/pkgconfig",
+ "*.la",
+ "*.a"
+ ],
+ "modules" : [
+ {
+ "name" : "gssdp",
+ "buildsystem" : "meson",
+ "sources" : [
+ {
+ "type" : "git",
+ "url" : "https://gitlab.gnome.org/GNOME/gssdp.git/",
+ "branch" : "wip/libsoup3"
+ }
+ ]
+ },
+ {
+ "name" : "gupnp",
+ "buildsystem" : "meson",
+ "sources" : [
+ {
+ "type" : "git",
+ "url" : "https://gitlab.gnome.org/GNOME/gupnp.git/",
+ "branch" : "wip/phako/libsoup3"
+ }
+ ]
+ }
+ ]
+}
diff --git a/libgupnp/gupnp-context.c b/libgupnp/gupnp-context.c
index 6a0caa4..04b521d 100644
--- a/libgupnp/gupnp-context.c
+++ b/libgupnp/gupnp-context.c
@@ -628,6 +628,7 @@ make_server_uri (GUPnPContext *context)
{
GUri *uri = g_uri_ref (uris->data);
g_slist_free_full (uris, (GDestroyNotify) g_uri_unref);
+
return uri;
}
return NULL;
@@ -946,6 +947,7 @@ host_path_handler (G_GNUC_UNUSED SoupServer *server,
HostPathData *host_path_data;
const char *user_agent;
const char *host;
+ GBytes *buffer = NULL;
orig_locales = NULL;
locales = NULL;
@@ -1092,7 +1094,7 @@ host_path_handler (G_GNUC_UNUSED SoupServer *server,
// Creating the buffer here regardless of whether we use it.
// It will take ownership of the mapped file and we can unref it on exit
// This will prevent leaking the mapped file in other cases
- GBytes *buffer = g_bytes_new_with_free_func (
+ buffer = g_bytes_new_with_free_func (
g_mapped_file_get_contents (mapped_file),
g_mapped_file_get_length (mapped_file),
(GDestroyNotify) g_mapped_file_unref,
diff --git a/libgupnp/gupnp-resource-factory.c b/libgupnp/gupnp-resource-factory.c
index 5ad58d2..e5c3f3a 100644
--- a/libgupnp/gupnp-resource-factory.c
+++ b/libgupnp/gupnp-resource-factory.c
@@ -36,8 +36,7 @@ typedef struct _GUPnPResourceFactoryPrivate GUPnPResourceFactoryPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (GUPnPResourceFactory,
gupnp_resource_factory,
- G_TYPE_OBJECT);
-
+ G_TYPE_OBJECT)
static void
gupnp_resource_factory_init (GUPnPResourceFactory *factory)
diff --git a/libgupnp/gupnp-root-device.c b/libgupnp/gupnp-root-device.c
index 6643dc9..3c337fc 100644
--- a/libgupnp/gupnp-root-device.c
+++ b/libgupnp/gupnp-root-device.c
@@ -92,10 +92,7 @@ gupnp_root_device_dispose (GObject *object)
device = GUPNP_ROOT_DEVICE (object);
priv = gupnp_root_device_get_instance_private (device);
- if (priv->group) {
- g_object_unref (priv->group);
- priv->group = NULL;
- }
+ g_clear_object (&priv->group);
/* Call super */
object_class = G_OBJECT_CLASS (gupnp_root_device_parent_class);
diff --git a/libgupnp/gupnp-service-info.c b/libgupnp/gupnp-service-info.c
index 2a66141..ccc0f23 100644
--- a/libgupnp/gupnp-service-info.c
+++ b/libgupnp/gupnp-service-info.c
@@ -81,8 +81,8 @@ typedef struct {
static void
get_scpd_url_data_free (GetSCPDURLData *data)
{
- if (data->cancellable)
- g_object_unref (data->cancellable);
+ g_clear_object (&data->cancellable);
+ g_clear_object (&data->message);
g_slice_free (GetSCPDURLData, data);
}
@@ -209,10 +209,7 @@ gupnp_service_info_dispose (GObject *object)
priv->context = NULL;
}
- if (priv->doc) {
- g_object_unref (priv->doc);
- priv->doc = NULL;
- }
+ g_clear_object (&priv->doc);
G_OBJECT_CLASS (gupnp_service_info_parent_class)->dispose (object);
}
@@ -625,13 +622,10 @@ got_scpd_url (GObject *source, GAsyncResult *res, GetSCPDURLData *data)
priv = gupnp_service_info_get_instance_private (data->info);
priv->pending_gets = g_list_remove (priv->pending_gets, data);
- data->callback (data->info,
- introspection,
- error,
- data->user_data);
+ data->callback (data->info, introspection, error, data->user_data);
- if (error)
- g_error_free (error);
+ g_clear_error (&error);
+ g_clear_pointer (&body, g_bytes_unref);
get_scpd_url_data_free (data);
}
diff --git a/libgupnp/gupnp-service.c b/libgupnp/gupnp-service.c
index 14f34ce..d80bb3c 100644
--- a/libgupnp/gupnp-service.c
+++ b/libgupnp/gupnp-service.c
@@ -108,8 +108,15 @@ typedef struct {
subscription */
gboolean initial_state_sent;
gboolean to_delete;
+ GCancellable *cancellable;
} SubscriptionData;
+typedef struct {
+ SubscriptionData *data;
+ SoupMessage *msg;
+ GBytes *property_set;
+} NotifySubscriberData;
+
static gboolean
subscription_data_can_delete (SubscriptionData *data) {
return data->initial_state_sent && data->to_delete;
@@ -161,22 +168,17 @@ gupnp_service_get_session (GUPnPService *service)
static void
subscription_data_free (SubscriptionData *data)
{
- // SoupSession *session;
+ g_cancellable_cancel (data->cancellable);
+ g_clear_object (&data->cancellable);
// session = gupnp_service_get_session (data->service);
/* Cancel pending messages */
while (data->pending_messages) {
- /*
- SoupMessage *msg;
-
- msg = data->pending_messages->data;
-
- * FIXME: cancel elsewhere
- soup_session_cancel_message (session,
- msg,
- SOUP_STATUS_CANCELLED);
- */
+ NotifySubscriberData *d = data->pending_messages->data;
+ g_object_unref (d->msg);
+ g_bytes_unref (d->property_set);
+ g_free (d);
data->pending_messages =
g_list_delete_link (data->pending_messages,
@@ -1265,6 +1267,7 @@ subscribe (GUPnPService *service, SoupServerMessage *msg, const char *callback)
(GUPNP_SERVICE_INFO (service));
data = g_slice_new0 (SubscriptionData);
+ data->cancellable = g_cancellable_new ();
/* Parse callback list */
start = (char *) callback;
@@ -1334,6 +1337,9 @@ subscribe (GUPnPService *service, SoupServerMessage *msg, const char *callback)
/* Respond */
subscription_response (service, msg, data->sid, SUBSCRIPTION_TIMEOUT);
+ // FIXME: Should we only send this if we priv->inspection is not NULL?
+ // There might not be any useful data in the notification if there is no
+ // introspection yet
send_initial_state (data);
}
@@ -1892,7 +1898,7 @@ gupnp_service_class_init (GUPnPServiceClass *klass)
/**
* GUPnPService::notify-failed:
* @service: The #GUPnPService that received the signal
- * @callback_url: (type GList)(element-type SoupURI):A #GList of callback URLs
+ * @callback_url: (type GList)(element-type GUri):A #GList of callback URLs
* @reason: (type GError): A pointer to a #GError describing why the notify failed
*
* Emitted whenever notification of a client fails.
@@ -1979,11 +1985,6 @@ gupnp_service_notify_valist (GUPnPService *service,
}
}
-typedef struct {
- SubscriptionData *data;
- SoupMessage *msg;
- GBytes *property_set;
-} NotifySubscriberData;
/* Received notify response. */
static void
@@ -1992,6 +1993,7 @@ notify_got_response (GObject *source, GAsyncResult *res, gpointer user_data)
GBytes *body;
GError *error = NULL;
+ NotifySubscriberData *data = user_data;
body = soup_session_send_and_read_finish (SOUP_SESSION (source),
res,
@@ -2000,20 +2002,19 @@ notify_got_response (GObject *source, GAsyncResult *res, gpointer user_data)
/* Cancelled? */
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
g_clear_error (&error);
-
+ // Do nothing else. The data was freed after the message was
+ // cancelled
return;
}
// We don't need the body
g_clear_pointer (&body, g_bytes_unref);
- NotifySubscriberData *data = user_data;
-
SoupStatus status = soup_message_get_status (data->msg);
/* Remove from pending messages list */
data->data->pending_messages =
- g_list_remove (data->data->pending_messages, data->msg);
+ g_list_remove (data->data->pending_messages, data);
if (SOUP_STATUS_IS_SUCCESSFUL (status)) {
data->data->initial_state_sent = TRUE;
@@ -2035,7 +2036,6 @@ notify_got_response (GObject *source, GAsyncResult *res, gpointer user_data)
notify_subscriber (NULL,
data->data,
g_bytes_ref (data->property_set));
- g_bytes_unref (data->property_set);
} else {
/* Emit 'notify-failed' signal */
GError *inner_error;
@@ -2058,7 +2058,6 @@ notify_got_response (GObject *source, GAsyncResult *res, gpointer user_data)
g_list_first (data->data->callbacks);
}
}
-
g_clear_error (&error);
g_bytes_unref (data->property_set);
g_object_unref (data->msg);
@@ -2091,9 +2090,7 @@ notify_subscriber (G_GNUC_UNUSED gpointer key,
soup_message_get_request_headers (data->msg);
soup_message_headers_append (request_headers, "NT", "upnp:event");
-
soup_message_headers_append (request_headers, "NTS", "upnp:propchange");
-
soup_message_headers_append (request_headers, "SID", data->data->sid);
tmp = g_strdup_printf ("%d", data->data->seq);
@@ -2113,7 +2110,7 @@ notify_subscriber (G_GNUC_UNUSED gpointer key,
/* Queue */
data->data->pending_messages =
- g_list_prepend (data->data->pending_messages, data->msg);
+ g_list_prepend (data->data->pending_messages, data);
soup_message_headers_append (request_headers, "Connection", "close");
session = gupnp_service_get_session (data->data->service);
@@ -2122,7 +2119,7 @@ notify_subscriber (G_GNUC_UNUSED gpointer key,
session,
data->msg,
G_PRIORITY_DEFAULT,
- NULL,
+ data->data->cancellable,
(GAsyncReadyCallback) notify_got_response,
data);
}
diff --git a/libgupnp/meson.build b/libgupnp/meson.build
index cb8a102..1484ce0 100644
--- a/libgupnp/meson.build
+++ b/libgupnp/meson.build
@@ -136,7 +136,7 @@ pkg.generate(
)
if get_option('introspection')
- gir_includes = ['GObject-2.0', 'Gio-2.0', 'Soup-2.4', 'libxml2-2.0']
+ gir_includes = ['GObject-2.0', 'Gio-2.0', 'Soup-3.0', 'libxml2-2.0']
if gssdp_dep.type_name() == 'internal'
gir_includes += subproject('gssdp-1.2').get_variable('gir').get(0)
else
diff --git a/tests/meson.build b/tests/meson.build
index 33637d7..a6f0b4b 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -1,11 +1,12 @@
-foreach program : ['context', 'bugs']
+foreach program : ['context', 'bugs', 'service']
test(
program,
executable(
'test-' + program,
'test-@0@.c'.format (program),
dependencies : gupnp,
- c_args : '-DDATA_PATH="@0@/data"'.format(meson.current_source_dir())
+ c_args : '-DDATA_PATH="@0@/data"'.format(meson.current_source_dir()),
+ include_directories : config_h_inc,
),
is_parallel : false
)
diff --git a/tests/test-bugs.c b/tests/test-bugs.c
index b99ffd2..0b41011 100644
--- a/tests/test-bugs.c
+++ b/tests/test-bugs.c
@@ -6,9 +6,7 @@
* 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>
diff --git a/tests/test-service.c b/tests/test-service.c
new file mode 100644
index 0000000..c69910c
--- /dev/null
+++ b/tests/test-service.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+#include <config.h>
+
+#include <libgupnp/gupnp-xml-doc.h>
+
+#include <libgupnp/gupnp-context-private.h>
+#include <libgupnp/gupnp-service-private.h>
+#include <libgupnp/gupnp.h>
+
+static GUPnPContext *
+create_context (guint16 port, GError **error)
+{
+ return GUPNP_CONTEXT (g_initable_new (GUPNP_TYPE_CONTEXT,
+ NULL,
+ error,
+ "host-ip",
+ "127.0.0.1",
+ "msearch-port",
+ port,
+ NULL));
+}
+
+typedef struct {
+ GMainLoop *loop;
+ SoupServerMessage *message;
+} TestServiceNotificationCancelledData;
+
+void
+on_notify (SoupServer *server,
+ SoupServerMessage *msg,
+ const char *path,
+ GHashTable *query,
+ gpointer user_data)
+{
+ TestServiceNotificationCancelledData *data = user_data;
+
+ // Pause message, quit mainlopp
+ soup_server_pause_message (server, msg);
+ data->message = msg;
+ g_main_loop_quit (data->loop);
+}
+
+void
+on_subscribe (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ GError *error = NULL;
+
+ GBytes *data = soup_session_send_and_read_finish (SOUP_SESSION (source),
+ res,
+ &error);
+
+ g_assert_no_error (error);
+ g_clear_pointer (&data, g_bytes_unref);
+}
+
+static void
+on_finished (SoupServerMessage *msg, TestServiceNotificationCancelledData *data)
+{
+ g_assert_cmpint (soup_server_message_get_status (msg),
+ ==,
+ SOUP_STATUS_INTERNAL_SERVER_ERROR);
+ g_main_loop_quit (data->loop);
+}
+
+static void
+test_service_notification_cancelled ()
+{
+ GUPnPContext *context = NULL;
+ GError *error = NULL;
+ GUPnPRootDevice *rd;
+ GUPnPServiceInfo *info = NULL;
+
+ TestServiceNotificationCancelledData data = { NULL, NULL };
+
+ data.loop = g_main_loop_new (NULL, FALSE);
+
+ context = create_context (0, &error);
+ g_assert_no_error (error);
+ g_assert (context != NULL);
+
+ rd = gupnp_root_device_new (context,
+ "TestDevice.xml",
+ DATA_PATH,
+ &error);
+ g_assert_no_error (error);
+ g_assert (rd != NULL);
+ gupnp_root_device_set_available (rd, TRUE);
+
+ SoupServer *server = soup_server_new (NULL, NULL);
+ soup_server_add_handler (server, "/Notify", on_notify, &data, NULL);
+ soup_server_listen_local (server,
+ 0,
+ SOUP_SERVER_LISTEN_IPV4_ONLY,
+ &error);
+ g_assert_no_error (error);
+
+ // Generate SUBSCRIBE message
+ info = gupnp_device_info_get_service (
+ GUPNP_DEVICE_INFO (rd),
+ "urn:test-gupnp-org:service:TestService:1");
+ char *url = gupnp_service_info_get_event_subscription_url (info);
+ SoupMessage *msg = soup_message_new ("SUBSCRIBE", url);
+ g_free (url);
+
+ GSList *uris = soup_server_get_uris (server);
+ GUri *subscription =
+ soup_uri_copy (uris->data, SOUP_URI_PATH, "/Notify", NULL);
+ char *uri_string = g_uri_to_string (subscription);
+ char *callback = g_strdup_printf ("<%s>", uri_string);
+ g_free (uri_string);
+ g_slist_free_full (uris, (GDestroyNotify) g_uri_unref);
+ g_uri_unref (subscription);
+
+ SoupMessageHeaders *h = soup_message_get_request_headers (msg);
+ soup_message_headers_append (h, "Callback", callback);
+ g_free (callback);
+
+ soup_message_headers_append (h, "NT", "upnp:event");
+ SoupSession *session = soup_session_new ();
+ // FIXME: Add timeout header
+ soup_session_send_and_read_async (session,
+ msg,
+ G_PRIORITY_DEFAULT,
+ NULL,
+ on_subscribe,
+ &data);
+
+ g_main_loop_run (data.loop);
+ g_signal_connect (data.message,
+ "finished",
+ G_CALLBACK (on_finished),
+ &data);
+
+ g_clear_object (&info);
+
+ soup_server_unpause_message (server, data.message);
+
+ g_main_loop_run (data.loop);
+ g_clear_object (&rd);
+ g_clear_object (&msg);
+ g_clear_object (&session);
+ g_clear_object (&server);
+ g_clear_object (&context);
+ g_main_loop_unref (data.loop);
+}
+int
+main (int argc, char *argv[])
+{
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add_func ("/service/notify/cancel",
+ test_service_notification_cancelled);
+
+ return g_test_run ();
+}
diff --git a/vala/gupnp-1.2.deps b/vala/gupnp-1.2.deps
index 48dcf61..1085e17 100644
--- a/vala/gupnp-1.2.deps
+++ b/vala/gupnp-1.2.deps
@@ -1,3 +1,3 @@
gssdp-1.2
-libsoup-2.4
+libsoup-3.0
libxml-2.0
diff --git a/vala/meson.build b/vala/meson.build
index aacaa71..3ab40fc 100644
--- a/vala/meson.build
+++ b/vala/meson.build
@@ -8,7 +8,7 @@ endif
gnome.generate_vapi('gupnp-1.2',
sources : [gir.get(0), 'gupnp-1.2-custom.vala'],
- packages : [gssdp_vala_package, 'gio-2.0', 'libsoup-2.4', 'libxml-2.0'],
+ packages : [gssdp_vala_package, 'gio-2.0', 'libsoup-3.0', 'libxml-2.0'],
gir_dirs : gssdp_gir_dirs,
install : true
)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]