summaryrefslogtreecommitdiff
path: root/libsoup
diff options
context:
space:
mode:
Diffstat (limited to 'libsoup')
-rw-r--r--libsoup/soup-message-private.h6
-rw-r--r--libsoup/soup-message.c97
-rw-r--r--libsoup/soup-session.c5
3 files changed, 106 insertions, 2 deletions
diff --git a/libsoup/soup-message-private.h b/libsoup/soup-message-private.h
index 82bf7d89..8b3ad56f 100644
--- a/libsoup/soup-message-private.h
+++ b/libsoup/soup-message-private.h
@@ -100,6 +100,12 @@ GList *soup_message_get_disabled_features (SoupMessage *msg);
SoupConnection *soup_message_get_connection (SoupMessage *msg);
void soup_message_set_connection (SoupMessage *msg,
SoupConnection *conn);
+void soup_message_transfer_connection (SoupMessage *preconnect_msg,
+ SoupMessage *msg);
+void soup_message_set_is_preconnect (SoupMessage *msg,
+ gboolean is_preconnect);
+gboolean soup_message_has_pending_tls_cert_request (SoupMessage *msg);
+gboolean soup_message_has_pending_tls_cert_pass_request (SoupMessage *msg);
SoupClientMessageIO *soup_message_get_io_data (SoupMessage *msg);
diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c
index 0f977816..41aed806 100644
--- a/libsoup/soup-message.c
+++ b/libsoup/soup-message.c
@@ -92,12 +92,15 @@ typedef struct {
GTlsCertificate *tls_client_certificate;
GTask *pending_tls_cert_request;
+ GTlsClientConnection *pending_tls_cert_conn;
GTask *pending_tls_cert_pass_request;
+ GTlsPassword *pending_tls_cert_password;
SoupMessagePriority priority;
gboolean is_top_level_navigation;
gboolean is_options_ping;
+ gboolean is_preconnect;
gboolean force_http1;
gboolean is_misdirected_retry;
guint last_connection_id;
@@ -181,11 +184,13 @@ soup_message_finalize (GObject *object)
g_task_return_int (priv->pending_tls_cert_request, G_TLS_INTERACTION_FAILED);
g_object_unref (priv->pending_tls_cert_request);
}
+ g_clear_object (&priv->pending_tls_cert_conn);
if (priv->pending_tls_cert_pass_request) {
g_task_return_int (priv->pending_tls_cert_pass_request, G_TLS_INTERACTION_FAILED);
g_object_unref (priv->pending_tls_cert_pass_request);
}
+ g_clear_object (&priv->pending_tls_cert_password);
soup_message_set_connection (msg, NULL);
@@ -1476,6 +1481,15 @@ re_emit_request_certificate (SoupMessage *msg,
priv->pending_tls_cert_request = g_object_ref (task);
+ /* Skip interaction for preconnect requests, keep the operation
+ * pending that will be handled by the new message once the
+ * connection is transferred.
+ */
+ if (priv->is_preconnect) {
+ priv->pending_tls_cert_conn = g_object_ref (tls_conn);
+ return TRUE;
+ }
+
g_signal_emit (msg, signals[REQUEST_CERTIFICATE], 0, tls_conn, &handled);
if (!handled)
g_clear_object (&priv->pending_tls_cert_request);
@@ -1493,6 +1507,15 @@ re_emit_request_certificate_password (SoupMessage *msg,
priv->pending_tls_cert_pass_request = g_object_ref (task);
+ /* Skip interaction for preconnect requests, keep the operation
+ * pending that will be handled by the new message once the
+ * connection is transferred.
+ */
+ if (priv->is_preconnect) {
+ priv->pending_tls_cert_password = g_object_ref (password);
+ return TRUE;
+ }
+
g_signal_emit (msg, signals[REQUEST_CERTIFICATE_PASSWORD], 0, password, &handled);
if (!handled)
g_clear_object (&priv->pending_tls_cert_pass_request);
@@ -1580,6 +1603,80 @@ soup_message_set_connection (SoupMessage *msg,
msg, G_CONNECT_SWAPPED);
}
+void
+soup_message_set_is_preconnect (SoupMessage *msg,
+ gboolean is_preconnect)
+{
+ SoupMessagePrivate *priv = soup_message_get_instance_private (msg);
+
+ priv->is_preconnect = is_preconnect;
+}
+
+void
+soup_message_transfer_connection (SoupMessage *preconnect_msg,
+ SoupMessage *msg)
+{
+ SoupMessagePrivate *preconnect_priv = soup_message_get_instance_private (preconnect_msg);
+ SoupMessagePrivate *priv = soup_message_get_instance_private (msg);
+ GTlsCertificate *client_certificate = NULL;
+
+ g_assert (preconnect_priv->is_preconnect);
+ g_assert (!priv->connection);
+ client_certificate = g_steal_pointer (&priv->tls_client_certificate);
+ soup_message_set_connection (msg, preconnect_priv->connection);
+
+ /* If connection has pending interactions, transfer them too */
+ g_assert (!priv->pending_tls_cert_request);
+ priv->pending_tls_cert_request = g_steal_pointer (&preconnect_priv->pending_tls_cert_request);
+ if (priv->pending_tls_cert_request) {
+ if (client_certificate) {
+ soup_connection_complete_tls_certificate_request (priv->connection,
+ client_certificate,
+ g_steal_pointer (&priv->pending_tls_cert_request));
+ g_object_unref (client_certificate);
+ } else {
+ gboolean handled = FALSE;
+
+ g_signal_emit (msg, signals[REQUEST_CERTIFICATE], 0, preconnect_priv->pending_tls_cert_conn, &handled);
+ g_clear_object (&preconnect_priv->pending_tls_cert_conn);
+ if (!handled)
+ g_clear_object (&priv->pending_tls_cert_request);
+ }
+ } else if (client_certificate) {
+ soup_connection_set_tls_client_certificate (priv->connection, client_certificate);
+ g_object_unref (client_certificate);
+ }
+
+ g_assert (!priv->pending_tls_cert_pass_request);
+ priv->pending_tls_cert_pass_request = g_steal_pointer (&preconnect_priv->pending_tls_cert_pass_request);
+ if (priv->pending_tls_cert_pass_request) {
+ gboolean handled = FALSE;
+
+ g_signal_emit (msg, signals[REQUEST_CERTIFICATE_PASSWORD], 0, preconnect_priv->pending_tls_cert_password, &handled);
+ g_clear_object (&preconnect_priv->pending_tls_cert_password);
+ if (!handled)
+ g_clear_object (&priv->pending_tls_cert_pass_request);
+ }
+
+ soup_message_set_connection (preconnect_msg, NULL);
+}
+
+gboolean
+soup_message_has_pending_tls_cert_request (SoupMessage *msg)
+{
+ SoupMessagePrivate *priv = soup_message_get_instance_private (msg);
+
+ return priv->pending_tls_cert_request != NULL;
+}
+
+gboolean
+soup_message_has_pending_tls_cert_pass_request (SoupMessage *msg)
+{
+ SoupMessagePrivate *priv = soup_message_get_instance_private (msg);
+
+ return priv->pending_tls_cert_pass_request != NULL;
+}
+
/**
* soup_message_cleanup_response:
* @msg: a #SoupMessage
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index 4789fc63..9c674e57 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -1360,6 +1360,7 @@ soup_session_append_queue_item (SoupSession *session,
soup_message_set_metrics_timestamp (msg, SOUP_MESSAGE_METRICS_FETCH_START);
soup_message_cleanup_response (msg);
+ soup_message_set_is_preconnect (msg, FALSE);
item = soup_message_queue_item_new (session, msg, async, cancellable);
g_queue_insert_sorted (priv->queue,
@@ -1786,8 +1787,7 @@ steal_preconnection (SoupSession *session,
if (!preconnect_item->connect_only || preconnect_item->state != SOUP_MESSAGE_CONNECTING)
return FALSE;
- soup_message_set_connection (item->msg, conn);
- soup_message_set_connection (preconnect_item->msg, NULL);
+ soup_message_transfer_connection (preconnect_item->msg, item->msg);
g_assert (preconnect_item->related == NULL);
preconnect_item->related = soup_message_queue_item_ref (item);
@@ -4040,6 +4040,7 @@ soup_session_preconnect_async (SoupSession *session,
item = soup_session_append_queue_item (session, msg, TRUE, cancellable);
item->connect_only = TRUE;
item->io_priority = io_priority;
+ soup_message_set_is_preconnect (msg, TRUE);
task = g_task_new (session, item->cancellable, callback, user_data);
g_task_set_priority (task, io_priority);