From 920380afbb8776bc763737d0cc6cc8f894298b1e Mon Sep 17 00:00:00 2001
From: marcin <marcin@ipv8.pl>
Date: Sun, 7 Aug 2022 03:57:25 +0200
Subject: [PATCH] Preliminary port to libsoup-3.0 (patch v2)
---
meson.build | 2 +-
src/cm-client.c | 7 ++--
src/cm-net.c | 80 +++++++++++-------------------------------
src/cm-utils-private.h | 3 --
src/cm-utils.c | 58 +++++++++---------------------
5 files changed, 41 insertions(+), 109 deletions(-)
diff --git a/meson.build b/meson.build
index 295633a..f0ea89b 100644
--- a/meson.build
+++ b/meson.build
@@ -112,7 +112,7 @@ src_inc = include_directories('src')
gio_dep = dependency('gio-2.0', version: '>= 2.66')
cmatrix_deps = [
dependency('libgcrypt'),
- dependency('libsoup-2.4'),
+ dependency('libsoup-3.0'),
dependency('json-glib-1.0'),
dependency('sqlite3', version: '>=3.26.0'),
libolm_dep,
diff --git a/src/cm-client.c b/src/cm-client.c
index 0cb0fc8..4b54b3a 100644
--- a/src/cm-client.c
+++ b/src/cm-client.c
@@ -241,9 +241,8 @@ handle_matrix_glitches (CmClient *self,
* The G_RESOLVER_ERROR may be suggesting that the hostname is wrong, but we don't
* know if it's network/DNS/Proxy error. So keep retrying.
*/
- if ((error->domain == SOUP_HTTP_ERROR &&
- error->code <= SOUP_STATUS_TLS_FAILED &&
- error->code > SOUP_STATUS_CANCELLED) ||
+ if (error->domain == SOUP_TLD_ERROR ||
+ error->domain == G_TLS_ERROR ||
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NETWORK_UNREACHABLE) ||
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT) ||
/* Should we handle connection_refused, or just keep it for localhost? */
@@ -947,7 +946,7 @@ gboolean
cm_client_set_homeserver (CmClient *self,
const char *homeserver)
{
- g_autoptr(SoupURI) uri = NULL;
+ g_autoptr(GUri) uri = NULL;
GString *server;
g_return_val_if_fail (CM_IS_CLIENT (self), FALSE);
diff --git a/src/cm-net.c b/src/cm-net.c
index 8cca289..4eaa52a 100644
--- a/src/cm-net.c
+++ b/src/cm-net.c
@@ -182,7 +182,8 @@ queue_data (CmNet *self,
GTask *task)
{
g_autoptr(SoupMessage) message = NULL;
- g_autoptr(SoupURI) uri = NULL;
+ g_autoptr(GUri) uri = NULL;
+ g_autoptr(GBytes) content_data = NULL;
GCancellable *cancellable;
SoupMessagePriority msg_priority;
int priority = 0;
@@ -196,20 +197,20 @@ queue_data (CmNet *self,
method == SOUP_METHOD_POST ||
method == SOUP_METHOD_PUT);
- uri = soup_uri_new (self->homeserver);
- soup_uri_set_path (uri, uri_path);
+ uri = g_uri_parse (self->homeserver, SOUP_HTTP_URI_FLAGS, NULL);
+ uri = soup_uri_copy (uri, SOUP_URI_PATH, uri_path, SOUP_URI_NONE);
if (self->access_token) {
if (!query)
query = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
g_hash_table_replace (query, g_strdup ("access_token"), g_strdup (self->access_token));
- soup_uri_set_query_from_form (uri, query);
+ uri = soup_uri_copy(uri, SOUP_URI_QUERY, soup_form_encode_hash(query), SOUP_URI_NONE);
g_hash_table_unref (query);
}
message = soup_message_new_from_uri (method, uri);
- soup_message_headers_append (message->request_headers, "Accept-Encoding", "gzip");
+ soup_message_headers_append (soup_message_get_request_headers(message), "Accept-Encoding", "gzip");
priority = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (task), "priority"));
@@ -226,12 +227,14 @@ queue_data (CmNet *self,
soup_message_set_priority (message, msg_priority);
- if (data)
- soup_message_set_request (message, "application/json", SOUP_MEMORY_TAKE, data, size);
+ if (data) {
+ content_data = g_bytes_new_static (data, size);
+ soup_message_set_request_body_from_bytes (message, "application/json", content_data);
+ }
cancellable = g_task_get_cancellable (task);
g_task_set_task_data (task, g_object_ref (message), g_object_unref);
- soup_session_send_async (self->soup_session, message, cancellable,
+ soup_session_send_async (self->soup_session, message, msg_priority, cancellable,
session_send_cb, task);
}
@@ -324,7 +327,7 @@ cm_net_get_access_token (CmNet *self)
* @size: The @data size in bytes
* @uri_path: A string of the matrix uri path
* @method: An interned string for GET, PUT, POST, etc.
- * @query: (nullable): A query to pass to internal #SoupURI
+ * @query: (nullable): A query to pass to internal #GUri
* @cancellable: (nullable): A #GCancellable
* @callback: The callback to run when completed
* @user_data: user data for @callback
@@ -375,7 +378,7 @@ cm_net_send_data_async (CmNet *self,
* @object: (nullable) (transfer full): The data to send
* @uri_path: A string of the matrix uri path
* @method: An interned string for GET, PUT, POST, etc.
- * @query: (nullable): A query to pass to internal #SoupURI
+ * @query: (nullable): A query to pass to internal #GUri
* @cancellable: (nullable): A #GCancellable
* @callback: The callback to run when completed
* @user_data: user data for @callback
@@ -477,7 +480,7 @@ cm_net_get_file_async (CmNet *self,
g_object_set_data (G_OBJECT (task), "file", enc_file);
g_object_set_data_full (G_OBJECT (task), "msg", msg, g_object_unref);
- soup_session_send_async (self->file_session, msg, cancellable,
+ soup_session_send_async (self->file_session, msg, 0, cancellable,
net_get_file_stream_cb, task);
}
@@ -531,42 +534,10 @@ put_file_async_cb (GObject *obj,
}
}
-static void
-put_file_chunk (GTask *task,
- SoupMessage *msg)
-{
- CmNet *self;
- GInputStream *stream;
- char buffer[8 * 1024];
- gssize n_read;
-
- g_assert (G_IS_TASK (task));
- g_assert (SOUP_IS_MESSAGE (msg));
-
- self = g_task_get_source_object (task);
- g_assert (CM_IS_NET (self));
-
- stream = g_object_get_data (G_OBJECT (task), "stream");
- n_read = g_input_stream_read (stream, buffer, 8 * 1024, NULL, NULL);
-
- if (n_read == 0)
- {
- soup_message_body_complete (msg->request_body);
- }
- else if (n_read == -1)
- {
- soup_session_cancel_message (self->file_session, msg, SOUP_STATUS_CANCELLED);
- }
- else
- {
- soup_message_body_append (msg->request_body, SOUP_MEMORY_COPY, buffer, n_read);
- }
-}
-
static void
wrote_body_data_cb (GTask *task,
SoupMessage *msg,
- SoupBuffer *chunk)
+ guint chunk_size)
{
GFileProgressCallback progress_cb;
gpointer progress_user_data;
@@ -614,18 +585,13 @@ cm_net_put_file_async (CmNet *self,
url = g_strconcat (self->homeserver, "/_matrix/media/r0/upload", NULL);
msg = soup_message_new (SOUP_METHOD_POST, url);
- soup_uri_set_query_from_form (soup_message_get_uri (msg), query);
+ soup_message_set_uri(msg, soup_uri_copy(soup_message_get_uri(msg), SOUP_URI_QUERY, soup_form_encode_hash(query), SOUP_URI_NONE));
/* We're uploading files in chunk */
- soup_message_headers_set_encoding (msg->request_headers, SOUP_ENCODING_CHUNKED);
- soup_message_body_set_accumulate (msg->request_body, FALSE);
- soup_message_headers_set_content_length (msg->request_headers,
- cm_input_stream_get_size (cm_stream));
- soup_message_headers_set_content_type (msg->request_headers,
- cm_input_stream_get_content_type (cm_stream), NULL);
-
- /* Use this once we port to libsoup-3 */
- /* soup_message_set_request_body (msg, "fixme", G_INPUT_STREAM (cm_stream), -1); */
+ soup_message_set_request_body (msg,
+ cm_input_stream_get_content_type (cm_stream),
+ G_INPUT_STREAM (cm_stream),
+ cm_input_stream_get_size (cm_stream));
g_task_set_task_data (task, g_object_ref (file), g_object_unref);
g_object_set_data_full (G_OBJECT (task), "msg", msg, g_object_unref);
@@ -634,15 +600,11 @@ cm_net_put_file_async (CmNet *self,
local_task = g_task_new (self, cancellable, put_file_async_cb, self);
g_task_set_task_data (local_task, task, g_object_unref);
- g_signal_connect_object (msg, "wrote-headers",
- G_CALLBACK (put_file_chunk), task, G_CONNECT_SWAPPED);
- g_signal_connect_object (msg, "wrote-chunk",
- G_CALLBACK (put_file_chunk), task, G_CONNECT_SWAPPED);
if (progress_callback)
g_signal_connect_object (msg, "wrote-body-data",
G_CALLBACK (wrote_body_data_cb), task, G_CONNECT_SWAPPED);
- soup_session_send_async (self->file_session, msg, cancellable,
+ soup_session_send_async (self->file_session, msg, 0, cancellable,
session_send_cb, local_task);
}
diff --git a/src/cm-utils-private.h b/src/cm-utils-private.h
index 50694b9..669d250 100644
--- a/src/cm-utils-private.h
+++ b/src/cm-utils-private.h
@@ -31,9 +31,6 @@ JsonObject *cm_utils_json_object_get_object (JsonObject *object,
const char *member);
JsonArray *cm_utils_json_object_get_array (JsonObject *object,
const char *member);
-
-JsonObject *cm_utils_get_message_json_object (SoupMessage *message,
- const char *member);
void cm_utils_clear (char *buffer,
size_t length);
void cm_utils_free_buffer (char *buffer);
diff --git a/src/cm-utils.c b/src/cm-utils.c
index 7cebce3..42894ec 100644
--- a/src/cm-utils.c
+++ b/src/cm-utils.c
@@ -241,16 +241,16 @@ cm_utils_home_server_valid (const char *homeserver)
if (homeserver)
{
g_autofree char *server = NULL;
- g_autoptr(SoupURI) uri = NULL;
+ g_autoptr(GUri) uri = NULL;
if (!strstr (homeserver, "//"))
server = g_strconcat ("https://", homeserver, NULL);
- uri = soup_uri_new (server ?: homeserver);
+ uri = g_uri_parse (server ?: homeserver, SOUP_HTTP_URI_FLAGS, NULL);
- valid = SOUP_URI_VALID_FOR_HTTP (uri);
+ valid = !!uri;
/* We need an absolute path URI */
- valid = valid && *uri->host && g_str_equal (soup_uri_get_path (uri), "/");
+ valid = valid && *g_uri_get_host(uri) && g_str_equal (g_uri_get_path (uri), "/");
}
return valid;
@@ -465,38 +465,6 @@ cm_utils_json_object_get_array (JsonObject *object,
return NULL;
}
-JsonObject *
-cm_utils_get_message_json_object (SoupMessage *message,
- const char *member)
-{
- g_autoptr(JsonParser) parser = NULL;
- g_autoptr(SoupBuffer) buffer = NULL;
- JsonObject *object = NULL;
- gboolean is_json;
-
- if (!message || !message->response_body)
- return NULL;
-
- buffer = soup_message_body_flatten (message->response_body);
- parser = json_parser_new ();
- is_json = json_parser_load_from_data (parser, buffer->data, buffer->length, NULL);
-
- if (is_json)
-{
- JsonNode *root;
-
- root = json_parser_get_root (parser);
-
- if (root && JSON_NODE_HOLDS_OBJECT (root))
- object = json_node_get_object (root);
-
- if (member && object)
- object = json_object_get_object_member (object, member);
- }
-
- return object ? json_object_ref (object) : NULL;
-}
-
static void
load_from_stream_cb (JsonParser *parser,
GAsyncResult *result,
@@ -575,11 +543,8 @@ uri_file_read_cb (GObject *object,
return;
}
- soup_message_get_https_status (message, NULL, &err_flags);
-
if (message &&
- soup_message_get_https_status (message, NULL, &err_flags) &&
- err_flags)
+ (err_flags = soup_message_get_tls_peer_certificate_errors (message)))
{
guint timeout_id, timeout;
@@ -624,6 +589,14 @@ message_network_event_cb (SoupMessage *msg,
g_object_set_data_full (user_data, "address", address, g_object_unref);
}
+static gboolean
+accept_certificate_callback (SoupMessage *msg, GTlsCertificate *certificate,
+ GTlsCertificateFlags tls_errors, gpointer user_data)
+{
+ // Returning TRUE trusts it anyway.
+ return TRUE;
+}
+
void
cm_utils_read_uri_async (const char *uri,
guint timeout,
@@ -670,9 +643,10 @@ cm_utils_read_uri_async (const char *uri,
G_CALLBACK (message_network_event_cb), task,
G_CONNECT_AFTER);
session = soup_session_new ();
- g_object_set (G_OBJECT (session), SOUP_SESSION_SSL_STRICT, FALSE, NULL);
+ /* Accept invalid certificates */
+ g_signal_connect (message, "accept-certificate", G_CALLBACK (accept_certificate_callback), NULL);
- soup_session_send_async (session, message, cancel,
+ soup_session_send_async (session, message, 0, cancel,
uri_file_read_cb,
g_steal_pointer (&task));
}
--
2.35.1