[gupnp/wip/phako/libsoup3] Initial port to libsoup3 API




commit 5248162f915fc7915b728b7adb54cc669e18db5b
Author: Jens Georg <mail jensge org>
Date:   Mon Jul 26 23:30:01 2021 +0200

    Initial port to libsoup3 API

 libgupnp/gupnp-acl-private.h                  |   6 +-
 libgupnp/gupnp-acl.c                          |   6 +-
 libgupnp/gupnp-context-manager.c              |   3 +-
 libgupnp/gupnp-context-private.h              |   4 +-
 libgupnp/gupnp-context.c                      | 211 +++++++-------
 libgupnp/gupnp-control-point.c                |  62 +++--
 libgupnp/gupnp-device-info.c                  |  17 +-
 libgupnp/gupnp-device-info.h                  |   3 +-
 libgupnp/gupnp-device-proxy.c                 |   4 +-
 libgupnp/gupnp-device.c                       |   4 +-
 libgupnp/gupnp-error.c                        |   8 +-
 libgupnp/gupnp-resource-factory-private.h     |   8 +-
 libgupnp/gupnp-resource-factory.c             |   8 +-
 libgupnp/gupnp-root-device.c                  |  17 +-
 libgupnp/gupnp-service-info.c                 |  44 +--
 libgupnp/gupnp-service-info.h                 |   3 +-
 libgupnp/gupnp-service-private.h              |   2 +-
 libgupnp/gupnp-service-proxy-action-private.h |   1 +
 libgupnp/gupnp-service-proxy-action.c         |  21 +-
 libgupnp/gupnp-service-proxy.c                | 318 +++++++++++++--------
 libgupnp/gupnp-service.c                      | 380 +++++++++++++++-----------
 libgupnp/gupnp-service.h                      |   2 +-
 libgupnp/gupnp-unix-context-manager.c         |   1 -
 libgupnp/http-headers.c                       |  25 +-
 libgupnp/http-headers.h                       |   8 +-
 libgupnp/xml-util.c                           |  19 +-
 libgupnp/xml-util.h                           |   7 +-
 meson.build                                   |   8 +-
 tests/test-bugs.c                             |  17 +-
 tests/test-context.c                          |  67 +++--
 30 files changed, 734 insertions(+), 550 deletions(-)
---
diff --git a/libgupnp/gupnp-acl-private.h b/libgupnp/gupnp-acl-private.h
index f243569..0a10f47 100644
--- a/libgupnp/gupnp-acl-private.h
+++ b/libgupnp/gupnp-acl-private.h
@@ -43,10 +43,9 @@ typedef struct _AclServerHandler
 typedef struct _AclAsyncHandler
 {
         SoupServer *server;
-        SoupMessage *message;
+        SoupServerMessage *message;
         char *path;
         GHashTable *query;
-        SoupClientContext *client;
         AclServerHandler *handler;
 } AclAsyncHandler;
 
@@ -62,10 +61,9 @@ acl_server_handler_free (AclServerHandler *handler);
 
 G_GNUC_INTERNAL AclAsyncHandler *
 acl_async_handler_new (SoupServer *server,
-                       SoupMessage *message,
+                       SoupServerMessage *message,
                        const char *path,
                        GHashTable *query,
-                       SoupClientContext *client,
                        AclServerHandler *handler);
 
 G_GNUC_INTERNAL void
