[gupnp/wip/phako/libsoup3] Initial port to libsoup3 API
- From: Jens Georg <jensgeorg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gupnp/wip/phako/libsoup3] Initial port to libsoup3 API
- Date: Fri, 29 Oct 2021 16:36:09 +0000 (UTC)
commit e2e8284fe143249ac6d704ffa3ef9e50e0269c8e
Author: Jens Georg <mail jensge org>
Date: Mon Jul 26 23:36:39 2021 +0200
Initial port to libsoup3 API
libgupnp/gupnp-acl-private.h | 6 +-
libgupnp/gupnp-acl.c | 6 +-
libgupnp/gupnp-context-manager.c | 26 +-
libgupnp/gupnp-context-private.h | 7 +-
libgupnp/gupnp-context.c | 337 ++++++++++--------
libgupnp/gupnp-control-point.c | 116 ++++---
libgupnp/gupnp-device-info.c | 44 +--
libgupnp/gupnp-device-info.h | 5 +-
libgupnp/gupnp-device-proxy.c | 4 +-
libgupnp/gupnp-device.c | 4 +-
libgupnp/gupnp-error.c | 16 +-
libgupnp/gupnp-resource-factory-private.h | 58 ++--
libgupnp/gupnp-resource-factory.c | 62 ++--
libgupnp/gupnp-root-device.c | 18 +-
libgupnp/gupnp-service-info.c | 72 ++--
libgupnp/gupnp-service-info.h | 5 +-
libgupnp/gupnp-service-private.h | 2 +-
libgupnp/gupnp-service-proxy-action-private.h | 1 +
libgupnp/gupnp-service-proxy-action.c | 30 +-
libgupnp/gupnp-service-proxy.c | 381 ++++++++++++--------
libgupnp/gupnp-service.c | 477 +++++++++++++++-----------
libgupnp/gupnp-service.h | 4 +-
libgupnp/gupnp-unix-context-manager.c | 1 -
libgupnp/http-headers.c | 46 ++-
libgupnp/http-headers.h | 20 +-
libgupnp/xml-util.c | 28 +-
libgupnp/xml-util.h | 15 +-
meson.build | 8 +-
tests/test-bugs.c | 21 +-
tests/test-context.c | 88 +++--
30 files changed, 1088 insertions(+), 820 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..4a337c6 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..1f2ec73 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>
@@ -487,18 +486,19 @@ gupnp_context_manager_class_init (GUPnPContextManagerClass *klass)
* Port the contexts listen on, or 0 if you don't care what
* port is used by #GUPnPContext objects created by this object.
**/
- g_object_class_install_property
- (object_class,
- PROP_PORT,
- g_param_spec_uint ("port",
- "Port",
- "Port to create contexts for",
- 0, G_MAXUINT, SOUP_ADDRESS_ANY_PORT,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB));
+ g_object_class_install_property (
+ object_class,
+ PROP_PORT,
+ g_param_spec_uint ("port",
+ "Port",
+ "Port to create contexts for",
+ 0,
+ G_MAXUINT,
+ 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
/**
* GUPnPContextManager:family:
*
diff --git a/libgupnp/gupnp-context-private.h b/libgupnp/gupnp-context-private.h
index e5cd507..b99230f 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,9 +23,8 @@ _gupnp_context_add_server_handler_with_data (GUPnPContext *context,
const char *path,
AclServerHandler *data);
-G_GNUC_INTERNAL SoupURI *
-gupnp_context_rewrite_uri_to_uri (GUPnPContext *context,
- const char *uri);
+G_GNUC_INTERNAL GUri *
+gupnp_context_rewrite_uri_to_uri (GUPnPContext *context, const char *uri);
G_GNUC_INTERNAL gboolean
gupnp_context_validate_host_header (GUPnPContext *context, const char *host);
diff --git a/libgupnp/gupnp-context.c b/libgupnp/gupnp-context.c
index efec13f..6a0caa4 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);
@@ -412,18 +408,19 @@ gupnp_context_class_init (GUPnPContextClass *klass)
*
* The port to run on. Set to 0 if you don't care what port to run on.
**/
- g_object_class_install_property
- (object_class,
- PROP_PORT,
- g_param_spec_uint ("port",
- "Port",
- "Port to run on",
- 0, G_MAXUINT, SOUP_ADDRESS_ANY_PORT,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB));
+ g_object_class_install_property (
+ object_class,
+ PROP_PORT,
+ g_param_spec_uint ("port",
+ "Port",
+ "Port to run on",
+ 0,
+ G_MAXUINT,
+ 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
/**
* GUPnPContext:server:
@@ -548,14 +545,15 @@ gupnp_context_get_session (GUPnPContext *context)
* Default server handler: Return 404 not found.
**/
static void
-default_server_handler (G_GNUC_UNUSED SoupServer *server,
- SoupMessage *msg,
- G_GNUC_UNUSED const char *path,
- G_GNUC_UNUSED GHashTable *query,
- G_GNUC_UNUSED SoupClientContext *client,
- G_GNUC_UNUSED gpointer user_data)
+default_server_handler (G_GNUC_UNUSED SoupServer *server,
+ SoupServerMessage *msg,
+ G_GNUC_UNUSED const char *path,
+ G_GNUC_UNUSED GHashTable *query,
+ 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 +619,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 +643,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 +692,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 +889,20 @@ 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,
- "Location", redir_uri);
- soup_message_set_status (msg,
- SOUP_STATUS_MOVED_PERMANENTLY);
+ soup_message_headers_append (
+ soup_server_message_get_response_headers (msg),
+ "Location",
+ redir_uri);
+ soup_server_message_set_status (msg,
+ SOUP_STATUS_MOVED_PERMANENTLY,
+ "Moved permanently");
g_free (redir_uri);
g_free (uri);
}
@@ -930,12 +931,11 @@ update_client_cache (GUPnPContext *context,
/* Serve @path. Note that we do not need to check for path including bogus
* '..' as libsoup does this for us. */
static void
-host_path_handler (G_GNUC_UNUSED SoupServer *server,
- SoupMessage *msg,
- const char *path,
- G_GNUC_UNUSED GHashTable *query,
- SoupClientContext *client_ctx,
- gpointer user_data)
+host_path_handler (G_GNUC_UNUSED SoupServer *server,
+ SoupServerMessage *msg,
+ const char *path,
+ G_GNUC_UNUSED GHashTable *query,
+ gpointer user_data)
{
char *local_path, *path_to_open;
GStatBuf st;
@@ -953,9 +953,11 @@ 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 +966,18 @@ 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,
- "Connection",
- "close");
+ 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");
- host = soup_client_context_get_host (client_ctx);
+ user_agent = soup_message_headers_get_one (
+ soup_server_message_get_request_headers (msg),
+ "User-Agent");
+ 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,9 +989,10 @@ 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,
- "User-Agent",
- user_agent);
+ soup_message_headers_append (
+ soup_server_message_get_response_headers (msg),
+ "User-Agent",
+ user_agent);
}
} else {
update_client_cache (host_path_data->context, host, user_agent);
@@ -996,13 +1001,16 @@ 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 +1019,9 @@ 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 +1030,15 @@ 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 +1073,40 @@ 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;
-
- if (msg->method == SOUP_METHOD_GET) {
+ 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 (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 +1118,89 @@ 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
- (msg,
- SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE);
- soup_message_headers_free_ranges (msg->request_headers,
+ soup_server_message_set_status (
+ msg,
+ 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,
- ranges[0].start,
- ranges[0].end,
- buffer->length);
- range_buffer = soup_buffer_new_subbuffer (
- buffer,
- ranges[0].start,
- ranges[0].end - ranges[0].start + 1);
- soup_message_body_append_buffer (msg->response_body,
- range_buffer);
+ response_headers,
+ ranges[0].start,
+ ranges[0].end,
+ 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_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,
- (guchar *) g_mapped_file_get_contents
- (mapped_file),
- st.st_size);
+ 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 +1456,14 @@ 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 +1471,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 +1483,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,8 +1495,9 @@ gupnp_acl_server_handler (SoupServer *server,
}
}
- agent = soup_message_headers_get_one (msg->request_headers,
- "User-Agent");
+ agent = soup_message_headers_get_one (
+ soup_server_message_get_request_headers (msg),
+ "User-Agent");
if (agent == NULL) {
agent = gssdp_client_guess_user_agent
(GSSDP_CLIENT (handler->context),
@@ -1483,32 +1512,40 @@ 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),
- agent,
- NULL,
- (GAsyncReadyCallback) gupnp_acl_async_callback,
- data);
+ gupnp_acl_is_allowed_async (
+ priv->acl,
+ device,
+ handler->service,
+ path,
+ host,
+ agent,
+ NULL,
+ (GAsyncReadyCallback) gupnp_acl_async_callback,
+ data);
return;
}
}
/* 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 +1600,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 +1646,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 +1655,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 +1675,28 @@ 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 +1707,11 @@ 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..97bdfa5 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) {
@@ -284,13 +286,13 @@ find_device_node (GUPnPControlPoint *control_point,
}
static void
-create_and_report_service_proxy (GUPnPControlPoint *control_point,
- GUPnPXMLDoc *doc,
- xmlNode *element,
- const char *udn,
- const char *service_type,
- const char *description_url,
- SoupURI *url_base)
+create_and_report_service_proxy (GUPnPControlPoint *control_point,
+ GUPnPXMLDoc *doc,
+ xmlNode *element,
+ const char *udn,
+ const char *service_type,
+ const char *description_url,
+ GUri *url_base)
{
GUPnPServiceProxy *proxy;
GUPnPResourceFactory *factory;
@@ -324,12 +326,12 @@ create_and_report_service_proxy (GUPnPControlPoint *control_point,
}
static void
-create_and_report_device_proxy (GUPnPControlPoint *control_point,
- GUPnPXMLDoc *doc,
- xmlNode *element,
- const char *udn,
- const char *description_url,
- SoupURI *url_base)
+create_and_report_device_proxy (GUPnPControlPoint *control_point,
+ GUPnPXMLDoc *doc,
+ xmlNode *element,
+ const char *udn,
+ const char *description_url,
+ GUri *url_base)
{
GUPnPDeviceProxy *proxy;
GUPnPResourceFactory *factory;
@@ -400,13 +402,13 @@ compare_service_types_versioned (const char *searched_service,
/* Search @element for matching services */
static void
-process_service_list (xmlNode *element,
+process_service_list (xmlNode *element,
GUPnPControlPoint *control_point,
- GUPnPXMLDoc *doc,
- const char *udn,
- const char *service_type,
- const char *description_url,
- SoupURI *url_base)
+ GUPnPXMLDoc *doc,
+ const char *udn,
+ const char *service_type,
+ const char *description_url,
+ GUri *url_base)
{
g_object_ref (control_point);
@@ -446,13 +448,13 @@ process_service_list (xmlNode *element,
/* Recursively search @element for matching devices */
static void
-process_device_list (xmlNode *element,
+process_device_list (xmlNode *element,
GUPnPControlPoint *control_point,
- GUPnPXMLDoc *doc,
- const char *udn,
- const char *service_type,
- const char *description_url,
- SoupURI *url_base)
+ GUPnPXMLDoc *doc,
+ const char *udn,
+ const char *service_type,
+ const char *description_url,
+ 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,8 @@ 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 +566,7 @@ description_loaded (GUPnPControlPoint *control_point,
url_base);
/* Cleanup */
- soup_uri_free (url_base);
+ g_uri_unref (url_base);
}
@@ -574,15 +577,23 @@ 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 +611,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,18 +651,18 @@ 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,
- data->timeout);
+ g_warning (
+ "Failed to GET %s: %s, retrying in %d seconds",
+ data->description_url,
+ soup_message_get_reason_phrase (message),
+ data->timeout);
data->timeout_source = g_timeout_source_new_seconds
(data->timeout);
@@ -662,6 +676,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 +753,13 @@ 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..c7d9374 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);
}
@@ -290,18 +290,17 @@ gupnp_device_info_class_init (GUPnPDeviceInfoClass *klass)
*
* The URL base (#SoupURI).
**/
- g_object_class_install_property
- (object_class,
- PROP_URL_BASE,
- g_param_spec_boxed ("url-base",
- "URL base",
- "The URL base",
- SOUP_TYPE_URI,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB));
+ g_object_class_install_property (
+ object_class,
+ PROP_URL_BASE,
+ g_param_spec_boxed ("url-base",
+ "URL base",
+ "The URL base",
+ G_TYPE_URI,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
/**
* GUPnPDeviceInfo:document:
@@ -413,7 +412,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 +909,15 @@ gupnp_device_info_get_icon_url (GUPnPDeviceInfo *info,
*height = icon->height;
if (icon->url) {
- SoupURI *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);
+ GUri *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..2fb2a85 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,8 +55,8 @@ gupnp_device_info_get_context (GUPnPDeviceInfo *info);
const char *
gupnp_device_info_get_location (GUPnPDeviceInfo *info);
-const SoupURI *
-gupnp_device_info_get_url_base (GUPnPDeviceInfo *info);
+const GUri *
+gupnp_device_info_get_url_base (GUPnPDeviceInfo *info);
const char *
gupnp_device_info_get_udn (GUPnPDeviceInfo *info);
diff --git a/libgupnp/gupnp-device-proxy.c b/libgupnp/gupnp-device-proxy.c
index ea0d6ca..762dae0 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..ea49f57 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..778854e 100644
--- a/libgupnp/gupnp-error.c
+++ b/libgupnp/gupnp-error.c
@@ -128,17 +128,19 @@ void
_gupnp_error_set_server_error (GError **error,
SoupMessage *msg)
{
- g_set_error_literal (error,
- GUPNP_SERVER_ERROR,
- code_from_status_code (msg->status_code),
- msg->reason_phrase);
+ g_set_error_literal (
+ error,
+ GUPNP_SERVER_ERROR,
+ code_from_status_code (soup_message_get_status (msg)),
+ soup_message_get_reason_phrase (msg));
}
/* Create a #GError with status of @msg */
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);
+ return g_error_new_literal (
+ GUPNP_SERVER_ERROR,
+ 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..fe9e4a7 100644
--- a/libgupnp/gupnp-resource-factory-private.h
+++ b/libgupnp/gupnp-resource-factory-private.h
@@ -22,43 +22,41 @@
G_BEGIN_DECLS
G_GNUC_INTERNAL GUPnPDeviceProxy *
-gupnp_resource_factory_create_device_proxy
- (GUPnPResourceFactory *factory,
- GUPnPContext *context,
- GUPnPXMLDoc *doc,
- xmlNode *element,
- const char *udn,
- const char *location,
- const SoupURI *url_base);
+gupnp_resource_factory_create_device_proxy (GUPnPResourceFactory *factory,
+ GUPnPContext *context,
+ GUPnPXMLDoc *doc,
+ xmlNode *element,
+ const char *udn,
+ const char *location,
+ const GUri *url_base);
G_GNUC_INTERNAL GUPnPServiceProxy *
-gupnp_resource_factory_create_service_proxy
- (GUPnPResourceFactory *factory,
- GUPnPContext *context,
- GUPnPXMLDoc *doc,
- xmlNode *element,
- const char *udn,
- const char *service_type,
- const char *location,
- const SoupURI *url_base);
+gupnp_resource_factory_create_service_proxy (GUPnPResourceFactory *factory,
+ GUPnPContext *context,
+ GUPnPXMLDoc *doc,
+ xmlNode *element,
+ const char *udn,
+ const char *service_type,
+ const char *location,
+ const GUri *url_base);
G_GNUC_INTERNAL GUPnPDevice *
-gupnp_resource_factory_create_device (GUPnPResourceFactory *factory,
- GUPnPContext *context,
- GUPnPDevice *root_device,
- xmlNode *element,
- const char *udn,
- const char *location,
- const SoupURI *url_base);
+gupnp_resource_factory_create_device (GUPnPResourceFactory *factory,
+ GUPnPContext *context,
+ GUPnPDevice *root_device,
+ xmlNode *element,
+ const char *udn,
+ const char *location,
+ const GUri *url_base);
G_GNUC_INTERNAL GUPnPService *
gupnp_resource_factory_create_service (GUPnPResourceFactory *factory,
- GUPnPContext *context,
- GUPnPDevice *root_device,
- xmlNode *element,
- const char *udn,
- const char *location,
- const SoupURI *url_base);
+ GUPnPContext *context,
+ GUPnPDevice *root_device,
+ xmlNode *element,
+ const char *udn,
+ const char *location,
+ const GUri *url_base);
G_END_DECLS
diff --git a/libgupnp/gupnp-resource-factory.c b/libgupnp/gupnp-resource-factory.c
index 8d7e362..5ad58d2 100644
--- a/libgupnp/gupnp-resource-factory.c
+++ b/libgupnp/gupnp-resource-factory.c
@@ -192,14 +192,13 @@ lookup_type_with_fallback (GHashTable *resource_types,
* Return value:(nullable)(transfer full): A new #GUPnPDeviceProxy.
**/
GUPnPDeviceProxy *
-gupnp_resource_factory_create_device_proxy
- (GUPnPResourceFactory *factory,
- GUPnPContext *context,
- GUPnPXMLDoc *doc,
- xmlNode *element,
- const char *udn,
- const char *location,
- const SoupURI *url_base)
+gupnp_resource_factory_create_device_proxy (GUPnPResourceFactory *factory,
+ GUPnPContext *context,
+ GUPnPXMLDoc *doc,
+ xmlNode *element,
+ const char *udn,
+ const char *location,
+ const GUri *url_base)
{
GUPnPDeviceProxy *proxy;
GType proxy_type;
@@ -251,15 +250,14 @@ gupnp_resource_factory_create_device_proxy
* Return value:(nullable)(transfer full): A new #GUPnPServiceProxy.
**/
GUPnPServiceProxy *
-gupnp_resource_factory_create_service_proxy
- (GUPnPResourceFactory *factory,
- GUPnPContext *context,
- GUPnPXMLDoc *doc,
- xmlNode *element,
- const char *udn,
- const char *service_type,
- const char *location,
- const SoupURI *url_base)
+gupnp_resource_factory_create_service_proxy (GUPnPResourceFactory *factory,
+ GUPnPContext *context,
+ GUPnPXMLDoc *doc,
+ xmlNode *element,
+ const char *udn,
+ const char *service_type,
+ const char *location,
+ const GUri *url_base)
{
GUPnPServiceProxy *proxy;
GType proxy_type = GUPNP_TYPE_SERVICE_PROXY;
@@ -309,14 +307,13 @@ gupnp_resource_factory_create_service_proxy
* Return value: (nullable)(transfer full): A new #GUPnPDevice.
**/
GUPnPDevice *
-gupnp_resource_factory_create_device
- (GUPnPResourceFactory *factory,
- GUPnPContext *context,
- GUPnPDevice *root_device,
- xmlNode *element,
- const char *udn,
- const char *location,
- const SoupURI *url_base)
+gupnp_resource_factory_create_device (GUPnPResourceFactory *factory,
+ GUPnPContext *context,
+ GUPnPDevice *root_device,
+ xmlNode *element,
+ const char *udn,
+ const char *location,
+ const GUri *url_base)
{
GUPnPDevice *device;
GType device_type = GUPNP_TYPE_DEVICE;
@@ -365,14 +362,13 @@ gupnp_resource_factory_create_device
* Return value: (nullable)(transfer full): A new #GUPnPService.
**/
GUPnPService *
-gupnp_resource_factory_create_service
- (GUPnPResourceFactory *factory,
- GUPnPContext *context,
- GUPnPDevice *root_device,
- xmlNode *element,
- const char *udn,
- const char *location,
- const SoupURI *url_base)
+gupnp_resource_factory_create_service (GUPnPResourceFactory *factory,
+ GUPnPContext *context,
+ GUPnPDevice *root_device,
+ xmlNode *element,
+ const char *udn,
+ const char *location,
+ 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..9198617 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,10 @@ 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 +420,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 +447,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..2a66141 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);
}
@@ -323,18 +325,17 @@ gupnp_service_info_class_init (GUPnPServiceInfoClass *klass)
*
* The URL base (#SoupURI).
**/
- g_object_class_install_property
- (object_class,
- PROP_URL_BASE,
- g_param_spec_boxed ("url-base",
- "URL base",
- "The URL base",
- SOUP_TYPE_URI,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB));
+ g_object_class_install_property (
+ object_class,
+ PROP_URL_BASE,
+ g_param_spec_boxed ("url-base",
+ "URL base",
+ "The URL base",
+ G_TYPE_URI,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
/**
* GUPnPServiceInfo:document:
@@ -426,7 +427,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,9 +576,7 @@ gupnp_service_info_get_event_subscription_url (GUPnPServiceInfo *info)
* SCPD URL downloaded.
*/
static void
-got_scpd_url (G_GNUC_UNUSED SoupSession *session,
- SoupMessage *msg,
- GetSCPDURLData *data)
+got_scpd_url (GObject *source, GAsyncResult *res, GetSCPDURLData *data)
{
GUPnPServiceIntrospection *introspection;
GError *error;
@@ -586,14 +585,22 @@ 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;
+
+ gconstpointer data = g_bytes_get_data (body, &length);
- scpd = xmlRecoverMemory (msg->response_body->data,
- msg->response_body->length);
+ scpd = xmlRecoverMemory (data, length);
if (scpd) {
introspection = gupnp_service_introspection_new (scpd);
@@ -607,7 +614,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 +642,7 @@ cancellable_cancelled_cb (GCancellable *cancellable,
{
GUPnPServiceInfo *info;
GetSCPDURLData *data;
- SoupSession *session;
+ // SoupSession *session;
GError *error;
GUPnPServiceInfoPrivate *priv;
@@ -644,10 +651,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 +790,12 @@ 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..2c561c0 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,8 +56,8 @@ gupnp_service_info_get_context (GUPnPServiceInfo *info);
const char *
gupnp_service_info_get_location (GUPnPServiceInfo *info);
-const SoupURI *
-gupnp_service_info_get_url_base (GUPnPServiceInfo *info);
+const GUri *
+gupnp_service_info_get_url_base (GUPnPServiceInfo *info);
const char *
gupnp_service_info_get_udn (GUPnPServiceInfo *info);
diff --git a/libgupnp/gupnp-service-private.h b/libgupnp/gupnp-service-private.h
index 1915505..c8a6096 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..733e1ab 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,21 +88,24 @@ 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,
"Could not parse SOAP response");
} else {
- g_set_error_literal
- (error,
- GUPNP_SERVER_ERROR,
- GUPNP_SERVER_ERROR_INTERNAL_SERVER_ERROR,
- action->msg->reason_phrase);
+ g_set_error_literal (
+ error,
+ GUPNP_SERVER_ERROR,
+ GUPNP_SERVER_ERROR_INTERNAL_SERVER_ERROR,
+ 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,8 @@ 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..349d90c 100644
--- a/libgupnp/gupnp-service-proxy.c
+++ b/libgupnp/gupnp-service-proxy.c
@@ -90,9 +90,8 @@ 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 +222,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 +257,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 +608,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,29 +675,26 @@ 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,
- "SOAPAction",
- full_action);
+ soup_message_headers_append (headers, "SOAPAction", full_action);
g_free (full_action);
/* Specify language */
http_request_set_accept_language (action->msg);
/* Accept gzip encoding */
- soup_message_headers_append (action->msg->request_headers,
- "Accept-Encoding", "gzip");
+ soup_message_headers_append (headers, "Accept-Encoding", "gzip");
gupnp_service_proxy_action_serialize (action, service_type);
- soup_message_set_request (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);
+ soup_message_set_request_body_from_bytes (
+ action->msg,
+ "text/xml; charset=\"utf-8\"",
+ g_string_free_to_bytes (action->msg_str));
action->msg_str = NULL;
return TRUE;
@@ -702,51 +706,55 @@ 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,
- gpointer user_data)
+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 +791,13 @@ 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;
}
@@ -1493,12 +1504,11 @@ emit_notifications (gpointer user_data)
* message with our SID.
*/
static void
-server_handler (G_GNUC_UNUSED SoupServer *soup_server,
- SoupMessage *msg,
- G_GNUC_UNUSED const char *server_path,
- G_GNUC_UNUSED GHashTable *query,
- G_GNUC_UNUSED SoupClientContext *soup_client,
- gpointer user_data)
+server_handler (G_GNUC_UNUSED SoupServer *soup_server,
+ SoupServerMessage *msg,
+ G_GNUC_UNUSED const char *server_path,
+ G_GNUC_UNUSED GHashTable *query,
+ gpointer user_data)
{
GUPnPServiceProxy *proxy;
GUPnPServiceProxyPrivate *priv;
@@ -1510,19 +1520,27 @@ 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 +1548,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 +1569,41 @@ 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 +1615,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 +1641,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 +1660,11 @@ make_timeout_header (GUPnPContext *context)
return g_strdup ("infinite");
}
+typedef struct {
+ GUPnPServiceProxy *proxy;
+ SoupMessage *msg;
+} SubscriptionCallData;
+
/*
* Subscription expired.
*/
@@ -1658,6 +1694,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,15 +1702,14 @@ 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,
- "SID",
- priv->sid);
+ soup_message_headers_append (request_headers, "SID", priv->sid);
timeout = make_timeout_header (context);
- soup_message_headers_append (msg->request_headers,
- "Timeout",
- timeout);
+ soup_message_headers_append (request_headers, "Timeout", timeout);
g_free (timeout);
/* And send it off */
@@ -1682,11 +1718,17 @@ 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,44 +1737,56 @@ 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,
- "SID");
+ hdr = soup_message_headers_get_one (response_headers, "SID");
if (hdr == NULL) {
error = g_error_new
(GUPNP_EVENTING_ERROR,
@@ -1745,12 +1799,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) {
@@ -1772,10 +1826,10 @@ subscribe_got_response (G_GNUC_UNUSED SoupSession *session,
/* Add actual timeout */
priv->subscription_timeout_src =
g_timeout_source_new_seconds (timeout);
- g_source_set_callback
- (priv->subscription_timeout_src,
- subscription_expire,
- proxy, NULL);
+ g_source_set_callback (priv->subscription_timeout_src,
+ subscription_expire,
+ data->proxy,
+ NULL);
g_source_attach (priv->subscription_timeout_src,
g_main_context_get_thread_default ());
@@ -1786,31 +1840,35 @@ subscribe_got_response (G_GNUC_UNUSED SoupSession *session,
SoupServer *server;
/* Subscription failed. */
- error = g_error_new_literal
- (GUPNP_EVENTING_ERROR,
- GUPNP_EVENTING_ERROR_SUBSCRIPTION_FAILED,
- msg->reason_phrase);
+ error = g_error_new_literal (
+ GUPNP_EVENTING_ERROR,
+ GUPNP_EVENTING_ERROR_SUBSCRIPTION_FAILED,
+ soup_message_get_reason_phrase (data->msg));
hdr_err:
/* Remove listener */
- context = gupnp_service_info_get_context
- (GUPNP_SERVICE_INFO (proxy));
+ context = gupnp_service_info_get_context (
+ 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 +1882,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 +1904,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,25 +1936,25 @@ 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,
- "Callback",
- delivery_url);
+ 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,
- "NT",
- "upnp:event");
+ soup_message_headers_append (request_headers, "NT", "upnp:event");
timeout = make_timeout_header (context);
- soup_message_headers_append (msg->request_headers,
- "Timeout",
- timeout);
+ soup_message_headers_append (request_headers, "Timeout", timeout);
g_free (timeout);
/* Listen for events */
@@ -1913,13 +1972,28 @@ 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 +2028,21 @@ unsubscribe (GUPnPServiceProxy *proxy)
if (msg != NULL) {
/* Add headers */
- soup_message_headers_append (msg->request_headers,
- "SID",
- priv->sid);
+ 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 +2247,32 @@ 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..287544b 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,14 @@ 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,
- NULL);
+ 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 +161,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 +184,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 +274,8 @@ 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 +285,36 @@ 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 +355,8 @@ 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 +640,8 @@ 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 +683,8 @@ 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 +709,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 +791,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 +805,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
- * after using it.
+ * 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);
@@ -903,12 +917,11 @@ query_state_variable (GUPnPService *service,
/* controlURL handler */
static void
-control_server_handler (SoupServer *server,
- SoupMessage *msg,
- G_GNUC_UNUSED const char *server_path,
- G_GNUC_UNUSED GHashTable *query,
- G_GNUC_UNUSED SoupClientContext *soup_client,
- gpointer user_data)
+control_server_handler (SoupServer *server,
+ SoupServerMessage *msg,
+ G_GNUC_UNUSED const char *server_path,
+ G_GNUC_UNUSED GHashTable *query,
+ gpointer user_data)
{
GUPnPService *service;
GUPnPContext *context;
@@ -922,22 +935,33 @@ 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 +969,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 +977,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,
- "SOAPAction");
+ 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 +1017,11 @@ 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 +1032,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 +1055,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,9 +1104,9 @@ control_server_handler (SoupServer *server,
/* Generates a standard (re)subscription response */
static void
subscription_response (GUPnPService *service,
- SoupMessage *msg,
- const char *sid,
- int timeout)
+ SoupServerMessage *msg,
+ const char *sid,
+ int timeout)
{
GUPnPContext *context;
GSSDPClient *client;
@@ -1080,15 +1115,16 @@ 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,
- "SID",
- sid);
+ soup_message_headers_append (response_headers, "SID", sid);
/* Timeout header */
if (timeout > 0)
@@ -1096,13 +1132,11 @@ subscription_response (GUPnPService *service,
else
tmp = g_strdup ("infinite");
- soup_message_headers_append (msg->response_headers,
- "Timeout",
- tmp);
+ 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 +1184,6 @@ static void
send_initial_state (SubscriptionData *data)
{
GQueue *queue;
- char *mem;
GList *l;
GUPnPServicePrivate *priv;
@@ -1181,13 +1214,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 +1228,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;
+ 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
@@ -1218,9 +1251,7 @@ add_subscription_callback (GUPnPContext *context,
/* Subscription request */
static void
-subscribe (GUPnPService *service,
- SoupMessage *msg,
- const char *callback)
+subscribe (GUPnPService *service, SoupServerMessage *msg, const char *callback)
{
SubscriptionData *data;
char *start, *end;
@@ -1269,7 +1300,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);
@@ -1305,9 +1338,7 @@ subscribe (GUPnPService *service,
/* Resubscription request */
static void
-resubscribe (GUPnPService *service,
- SoupMessage *msg,
- const char *sid)
+resubscribe (GUPnPService *service, SoupServerMessage *msg, const char *sid)
{
SubscriptionData *data;
GUPnPServicePrivate *priv;
@@ -1316,7 +1347,10 @@ 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;
}
@@ -1344,9 +1378,7 @@ resubscribe (GUPnPService *service,
/* Unsubscription request */
static void
-unsubscribe (GUPnPService *service,
- SoupMessage *msg,
- const char *sid)
+unsubscribe (GUPnPService *service, SoupServerMessage *msg, const char *sid)
{
SubscriptionData *data;
GUPnPServicePrivate *priv;
@@ -1360,27 +1392,34 @@ 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,
- G_GNUC_UNUSED const char *server_path,
- G_GNUC_UNUSED GHashTable *query,
- G_GNUC_UNUSED SoupClientContext *soup_client,
- gpointer user_data)
+subscription_server_handler (G_GNUC_UNUSED SoupServer *server,
+ SoupServerMessage *msg,
+ G_GNUC_UNUSED const char *server_path,
+ G_GNUC_UNUSED GHashTable *query,
+ gpointer user_data)
{
GUPnPService *service;
const char *callback, *nt, *sid;
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 +1427,32 @@ 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");
- nt = soup_message_headers_get_one (msg->request_headers, "NT");
- sid = soup_message_headers_get_one (msg->request_headers, "SID");
+ callback = soup_message_headers_get_one (request_headers, "Callback");
+ 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 +1461,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 +1472,19 @@ 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,14 +1492,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 {
- soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
-
+ soup_server_message_set_status (msg,
+ SOUP_STATUS_NOT_IMPLEMENTED,
+ NULL);
}
}
@@ -1523,12 +1575,18 @@ 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,71 +1978,90 @@ 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,
- gpointer user_data)
+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;
+ }
- data = user_data;
+ // We don't need the body
+ g_clear_pointer (&body, g_bytes_unref);
+
+ NotifySubscriberData *data = user_data;
+
+ SoupStatus status = soup_message_get_status (data->msg);
/* Remove from pending messages list */
- data->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
- (GUPNP_EVENTING_ERROR,
- GUPNP_EVENTING_ERROR_NOTIFY_FAILED,
- msg->reason_phrase);
+ inner_error = g_error_new_literal (
+ GUPNP_EVENTING_ERROR,
+ GUPNP_EVENTING_ERROR_NOTIFY_FAILED,
+ 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 */
@@ -1993,69 +2070,64 @@ 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,
- "NT",
- "upnp:event");
+ soup_message_headers_append (request_headers, "NT", "upnp:event");
- soup_message_headers_append (msg->request_headers,
- "NTS",
- "upnp:propchange");
+ soup_message_headers_append (request_headers, "NTS", "upnp:propchange");
- soup_message_headers_append (msg->request_headers,
- "SID",
- data->sid);
+ soup_message_headers_append (request_headers, "SID", data->data->sid);
- tmp = g_strdup_printf ("%d", data->seq);
- soup_message_headers_append (msg->request_headers,
- "SEQ",
- tmp);
+ 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,
- "text/xml; charset=\"utf-8\"",
- SOUP_MEMORY_TAKE,
- g_strdup (property_set),
- strlen (property_set));
+ soup_message_set_request_body_from_bytes (data->msg,
+ "text/xml; charset=\"utf-8\"",
+ data->property_set);
/* Queue */
- data->pending_messages = g_list_prepend (data->pending_messages, msg);
- soup_message_headers_append (msg->request_headers,
- "Connection", "close");
-
- session = gupnp_service_get_session (data->service);
-
- soup_session_queue_message (session,
- msg,
- notify_got_response,
- data);
+ 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->data->service);
+
+ 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 +2156,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..dc0d808 100644
--- a/libgupnp/gupnp-service.h
+++ b/libgupnp/gupnp-service.h
@@ -114,8 +114,8 @@ gupnp_service_action_return_error (GUPnPServiceAction *action,
guint error_code,
const char *error_description);
-SoupMessage *
-gupnp_service_action_get_message (GUPnPServiceAction *action);
+SoupServerMessage *
+gupnp_service_action_get_message (GUPnPServiceAction *action);
guint
gupnp_service_action_get_argument_count
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..ab0d5b1 100644
--- a/libgupnp/http-headers.c
+++ b/libgupnp/http-headers.c
@@ -141,7 +141,10 @@ 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 +180,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,15 +227,15 @@ http_request_get_accept_locales (SoupMessage *message)
/* Set Accept-Language header according to @locale. */
void
-http_response_set_content_locale (SoupMessage *msg,
- const char *locale)
+http_response_set_content_locale (SoupMessageHeaders *response_headers,
+ const char *locale)
{
char *lang;
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,10 +245,10 @@ 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,
- const char *path,
+http_response_set_content_type (SoupMessageHeaders *response_headers,
+ const char *path,
const guchar *data,
- gsize data_size)
+ gsize data_size)
{
char *content_type, *mime;
@@ -262,9 +265,7 @@ http_response_set_content_type (SoupMessage *msg,
mime = g_strdup ("text/xml; charset=\"utf-8\"");
}
- soup_message_headers_append (msg->response_headers,
- "Content-Type",
- mime);
+ soup_message_headers_append (response_headers, "Content-Type", mime);
g_free (mime);
g_free (content_type);
@@ -272,16 +273,22 @@ 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,
- const char *body,
- const gsize length)
+http_response_set_body_gzip (SoupServerMessage *msg,
+ const char *body,
+ const gsize length)
{
GZlibCompressor *compressor;
gboolean finished = FALSE;
gsize converted = 0;
- soup_message_headers_append (msg->response_headers,
- "Content-Encoding", "gzip");
+ 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,9 +324,10 @@ 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);
+ buf,
+ bytes_written);
}
g_object_unref (compressor);
diff --git a/libgupnp/http-headers.h b/libgupnp/http-headers.h
index 5b07a10..ff65314 100644
--- a/libgupnp/http-headers.h
+++ b/libgupnp/http-headers.h
@@ -23,17 +23,17 @@ 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,
- const char *locale);
+http_response_set_content_locale (SoupMessageHeaders *message,
+ const char *locale);
G_GNUC_INTERNAL void
-http_response_set_content_type (SoupMessage *message,
- const char *path,
- const guchar *data,
- gsize data_size);
+http_response_set_content_type (SoupMessageHeaders *response_headers,
+ const char *path,
+ const guchar *data,
+ gsize data_size);
G_GNUC_INTERNAL void
http_response_set_content_range (SoupMessage *message,
@@ -42,9 +42,9 @@ http_response_set_content_range (SoupMessage *message,
gsize total);
G_GNUC_INTERNAL void
-http_response_set_body_gzip (SoupMessage *msg,
- const char *body,
- const gsize length);
+http_response_set_body_gzip (SoupServerMessage *msg,
+ const char *body,
+ const gsize length);
G_END_DECLS
diff --git a/libgupnp/xml-util.c b/libgupnp/xml-util.c
index 6c05668..cdef2ed 100644
--- a/libgupnp/xml-util.c
+++ b/libgupnp/xml-util.c
@@ -93,22 +93,27 @@ xml_util_get_child_element_content_glib (xmlNode *node,
return copy;
}
-SoupURI *
-xml_util_get_child_element_content_uri (xmlNode *node,
+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);
@@ -116,20 +121,19 @@ xml_util_get_child_element_content_uri (xmlNode *node,
}
char *
-xml_util_get_child_element_content_url (xmlNode *node,
+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..a02eb3d 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 *
-xml_util_get_child_element_content_uri (xmlNode *node,
- const char *child_name,
- SoupURI *base);
+G_GNUC_INTERNAL GUri *
+xml_util_get_child_element_content_uri (xmlNode *node,
+ const char *child_name,
+ GUri *base);
G_GNUC_INTERNAL char *
-xml_util_get_child_element_content_url (xmlNode *node,
- const char *child_name,
- SoupURI *base);
+xml_util_get_child_element_content_url (xmlNode *node,
+ const char *child_name,
+ 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..b99ffd2 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_assert_not_reached ();
+ g_print ("Timeout in %s\n", (const char *) user_data);
+ g_assert_not_reached ();
- return FALSE;
+ 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..2733512 100644
--- a/tests/test-context.c
+++ b/tests/test-context.c
@@ -25,13 +25,22 @@ 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;
- g_main_loop_quit (loop);
+ h->body = soup_session_send_and_read_finish (SOUP_SESSION (source),
+ res,
+ &h->error);
+
+ g_main_loop_quit (h->loop);
}
static void
@@ -50,11 +59,11 @@ 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,
- want_start,
- want_end);
+ SoupMessageHeaders *request_headers =
+ soup_message_get_request_headers (message);
+
+ soup_message_headers_set_range (request_headers, want_start, want_end);
/* interpretation according to SoupRange documentation */
if (want_end == -1) {
@@ -70,33 +79,39 @@ request_range_and_compare (GMappedFile *file,
} else
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
@@ -170,18 +185,27 @@ 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,
- file_length,
- file_length);
- soup_session_queue_message (session,
- message,
- on_message_finished,
- loop);
+ RangeHelper h = { loop, NULL, NULL };
+ soup_message_headers_set_range (
+ soup_message_get_request_headers (message),
+ file_length,
+ file_length);
+ 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]