diff options
Diffstat (limited to 'libsoup')
-rw-r--r-- | libsoup/soup-message-private.h | 6 | ||||
-rw-r--r-- | libsoup/soup-message.c | 97 | ||||
-rw-r--r-- | libsoup/soup-session.c | 5 |
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); |