diff --git a/libgupnp/gupnp-acl.c b/libgupnp/gupnp-acl.c
index ff8c4f9..e7f7e88 100644
--- a/libgupnp/gupnp-acl.c
+++ b/libgupnp/gupnp-acl.c
@@ -219,10 +219,9 @@ acl_server_handler_free (AclServerHandler *handler)
  */
 AclAsyncHandler *
 acl_async_handler_new (SoupServer *server,
-                       SoupMessage *message,
+                       SoupServerMessage *message,
                        const char *path,
                        GHashTable *query,
-                       SoupClientContext *client,
                        AclServerHandler *handler)
 {
         AclAsyncHandler *data = g_slice_new0 (AclAsyncHandler);
@@ -232,7 +231,6 @@ acl_async_handler_new (SoupServer *server,
         data->path = g_strdup (path);
         if (query != NULL)
                 data->query = g_hash_table_ref (query);
-        data->client = g_boxed_copy (SOUP_TYPE_CLIENT_CONTEXT, client);
         data->handler = handler;
 
         return data;
@@ -253,7 +251,7 @@ acl_async_handler_free (AclAsyncHandler *handler)
         g_free (handler->path);
         if (handler->query != NULL)
                 g_hash_table_unref (handler->query);
-        g_boxed_free (SOUP_TYPE_CLIENT_CONTEXT, handler->client);
+        //g_boxed_free (SOUP_TYPE_CLIENT_CONTEXT, handler->client);
 
         g_slice_free (AclAsyncHandler, handler);
 }
diff --git a/libgupnp/gupnp-context-manager.c b/libgupnp/gupnp-context-manager.c
index 534899d..66bfca0 100644
--- a/libgupnp/gupnp-context-manager.c
+++ b/libgupnp/gupnp-context-manager.c
@@ -29,7 +29,6 @@
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
-#include <libsoup/soup-address.h>
 #include <glib.h>
 #include <glib/gstdio.h>
 
@@ -493,7 +492,7 @@ gupnp_context_manager_class_init (GUPnPContextManagerClass *klass)
                  g_param_spec_uint ("port",
                                     "Port",
                                     "Port to create contexts for",
-                                    0, G_MAXUINT, SOUP_ADDRESS_ANY_PORT,
+                                    0, G_MAXUINT, 0,
                                     G_PARAM_READWRITE |
                                     G_PARAM_CONSTRUCT_ONLY |
                                     G_PARAM_STATIC_NAME |
diff --git a/libgupnp/gupnp-context-private.h b/libgupnp/gupnp-context-private.h
index e5cd507..2259582 100644
--- a/libgupnp/gupnp-context-private.h
+++ b/libgupnp/gupnp-context-private.h
@@ -15,7 +15,7 @@
 
 G_BEGIN_DECLS
 
-G_GNUC_INTERNAL SoupURI *
+G_GNUC_INTERNAL GUri *
 _gupnp_context_get_server_uri (GUPnPContext *context);
 
 G_GNUC_INTERNAL void
@@ -23,7 +23,7 @@ _gupnp_context_add_server_handler_with_data (GUPnPContext *context,
                                              const char *path,
                                              AclServerHandler *data);
 
-G_GNUC_INTERNAL SoupURI *
+G_GNUC_INTERNAL GUri *
 gupnp_context_rewrite_uri_to_uri (GUPnPContext *context,
                                   const char   *uri);
 
diff --git a/libgupnp/gupnp-context.c b/libgupnp/gupnp-context.c
index efec13f..45fe816 100644
--- a/libgupnp/gupnp-context.c
+++ b/libgupnp/gupnp-context.c
@@ -36,7 +36,6 @@
 #endif
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <libsoup/soup-address.h>
 #include <glib/gstdio.h>
 
 #include "gupnp-acl.h"
@@ -52,10 +51,9 @@
 
 static void
 gupnp_acl_server_handler (SoupServer *server,
-                          SoupMessage *msg,
+                          SoupServerMessage *msg,
                           const char *path,
                           GHashTable *query,
-                          SoupClientContext *client,
                           gpointer user_data);
 
 static void
@@ -70,7 +68,7 @@ struct _GUPnPContextPrivate {
         SoupSession *session;
 
         SoupServer  *server; /* Started on demand */
-        SoupURI     *server_uri;
+        GUri     *server_uri;
         char        *default_language;
 
         GList       *host_path_datas;
@@ -189,15 +187,13 @@ gupnp_context_initable_init (GInitable     *initable,
 
         user_agent = g_strdup_printf ("%s GUPnP/" VERSION " DLNADOC/1.50",
                                       g_get_prgname ()? : "");
-        g_object_set (priv->session,
-                      SOUP_SESSION_USER_AGENT,
-                      user_agent,
-                      NULL);
+
+        soup_session_set_user_agent (priv->session, user_agent);
         g_free (user_agent);
 
         if (g_getenv ("GUPNP_DEBUG")) {
                 SoupLogger *logger;
-                logger = soup_logger_new (SOUP_LOGGER_LOG_BODY, -1);
+                logger = soup_logger_new (SOUP_LOGGER_LOG_BODY);
                 soup_session_add_feature (priv->session,
                                           SOUP_SESSION_FEATURE (logger));
         }
@@ -349,7 +345,7 @@ gupnp_context_finalize (GObject *object)
         g_free (priv->default_language);
 
         if (priv->server_uri)
-                soup_uri_free (priv->server_uri);
+                g_uri_unref (priv->server_uri);
 
         /* Call super */
         object_class = G_OBJECT_CLASS (gupnp_context_parent_class);
@@ -418,7 +414,7 @@ gupnp_context_class_init (GUPnPContextClass *klass)
                  g_param_spec_uint ("port",
                                     "Port",
                                     "Port to run on",
-                                    0, G_MAXUINT, SOUP_ADDRESS_ANY_PORT,
+                                    0, G_MAXUINT, 0,
                                     G_PARAM_READWRITE |
                                     G_PARAM_CONSTRUCT_ONLY |
                                     G_PARAM_STATIC_NAME |
@@ -549,13 +545,12 @@ gupnp_context_get_session (GUPnPContext *context)
  **/
 static void
 default_server_handler (G_GNUC_UNUSED SoupServer        *server,
-                        SoupMessage                     *msg,
+                        SoupServerMessage               *msg,
                         G_GNUC_UNUSED const char        *path,
                         G_GNUC_UNUSED GHashTable        *query,
-                        G_GNUC_UNUSED SoupClientContext *client,
                         G_GNUC_UNUSED gpointer           user_data)
 {
-        soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND);
+        soup_server_message_set_status (msg, SOUP_STATUS_NOT_FOUND, "Not found");
 }
 
 /**
@@ -621,21 +616,21 @@ gupnp_context_get_server (GUPnPContext *context)
 /*
  * Makes a SoupURI that refers to our server.
  **/
-static SoupURI *
+static GUri *
 make_server_uri (GUPnPContext *context)
 {
         SoupServer *server = gupnp_context_get_server (context);
         GSList *uris = soup_server_get_uris (server);
         if (uris)
         {
-                SoupURI *uri = soup_uri_copy (uris->data);
-                g_slist_free_full (uris, (GDestroyNotify) soup_uri_free);
+                GUri *uri = g_uri_ref (uris->data);
+                g_slist_free_full (uris, (GDestroyNotify) g_uri_unref);
                 return uri;
         }
         return NULL;
 }
 
-SoupURI *
+GUri *
 _gupnp_context_get_server_uri (GUPnPContext *context)
 {
         GUPnPContextPrivate *priv;
@@ -645,7 +640,7 @@ _gupnp_context_get_server_uri (GUPnPContext *context)
                 priv->server_uri = make_server_uri (context);
 
         if (priv->server_uri)
-                return soup_uri_copy (priv->server_uri);
+                return g_uri_ref (priv->server_uri);
 
         return NULL;
 }
@@ -694,7 +689,7 @@ gupnp_context_get_port (GUPnPContext *context)
         if (priv->server_uri == NULL)
                 priv->server_uri = make_server_uri (context);
 
-        return soup_uri_get_port (priv->server_uri);
+        return g_uri_get_port (priv->server_uri);
 }
 
 /**
@@ -891,17 +886,17 @@ append_locale (const char *local_path, GList *locales)
 
 /* Redirect @msg to the same URI, but with a slash appended. */
 static void
-redirect_to_folder (SoupMessage *msg)
+redirect_to_folder (SoupServerMessage *msg)
 {
         char *uri, *redir_uri;
 
-        uri = soup_uri_to_string (soup_message_get_uri (msg),
-                                  FALSE);
+        uri = g_uri_to_string_partial (soup_server_message_get_uri (msg), G_URI_HIDE_PASSWORD);
         redir_uri = g_strdup_printf ("%s/", uri);
-        soup_message_headers_append (msg->response_headers,
+        soup_message_headers_append (soup_server_message_get_response_headers (msg),
                                      "Location", redir_uri);
-        soup_message_set_status (msg,
-                                 SOUP_STATUS_MOVED_PERMANENTLY);
+        soup_server_message_set_status (msg,
+                                        SOUP_STATUS_MOVED_PERMANENTLY,
+                                        "Moved permanently");
         g_free (redir_uri);
         g_free (uri);
 }
@@ -931,10 +926,9 @@ update_client_cache (GUPnPContext *context,
  * '..' as libsoup does this for us. */
 static void
 host_path_handler (G_GNUC_UNUSED SoupServer        *server,
-                   SoupMessage                     *msg,
+                   SoupServerMessage               *msg,
                    const char                      *path,
                    G_GNUC_UNUSED GHashTable        *query,
-                   SoupClientContext               *client_ctx,
                    gpointer                         user_data)
 {
         char *local_path, *path_to_open;
@@ -953,9 +947,9 @@ host_path_handler (G_GNUC_UNUSED SoupServer        *server,
         path_to_open = NULL;
         host_path_data = (HostPathData *) user_data;
 
-        if (msg->method != SOUP_METHOD_GET &&
-            msg->method != SOUP_METHOD_HEAD) {
-                soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
+        if (soup_server_message_get_method (msg) != SOUP_METHOD_GET &&
+            soup_server_message_get_method (msg) != SOUP_METHOD_HEAD) {
+                soup_server_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED, "Not implemented");
 
                 goto DONE;
         }
@@ -964,16 +958,16 @@ host_path_handler (G_GNUC_UNUSED SoupServer        *server,
          * Also set Connection: close header, since the request originated
          * from a HTTP 1.0 client
          */
-        if (soup_message_get_http_version (msg) == SOUP_HTTP_1_0) {
-                soup_message_set_http_version (msg, SOUP_HTTP_1_1);
-                soup_message_headers_append (msg->response_headers,
+        if (soup_server_message_get_http_version (msg) == SOUP_HTTP_1_0) {
+                soup_server_message_set_http_version (msg, SOUP_HTTP_1_1);
+                soup_message_headers_append (soup_server_message_get_response_headers (msg),
                                              "Connection",
                                              "close");
         }
 
-        user_agent = soup_message_headers_get_one (msg->request_headers,
+        user_agent = soup_message_headers_get_one (soup_server_message_get_request_headers (msg),
                                                    "User-Agent");
-        host = soup_client_context_get_host (client_ctx);
+        host = soup_server_message_get_remote_host (msg);
 
         /* If there was no User-Agent in the request, try to guess from the
          * discovery message and put it into the response headers for further
@@ -985,7 +979,7 @@ host_path_handler (G_GNUC_UNUSED SoupServer        *server,
                 user_agent = gssdp_client_guess_user_agent (client, host);
 
                 if (user_agent != NULL) {
-                        soup_message_headers_append (msg->response_headers,
+                        soup_message_headers_append (soup_server_message_get_response_headers (msg),
                                                      "User-Agent",
                                                      user_agent);
                 }
@@ -996,13 +990,13 @@ host_path_handler (G_GNUC_UNUSED SoupServer        *server,
         /* Construct base local path */
         local_path = construct_local_path (path, user_agent, host_path_data);
         if (!local_path) {
-                soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST);
+                soup_server_message_set_status (msg, SOUP_STATUS_BAD_REQUEST, "Bad request");
 
                 goto DONE;
         }
 
         /* Get preferred locales */
-        orig_locales = locales = http_request_get_accept_locales (msg);
+        orig_locales = locales = http_request_get_accept_locales (soup_server_message_get_request_headers 
(msg));
 
  AGAIN:
         /* Add locale suffix if available */
@@ -1011,7 +1005,7 @@ host_path_handler (G_GNUC_UNUSED SoupServer        *server,
         /* See what we've got */
         if (g_stat (path_to_open, &st) == -1) {
                 if (errno == EPERM)
-                        soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN);
+                        soup_server_message_set_status (msg, SOUP_STATUS_FORBIDDEN, "Forbidden");
                 else if (errno == ENOENT) {
                         if (locales) {
                                 g_free (path_to_open);
@@ -1020,11 +1014,12 @@ host_path_handler (G_GNUC_UNUSED SoupServer        *server,
 
                                 goto AGAIN;
                         } else
-                                soup_message_set_status (msg,
-                                                         SOUP_STATUS_NOT_FOUND);
+                                soup_server_message_set_status (msg,
+                                                         SOUP_STATUS_NOT_FOUND,
+                                                         "Not found");
                 } else
-                        soup_message_set_status
-                                (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
+                        soup_server_message_set_status
+                                (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR, "Internal server error");
 
                 goto DONE;
         }
@@ -1059,25 +1054,36 @@ host_path_handler (G_GNUC_UNUSED SoupServer        *server,
 
                 g_error_free (error);
 
-                soup_message_set_status (msg,
-                                         SOUP_STATUS_INTERNAL_SERVER_ERROR);
+                soup_server_message_set_status (msg,
+                                         SOUP_STATUS_INTERNAL_SERVER_ERROR, "Internal server error");
 
                 goto DONE;
         }
 
         /* Handle method (GET or HEAD) */
         status = SOUP_STATUS_OK;
+        SoupMessageHeaders *response_headers = soup_server_message_get_response_headers (msg);
+        SoupMessageHeaders *request_headers = soup_server_message_get_request_headers (msg);
+
+        /* Add requested content */
+        // 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 (g_mapped_file_get_contents (mapped_file),
+                                                     g_mapped_file_get_length (mapped_file),
+                                                     (GDestroyNotify) g_mapped_file_unref,
+                                                     mapped_file);
 
-        if (msg->method == SOUP_METHOD_GET) {
+
+        if (soup_server_message_get_method (msg)== SOUP_METHOD_GET) {
                 gboolean have_range;
-                SoupBuffer *buffer;
                 SoupRange *ranges;
                 int nranges;
 
                 /* Find out range */
                 have_range = FALSE;
 
-                if (soup_message_headers_get_ranges (msg->request_headers,
+                if (soup_message_headers_get_ranges (request_headers,
                                                      st.st_size,
                                                      &ranges,
                                                      &nranges))
@@ -1089,90 +1095,86 @@ host_path_handler (G_GNUC_UNUSED SoupServer        *server,
                                    st.st_size < 0 ||
                                    ranges[0].start >= st.st_size ||
                                    ranges[0].start > ranges[0].end)) {
-                        soup_message_set_status
+                        soup_server_message_set_status
                                 (msg,
-                                 SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE);
-                        soup_message_headers_free_ranges (msg->request_headers,
+                                 SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE,
+                                 "Range not satisfyable");
+                        soup_message_headers_free_ranges (request_headers,
                                                           ranges);
 
                         goto DONE;
                 }
 
-                /* Add requested content */
-                buffer = soup_buffer_new_with_owner
-                             (g_mapped_file_get_contents (mapped_file),
-                              g_mapped_file_get_length (mapped_file),
-                              mapped_file,
-                              (GDestroyNotify) g_mapped_file_unref);
+                SoupMessageBody *message_body = soup_server_message_get_response_body (msg);
 
                 /* Set range and status */
                 if (have_range) {
-                        SoupBuffer *range_buffer;
+                        GBytes *range_buffer;
 
-                        soup_message_body_truncate (msg->response_body);
+                        soup_message_body_truncate (message_body);
                         soup_message_headers_set_content_range (
-                                                          msg->response_headers,
+                                                          response_headers,
                                                           ranges[0].start,
                                                           ranges[0].end,
-                                                          buffer->length);
-                        range_buffer = soup_buffer_new_subbuffer (
-                                           buffer,
+                                                          g_bytes_get_size (buffer));
+                        range_buffer = g_bytes_new_from_bytes (buffer,
                                            ranges[0].start,
                                            ranges[0].end - ranges[0].start + 1);
-                        soup_message_body_append_buffer (msg->response_body,
-                                                         range_buffer);
+                        soup_message_body_append_bytes (message_body,
+                                                        range_buffer);
                         status = SOUP_STATUS_PARTIAL_CONTENT;
 
-                        soup_message_headers_free_ranges (msg->request_headers,
+                        soup_message_headers_free_ranges (request_headers,
                                                           ranges);
-                        soup_buffer_free (range_buffer);
+                        g_bytes_unref (range_buffer);
                 } else
-                        soup_message_body_append_buffer (msg->response_body, buffer);
+                        soup_message_body_append_bytes (message_body, buffer);
 
-                soup_buffer_free (buffer);
-        } else if (msg->method == SOUP_METHOD_HEAD) {
+        } else if (soup_server_message_get_method (msg) == SOUP_METHOD_HEAD) {
                 char *length;
 
-                length = g_strdup_printf ("%lu", (gulong) st.st_size);
-                soup_message_headers_append (msg->response_headers,
+                length = g_strdup_printf ("%zu", st.st_size);
+                soup_message_headers_append (response_headers,
                                              "Content-Length",
                                              length);
                 g_free (length);
 
         } else {
-                soup_message_set_status (msg,
-                                         SOUP_STATUS_METHOD_NOT_ALLOWED);
+                soup_server_message_set_status (msg,
+                                         SOUP_STATUS_METHOD_NOT_ALLOWED,
+                                         "Method not allowed");
 
                 goto DONE;
         }
 
         /* Set Content-Type */
-        http_response_set_content_type (msg,
-                                        path_to_open, 
+        http_response_set_content_type (response_headers,
+                                        path_to_open,
                                         (guchar *) g_mapped_file_get_contents
                                                                 (mapped_file),
                                         st.st_size);
 
         /* Set Content-Language */
         if (locales)
-                http_response_set_content_locale (msg, locales->data);
-        else if (soup_message_headers_get_one (msg->request_headers,
+                http_response_set_content_locale (response_headers, locales->data);
+        else if (soup_message_headers_get_one (request_headers,
                                                "Accept-Language")) {
-                soup_message_headers_append (msg->response_headers,
+                soup_message_headers_append (response_headers,
                                              "Content-Language",
                                              host_path_data->default_language);
         }
 
         /* Set Accept-Ranges */
-        soup_message_headers_append (msg->response_headers,
+        soup_message_headers_append (response_headers,
                                      "Accept-Ranges",
                                      "bytes");
 
         /* Set status */
-        soup_message_set_status (msg, status);
+        soup_server_message_set_status (msg, status, NULL);
 
  DONE:
         /* Cleanup */
+        g_bytes_unref (buffer);
         g_free (path_to_open);
         g_free (local_path);
 
@@ -1428,13 +1430,12 @@ gupnp_acl_async_callback (GUPnPAcl *acl,
         allowed = gupnp_acl_is_allowed_finish (acl, res, &error);
         soup_server_unpause_message (data->server, data->message);
         if (!allowed)
-                soup_message_set_status (data->message, SOUP_STATUS_FORBIDDEN);
+                soup_server_message_set_status (data->message, SOUP_STATUS_FORBIDDEN, "Forbidden");
         else
                 data->handler->callback (data->server,
                                          data->message,
                                          data->path,
                                          data->query,
-                                         data->client,
                                          data->handler->user_data);
 
         acl_async_handler_free (data);
@@ -1442,10 +1443,9 @@ gupnp_acl_async_callback (GUPnPAcl *acl,
 
 static void
 gupnp_acl_server_handler (SoupServer *server,
-                          SoupMessage *msg,
+                          SoupServerMessage *msg,
                           const char *path,
                           GHashTable *query,
-                          SoupClientContext *client,
                           gpointer user_data)
 {
         AclServerHandler *handler = (AclServerHandler *) user_data;
@@ -1455,7 +1455,7 @@ gupnp_acl_server_handler (SoupServer *server,
         GUPnPContextPrivate *priv;
 
         priv = gupnp_context_get_instance_private (handler->context);
-        host = soup_client_context_get_host (client);
+        host = soup_server_message_get_remote_host (msg);
 
         if (handler->service) {
                 g_object_get (handler->service,
@@ -1467,7 +1467,7 @@ gupnp_acl_server_handler (SoupServer *server,
                 }
         }
 
-        agent = soup_message_headers_get_one (msg->request_headers,
+        agent = soup_message_headers_get_one (soup_server_message_get_request_headers (msg),
                                               "User-Agent");
         if (agent == NULL) {
                 agent = gssdp_client_guess_user_agent
@@ -1483,21 +1483,21 @@ gupnp_acl_server_handler (SoupServer *server,
                                                    path,
                                                    host,
                                                    agent)) {
-                                soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN);
+                                soup_server_message_set_status (msg, SOUP_STATUS_FORBIDDEN, "Forbidden");
 
                                 return;
                         }
                 } else {
                         AclAsyncHandler *data;
 
-                        data = acl_async_handler_new (server, msg, path, query, client, handler);
+                        data = acl_async_handler_new (server, msg, path, query, handler);
 
                         soup_server_pause_message (server, msg);
                         gupnp_acl_is_allowed_async (priv->acl,
                                                     device,
                                                     handler->service,
                                                     path,
-                                                    soup_client_context_get_host (client),
+                                                    host,
                                                     agent,
                                                     NULL,
                                                     (GAsyncReadyCallback) gupnp_acl_async_callback,
@@ -1508,7 +1508,7 @@ gupnp_acl_server_handler (SoupServer *server,
         }
 
         /* Delegate to orignal callback */
-        handler->callback (server, msg, path, query, client, handler->user_data);
+        handler->callback (server, msg, path, query, handler->user_data);
 }
 
 /**
@@ -1563,6 +1563,8 @@ _gupnp_context_add_server_handler_with_data (GUPnPContext *context,
 
         g_return_if_fail (GUPNP_IS_CONTEXT (context));
 
+        g_print ("Adding ACL-Protected handler for %s\n", path);
+
         priv = gupnp_context_get_instance_private (context);
         soup_server_add_handler (priv->server,
                                  path,
@@ -1607,7 +1609,7 @@ gupnp_context_remove_server_handler (GUPnPContext *context, const char *path)
 char *
 gupnp_context_rewrite_uri (GUPnPContext *context, const char *uri)
 {
-        SoupURI *soup_uri = NULL;
+        GUri *soup_uri = NULL;
         char *retval = NULL;
 
         soup_uri = gupnp_context_rewrite_uri_to_uri (context, uri);
@@ -1616,8 +1618,8 @@ gupnp_context_rewrite_uri (GUPnPContext *context, const char *uri)
                 return NULL;
         }
 
-        retval = soup_uri_to_string (soup_uri, FALSE);
-        soup_uri_free (soup_uri);
+        retval = g_uri_to_string_partial (soup_uri, G_URI_HIDE_PASSWORD);
+        g_uri_unref (soup_uri);
 
         return retval;
 }
@@ -1636,23 +1638,26 @@ gupnp_context_rewrite_uri (GUPnPContext *context, const char *uri)
  * Since: 1.2.3
  * Stability: Private
  */
-SoupURI *
+GUri *
 gupnp_context_rewrite_uri_to_uri (GUPnPContext *context, const char *uri)
 {
         const char *host = NULL;
-        SoupURI *soup_uri = NULL;
+        GUri *soup_uri = NULL;
         GInetAddress *addr = NULL;
         int index = -1;
+        GError *error = NULL;
 
-        soup_uri = soup_uri_new (uri);
+        soup_uri = g_uri_parse (uri, G_URI_FLAGS_NONE, &error);
 
-        if (soup_uri == NULL) {
-                g_warning ("Invalid call-back url: %s", uri);
+        if (error != NULL ) {
+                g_warning ("Invalid call-back url: %s (%s)", uri, error->message);
+
+                g_clear_error (&error);
 
                 return NULL;
         }
 
-        host = soup_uri_get_host (soup_uri);
+        host = g_uri_get_host (soup_uri);
         addr = g_inet_address_new_from_string (host);
         index = gssdp_client_get_index (GSSDP_CLIENT (context));
 
@@ -1663,8 +1668,10 @@ gupnp_context_rewrite_uri_to_uri (GUPnPContext *context, const char *uri)
                 new_host = g_strdup_printf ("%s%%%d",
                                             host,
                                             index);
-                soup_uri_set_host (soup_uri, new_host);
+                GUri *new_uri = soup_uri_copy (soup_uri, SOUP_URI_HOST, new_host, NULL);
                 g_free (new_host);
+                g_uri_unref (soup_uri);
+                soup_uri = new_uri;
         }
 
         g_object_unref (addr);
diff --git a/libgupnp/gupnp-control-point.c b/libgupnp/gupnp-control-point.c
index dc04732..50f032a 100644
--- a/libgupnp/gupnp-control-point.c
+++ b/libgupnp/gupnp-control-point.c
@@ -84,6 +84,7 @@ get_description_url_data_free (GetDescriptionURLData *data)
 {
         gupnp_control_point_remove_pending_get (data->control_point, data);
         if (data->message) {
+#if 0
                 GUPnPContext *context;
                 SoupSession *session;
 
@@ -94,6 +95,7 @@ get_description_url_data_free (GetDescriptionURLData *data)
                 soup_session_cancel_message (session,
                                              data->message,
                                              SOUP_STATUS_CANCELLED);
+#endif
         }
 
         if (data->timeout_source) {
@@ -290,7 +292,7 @@ create_and_report_service_proxy (GUPnPControlPoint  *control_point,
                                  const char         *udn,
                                  const char         *service_type,
                                  const char         *description_url,
-                                 SoupURI            *url_base)
+                                 GUri            *url_base)
 {
         GUPnPServiceProxy *proxy;
         GUPnPResourceFactory *factory;
@@ -329,7 +331,7 @@ create_and_report_device_proxy (GUPnPControlPoint  *control_point,
                                 xmlNode            *element,
                                 const char         *udn,
                                 const char         *description_url,
-                                SoupURI            *url_base)
+                                GUri            *url_base)
 {
         GUPnPDeviceProxy *proxy;
         GUPnPResourceFactory *factory;
@@ -406,7 +408,7 @@ process_service_list (xmlNode           *element,
                       const char        *udn,
                       const char        *service_type,
                       const char        *description_url,
-                      SoupURI           *url_base)
+                      GUri           *url_base)
 {
         g_object_ref (control_point);
 
@@ -452,7 +454,7 @@ process_device_list (xmlNode           *element,
                      const char        *udn,
                      const char        *service_type,
                      const char        *description_url,
-                     SoupURI           *url_base)
+                     GUri           *url_base)
 {
         g_object_ref (control_point);
 
@@ -531,7 +533,7 @@ description_loaded (GUPnPControlPoint *control_point,
                     const char        *description_url)
 {
         xmlNode *element;
-        SoupURI *url_base;
+        GUri *url_base;
 
         /* Save the URL base, if any */
         element = xml_util_get_element ((xmlNode *)
@@ -551,7 +553,7 @@ description_loaded (GUPnPControlPoint *control_point,
                                                            "URLBase",
                                                            NULL);
         if (!url_base)
-                url_base = soup_uri_new (description_url);
+                url_base = g_uri_parse (description_url, G_URI_FLAGS_NONE, NULL);
 
         /* Iterate matching devices */
         process_device_list (element,
@@ -563,7 +565,7 @@ description_loaded (GUPnPControlPoint *control_point,
                              url_base);
 
         /* Cleanup */
-        soup_uri_free (url_base);
+        g_uri_unref (url_base);
 }
 
 
@@ -574,15 +576,21 @@ description_url_retry_timeout (gpointer user_data);
  * Description URL downloaded.
  */
 static void
-got_description_url (SoupSession           *session,
-                     SoupMessage           *msg,
+got_description_url (GObject           *source,
+                     GAsyncResult *res,
                      GetDescriptionURLData *data)
 {
         GUPnPXMLDoc *doc;
         GUPnPControlPointPrivate *priv;
+        GError *error = NULL;
+        SoupMessage *message = data->message;
 
-        if (msg->status_code == SOUP_STATUS_CANCELLED)
-                return;
+        GBytes *body = soup_session_send_and_read_finish (SOUP_SESSION (source), res, &error);
+
+        if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+                goto out;
+
+        // FIXME: What to do on other errors...
 
         data->message = NULL;
         priv = gupnp_control_point_get_instance_private (data->control_point);
@@ -600,16 +608,19 @@ got_description_url (SoupSession           *session,
 
                 get_description_url_data_free (data);
 
-                return;
+                goto out;
         }
 
         /* Not cached */
-        if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
+        if (SOUP_STATUS_IS_SUCCESSFUL (soup_message_get_status (message))) {
                 xmlDoc *xml_doc;
+                gsize length;
+                gconstpointer body_data;
+
+                body_data = g_bytes_get_data (body, &length);
 
                 /* Parse response */
-                xml_doc = xmlRecoverMemory (msg->response_body->data,
-                                            msg->response_body->length);
+                xml_doc = xmlRecoverMemory (body_data, length);
                 if (xml_doc) {
                         doc = gupnp_xml_doc_new (xml_doc);
 
@@ -637,17 +648,15 @@ got_description_url (SoupSession           *session,
 
                 get_description_url_data_free (data);
         } else {
-                GMainContext *async_context;
+                GMainContext *async_context = g_main_context_get_thread_default ();
 
                 /* Retry GET after a timeout */
-                async_context = soup_session_get_async_context (session);
-
                 data->tries--;
 
                 if (data->tries > 0) {
                         g_warning ("Failed to GET %s: %s, retrying in %d seconds",
                                    data->description_url,
-                                   msg->reason_phrase,
+                                   soup_message_get_reason_phrase (message),
                                    data->timeout);
 
                         data->timeout_source = g_timeout_source_new_seconds
@@ -662,6 +671,10 @@ got_description_url (SoupSession           *session,
                         g_warning ("Maximum number of retries failed, not trying again");
                 }
         }
+
+out:
+        g_bytes_unref (body);
+        g_object_unref (message);
 }
 
 /*
@@ -735,11 +748,12 @@ load_description (GUPnPControlPoint *control_point,
                 priv->pending_gets = g_list_prepend (priv->pending_gets,
                                                      data);
 
-                soup_session_queue_message (session,
-                                            data->message,
-                                            (SoupSessionCallback)
-                                                   got_description_url,
-                                            data);
+                soup_session_send_and_read_async (session,
+                                                  data->message,
+                                                  G_PRIORITY_DEFAULT,
+                                                  NULL,
+                                                  (GAsyncReadyCallback)got_description_url,
+                                                  data);
         }
 }
 
diff --git a/libgupnp/gupnp-device-info.c b/libgupnp/gupnp-device-info.c
index fd3d8ce..7c1b6be 100644
--- a/libgupnp/gupnp-device-info.c
+++ b/libgupnp/gupnp-device-info.c
@@ -31,7 +31,7 @@ struct _GUPnPDeviceInfoPrivate {
         char *udn;
         char *device_type;
 
-        SoupURI *url_base;
+        GUri *url_base;
 
         GUPnPXMLDoc *doc;
 
@@ -177,7 +177,7 @@ gupnp_device_info_finalize (GObject *object)
         g_free (priv->udn);
         g_free (priv->device_type);
 
-        g_clear_pointer (&priv->url_base, soup_uri_free);
+        g_clear_pointer (&priv->url_base, g_uri_unref);
 
         G_OBJECT_CLASS (gupnp_device_info_parent_class)->finalize (object);
 }
@@ -296,7 +296,7 @@ gupnp_device_info_class_init (GUPnPDeviceInfoClass *klass)
                  g_param_spec_boxed ("url-base",
                                      "URL base",
                                      "The URL base",
-                                     SOUP_TYPE_URI,
+                                     G_TYPE_URI,
                                      G_PARAM_READWRITE |
                                      G_PARAM_CONSTRUCT |
                                      G_PARAM_STATIC_NAME |
@@ -413,7 +413,7 @@ gupnp_device_info_get_location (GUPnPDeviceInfo *info)
  *
  * Returns: A #SoupURI.
  **/
-const SoupURI *
+const GUri *
 gupnp_device_info_get_url_base (GUPnPDeviceInfo *info)
 {
         GUPnPDeviceInfoPrivate *priv;
@@ -910,12 +910,11 @@ gupnp_device_info_get_icon_url (GUPnPDeviceInfo *info,
                         *height = icon->height;
 
                 if (icon->url) {
-                        SoupURI *uri;
+                        GUri *uri;
 
-                        uri = soup_uri_new_with_base (priv->url_base,
-                                                      (const char *) icon->url);
-                        ret = soup_uri_to_string (uri, FALSE);
-                        soup_uri_free (uri);
+                        uri = g_uri_parse_relative (priv->url_base, (const char *) icon->url, 
G_URI_FLAGS_NONE, NULL);
+                        ret = g_uri_to_string_partial (uri, G_URI_HIDE_PASSWORD);
+                        g_uri_unref (uri);
                 } else
                         ret = NULL;
         } else {
diff --git a/libgupnp/gupnp-device-info.h b/libgupnp/gupnp-device-info.h
index 8ee35d7..0a08bdf 100644
--- a/libgupnp/gupnp-device-info.h
+++ b/libgupnp/gupnp-device-info.h
@@ -11,7 +11,6 @@
 
 #include <glib-object.h>
 #include <libxml/tree.h>
-#include <libsoup/soup-uri.h>
 
 #include "gupnp-context.h"
 #include "gupnp-service-info.h"
@@ -56,7 +55,7 @@ gupnp_device_info_get_context            (GUPnPDeviceInfo *info);
 const char *
 gupnp_device_info_get_location           (GUPnPDeviceInfo *info);
 
-const SoupURI *
+const GUri *
 gupnp_device_info_get_url_base           (GUPnPDeviceInfo *info);
 
 const char *
diff --git a/libgupnp/gupnp-device-proxy.c b/libgupnp/gupnp-device-proxy.c
index ea0d6ca..ea9ff9c 100644
--- a/libgupnp/gupnp-device-proxy.c
+++ b/libgupnp/gupnp-device-proxy.c
@@ -37,7 +37,7 @@ gupnp_device_proxy_get_device (GUPnPDeviceInfo *info,
         GUPnPContext         *context;
         GUPnPXMLDoc          *doc;
         const char           *location;
-        const SoupURI        *url_base;
+        const GUri        *url_base;
 
         factory = gupnp_device_info_get_resource_factory (info);
         context = gupnp_device_info_get_context (info);
@@ -65,7 +65,7 @@ gupnp_device_proxy_get_service (GUPnPDeviceInfo *info,
         GUPnPContext         *context;
         GUPnPXMLDoc          *doc;
         const char           *location, *udn;
-        const SoupURI        *url_base;
+        const GUri        *url_base;
 
         factory = gupnp_device_info_get_resource_factory (info);
         context = gupnp_device_info_get_context (info);
diff --git a/libgupnp/gupnp-device.c b/libgupnp/gupnp-device.c
index 71b11cf..ad39345 100644
--- a/libgupnp/gupnp-device.c
+++ b/libgupnp/gupnp-device.c
@@ -50,7 +50,7 @@ gupnp_device_get_device (GUPnPDeviceInfo *info,
         GUPnPContext         *context;
         GUPnPDevice          *root_device;
         const char           *location;
-        const SoupURI        *url_base;
+        const GUri        *url_base;
 
         device = GUPNP_DEVICE (info);
         priv = gupnp_device_get_instance_private (device);
@@ -90,7 +90,7 @@ gupnp_device_get_service (GUPnPDeviceInfo *info,
         GUPnPContext         *context;
         GUPnPDevice          *root_device;
         const char           *location, *udn;
-        const SoupURI        *url_base;
+        const GUri        *url_base;
 
         device = GUPNP_DEVICE (info);
         priv = gupnp_device_get_instance_private (device);
diff --git a/libgupnp/gupnp-error.c b/libgupnp/gupnp-error.c
index 7dcf5db..079ddd4 100644
--- a/libgupnp/gupnp-error.c
+++ b/libgupnp/gupnp-error.c
@@ -130,8 +130,8 @@ _gupnp_error_set_server_error (GError     **error,
 {
         g_set_error_literal (error,
                              GUPNP_SERVER_ERROR,
-                             code_from_status_code (msg->status_code),
-                             msg->reason_phrase);
+                             code_from_status_code (soup_message_get_status (msg)),
+                             soup_message_get_reason_phrase (msg));
 }
 
 /* Create a #GError with status of @msg */
@@ -139,6 +139,6 @@ GError *
 _gupnp_error_new_server_error (SoupMessage *msg)
 {
         return g_error_new_literal (GUPNP_SERVER_ERROR,
-                                    code_from_status_code (msg->status_code),
-                                    msg->reason_phrase);
+                                    code_from_status_code (soup_message_get_status (msg)),
+                                    soup_message_get_reason_phrase (msg));
 }
diff --git a/libgupnp/gupnp-resource-factory-private.h b/libgupnp/gupnp-resource-factory-private.h
index 9a5f10d..a850d84 100644
--- a/libgupnp/gupnp-resource-factory-private.h
+++ b/libgupnp/gupnp-resource-factory-private.h
@@ -29,7 +29,7 @@ gupnp_resource_factory_create_device_proxy
                                        xmlNode              *element,
                                        const char           *udn,
                                        const char           *location,
-                                       const SoupURI        *url_base);
+                                       const GUri        *url_base);
 
 G_GNUC_INTERNAL GUPnPServiceProxy *
 gupnp_resource_factory_create_service_proxy
@@ -40,7 +40,7 @@ gupnp_resource_factory_create_service_proxy
                                        const char           *udn,
                                        const char           *service_type,
                                        const char           *location,
-                                       const SoupURI        *url_base);
+                                       const GUri        *url_base);
 
 G_GNUC_INTERNAL GUPnPDevice *
 gupnp_resource_factory_create_device  (GUPnPResourceFactory *factory,
@@ -49,7 +49,7 @@ gupnp_resource_factory_create_device  (GUPnPResourceFactory *factory,
                                        xmlNode              *element,
                                        const char           *udn,
                                        const char           *location,
-                                       const SoupURI        *url_base);
+                                       const GUri        *url_base);
 
 G_GNUC_INTERNAL GUPnPService *
 gupnp_resource_factory_create_service (GUPnPResourceFactory *factory,
@@ -58,7 +58,7 @@ gupnp_resource_factory_create_service (GUPnPResourceFactory *factory,
                                        xmlNode              *element,
                                        const char           *udn,
                                        const char           *location,
-                                       const SoupURI        *url_base);
+                                       const GUri        *url_base);
 
 G_END_DECLS
 
diff --git a/libgupnp/gupnp-resource-factory.c b/libgupnp/gupnp-resource-factory.c
index 8d7e362..1a23104 100644
--- a/libgupnp/gupnp-resource-factory.c
+++ b/libgupnp/gupnp-resource-factory.c
@@ -199,7 +199,7 @@ gupnp_resource_factory_create_device_proxy
                                  xmlNode              *element,
                                  const char           *udn,
                                  const char           *location,
-                                 const SoupURI        *url_base)
+                                 const GUri        *url_base)
 {
         GUPnPDeviceProxy *proxy;
         GType proxy_type;
@@ -259,7 +259,7 @@ gupnp_resource_factory_create_service_proxy
                                  const char           *udn,
                                  const char           *service_type,
                                  const char           *location,
-                                 const SoupURI        *url_base)
+                                 const GUri        *url_base)
 {
         GUPnPServiceProxy *proxy;
         GType              proxy_type = GUPNP_TYPE_SERVICE_PROXY;
@@ -316,7 +316,7 @@ gupnp_resource_factory_create_device
                                  xmlNode              *element,
                                  const char           *udn,
                                  const char           *location,
-                                 const SoupURI        *url_base)
+                                 const GUri        *url_base)
 {
         GUPnPDevice *device;
         GType        device_type = GUPNP_TYPE_DEVICE;
@@ -372,7 +372,7 @@ gupnp_resource_factory_create_service
                                  xmlNode              *element,
                                  const char           *udn,
                                  const char           *location,
-                                 const SoupURI        *url_base)
+                                 const GUri        *url_base)
 {
         GUPnPService *service;
         GType         service_type = GUPNP_TYPE_SERVICE;
diff --git a/libgupnp/gupnp-root-device.c b/libgupnp/gupnp-root-device.c
index 48987c4..fa96012 100644
--- a/libgupnp/gupnp-root-device.c
+++ b/libgupnp/gupnp-root-device.c
@@ -288,10 +288,10 @@ gupnp_root_device_initable_init (GInitable     *initable,
         GUPnPRootDevice *device;
         GUPnPContext *context;
         const char *udn;
-        SoupURI *uri;
+        GUri *uri;
         char *desc_path, *location, *usn, *relative_location;
         xmlNode *root_element, *element;
-        SoupURI *url_base;
+        GUri *url_base;
         gboolean result = FALSE;
         GUPnPRootDevicePrivate *priv;
 
@@ -409,9 +409,9 @@ gupnp_root_device_initable_init (GInitable     *initable,
         gupnp_context_host_path (context, priv->description_dir, "");
 
         /* Generate full location */
-        soup_uri_set_path (uri, relative_location);
-        location = soup_uri_to_string (uri, FALSE);
-
+        GUri *new_uri = soup_uri_copy (uri, SOUP_URI_PATH, relative_location, NULL);
+        location = g_uri_to_string_partial (new_uri, G_URI_HIDE_PASSWORD);
+        g_uri_unref (new_uri);
         g_free (relative_location);
 
         /* Save the URL base, if any */
@@ -419,15 +419,14 @@ gupnp_root_device_initable_init (GInitable     *initable,
                                                            "URLBase",
                                                            NULL);
         if (!url_base)
-                url_base = soup_uri_new (location);
+                url_base = g_uri_parse (location, G_URI_FLAGS_NONE, NULL);
 
         /* Set additional properties */
         g_object_set (G_OBJECT (device),
                       "location", location,
                       "url-base", url_base,
                       NULL);
-
-        soup_uri_free (url_base);
+        g_uri_unref (url_base);
 
         /* Create resource group */
         priv->group = gssdp_resource_group_new (GSSDP_CLIENT (context));
@@ -447,7 +446,7 @@ gupnp_root_device_initable_init (GInitable     *initable,
  DONE:
         /* Cleanup */
         if (uri)
-                soup_uri_free (uri);
+                g_uri_unref (uri);
 
         g_free (desc_path);
         g_free (location);
diff --git a/libgupnp/gupnp-service-info.c b/libgupnp/gupnp-service-info.c
index 9a9f4de..1705306 100644
--- a/libgupnp/gupnp-service-info.c
+++ b/libgupnp/gupnp-service-info.c
@@ -38,7 +38,7 @@ struct _GUPnPServiceInfoPrivate {
         char *udn;
         char *service_type;
 
-        SoupURI *url_base;
+        GUri *url_base;
 
         GUPnPXMLDoc *doc;
 
@@ -178,9 +178,9 @@ gupnp_service_info_dispose (GObject *object)
 
         /* Cancel any pending SCPD GETs */
         if (priv->context) {
-                SoupSession *session;
+                //SoupSession *session;
 
-                session = gupnp_context_get_session (priv->context);
+                //session = gupnp_context_get_session (priv->context);
 
                 while (priv->pending_gets) {
                         GetSCPDURLData *data;
@@ -191,9 +191,11 @@ gupnp_service_info_dispose (GObject *object)
                                 g_cancellable_disconnect (data->cancellable,
                                                           data->cancelled_id);
 
+                        /*
                         soup_session_cancel_message (session,
                                                      data->message,
                                                      SOUP_STATUS_CANCELLED);
+                       */
 
                         get_scpd_url_data_free (data);
 
@@ -228,7 +230,7 @@ gupnp_service_info_finalize (GObject *object)
         g_free (priv->udn);
         g_free (priv->service_type);
 
-        soup_uri_free (priv->url_base);
+        g_uri_unref (priv->url_base);
 
         G_OBJECT_CLASS (gupnp_service_info_parent_class)->finalize (object);
 }
@@ -329,7 +331,7 @@ gupnp_service_info_class_init (GUPnPServiceInfoClass *klass)
                  g_param_spec_boxed ("url-base",
                                      "URL base",
                                      "The URL base",
-                                     SOUP_TYPE_URI,
+                                     G_TYPE_URI,
                                      G_PARAM_READWRITE |
                                      G_PARAM_CONSTRUCT_ONLY |
                                      G_PARAM_STATIC_NAME |
@@ -426,7 +428,7 @@ gupnp_service_info_get_location (GUPnPServiceInfo *info)
  *
  * Returns: A constant #SoupURI.
  **/
-const SoupURI *
+const GUri *
 gupnp_service_info_get_url_base (GUPnPServiceInfo *info)
 {
         GUPnPServiceInfoPrivate *priv;
@@ -575,8 +577,8 @@ gupnp_service_info_get_event_subscription_url (GUPnPServiceInfo *info)
  * SCPD URL downloaded.
  */
 static void
-got_scpd_url (G_GNUC_UNUSED SoupSession *session,
-              SoupMessage               *msg,
+got_scpd_url (GObject *source,
+              GAsyncResult *res,
               GetSCPDURLData            *data)
 {
         GUPnPServiceIntrospection *introspection;
@@ -586,14 +588,20 @@ got_scpd_url (G_GNUC_UNUSED SoupSession *session,
         introspection = NULL;
         error = NULL;
 
-        if (msg->status_code == SOUP_STATUS_CANCELLED)
+        GBytes *body = soup_session_send_and_read_finish (SOUP_SESSION (source), res, &error);
+
+        SoupStatus status = soup_message_get_status (data->message);
+
+        if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
                 return;
 
-        if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
+        if (SOUP_STATUS_IS_SUCCESSFUL (status)) {
                 xmlDoc *scpd;
+                gsize length;
 
-                scpd = xmlRecoverMemory (msg->response_body->data,
-                                         msg->response_body->length);
+                gconstpointer data = g_bytes_get_data (body, &length);
+
+                scpd = xmlRecoverMemory (data, length);
                 if (scpd) {
                         introspection = gupnp_service_introspection_new (scpd);
 
@@ -607,7 +615,7 @@ got_scpd_url (G_GNUC_UNUSED SoupSession *session,
                                          "Could not parse SCPD");
                 }
         } else
-                error = _gupnp_error_new_server_error (msg);
+                error = _gupnp_error_new_server_error (data->message);
 
         /* prevent the callback from canceling the cancellable
          * (and so freeing data just before we do) */
@@ -635,7 +643,7 @@ cancellable_cancelled_cb (GCancellable *cancellable,
 {
         GUPnPServiceInfo *info;
         GetSCPDURLData *data;
-        SoupSession *session;
+        //SoupSession *session;
         GError *error;
         GUPnPServiceInfoPrivate *priv;
 
@@ -644,10 +652,13 @@ cancellable_cancelled_cb (GCancellable *cancellable,
 
         priv = gupnp_service_info_get_instance_private (info);
 
+        /*
+        FIXME: Should have been part of the cancellable
         session = gupnp_context_get_session (priv->context);
         soup_session_cancel_message (session,
                                      data->message,
                                      SOUP_STATUS_CANCELLED);
+                                     */
 
         priv->pending_gets = g_list_remove (priv->pending_gets, data);
 
@@ -780,10 +791,7 @@ gupnp_service_info_get_introspection_async_full
 
         session = gupnp_context_get_session (priv->context);
 
-        soup_session_queue_message (session,
-                                    data->message,
-                                    (SoupSessionCallback) got_scpd_url,
-                                    data);
+        soup_session_send_and_read_async (session, data->message, G_PRIORITY_DEFAULT, cancellable, 
(GAsyncReadyCallback)got_scpd_url, data);
 
         data->cancellable = cancellable;
         if (data->cancellable) {
diff --git a/libgupnp/gupnp-service-info.h b/libgupnp/gupnp-service-info.h
index a853c2f..dc42964 100644
--- a/libgupnp/gupnp-service-info.h
+++ b/libgupnp/gupnp-service-info.h
@@ -10,7 +10,6 @@
 #define GUPNP_SERVICE_INFO_H
 
 #include <glib-object.h>
-#include <libsoup/soup-uri.h>
 
 #include "gupnp-context.h"
 #include "gupnp-service-introspection.h"
@@ -57,7 +56,7 @@ gupnp_service_info_get_context                (GUPnPServiceInfo *info);
 const char *
 gupnp_service_info_get_location               (GUPnPServiceInfo *info);
 
-const SoupURI *
+const GUri *
 gupnp_service_info_get_url_base               (GUPnPServiceInfo *info);
 
 const char *
diff --git a/libgupnp/gupnp-service-private.h b/libgupnp/gupnp-service-private.h
index 1915505..f1f31c8 100644
--- a/libgupnp/gupnp-service-private.h
+++ b/libgupnp/gupnp-service-private.h
@@ -14,7 +14,7 @@ struct _GUPnPServiceAction {
 
         char         *name;
 
-        SoupMessage  *msg;
+        SoupServerMessage  *msg;
         gboolean      accept_gzip;
 
         GUPnPXMLDoc  *doc;
diff --git a/libgupnp/gupnp-service-proxy-action-private.h b/libgupnp/gupnp-service-proxy-action-private.h
index cb6492b..8fc8981 100644
--- a/libgupnp/gupnp-service-proxy-action-private.h
+++ b/libgupnp/gupnp-service-proxy-action-private.h
@@ -137,6 +137,7 @@ struct _GUPnPServiceProxyAction {
         gint header_pos;
 
         SoupMessage *msg;
+        GBytes *response;
         GString *msg_str;
 
         GCancellable *cancellable;
diff --git a/libgupnp/gupnp-service-proxy-action.c b/libgupnp/gupnp-service-proxy-action.c
index 4d9336c..dedf3b4 100644
--- a/libgupnp/gupnp-service-proxy-action.c
+++ b/libgupnp/gupnp-service-proxy-action.c
@@ -65,7 +65,7 @@ check_action_response (G_GNUC_UNUSED GUPnPServiceProxy *proxy,
         xmlDoc *response;
         int code;
 
-        if (action->msg == NULL) {
+        if (action->msg == NULL || action->response == NULL) {
                 g_set_error (error,
                              GUPNP_SERVER_ERROR,
                              GUPNP_SERVER_ERROR_INVALID_RESPONSE,
@@ -74,8 +74,10 @@ check_action_response (G_GNUC_UNUSED GUPnPServiceProxy *proxy,
                 return NULL;
         }
 
+        SoupStatus status = soup_message_get_status (action->msg);
+
         /* Check for errors */
-        switch (action->msg->status_code) {
+        switch (status) {
         case SOUP_STATUS_OK:
         case SOUP_STATUS_INTERNAL_SERVER_ERROR:
                 break;
@@ -86,11 +88,14 @@ check_action_response (G_GNUC_UNUSED GUPnPServiceProxy *proxy,
         }
 
         /* Parse response */
-        response = xmlRecoverMemory (action->msg->response_body->data,
-                                     action->msg->response_body->length);
+        gconstpointer data;
+        gsize length;
+        data = g_bytes_get_data (action->response, &length);
+        response = xmlRecoverMemory (data, length);
+        g_clear_pointer (&action->response, g_bytes_unref);
 
         if (!response) {
-                if (action->msg->status_code == SOUP_STATUS_OK) {
+                if (status == SOUP_STATUS_OK) {
                         g_set_error (error,
                                      GUPNP_SERVER_ERROR,
                                      GUPNP_SERVER_ERROR_INVALID_RESPONSE,
@@ -100,7 +105,7 @@ check_action_response (G_GNUC_UNUSED GUPnPServiceProxy *proxy,
                                     (error,
                                      GUPNP_SERVER_ERROR,
                                      GUPNP_SERVER_ERROR_INTERNAL_SERVER_ERROR,
-                                     action->msg->reason_phrase);
+                                     soup_message_get_reason_phrase (action->msg));
                 }
 
                 return NULL;
@@ -137,7 +142,7 @@ check_action_response (G_GNUC_UNUSED GUPnPServiceProxy *proxy,
         }
 
         /* Check whether we have a Fault */
-        if (action->msg->status_code == SOUP_STATUS_INTERNAL_SERVER_ERROR) {
+        if (status == SOUP_STATUS_INTERNAL_SERVER_ERROR) {
                 xmlNode *param;
                 char *desc;
 
@@ -175,7 +180,7 @@ check_action_response (G_GNUC_UNUSED GUPnPServiceProxy *proxy,
                 desc = xml_util_get_child_element_content_glib
                                         (param, "errorDescription");
                 if (desc == NULL)
-                        desc = g_strdup (action->msg->reason_phrase);
+                        desc = g_strdup (soup_message_get_reason_phrase (action->msg));
 
                 g_set_error_literal (error,
                                      GUPNP_CONTROL_ERROR,
diff --git a/libgupnp/gupnp-service-proxy.c b/libgupnp/gupnp-service-proxy.c
index 9f4b61e..953c88a 100644
--- a/libgupnp/gupnp-service-proxy.c
+++ b/libgupnp/gupnp-service-proxy.c
@@ -90,9 +90,10 @@ typedef struct {
 } EmitNotifyData;
 
 static void
-subscribe_got_response (SoupSession       *session,
-                        SoupMessage       *msg,
-                        GUPnPServiceProxy *proxy);
+subscribe_got_response (GObject *source,
+                        GAsyncResult *res,
+                        gpointer user_data);
+
 static void
 subscribe (GUPnPServiceProxy *proxy);
 static void
@@ -223,7 +224,7 @@ gupnp_service_proxy_dispose (GObject *object)
         GUPnPServiceProxyPrivate *priv;
         GObjectClass *object_class;
         GUPnPContext *context;
-        SoupSession *session;
+        //SoupSession *session;
 
         proxy = GUPNP_SERVICE_PROXY (object);
         priv = gupnp_service_proxy_get_instance_private (proxy);
@@ -258,19 +259,24 @@ gupnp_service_proxy_dispose (GObject *object)
         }
 
         /* Cancel pending messages */
+#if 0
         if (context)
                 session = gupnp_context_get_session (context);
         else
                 session = NULL; /* Not the first time dispose is called. */
+#endif
 
         while (priv->pending_messages) {
+                /*
                 SoupMessage *msg;
 
                 msg = priv->pending_messages->data;
 
+                 * FIXME: Porbably cancelled above...
                 soup_session_cancel_message (session,
                                              msg,
                                              SOUP_STATUS_CANCELLED);
+                                             */
 
                 priv->pending_messages =
                         g_list_delete_link (priv->pending_messages,
@@ -604,17 +610,20 @@ on_action_cancelled (GCancellable *cancellable, gpointer user_data)
 {
         GUPnPServiceProxyAction *action = (GUPnPServiceProxyAction *) user_data;
 
-        GUPnPContext *context;
-        SoupSession *session;
+//        GUPnPContext *context;
+//        SoupSession *session;
 
         if (action->msg != NULL && action->proxy != NULL) {
+#if 0
                 context = gupnp_service_info_get_context
                                         (GUPNP_SERVICE_INFO (action->proxy));
                 session = gupnp_context_get_session (context);
 
+                FIXME: Cancellable?
                 soup_session_cancel_message (session,
                                              action->msg,
                                              SOUP_STATUS_CANCELLED);
+#endif
                 action->cancellable_connection_id = 0;
         }
 }
@@ -668,9 +677,11 @@ prepare_action_msg (GUPnPServiceProxy *proxy,
         action->msg = soup_message_new (SOUP_METHOD_POST, local_control_url);
         g_free (local_control_url);
 
+        SoupMessageHeaders *headers = soup_message_get_request_headers (action->msg);
+
         /* Specify action */
         full_action = g_strdup_printf ("\"%s#%s\"", service_type, action->name);
-        soup_message_headers_append (action->msg->request_headers,
+        soup_message_headers_append (headers,
                                      "SOAPAction",
                                      full_action);
         g_free (full_action);
@@ -679,18 +690,14 @@ prepare_action_msg (GUPnPServiceProxy *proxy,
         http_request_set_accept_language (action->msg);
 
         /* Accept gzip encoding */
-        soup_message_headers_append (action->msg->request_headers,
+        soup_message_headers_append (headers,
                                      "Accept-Encoding", "gzip");
 
         gupnp_service_proxy_action_serialize (action, service_type);
 
-        soup_message_set_request (action->msg,
+        soup_message_set_request_body_from_bytes (action->msg,
                                   "text/xml; charset=\"utf-8\"",
-                                  SOUP_MEMORY_TAKE,
-                                  action->msg_str->str,
-                                  action->msg_str->len);
-
-        g_string_free (action->msg_str, FALSE);
+                                  g_string_free_to_bytes (action->msg_str));
         action->msg_str = NULL;
 
         return TRUE;
@@ -702,51 +709,51 @@ update_message_after_not_allowed (SoupMessage *msg)
         const char *full_action;
 
         /* Retry with M-POST */
-        msg->method = "M-POST";
+        soup_message_set_method (msg, "M-POST");
+
+        SoupMessageHeaders *headers = soup_message_get_request_headers (msg);
 
-        soup_message_headers_append
-                        (msg->request_headers,
-                         "Man",
-                         "\"http://schemas.xmlsoap.org/soap/envelope/\";; ns=s");
+        soup_message_headers_append (headers,
+                                     "Man",
+                                     "\"http://schemas.xmlsoap.org/soap/envelope/\";; ns=s");
 
         /* Rename "SOAPAction" to "s-SOAPAction" */
-        full_action = soup_message_headers_get_one
-                        (msg->request_headers,
-                         "SOAPAction");
-        soup_message_headers_append (msg->request_headers,
-                                     "s-SOAPAction",
-                                     full_action);
-        soup_message_headers_remove (msg->request_headers,
-                                     "SOAPAction");
+        full_action = soup_message_headers_get_one (headers, "SOAPAction");
+        soup_message_headers_append (headers, "s-SOAPAction", full_action);
+        soup_message_headers_remove (headers, "SOAPAction");
 }
 
 static void
-action_task_got_response (SoupSession *session,
-                          SoupMessage *msg,
+action_task_got_response (GObject *source,
+                          GAsyncResult *res,
                           gpointer    user_data)
 {
         GTask *task = G_TASK (user_data);
+        GError *error = NULL;
         GUPnPServiceProxyAction *action = (GUPnPServiceProxyAction *) g_task_get_task_data (task);
 
-        switch (msg->status_code) {
-        case SOUP_STATUS_CANCELLED:
+        action->response = soup_session_send_and_read_finish (SOUP_SESSION (source), res, &error);
+
+        if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
                 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,
-                                         G_IO_ERROR,
-                                         G_IO_ERROR_CANCELLED,
-                                         "Action message was cancelled");
+        if (error != NULL) {
+                g_task_return_error (task, error);
                 g_object_unref (task);
-                break;
 
+                return;
+        }
+
+        switch (soup_message_get_status (action->msg)) {
         case SOUP_STATUS_METHOD_NOT_ALLOWED:
                 /* And re-queue */
-                update_message_after_not_allowed (msg);
-                soup_session_requeue_message (session, msg);
+                update_message_after_not_allowed (action->msg);
+                //FIXME: soup_session_requeue_message (session, msg);
 
                 break;
 
@@ -783,10 +790,12 @@ gupnp_service_proxy_action_queue_task (GTask *task)
                                 (GUPNP_SERVICE_INFO (action->proxy));
         session = gupnp_context_get_session (context);
 
-        soup_session_queue_message (session,
-                                    action->msg,
-                                    (SoupSessionCallback) action_task_got_response,
-                                    task);
+        soup_session_send_and_read_async (session,
+                                          action->msg,
+                                          G_PRIORITY_DEFAULT,
+                                          action->cancellable,
+                                          (GAsyncReadyCallback) action_task_got_response,
+                                          task);
         action->pending = TRUE;
 }
 
@@ -1494,10 +1503,9 @@ emit_notifications (gpointer user_data)
  */
 static void
 server_handler (G_GNUC_UNUSED SoupServer        *soup_server,
-                SoupMessage                     *msg,
+                SoupServerMessage               *msg,
                 G_GNUC_UNUSED const char        *server_path,
                 G_GNUC_UNUSED GHashTable        *query,
-                G_GNUC_UNUSED SoupClientContext *soup_client,
                 gpointer                         user_data)
 {
         GUPnPServiceProxy *proxy;
@@ -1510,19 +1518,26 @@ server_handler (G_GNUC_UNUSED SoupServer        *soup_server,
         EmitNotifyData *emit_notify_data;
 
         proxy = GUPNP_SERVICE_PROXY (user_data);
+        const char *method = soup_server_message_get_method (msg);
 
-        if (strcmp (msg->method, GENA_METHOD_NOTIFY) != 0) {
+        SoupMessageHeaders *request_headers = soup_server_message_get_request_headers (msg);
+
+        if (strcmp (method, GENA_METHOD_NOTIFY) != 0) {
                 /* We don't implement this method */
-                soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
+                soup_server_message_set_status (msg,
+                                                SOUP_STATUS_NOT_IMPLEMENTED,
+                                                "Method not supported");
 
                 return;
         }
 
-        nt = soup_message_headers_get_one (msg->request_headers, "NT");
-        nts = soup_message_headers_get_one (msg->request_headers, "NTS");
+        nt = soup_message_headers_get_one (request_headers, "NT");
+        nts = soup_message_headers_get_one (request_headers, "NTS");
         if (nt == NULL || nts == NULL) {
                 /* Required header is missing */
-                soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST);
+                soup_server_message_set_status (msg,
+                                                SOUP_STATUS_BAD_REQUEST,
+                                                "NT or NTS is missing");
 
                 return;
         }
@@ -1530,15 +1545,19 @@ server_handler (G_GNUC_UNUSED SoupServer        *soup_server,
         if (strcmp (nt, "upnp:event") != 0 ||
             strcmp (nts, "upnp:propchange") != 0) {
                 /* Unexpected header content */
-                soup_message_set_status (msg, SOUP_STATUS_PRECONDITION_FAILED);
+                soup_server_message_set_status (msg,
+                                                SOUP_STATUS_PRECONDITION_FAILED,
+                                                "Unexpected NT or NTS");
 
                 return;
         }
 
-        hdr = soup_message_headers_get_one (msg->request_headers, "SEQ");
+        hdr = soup_message_headers_get_one (request_headers, "SEQ");
         if (hdr == NULL) {
                 /* No SEQ header */
-                soup_message_set_status (msg, SOUP_STATUS_PRECONDITION_FAILED);
+                soup_server_message_set_status (msg,
+                                                SOUP_STATUS_PRECONDITION_FAILED,
+                                                "SEQ missing");
 
                 return;
         }
@@ -1547,32 +1566,38 @@ server_handler (G_GNUC_UNUSED SoupServer        *soup_server,
         seq_parsed = strtoul (hdr, NULL, 10);
         if (errno != 0 || seq_parsed > G_MAXUINT32) {
                 /* Invalid SEQ header value */
-                soup_message_set_status (msg, SOUP_STATUS_PRECONDITION_FAILED);
+                soup_server_message_set_status (msg,
+                                         SOUP_STATUS_PRECONDITION_FAILED,
+                                         "SEQ invalid");
 
                 return;
         }
 
         seq = (guint32) seq_parsed;
 
-        hdr = soup_message_headers_get_one (msg->request_headers, "SID");
+        hdr = soup_message_headers_get_one (request_headers, "SID");
         if (hdr == NULL ||
             strlen (hdr) <= strlen ("uuid:") ||
             strncmp (hdr, "uuid:", strlen ("uuid:")) != 0) {
                 /* No SID */
-                soup_message_set_status (msg, SOUP_STATUS_PRECONDITION_FAILED);
+                soup_server_message_set_status (msg,
+                                                SOUP_STATUS_PRECONDITION_FAILED,
+                                                "SID header missing or malformed");
 
                 return;
         }
 
+        SoupMessageBody *request_body = soup_server_message_get_request_body (msg);
+
         /* Parse the actual XML message content */
-        doc = xmlRecoverMemory (msg->request_body->data,
-                                msg->request_body->length);
+        doc = xmlRecoverMemory (request_body->data, request_body->length);
         if (doc == NULL) {
                 /* Failed */
                 g_warning ("Failed to parse NOTIFY message body");
 
-                soup_message_set_status (msg,
-                                         SOUP_STATUS_INTERNAL_SERVER_ERROR);
+                soup_server_message_set_status (msg,
+                                                SOUP_STATUS_INTERNAL_SERVER_ERROR,
+                                                "Unable to parse NOTIFY message");
 
                 return;
         }
@@ -1584,7 +1609,7 @@ server_handler (G_GNUC_UNUSED SoupServer        *soup_server,
                 /* Empty or unsupported */
                 xmlFreeDoc (doc);
 
-                soup_message_set_status (msg, SOUP_STATUS_OK);
+                soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL);
 
                 return;
         }
@@ -1610,7 +1635,7 @@ server_handler (G_GNUC_UNUSED SoupServer        *soup_server,
         }
 
         /* Everything went OK */
-        soup_message_set_status (msg, SOUP_STATUS_OK);
+        soup_server_message_set_status (msg, SOUP_STATUS_OK, "Ok");
 }
 
 /*
@@ -1629,6 +1654,11 @@ make_timeout_header (GUPnPContext *context)
                 return g_strdup ("infinite");
 }
 
+typedef struct {
+        GUPnPServiceProxy *proxy;
+        SoupMessage *msg;
+} SubscriptionCallData;
+
 /*
  * Subscription expired.
  */
@@ -1658,6 +1688,7 @@ subscription_expire (gpointer user_data)
                                                 (GUPNP_SERVICE_INFO (proxy));
 
         local_sub_url = gupnp_context_rewrite_uri (context, sub_url);
+
         g_free (sub_url);
 
         msg = soup_message_new (GENA_METHOD_SUBSCRIBE, local_sub_url);
@@ -1665,13 +1696,15 @@ subscription_expire (gpointer user_data)
 
         g_return_val_if_fail (msg != NULL, FALSE);
 
+        SoupMessageHeaders *request_headers = soup_message_get_request_headers (msg);
+
         /* Add headers */
-        soup_message_headers_append (msg->request_headers,
+        soup_message_headers_append (request_headers,
                                     "SID",
                                     priv->sid);
 
         timeout = make_timeout_header (context);
-        soup_message_headers_append (msg->request_headers,
+        soup_message_headers_append (request_headers,
                                      "Timeout",
                                      timeout);
         g_free (timeout);
@@ -1682,11 +1715,16 @@ subscription_expire (gpointer user_data)
 
         session = gupnp_context_get_session (context);
 
-        soup_session_queue_message (session,
-                                    msg,
-                                    (SoupSessionCallback)
-                                        subscribe_got_response,
-                                    proxy);
+        SubscriptionCallData *data = g_new0 (SubscriptionCallData, 1);
+        data->msg = msg;
+        data->proxy = proxy;
+
+        soup_session_send_and_read_async (session,
+                                          msg,
+                                          G_PRIORITY_DEFAULT,
+                                          NULL,
+                                          (GAsyncReadyCallback) subscribe_got_response,
+                                          data);
 
         return FALSE;
 }
@@ -1695,43 +1733,54 @@ subscription_expire (gpointer user_data)
  * Received subscription response.
  */
 static void
-subscribe_got_response (G_GNUC_UNUSED SoupSession *session,
-                        SoupMessage               *msg,
-                        GUPnPServiceProxy         *proxy)
+subscribe_got_response (GObject *source,
+                        GAsyncResult *res,
+                        gpointer user_data)
 {
-        GError *error;
+        GError *error = NULL;
         GUPnPServiceProxyPrivate *priv;
+        SubscriptionCallData *data = user_data;
+
+        GBytes *body = soup_session_send_and_read_finish (SOUP_SESSION (source), res, &error);
+
+        // We don't need the body, it should be empty anyway
+        g_clear_pointer (&body, g_bytes_unref);
 
         /* Cancelled? */
-        if (msg->status_code == SOUP_STATUS_CANCELLED)
-                return;
+        if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+                goto out;
+        } else if (error != NULL) {
+                // FIXME: Is just propagating the error the right way?
+                goto hdr_err;
+        }
 
         /* Remove from pending messages list */
-        priv = gupnp_service_proxy_get_instance_private (proxy);
-        priv->pending_messages = g_list_remove (priv->pending_messages, msg);
+        priv = gupnp_service_proxy_get_instance_private (data->proxy);
+        priv->pending_messages = g_list_remove (priv->pending_messages, data->msg);
 
         /* Remove subscription timeout */
-        if (priv->subscription_timeout_src) {
-                g_source_destroy (priv->subscription_timeout_src);
-                priv->subscription_timeout_src = NULL;
-        }
+        g_clear_pointer (&priv->subscription_timeout_src, g_source_destroy);
 
         /* Check whether the subscription is still wanted */
-        if (!priv->subscribed)
-                return;
+        if (!priv->subscribed) {
+                goto out;
+        }
 
         /* Reset SID */
         g_free (priv->sid);
         priv->sid = NULL;
 
+        SoupStatus status = soup_message_get_status (data->msg);
+        SoupMessageHeaders *response_headers = soup_message_get_response_headers (data->msg);
+
         /* Check message status */
-        if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
+        if (SOUP_STATUS_IS_SUCCESSFUL (status)) {
                 /* Success. */
                 const char *hdr;
                 int timeout;
 
                 /* Save SID. */
-                hdr = soup_message_headers_get_one (msg->response_headers,
+                hdr = soup_message_headers_get_one (response_headers,
                                                     "SID");
                 if (hdr == NULL) {
                         error = g_error_new
@@ -1745,12 +1794,12 @@ subscribe_got_response (G_GNUC_UNUSED SoupSession *session,
                 priv->sid = g_strdup (hdr);
 
                 /* Figure out when the subscription times out */
-                hdr = soup_message_headers_get_one (msg->response_headers,
+                hdr = soup_message_headers_get_one (response_headers,
                                                     "Timeout");
                 if (hdr == NULL) {
                         g_warning ("No Timeout in SUBSCRIBE response.");
 
-                        return;
+                        goto out;
                 }
 
                 if (strncmp (hdr, "Second-", strlen ("Second-")) == 0) {
@@ -1775,7 +1824,7 @@ subscribe_got_response (G_GNUC_UNUSED SoupSession *session,
                         g_source_set_callback
                                 (priv->subscription_timeout_src,
                                  subscription_expire,
-                                 proxy, NULL);
+                                 data->proxy, NULL);
                         g_source_attach (priv->subscription_timeout_src,
                                          g_main_context_get_thread_default ());
 
@@ -1789,28 +1838,32 @@ subscribe_got_response (G_GNUC_UNUSED SoupSession *session,
                 error = g_error_new_literal
                                 (GUPNP_EVENTING_ERROR,
                                  GUPNP_EVENTING_ERROR_SUBSCRIPTION_FAILED,
-                                 msg->reason_phrase);
+                                 soup_message_get_reason_phrase (data->msg));
 
 hdr_err:
                 /* Remove listener */
                 context = gupnp_service_info_get_context
-                                        (GUPNP_SERVICE_INFO (proxy));
+                                        (GUPNP_SERVICE_INFO (data->proxy));
 
                 server = gupnp_context_get_server (context);
                 soup_server_remove_handler (server, priv->path);
 
                 priv->subscribed = FALSE;
 
-                g_object_notify (G_OBJECT (proxy), "subscribed");
+                g_object_notify (G_OBJECT (data->proxy), "subscribed");
 
                 /* Emit subscription-lost */
-                g_signal_emit (proxy,
+                g_signal_emit (data->proxy,
                                signals[SUBSCRIPTION_LOST],
                                0,
                                error);
 
                 g_error_free (error);
         }
+
+out:
+        g_object_unref (data->msg);
+        g_free (user_data);
 }
 
 /*
@@ -1824,7 +1877,7 @@ subscribe (GUPnPServiceProxy *proxy)
         SoupMessage *msg;
         SoupSession *session;
         SoupServer *server;
-        SoupURI *uri;
+        GUri *uri;
         char *uri_string;
         char *sub_url, *delivery_url, *timeout;
 
@@ -1846,6 +1899,7 @@ subscribe (GUPnPServiceProxy *proxy)
                 char *local_sub_url = NULL;
 
                 local_sub_url = gupnp_context_rewrite_uri (context, sub_url);
+        g_print ("local_sub_uri: %s\n", local_sub_url);
                 g_free (sub_url);
 
                 msg = soup_message_new (GENA_METHOD_SUBSCRIBE, local_sub_url);
@@ -1877,23 +1931,28 @@ subscribe (GUPnPServiceProxy *proxy)
 
         /* Add headers */
         uri = _gupnp_context_get_server_uri (context);
-        soup_uri_set_path (uri, priv->path);
-        uri_string = soup_uri_to_string (uri, FALSE);
-        soup_uri_free (uri);
+        GUri *new_uri = soup_uri_copy (uri, SOUP_URI_PATH, priv->path, NULL);
+
+        uri_string = g_uri_to_string_partial (new_uri, G_URI_HIDE_PASSWORD);
+        g_uri_unref (new_uri);
+        g_uri_unref (uri);
+
         delivery_url = g_strdup_printf ("<%s>", uri_string);
         g_free (uri_string);
 
-        soup_message_headers_append (msg->request_headers,
+        SoupMessageHeaders *request_headers = soup_message_get_request_headers (msg);
+
+        soup_message_headers_append (request_headers,
                                      "Callback",
                                      delivery_url);
         g_free (delivery_url);
 
-        soup_message_headers_append (msg->request_headers,
+        soup_message_headers_append (request_headers,
                                      "NT",
                                      "upnp:event");
 
         timeout = make_timeout_header (context);
-        soup_message_headers_append (msg->request_headers,
+        soup_message_headers_append (request_headers,
                                      "Timeout",
                                      timeout);
         g_free (timeout);
@@ -1913,13 +1972,26 @@ subscribe (GUPnPServiceProxy *proxy)
 
         session = gupnp_context_get_session (context);
 
-        soup_session_queue_message (session,
-                                    msg,
-                                    (SoupSessionCallback)
-                                        subscribe_got_response,
-                                    proxy);
+        SubscriptionCallData *data = g_new0 (SubscriptionCallData, 1);
+
+        data->msg = msg;
+        data->proxy = proxy;
+
+        soup_session_send_and_read_async (session,
+                                          msg,
+                                          G_PRIORITY_DEFAULT,
+                                          NULL,
+                                          subscribe_got_response,
+                                          data);
 }
 
+
+static void
+soup_message_dont_care_for_result (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+        GInputStream *s = soup_session_send_finish (SOUP_SESSION (source), res, NULL);
+        g_clear_object (&s);
+}
 /*
  * Unsubscribe from this service.
  */
@@ -1954,14 +2026,19 @@ unsubscribe (GUPnPServiceProxy *proxy)
 
                 if (msg != NULL) {
                         /* Add headers */
-                        soup_message_headers_append (msg->request_headers,
+                        soup_message_headers_append (soup_message_get_request_headers (msg),
                                                      "SID",
                                                      priv->sid);
 
                         /* And queue it */
                         session = gupnp_context_get_session (context);
 
-                        soup_session_queue_message (session, msg, NULL, NULL);
+                        soup_session_send_async (session,
+                                                 msg,
+                                                 G_PRIORITY_DEFAULT,
+                                                 NULL,
+                                                 soup_message_dont_care_for_result,
+                                                 NULL);
                 }
 
                 /* Reset SID */
@@ -2166,28 +2243,31 @@ gupnp_service_proxy_call_action (GUPnPServiceProxy       *proxy,
 
         context = gupnp_service_info_get_context (GUPNP_SERVICE_INFO (proxy));
         session = gupnp_context_get_session (context);
-        soup_session_send_message (session, action->msg);
+        action->response = soup_session_send_and_read (session,
+                                                       action->msg,
+                                                       action->cancellable,
+                                                       error);
 
-        g_cancellable_disconnect (action->cancellable,
-                                  action->cancellable_connection_id);
-        action->cancellable_connection_id = 0;
-        g_clear_object (&action->cancellable);
+        if (error != NULL && *error != NULL)
+                return NULL;
 
         /* If not allowed, try again */
-        if (action->msg->status_code == SOUP_STATUS_METHOD_NOT_ALLOWED) {
+        if (soup_message_get_status (action->msg) == SOUP_STATUS_METHOD_NOT_ALLOWED) {
                 update_message_after_not_allowed (action->msg);
-                soup_session_send_message (session, action->msg);
+                action->response = soup_session_send_and_read (session,
+                                                               action->msg,
+                                                               action->cancellable,
+                                                               error);
+
         }
 
-        if (action->msg->status_code == SOUP_STATUS_CANCELLED) {
-                g_propagate_error (
-                        error,
-                        g_error_new (G_IO_ERROR,
-                                     G_IO_ERROR_CANCELLED,
-                                     "Action message was cancelled"));
+        g_cancellable_disconnect (action->cancellable,
+                                  action->cancellable_connection_id);
+        action->cancellable_connection_id = 0;
+        g_clear_object (&action->cancellable);
 
+        if (error != NULL && *error != NULL)
                 return NULL;
-        }
 
         return action;
 }
diff --git a/libgupnp/gupnp-service.c b/libgupnp/gupnp-service.c
index 2a33ea5..6ee80c7 100644
--- a/libgupnp/gupnp-service.c
+++ b/libgupnp/gupnp-service.c
@@ -19,7 +19,6 @@
 
 #include <gobject/gvaluecollector.h>
 #include <gmodule.h>
-#include <libsoup/soup-date.h>
 #include <string.h>
 
 #include "gupnp-service.h"
@@ -78,7 +77,7 @@ enum {
 
 static guint signals[LAST_SIGNAL];
 
-static char *
+static GBytes *
 create_property_set (GQueue *queue);
 
 static void
@@ -143,12 +142,12 @@ gupnp_service_get_session (GUPnPService *service)
                  * order. The session from GUPnPContext may use
                  * multiple connections.
                  */
-                priv->session = soup_session_new_with_options (SOUP_SESSION_MAX_CONNS_PER_HOST, 1,
+                priv->session = soup_session_new_with_options ("max-conns-per-host", 1,
                                                                         NULL);
 
                 if (g_getenv ("GUPNP_DEBUG")) {
                         SoupLogger *logger;
-                        logger = soup_logger_new (SOUP_LOGGER_LOG_BODY, -1);
+                        logger = soup_logger_new (SOUP_LOGGER_LOG_BODY);
                         soup_session_add_feature (priv->session,
                                                   SOUP_SESSION_FEATURE (logger));
                 }
@@ -160,19 +159,22 @@ gupnp_service_get_session (GUPnPService *service)
 static void
 subscription_data_free (SubscriptionData *data)
 {
-        SoupSession *session;
+        //SoupSession *session;
 
-        session = gupnp_service_get_session (data->service);
+        //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);
+                 */
 
                 data->pending_messages =
                         g_list_delete_link (data->pending_messages,
@@ -180,7 +182,7 @@ subscription_data_free (SubscriptionData *data)
         }
        
         /* Further cleanup */
-        g_list_free_full (data->callbacks, (GDestroyNotify) soup_uri_free);
+        g_list_free_full (data->callbacks, (GDestroyNotify) g_uri_unref);
 
         g_free (data->sid);
 
@@ -270,7 +272,7 @@ finalize_action (GUPnPServiceAction *action)
                                 "\"http://schemas.xmlsoap.org/soap/encoding/\";>"
                           "<s:Body>");
 
-        if (action->msg->status_code != SOUP_STATUS_INTERNAL_SERVER_ERROR) {
+        if (soup_server_message_get_status (action->msg) != SOUP_STATUS_INTERNAL_SERVER_ERROR) {
                 g_string_append (action->response_str, "</u:");
                 g_string_append (action->response_str, action->name);
                 g_string_append (action->response_str, "Response>");
@@ -280,31 +282,33 @@ finalize_action (GUPnPServiceAction *action)
                          "</s:Body>"
                          "</s:Envelope>");
 
-        soup_message_headers_replace (action->msg->response_headers,
+        SoupMessageHeaders *headers = soup_server_message_get_response_headers (action->msg);
+
+        soup_message_headers_replace (headers,
                                       "Content-Type",
                                       "text/xml; charset=\"utf-8\"");
 
         if (action->accept_gzip && action->response_str->len > 1024) {
+                // Fixme: Probably easier to use an output stream converter instead
                 http_response_set_body_gzip (action->msg,
                                              action->response_str->str,
                                              action->response_str->len);
                 g_string_free (action->response_str, TRUE);
         } else {
-                soup_message_body_append (action->msg->response_body,
-                                          SOUP_MEMORY_TAKE,
-                                          action->response_str->str,
-                                          action->response_str->len);
-                g_string_free (action->response_str, FALSE);
+                SoupMessageBody *msg_body = soup_server_message_get_response_body (action->msg);
+                soup_message_body_append_bytes (msg_body,
+                                g_string_free_to_bytes (action->response_str));
         }
+        action->response_str = NULL;
 
-        soup_message_headers_append (action->msg->response_headers, "Ext", "");
+        soup_message_headers_append (headers,
+                                     "Ext", "");
 
         /* Server header on response */
-        soup_message_headers_append
-                        (action->msg->response_headers,
-                         "Server",
-                         gssdp_client_get_server_id
-                                (GSSDP_CLIENT (action->context)));
+        soup_message_headers_append (headers,
+                                     "Server",
+                                     gssdp_client_get_server_id
+                                                (GSSDP_CLIENT (action->context)));
 
         /* Tell soup server that response is now ready */
         server = gupnp_context_get_server (action->context);
@@ -345,7 +349,7 @@ gupnp_service_action_get_locales (GUPnPServiceAction *action)
 {
         g_return_val_if_fail (action != NULL, NULL);
 
-        return http_request_get_accept_locales (action->msg);
+        return http_request_get_accept_locales (soup_server_message_get_request_headers (action->msg));
 }
 
 /**
@@ -629,7 +633,7 @@ gupnp_service_action_set_values (GUPnPServiceAction *action,
         g_return_if_fail (g_list_length (arg_names) ==
                           g_list_length (arg_values));
 
-        if (action->msg->status_code == SOUP_STATUS_INTERNAL_SERVER_ERROR) {
+        if (soup_server_message_get_status (action->msg) == SOUP_STATUS_INTERNAL_SERVER_ERROR) {
                 g_warning ("Calling gupnp_service_action_set_value() after "
                            "having called gupnp_service_action_return_error() "
                            "is not allowed.");
@@ -671,7 +675,7 @@ gupnp_service_action_set_value (GUPnPServiceAction *action,
         g_return_if_fail (argument != NULL);
         g_return_if_fail (value != NULL);
 
-        if (action->msg->status_code == SOUP_STATUS_INTERNAL_SERVER_ERROR) {
+        if (soup_server_message_get_status (action->msg)== SOUP_STATUS_INTERNAL_SERVER_ERROR) {
                 g_warning ("Calling gupnp_service_action_set_value() after "
                            "having called gupnp_service_action_return_error() "
                            "is not allowed.");
@@ -696,7 +700,7 @@ gupnp_service_action_return (GUPnPServiceAction *action)
 {
         g_return_if_fail (action != NULL);
 
-        soup_message_set_status (action->msg, SOUP_STATUS_OK);
+        soup_server_message_set_status (action->msg, SOUP_STATUS_OK, "Ok");
 
         finalize_action (action);
 }
@@ -778,8 +782,9 @@ gupnp_service_action_return_error (GUPnPServiceAction *action,
 
         xml_util_end_element (action->response_str, "s:Fault");
 
-        soup_message_set_status (action->msg,
-                                 SOUP_STATUS_INTERNAL_SERVER_ERROR);
+        soup_server_message_set_status (action->msg,
+                                 SOUP_STATUS_INTERNAL_SERVER_ERROR,
+                                 "Internal server error");
 
         finalize_action (action);
 }
@@ -791,12 +796,12 @@ gupnp_service_action_return_error (GUPnPServiceAction *action,
  * Get the #SoupMessage associated with @action. Mainly intended for
  * applications to be able to read HTTP headers received from clients.
  *
- * Return value: (transfer full): #SoupMessage associated with @action. Unref
+ * Return value: (transfer full): #SoupServerMessage associated with @action. Unref
  * after using it.
  *
  * Since: 0.14.0
  **/
-SoupMessage *
+SoupServerMessage *
 gupnp_service_action_get_message (GUPnPServiceAction *action)
 {
         return g_object_ref (action->msg);
@@ -904,10 +909,9 @@ query_state_variable (GUPnPService       *service,
 /* controlURL handler */
 static void
 control_server_handler (SoupServer                      *server,
-                        SoupMessage                     *msg,
+                        SoupServerMessage               *msg,
                         G_GNUC_UNUSED const char        *server_path,
                         G_GNUC_UNUSED GHashTable        *query,
-                        G_GNUC_UNUSED SoupClientContext *soup_client,
                         gpointer                         user_data)
 {
         GUPnPService *service;
@@ -922,22 +926,26 @@ control_server_handler (SoupServer                      *server,
 
         service = GUPNP_SERVICE (user_data);
 
-        if (msg->method != SOUP_METHOD_POST) {
-                soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
+        if (soup_server_message_get_method (msg) != SOUP_METHOD_POST) {
+                soup_server_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED, "Not implemented");
 
                 return;
         }
 
-        if (msg->request_body->length == 0) {
-                soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST);
+        SoupMessageBody *request_body = soup_server_message_get_request_body (msg);
+        SoupMessageHeaders *request_headers = soup_server_message_get_request_headers (msg);
+        SoupMessageHeaders *response_headers = soup_server_message_get_response_headers (msg);
+
+        if (request_body->length == 0) {
+                soup_server_message_set_status (msg, SOUP_STATUS_BAD_REQUEST, "Bad request");
 
                 return;
         }
 
         /* DLNA 7.2.5.6: Always use HTTP 1.1 */
-        if (soup_message_get_http_version (msg) == SOUP_HTTP_1_0) {
-                soup_message_set_http_version (msg, SOUP_HTTP_1_1);
-                soup_message_headers_append (msg->response_headers,
+        if (soup_server_message_get_http_version (msg) == SOUP_HTTP_1_0) {
+                soup_server_message_set_http_version (msg, SOUP_HTTP_1_1);
+                soup_message_headers_append (response_headers,
                                              "Connection",
                                              "close");
         }
@@ -945,7 +953,7 @@ control_server_handler (SoupServer                      *server,
         context = gupnp_service_info_get_context (GUPNP_SERVICE_INFO (service));
 
         const char *host_header =
-                soup_message_headers_get_one (msg->request_headers, "Host");
+                soup_message_headers_get_one (request_headers, "Host");
 
         if (!gupnp_context_validate_host_header (context, host_header)) {
                 g_warning ("Host header mismatch, expected %s:%d, got %s",
@@ -953,21 +961,29 @@ control_server_handler (SoupServer                      *server,
                            gupnp_context_get_port (context),
                            host_header);
 
-                soup_message_set_status (msg, SOUP_STATUS_PRECONDITION_FAILED);
+                soup_server_message_set_status (msg,
+                                                SOUP_STATUS_PRECONDITION_FAILED,
+                                                "Host header mismatch");
+
                 return;
         }
 
         /* Get action name */
-        soap_action = soup_message_headers_get_one (msg->request_headers,
+        soap_action = soup_message_headers_get_one (request_headers,
                                                     "SOAPAction");
         if (!soap_action) {
-                soup_message_set_status (msg, SOUP_STATUS_PRECONDITION_FAILED);
+                soup_server_message_set_status (msg,
+                                                SOUP_STATUS_PRECONDITION_FAILED,
+                                                "No SOAPAction header");
+
                 return;
         }
 
         action_name = strchr (soap_action, '#');
         if (!action_name) {
-                soup_message_set_status (msg, SOUP_STATUS_PRECONDITION_FAILED);
+                soup_server_message_set_status (msg,
+                                                SOUP_STATUS_PRECONDITION_FAILED,
+                                                "No action name");
 
                 return;
         }
@@ -985,10 +1001,12 @@ control_server_handler (SoupServer                      *server,
                 *end = '\0';
 
         /* Parse action_node */
-        doc = xmlRecoverMemory (msg->request_body->data,
-                                msg->request_body->length);
+        doc = xmlRecoverMemory (request_body->data,
+                                request_body->length);
         if (doc == NULL) {
-                soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST);
+                soup_server_message_set_status (msg,
+                                                SOUP_STATUS_BAD_REQUEST,
+                                                "Unable to parse action");
 
                 return;
         }
@@ -999,7 +1017,9 @@ control_server_handler (SoupServer                      *server,
                                             action_name,
                                             NULL);
         if (!action_node) {
-                soup_message_set_status (msg, SOUP_STATUS_PRECONDITION_FAILED);
+                soup_server_message_set_status (msg,
+                                                SOUP_STATUS_PRECONDITION_FAILED,
+                                                "Missing <action>");
 
                 return;
         }
@@ -1020,7 +1040,7 @@ control_server_handler (SoupServer                      *server,
                         action->argument_count++;
 
         /* Get accepted encodings */
-        accept_encoding = soup_message_headers_get_list (msg->request_headers,
+        accept_encoding = soup_message_headers_get_list (request_headers,
                                                          "Accept-Encoding");
 
         if (accept_encoding) {
@@ -1069,7 +1089,7 @@ control_server_handler (SoupServer                      *server,
 /* Generates a standard (re)subscription response */
 static void
 subscription_response (GUPnPService *service,
-                       SoupMessage  *msg,
+                       SoupServerMessage  *msg,
                        const char   *sid,
                        int           timeout)
 {
@@ -1080,13 +1100,15 @@ subscription_response (GUPnPService *service,
         context = gupnp_service_info_get_context (GUPNP_SERVICE_INFO (service));
         client = GSSDP_CLIENT (context);
 
+        SoupMessageHeaders *response_headers = soup_server_message_get_response_headers (msg);
+
         /* Server header on response */
-        soup_message_headers_append (msg->response_headers,
+        soup_message_headers_append (response_headers,
                                      "Server",
                                      gssdp_client_get_server_id (client));
 
         /* SID header */
-        soup_message_headers_append (msg->response_headers,
+        soup_message_headers_append (response_headers,
                                      "SID",
                                      sid);
 
@@ -1096,13 +1118,13 @@ subscription_response (GUPnPService *service,
         else
                 tmp = g_strdup ("infinite");
 
-        soup_message_headers_append (msg->response_headers,
+        soup_message_headers_append (response_headers,
                                      "Timeout",
                                      tmp);
         g_free (tmp);
 
         /* 200 OK */
-        soup_message_set_status (msg, SOUP_STATUS_OK);
+        soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL);
 }
 
 /**
@@ -1150,7 +1172,6 @@ static void
 send_initial_state (SubscriptionData *data)
 {
         GQueue *queue;
-        char *mem;
         GList *l;
         GUPnPServicePrivate *priv;
 
@@ -1181,13 +1202,13 @@ send_initial_state (SubscriptionData *data)
                 g_queue_push_tail (queue, ndata);
         }
 
-        mem = create_property_set (queue);
-        notify_subscriber (data->sid, data, mem);
+        GBytes *property_set = create_property_set (queue);
+        notify_subscriber (data->sid, data, property_set);
 
         /* Cleanup */
         g_queue_free (queue);
 
-        g_free (mem);
+        g_bytes_unref (property_set);
 }
 
 static GList *
@@ -1195,14 +1216,14 @@ add_subscription_callback (GUPnPContext *context,
                            GList *list,
                            const char *callback)
 {
-            SoupURI *local_uri = NULL;
+            GUri *local_uri = NULL;
 
             local_uri = gupnp_context_rewrite_uri_to_uri (context, callback);
             if (local_uri == NULL) {
                     return list;
             }
 
-            const char *host = soup_uri_get_host (local_uri);
+            const char *host = g_uri_get_host (local_uri);
             GSocketAddress *address = g_inet_socket_address_new_from_string (host, 0);
 
             // CVE-2020-12695: Ignore subscription call-backs that are not "in
@@ -1219,7 +1240,7 @@ add_subscription_callback (GUPnPContext *context,
 /* Subscription request */
 static void
 subscribe (GUPnPService *service,
-           SoupMessage  *msg,
+           SoupServerMessage  *msg,
            const char   *callback)
 {
         SubscriptionData *data;
@@ -1269,7 +1290,9 @@ subscribe (GUPnPService *service,
         }
 
         if (!data->callbacks) {
-                soup_message_set_status (msg, SOUP_STATUS_PRECONDITION_FAILED);
+                soup_server_message_set_status (msg,
+                                                SOUP_STATUS_PRECONDITION_FAILED,
+                                                "No valid callbacks found");
 
                 g_slice_free (SubscriptionData, data);
 
@@ -1306,7 +1329,7 @@ subscribe (GUPnPService *service,
 /* Resubscription request */
 static void
 resubscribe (GUPnPService *service,
-             SoupMessage  *msg,
+             SoupServerMessage  *msg,
              const char   *sid)
 {
         SubscriptionData *data;
@@ -1316,7 +1339,9 @@ resubscribe (GUPnPService *service,
 
         data = g_hash_table_lookup (priv->subscriptions, sid);
         if (!data) {
-                soup_message_set_status (msg, SOUP_STATUS_PRECONDITION_FAILED);
+                soup_server_message_set_status (msg,
+                                                SOUP_STATUS_PRECONDITION_FAILED,
+                                                "No previous subscription found");
 
                 return;
         }
@@ -1345,7 +1370,7 @@ resubscribe (GUPnPService *service,
 /* Unsubscription request */
 static void
 unsubscribe (GUPnPService *service,
-             SoupMessage  *msg,
+             SoupServerMessage  *msg,
              const char   *sid)
 {
         SubscriptionData *data;
@@ -1360,18 +1385,19 @@ unsubscribe (GUPnPService *service,
                                              sid);
                 else
                         data->to_delete = TRUE;
-                soup_message_set_status (msg, SOUP_STATUS_OK);
+                soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL);
         } else
-                soup_message_set_status (msg, SOUP_STATUS_PRECONDITION_FAILED);
+                soup_server_message_set_status (msg,
+                                                SOUP_STATUS_PRECONDITION_FAILED,
+                                                "No previous subscription found");
 }
 
 /* eventSubscriptionURL handler */
 static void
 subscription_server_handler (G_GNUC_UNUSED SoupServer        *server,
-                             SoupMessage                     *msg,
+                             SoupServerMessage               *msg,
                              G_GNUC_UNUSED const char        *server_path,
                              G_GNUC_UNUSED GHashTable        *query,
-                             G_GNUC_UNUSED SoupClientContext *soup_client,
                              gpointer                         user_data)
 {
         GUPnPService *service;
@@ -1379,8 +1405,12 @@ subscription_server_handler (G_GNUC_UNUSED SoupServer        *server,
 
         service = GUPNP_SERVICE (user_data);
 
+        SoupMessageHeaders *request_headers = soup_server_message_get_request_headers (msg);
+
+        g_print ("Got SUBSCRIBE handler request\n");
+
         const char *host =
-                soup_message_headers_get_one (msg->request_headers, "Host");
+                soup_message_headers_get_one (request_headers, "Host");
         GUPnPContext *context = gupnp_service_info_get_context (user_data);
         if (!gupnp_context_validate_host_header(context, host)) {
                 g_warning ("Host header mismatch, expected %s:%d, got %s",
@@ -1388,26 +1418,31 @@ subscription_server_handler (G_GNUC_UNUSED SoupServer        *server,
                            gupnp_context_get_port (context),
                            host);
 
-                soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST);
+                soup_server_message_set_status (msg, SOUP_STATUS_BAD_REQUEST, NULL);
 
                 return;
         }
 
-        callback = soup_message_headers_get_one (msg->request_headers,
+        callback = soup_message_headers_get_one (request_headers,
                                                  "Callback");
-        nt       = soup_message_headers_get_one (msg->request_headers, "NT");
-        sid      = soup_message_headers_get_one (msg->request_headers, "SID");
+        nt       = soup_message_headers_get_one (request_headers, "NT");
+        sid      = soup_message_headers_get_one (request_headers, "SID");
+        const char *method = soup_server_message_get_method (msg);
 
         /* Choose appropriate handler */
-        if (strcmp (msg->method, GENA_METHOD_SUBSCRIBE) == 0) {
+        if (strcmp (method, GENA_METHOD_SUBSCRIBE) == 0) {
                 if (callback) {
                         if (sid) {
-                                soup_message_set_status
-                                        (msg, SOUP_STATUS_BAD_REQUEST);
+                                soup_server_message_set_status
+                                        (msg,
+                                         SOUP_STATUS_BAD_REQUEST,
+                                         "SID must not be given on SUBSCRIBE");
 
                         } else if (!nt || strcmp (nt, "upnp:event") != 0) {
-                                soup_message_set_status
-                                        (msg, SOUP_STATUS_PRECONDITION_FAILED);
+                                soup_server_message_set_status
+                                        (msg,
+                                         SOUP_STATUS_PRECONDITION_FAILED,
+                                         "NT header missing or malformed");
 
                         } else {
                                 subscribe (service, msg, callback);
@@ -1416,8 +1451,10 @@ subscription_server_handler (G_GNUC_UNUSED SoupServer        *server,
 
                 } else if (sid) {
                         if (nt) {
-                                soup_message_set_status
-                                        (msg, SOUP_STATUS_BAD_REQUEST);
+                                soup_server_message_set_status
+                                        (msg,
+                                         SOUP_STATUS_BAD_REQUEST,
+                                         "NT must not be given on RESUBSCRIBE");
 
                         } else {
                                 resubscribe (service, msg, sid);
@@ -1425,16 +1462,16 @@ subscription_server_handler (G_GNUC_UNUSED SoupServer        *server,
                         }
 
                 } else {
-                        soup_message_set_status
-                                (msg, SOUP_STATUS_PRECONDITION_FAILED);
+                        soup_server_message_set_status
+                                (msg, SOUP_STATUS_PRECONDITION_FAILED, NULL);
 
                 }
 
-        } else if (strcmp (msg->method, GENA_METHOD_UNSUBSCRIBE) == 0) {
+        } else if (strcmp (method, GENA_METHOD_UNSUBSCRIBE) == 0) {
                 if (sid) {
                         if (nt || callback) {
-                                soup_message_set_status
-                                        (msg, SOUP_STATUS_BAD_REQUEST);
+                                soup_server_message_set_status
+                                        (msg, SOUP_STATUS_BAD_REQUEST, NULL);
 
                         } else {
                                 unsubscribe (service, msg, sid);
@@ -1442,13 +1479,13 @@ subscription_server_handler (G_GNUC_UNUSED SoupServer        *server,
                         }
 
                 } else {
-                        soup_message_set_status
-                                (msg, SOUP_STATUS_PRECONDITION_FAILED);
+                        soup_server_message_set_status
+                                (msg, SOUP_STATUS_PRECONDITION_FAILED, NULL);
 
                 }
 
         } else {
-                soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
+                soup_server_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED, NULL);
 
         }
 }
@@ -1523,12 +1560,19 @@ got_introspection (GUPnPServiceInfo          *info,
 static char *
 path_from_url (const char *url)
 {
-        SoupURI *uri;
         gchar   *path;
+        const char *query = NULL;
 
-        uri = soup_uri_new (url);
-        path = soup_uri_to_string (uri, TRUE);
-        soup_uri_free (uri);
+        GUri *uri = g_uri_parse (url, G_URI_FLAGS_NONE, NULL);
+
+        query = g_uri_get_query (uri);
+        if (query == NULL) {
+                path = g_strdup (g_uri_get_path (uri));
+        } else {
+                path = g_strdup_printf ("%s?%s",
+                                g_uri_get_path (uri), query);
+        }
+        g_uri_unref (uri);
 
         return path;
 }
@@ -1920,142 +1964,161 @@ gupnp_service_notify_valist (GUPnPService *service,
         }
 }
 
+typedef struct {
+        SubscriptionData *data;
+        SoupMessage *msg;
+        GBytes *property_set;
+} NotifySubscriberData;
+
 /* Received notify response. */
 static void
-notify_got_response (G_GNUC_UNUSED SoupSession *session,
-                     SoupMessage               *msg,
+notify_got_response (GObject *source,
+                     GAsyncResult *res,
                      gpointer                   user_data)
 {
-        SubscriptionData *data;
+
+        GBytes *body;
+        GError *error = NULL;
+
+        body = soup_session_send_and_read_finish (SOUP_SESSION (source),
+                                                  res,
+                                                  &error);
 
         /* Cancelled? */
-        if (msg->status_code == SOUP_STATUS_CANCELLED)
+        if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+                g_clear_error (&error);
+
                 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);
 
-        data = user_data;
 
         /* Remove from pending messages list */
-        data->pending_messages = g_list_remove (data->pending_messages, msg);
+        data->data->pending_messages = g_list_remove (data->data->pending_messages, data->msg);
 
-        if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
-                data->initial_state_sent = TRUE;
+        if (SOUP_STATUS_IS_SUCCESSFUL (status)) {
+                data->data->initial_state_sent = TRUE;
 
                 /* Success: reset callbacks pointer */
-                data->callbacks = g_list_first (data->callbacks);
+                data->data->callbacks = g_list_first (data->data->callbacks);
 
-        } else if (msg->status_code == SOUP_STATUS_PRECONDITION_FAILED) {
+        } else if (status == SOUP_STATUS_PRECONDITION_FAILED) {
                 /* Precondition failed: Cancel subscription */
-                gupnp_service_remove_subscription (data->service, data->sid);
+                gupnp_service_remove_subscription (data->data->service, data->data->sid);
 
         } else {
                 /* Other failure: Try next callback or signal failure. */
-                if (data->callbacks->next) {
-                        SoupBuffer *buffer;
-                        guint8 *property_set;
-                        gsize length;
-
+                if (data->data->callbacks->next) {
                         /* Call next callback */
-                        data->callbacks = data->callbacks->next;
-
-                        /* Get property-set from old message */
-                        buffer = soup_message_body_flatten (msg->request_body);
-                        soup_buffer_get_data (buffer,
-                                              (const guint8 **) &property_set,
-                                              &length);
-                        notify_subscriber (NULL, data, property_set);
-                        soup_buffer_free (buffer);
+                        data->data->callbacks = data->data->callbacks->next;
+
+                        notify_subscriber (NULL, data->data, g_bytes_ref (data->property_set));
+                        g_bytes_unref (data->property_set);
                 } else {
                         /* Emit 'notify-failed' signal */
-                        GError *error;
+                        GError *inner_error;
 
-                        error = g_error_new_literal
+                        inner_error = g_error_new_literal
                                         (GUPNP_EVENTING_ERROR,
                                          GUPNP_EVENTING_ERROR_NOTIFY_FAILED,
-                                         msg->reason_phrase);
+                                         soup_message_get_reason_phrase (data->msg));
 
-                        g_signal_emit (data->service,
+                        g_signal_emit (data->data->service,
                                        signals[NOTIFY_FAILED],
                                        0,
-                                       data->callbacks,
-                                       error);
+                                       data->data->callbacks,
+                                       inner_error);
 
-                        g_error_free (error);
+                        g_error_free (inner_error);
 
                         /* Reset callbacks pointer */
-                        data->callbacks = g_list_first (data->callbacks);
+                        data->data->callbacks = g_list_first (data->data->callbacks);
                 }
         }
+
+        g_clear_error (&error);
+        g_bytes_unref (data->property_set);
+        g_object_unref (data->msg);
+        g_free (data);
 }
 
+
 /* Send notification @user_data to subscriber @value */
 static void
 notify_subscriber (G_GNUC_UNUSED gpointer key,
                    gpointer value,
                    gpointer user_data)
 {
-        SubscriptionData *data;
-        const char *property_set;
         char *tmp;
-        SoupMessage *msg;
         SoupSession *session;
 
-        data = value;
-        property_set = user_data;
-
         /* Subscriber called unsubscribe */
-        if (subscription_data_can_delete (data))
+        if (subscription_data_can_delete ((SubscriptionData *)value))
                 return;
 
+        NotifySubscriberData *data = g_new0 (NotifySubscriberData, 1);
+
+        data->data = value;
+        data->property_set = g_bytes_ref ((GBytes *) user_data);
+
         /* Create message */
-        msg = soup_message_new_from_uri (GENA_METHOD_NOTIFY,
-                                         data->callbacks->data);
+        data->msg = soup_message_new_from_uri (GENA_METHOD_NOTIFY,
+                                               data->data->callbacks->data);
+
+        SoupMessageHeaders *request_headers = soup_message_get_request_headers (data->msg);
 
-        soup_message_headers_append (msg->request_headers,
+        soup_message_headers_append (request_headers,
                                      "NT",
                                      "upnp:event");
 
-        soup_message_headers_append (msg->request_headers,
+        soup_message_headers_append (request_headers,
                                      "NTS",
                                      "upnp:propchange");
 
-        soup_message_headers_append (msg->request_headers,
+        soup_message_headers_append (request_headers,
                                      "SID",
-                                     data->sid);
+                                     data->data->sid);
 
-        tmp = g_strdup_printf ("%d", data->seq);
-        soup_message_headers_append (msg->request_headers,
+        tmp = g_strdup_printf ("%d", data->data->seq);
+        soup_message_headers_append (request_headers,
                                      "SEQ",
                                      tmp);
         g_free (tmp);
 
         /* Handle overflow */
-        if (data->seq < G_MAXINT32)
-                data->seq++;
+        if (data->data->seq < G_MAXINT32)
+                data->data->seq++;
         else
-                data->seq = 1;
+                data->data->seq = 1;
 
         /* Add body */
-        soup_message_set_request (msg,
+        soup_message_set_request_body_from_bytes (data->msg,
                                   "text/xml; charset=\"utf-8\"",
-                                  SOUP_MEMORY_TAKE,
-                                  g_strdup (property_set),
-                                  strlen (property_set));
+                                  data->property_set);
 
         /* Queue */
-        data->pending_messages = g_list_prepend (data->pending_messages, msg);
-        soup_message_headers_append (msg->request_headers,
+        data->data->pending_messages = g_list_prepend (data->data->pending_messages, data->msg);
+        soup_message_headers_append (request_headers,
                                      "Connection", "close");
 
-        session = gupnp_service_get_session (data->service);
+        session = gupnp_service_get_session (data->data->service);
 
-        soup_session_queue_message (session,
-                                    msg,
-                                    notify_got_response,
-                                    data);
+        soup_session_send_and_read_async (session,
+                                          data->msg,
+                                          G_PRIORITY_DEFAULT,
+                                          NULL,
+                                          (GAsyncReadyCallback) notify_got_response,
+                                          data);
 }
 
 /* Create a property set from @queue */
-static char *
+static GBytes *
 create_property_set (GQueue *queue)
 {
         NotifyData *data;
@@ -2084,28 +2147,27 @@ create_property_set (GQueue *queue)
         g_string_append (str, "</e:propertyset>");
 
         /* Cleanup & return */
-        return g_string_free (str, FALSE);
+        return g_string_free_to_bytes (str);
 }
 
 /* Flush all queued notifications */
 static void
 flush_notifications (GUPnPService *service)
 {
-        char *mem;
         GUPnPServicePrivate *priv;
 
         priv = gupnp_service_get_instance_private (service);
 
         /* Create property set */
-        mem = create_property_set (priv->notify_queue);
+        GBytes *property_set = create_property_set (priv->notify_queue);
 
         /* And send it off */
         g_hash_table_foreach (priv->subscriptions,
                               notify_subscriber,
-                              mem);
+                              property_set);
 
         /* Cleanup */
-        g_free (mem);
+        g_bytes_unref (property_set);
 }
 
 /**
diff --git a/libgupnp/gupnp-service.h b/libgupnp/gupnp-service.h
index dc47e7d..5ad6c99 100644
--- a/libgupnp/gupnp-service.h
+++ b/libgupnp/gupnp-service.h
@@ -114,7 +114,7 @@ gupnp_service_action_return_error (GUPnPServiceAction *action,
                                    guint               error_code,
                                    const char         *error_description);
 
-SoupMessage *
+SoupServerMessage *
 gupnp_service_action_get_message  (GUPnPServiceAction *action);
 
 guint
diff --git a/libgupnp/gupnp-unix-context-manager.c b/libgupnp/gupnp-unix-context-manager.c
index 180d362..37b7c7b 100644
--- a/libgupnp/gupnp-unix-context-manager.c
+++ b/libgupnp/gupnp-unix-context-manager.c
@@ -30,7 +30,6 @@
 #include <arpa/inet.h>
 #include <net/if.h>
 #include <ifaddrs.h>
-#include <libsoup/soup-address.h>
 #include <glib/gstdio.h>
 #include <libgssdp/gssdp-error.h>
 
diff --git a/libgupnp/http-headers.c b/libgupnp/http-headers.c
index cb4e7a6..aa5cdf6 100644
--- a/libgupnp/http-headers.c
+++ b/libgupnp/http-headers.c
@@ -141,7 +141,9 @@ http_request_set_accept_language (SoupMessage *message)
 
         g_free (lang);
 
-        soup_message_headers_append (message->request_headers,
+        SoupMessageHeaders *request_headers = soup_message_get_request_headers (message);
+
+        soup_message_headers_append (request_headers,
                                      "Accept-Language",
                                      tmp->str);
 
@@ -177,14 +179,14 @@ sort_locales_by_quality (const char *a,
 /* Parses the Accept-Language header in @message, and returns its values
  * in an ordered list in UNIX locale format */
 GList *
-http_request_get_accept_locales (SoupMessage *message)
+http_request_get_accept_locales (SoupMessageHeaders *request_headers)
 {
         const char *header;
         char **bits;
         int i;
         GList *locales;
 
-        header = soup_message_headers_get_one (message->request_headers,
+        header = soup_message_headers_get_one (request_headers,
                                                "Accept-Language");
         if (header == NULL)
                 return NULL;
@@ -224,7 +226,7 @@ http_request_get_accept_locales (SoupMessage *message)
 
 /* Set Accept-Language header according to @locale. */
 void
-http_response_set_content_locale (SoupMessage *msg,
+http_response_set_content_locale (SoupMessageHeaders *response_headers,
                                   const char  *locale)
 {
         char *lang;
@@ -232,7 +234,7 @@ http_response_set_content_locale (SoupMessage *msg,
         lang = g_strdup (locale);
         http_language_from_locale (lang);
 
-        soup_message_headers_append (msg->response_headers,
+        soup_message_headers_append (response_headers,
                                      "Content-Language",
                                      lang);
 
@@ -242,7 +244,7 @@ http_response_set_content_locale (SoupMessage *msg,
 /* Set Content-Type header guessed from @path, @data and @data_size using
  * g_content_type_guess(). */
 void
-http_response_set_content_type (SoupMessage  *msg,
+http_response_set_content_type (SoupMessageHeaders  *response_headers,
                                 const char   *path,
                                 const guchar *data,
                                 gsize         data_size)
@@ -262,7 +264,7 @@ http_response_set_content_type (SoupMessage  *msg,
                 mime = g_strdup ("text/xml; charset=\"utf-8\"");
         }
 
-        soup_message_headers_append (msg->response_headers,
+        soup_message_headers_append (response_headers,
                                      "Content-Type",
                                      mime);
 
@@ -272,7 +274,7 @@ http_response_set_content_type (SoupMessage  *msg,
 
 /* Set Content-Encoding header to gzip and append compressed body */
 void
-http_response_set_body_gzip (SoupMessage *msg,
+http_response_set_body_gzip (SoupServerMessage *msg,
                              const char  *body,
                              const gsize  length)
 {
@@ -280,7 +282,10 @@ http_response_set_body_gzip (SoupMessage *msg,
         gboolean finished = FALSE;
         gsize converted = 0;
 
-        soup_message_headers_append (msg->response_headers,
+        SoupMessageBody *message_body = soup_server_message_get_response_body (msg);
+        SoupMessageHeaders *response_headers = soup_server_message_get_response_headers (msg);
+
+        soup_message_headers_append (response_headers,
                                      "Content-Encoding", "gzip");
 
         compressor = g_zlib_compressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP, -1);
@@ -317,7 +322,7 @@ http_response_set_body_gzip (SoupMessage *msg,
                 }
 
                 if (bytes_written)
-                        soup_message_body_append (msg->response_body,
+                        soup_message_body_append (message_body,
                                                   SOUP_MEMORY_COPY,
                                                   buf, bytes_written);
         }
diff --git a/libgupnp/http-headers.h b/libgupnp/http-headers.h
index 5b07a10..846c8c4 100644
--- a/libgupnp/http-headers.h
+++ b/libgupnp/http-headers.h
@@ -23,14 +23,14 @@ G_GNUC_INTERNAL void
 http_request_set_accept_language (SoupMessage  *message);
 
 G_GNUC_INTERNAL GList *
-http_request_get_accept_locales  (SoupMessage  *message);
+http_request_get_accept_locales  (SoupMessageHeaders  *message);
 
 G_GNUC_INTERNAL void
-http_response_set_content_locale (SoupMessage  *message,
+http_response_set_content_locale (SoupMessageHeaders  *message,
                                   const char   *locale);
 
 G_GNUC_INTERNAL void
-http_response_set_content_type   (SoupMessage  *message,
+http_response_set_content_type   (SoupMessageHeaders  *response_headers,
                                   const char   *path,
                                   const guchar *data,
                                   gsize         data_size);
@@ -42,7 +42,7 @@ http_response_set_content_range  (SoupMessage  *message,
                                   gsize         total);
 
 G_GNUC_INTERNAL void
-http_response_set_body_gzip      (SoupMessage   *msg,
+http_response_set_body_gzip      (SoupServerMessage   *msg,
                                   const char    *body,
                                   const gsize    length);
 
diff --git a/libgupnp/xml-util.c b/libgupnp/xml-util.c
index 6c05668..683a178 100644
--- a/libgupnp/xml-util.c
+++ b/libgupnp/xml-util.c
@@ -93,22 +93,22 @@ xml_util_get_child_element_content_glib (xmlNode    *node,
         return copy;
 }
 
-SoupURI *
+GUri *
 xml_util_get_child_element_content_uri (xmlNode    *node,
                                         const char *child_name,
-                                        SoupURI    *base)
+                                        GUri    *base)
 {
         xmlChar *content;
-        SoupURI *uri;
+        GUri *uri;
 
         content = xml_util_get_child_element_content (node, child_name);
         if (!content)
                 return NULL;
 
         if (base != NULL)
-                uri = soup_uri_new_with_base (base, (const char *) content);
+                uri = g_uri_parse_relative (base, (const char *) content, G_URI_FLAGS_NONE, NULL);
         else
-                uri = soup_uri_new ((const char *) content);
+                uri = g_uri_parse ((const char *) content, G_URI_FLAGS_NONE, NULL);
 
         xmlFree (content);
 
@@ -118,18 +118,17 @@ xml_util_get_child_element_content_uri (xmlNode    *node,
 char *
 xml_util_get_child_element_content_url (xmlNode    *node,
                                         const char *child_name,
-                                        SoupURI    *base)
+                                        GUri    *base)
 {
-        SoupURI *uri;
+        GUri *uri;
         char *url;
 
         uri = xml_util_get_child_element_content_uri (node, child_name, base);
         if (!uri)
                 return NULL;
 
-        url = soup_uri_to_string (uri, FALSE);
-
-        soup_uri_free (uri);
+        url = g_uri_to_string_partial (uri, G_URI_HIDE_PASSWORD);
+        g_uri_unref (uri);
 
         return url;
 }
diff --git a/libgupnp/xml-util.h b/libgupnp/xml-util.h
index 51d62ba..7078bd6 100644
--- a/libgupnp/xml-util.h
+++ b/libgupnp/xml-util.h
@@ -10,7 +10,6 @@
 #define GUPNP_XML_UTIL_H
 
 #include <libxml/tree.h>
-#include <libsoup/soup-uri.h>
 #include <stdarg.h>
 #include <glib-object.h>
 
@@ -31,15 +30,15 @@ G_GNUC_INTERNAL char *
 xml_util_get_child_element_content_glib (xmlNode    *node,
                                          const char *child_name);
 
-G_GNUC_INTERNAL SoupURI *
+G_GNUC_INTERNAL GUri *
 xml_util_get_child_element_content_uri  (xmlNode    *node,
                                          const char *child_name,
-                                         SoupURI    *base);
+                                         GUri    *base);
 
 G_GNUC_INTERNAL char *
 xml_util_get_child_element_content_url  (xmlNode    *node,
                                          const char *child_name,
-                                         SoupURI    *base);
+                                         GUri    *base);
 G_GNUC_INTERNAL xmlChar *
 xml_util_get_attribute_contents         (xmlNode    *node,
                                          const char *attribute_name);
diff --git a/meson.build b/meson.build
index 68b43f5..0b544e2 100644
--- a/meson.build
+++ b/meson.build
@@ -13,10 +13,10 @@ conf.set('HAVE_NETLINK', netlink_available)
 conf.set('HAVE_IFADDRS_H', ifaddrs_available)
 conf.set('HAVE_LINUX_WIRELESS_H', cc.has_header('linux/wireless.h'))
 
-glib_version = '2.66'
+glib_version = '2.69'
 add_project_arguments(cc.get_supported_arguments('-Werror=deprecated-declarations'), language: 'c')
-conf.set('GLIB_VERSION_MIN_REQUIRED', 'GLIB_VERSION_' + glib_version.underscorify())
-conf.set('GLIB_VERSION_MAX_ALLOWED', 'GLIB_VERSION_' + glib_version.underscorify())
+conf.set('GLIB_VERSION_MIN_REQUIRED', 'GLIB_VERSION_2_70'.format(glib_version.underscorify()))
+conf.set('GLIB_VERSION_MAX_ALLOWED', 'GLIB_VERSION_2_70'.format(glib_version.underscorify()))
 
 subdir('internal')
 guul = subproject('guul', default_options : ['default_library=static'])
@@ -30,7 +30,7 @@ dependencies = [
     dependency('gio-2.0', version : '>= ' + glib_version),
     dependency('gmodule-2.0', version : '>= ' + glib_version),
     dependency('gobject-2.0', version : '>= ' + glib_version),
-    dependency('libsoup-2.4', version : '>= 2.48.0'),
+    dependency('libsoup-3.0', version : '>= 2.99.0'),
     gssdp_dep,
     dependency('libxml-2.0'),
 ]
diff --git a/tests/test-bugs.c b/tests/test-bugs.c
index 9d118c7..8e8e600 100644
--- a/tests/test-bugs.c
+++ b/tests/test-bugs.c
@@ -163,19 +163,20 @@ test_bgo_690400_query_variable (GUPnPService *service,
 }
 
 static gboolean
-test_on_timeout (G_GNUC_UNUSED gpointer user_data)
+test_on_timeout (gpointer user_data)
 {
+    g_print ("Timeout in %s\n", (const char *) user_data);
     g_assert_not_reached ();
 
     return FALSE;
 }
 
 static void
-test_run_loop (GMainLoop *loop)
+test_run_loop (GMainLoop *loop, const char *name)
 {
     guint timeout_id = 0;
 
-    timeout_id = g_timeout_add_seconds (2, test_on_timeout, NULL);
+    timeout_id = g_timeout_add_seconds (2, test_on_timeout, (gpointer) name);
     g_main_loop_run (loop);
     g_source_remove (timeout_id);
 }
@@ -219,7 +220,7 @@ test_bgo_696762 (void)
                       G_CALLBACK (test_bgo_696762_on_browse_call),
                       &data);
 
-    test_run_loop (data.loop);
+    test_run_loop (data.loop, g_test_get_path ());
     g_assert (data.proxy != NULL);
 
     G_GNUC_BEGIN_IGNORE_DEPRECATIONS
@@ -236,7 +237,7 @@ test_bgo_696762 (void)
                                       NULL);
     G_GNUC_END_IGNORE_DEPRECATIONS
 
-    test_run_loop (data.loop);
+    test_run_loop (data.loop, g_test_get_path ());
 
     g_main_loop_unref (data.loop);
     g_object_unref (data.proxy);
@@ -287,7 +288,7 @@ test_bgo_678701 (void)
                       G_CALLBACK (test_bgo_678701_on_dp_available),
                       &data);
 
-    test_run_loop (data.loop);
+    test_run_loop (data.loop, g_test_get_path ());
     g_assert (data.proxy != NULL);
 
     info = gupnp_device_info_get_service (GUPNP_DEVICE_INFO (data.proxy),
@@ -341,7 +342,7 @@ test_bgo_690400 (void)
                       G_CALLBACK (test_bgo_690400_query_variable), NULL);
     gupnp_root_device_set_available (rd, TRUE);
 
-    test_run_loop (data.loop);
+    test_run_loop (data.loop, "690400 - waiting for query_variable");
     g_assert (data.proxy != NULL);
 
     gupnp_service_proxy_add_notify (data.proxy,
@@ -357,7 +358,7 @@ test_bgo_690400 (void)
 
     gupnp_service_proxy_set_subscribed (data.proxy, TRUE);
 
-    test_run_loop (data.loop);
+    test_run_loop (data.loop, "690400 - waiting for event");
 
     g_main_loop_unref (data.loop);
     g_object_unref (data.proxy);
diff --git a/tests/test-context.c b/tests/test-context.c
index c60ac72..2101328 100644
--- a/tests/test-context.c
+++ b/tests/test-context.c
@@ -25,13 +25,23 @@ create_context (guint16 port, GError **error) {
                                               NULL));
 }
 
+typedef struct {
+        GMainLoop *loop;
+        GBytes *body;
+        GError *error;
+} RangeHelper;
+
+
 static void
-on_message_finished (G_GNUC_UNUSED SoupSession *session,
-                     G_GNUC_UNUSED SoupMessage *message,
-                     gpointer                   user_data) {
-        GMainLoop *loop = (GMainLoop*) user_data;
+on_message_finished (GObject *source,
+                     GAsyncResult *res,
+                     gpointer                   user_data)
+{
+        RangeHelper *h = (RangeHelper *)user_data;
+
+        h->body = soup_session_send_and_read_finish (SOUP_SESSION (source), res, &h->error);
 
-        g_main_loop_quit (loop);
+        g_main_loop_quit (h->loop);
 }
 
 static void
@@ -50,9 +60,10 @@ request_range_and_compare (GMappedFile *file,
         full_length = g_mapped_file_get_length (file);
 
         message = soup_message_new ("GET", uri);
-        g_object_ref (message);
 
-        soup_message_headers_set_range (message->request_headers,
+        SoupMessageHeaders *request_headers = soup_message_get_request_headers (message);
+
+        soup_message_headers_set_range (request_headers,
                                         want_start,
                                         want_end);
 
@@ -71,32 +82,32 @@ request_range_and_compare (GMappedFile *file,
                 want_length = want_end - want_start + 1;
 
 
-        soup_session_queue_message (session,
-                                    message,
-                                    on_message_finished,
-                                    loop);
+
+        RangeHelper h = {loop, NULL, NULL};
+        soup_session_send_and_read_async (session, message, G_PRIORITY_DEFAULT, NULL, on_message_finished, 
&h);
 
         g_main_loop_run (loop);
-        g_assert_cmpint (message->status_code, ==, SOUP_STATUS_PARTIAL_CONTENT);
-        g_assert_cmpint (message->response_body->length, ==, want_length);
-        got_length = soup_message_headers_get_content_length
-                                        (message->response_headers);
+        g_assert_no_error (h.error);
+        g_assert_nonnull (h.body);
+
+        g_assert_cmpint (soup_message_get_status (message), ==, SOUP_STATUS_PARTIAL_CONTENT);
+        g_assert_cmpint (g_bytes_get_size (h.body), ==, want_length);
+        SoupMessageHeaders *response_headers = soup_message_get_response_headers (message);
+        got_length = soup_message_headers_get_content_length (response_headers);
         g_assert_cmpint (got_length, ==, want_length);
-        soup_message_headers_get_content_range (message->response_headers,
+        soup_message_headers_get_content_range (response_headers,
                                                 &got_start,
                                                 &got_end,
                                                 &got_length);
         g_assert_cmpint (got_start, ==, want_start);
         g_assert_cmpint (got_end, ==, want_end);
         result = memcmp (g_mapped_file_get_contents (file) + want_start,
-                         message->response_body->data,
+                         g_bytes_get_data (h.body, NULL),
                          want_length);
         g_assert_cmpint (result, ==, 0);
 
         g_object_unref (message);
-
-        message = soup_message_new ("GET", uri);
-        g_object_ref (message);
+        g_bytes_unref (h.body);
 }
 
 static void
@@ -139,6 +150,7 @@ test_gupnp_context_http_ranged_requests (void)
         /* Corner cases: First byte */
         request_range_and_compare (file, session, loop, uri, 0, 0);
 
+
         /* Corner cases: Last byte */
         request_range_and_compare (file,
                                    session,
@@ -170,18 +182,19 @@ test_gupnp_context_http_ranged_requests (void)
 
         /* Try to get 1 byte after the end of the file */
         message = soup_message_new ("GET", uri);
-        g_object_ref (message);
 
-        soup_message_headers_set_range (message->request_headers,
+        RangeHelper h = {loop, NULL, NULL};
+        soup_message_headers_set_range (soup_message_get_request_headers (message),
                                         file_length,
                                         file_length);
-        soup_session_queue_message (session,
-                                    message,
-                                    on_message_finished,
-                                    loop);
+        soup_session_send_and_read_async (session, message, G_PRIORITY_DEFAULT, NULL, on_message_finished, 
&h);
 
         g_main_loop_run (loop);
-        g_assert_cmpint (message->status_code, ==, SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE);
+
+        g_assert_no_error (h.error);
+        g_assert_nonnull (h.body);
+        g_bytes_unref (h.body);
+        g_assert_cmpint (soup_message_get_status (message), ==, SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE);
 
         g_object_unref (message);
 


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