diff options
author | Jens Georg <mail@jensge.org> | 2021-08-07 09:46:54 +0200 |
---|---|---|
committer | Jens Georg <mail@jensge.org> | 2021-09-19 23:51:52 +0200 |
commit | 2b28a0ba62547fbe5ed63de6a3cf8614c87c10e8 (patch) | |
tree | caea7035ff80d66bd01c4039476792f6a9c639a1 | |
parent | 04cabaa8aeac1d4550f367024350324418bde683 (diff) | |
download | gupnp-wip/phako/libsoup3.tar.gz |
wip: More libsoup3 fixeswip/phako/libsoup3
-rw-r--r-- | .gitlab-ci.yml | 3 | ||||
-rw-r--r-- | build-aux/org.gnome.GUPnP.json | 59 | ||||
-rw-r--r-- | libgupnp/gupnp-context.c | 4 | ||||
-rw-r--r-- | libgupnp/gupnp-resource-factory.c | 3 | ||||
-rw-r--r-- | libgupnp/gupnp-root-device.c | 5 | ||||
-rw-r--r-- | libgupnp/gupnp-service-info.c | 18 | ||||
-rw-r--r-- | libgupnp/gupnp-service.c | 51 | ||||
-rw-r--r-- | libgupnp/meson.build | 2 | ||||
-rw-r--r-- | tests/meson.build | 5 | ||||
-rw-r--r-- | tests/test-bugs.c | 2 | ||||
-rw-r--r-- | tests/test-service.c | 156 | ||||
-rw-r--r-- | vala/gupnp-1.2.deps | 2 | ||||
-rw-r--r-- | 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 32dca4b..6d2b798 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 ) |