[libsoup/carlosgc/tunnel-connect-error: 4/4] Handle io errors on connect message while tunneling




commit d6200373aa0d3de427ffcaa602a7557187dee88b
Author: Carlos Garcia Campos <cgarcia igalia com>
Date:   Tue Oct 11 14:21:16 2022 +0200

    Handle io errors on connect message while tunneling
    
    Fixes #283

 libsoup/http1/soup-client-message-io-http1.c |  9 ++++---
 libsoup/soup-session.c                       |  5 ++--
 tests/proxy-test.c                           | 37 +++++++++++++++++++++++++++-
 3 files changed, 45 insertions(+), 6 deletions(-)
---
diff --git a/libsoup/http1/soup-client-message-io-http1.c b/libsoup/http1/soup-client-message-io-http1.c
index dff6bbf2..8c647bfa 100644
--- a/libsoup/http1/soup-client-message-io-http1.c
+++ b/libsoup/http1/soup-client-message-io-http1.c
@@ -860,9 +860,12 @@ soup_client_message_io_http1_run (SoupClientMessageIO *iface,
                                        soup_client_message_io_http1_get_priority (client_io));
                 g_source_attach (io->io_source, g_main_context_get_thread_default ());
         } else {
-                if ((SoupClientMessageIOHTTP1 *)soup_message_get_io_data (msg) == client_io)
-                        soup_message_io_finish (msg, error);
-                g_error_free (error);
+                if ((SoupClientMessageIOHTTP1 *)soup_message_get_io_data (msg) == client_io) {
+                        g_assert (!client_io->msg_io->item->error);
+                        client_io->msg_io->item->error = g_steal_pointer (&error);
+                        soup_message_io_finish (msg, client_io->msg_io->item->error);
+                }
+                g_clear_error (&error);
 
         }
 
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index de0da49c..cfd4ef07 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -1518,6 +1518,7 @@ tunnel_message_completed (SoupMessage *msg, SoupMessageIOCompletion completion,
                 conn = soup_message_get_connection (tunnel_item->msg);
                if (conn) {
                         g_object_unref (conn);
+                        g_clear_object (&tunnel_item->error);
                        tunnel_item->state = SOUP_MESSAGE_RUNNING;
                        soup_session_send_queue_item (session, tunnel_item,
                                                      (SoupMessageIOCompletionFn)tunnel_message_completed);
@@ -1532,8 +1533,8 @@ tunnel_message_completed (SoupMessage *msg, SoupMessageIOCompletion completion,
        soup_session_unqueue_item (session, tunnel_item);
 
        status = soup_message_get_status (tunnel_item->msg);
-       if (!SOUP_STATUS_IS_SUCCESSFUL (status) || item->state == SOUP_MESSAGE_RESTARTING) {
-               tunnel_complete (tunnel_item, status, NULL);
+       if (!SOUP_STATUS_IS_SUCCESSFUL (status) || tunnel_item->error || item->state == 
SOUP_MESSAGE_RESTARTING) {
+               tunnel_complete (tunnel_item, status, g_steal_pointer (&tunnel_item->error));
                return;
        }
 
diff --git a/tests/proxy-test.c b/tests/proxy-test.c
index 9ca8699c..ec039367 100644
--- a/tests/proxy-test.c
+++ b/tests/proxy-test.c
@@ -340,11 +340,43 @@ do_proxy_auth_cache_test (void)
        g_object_unref (cache);
 }
 
+static void
+do_proxy_connect_error_test (gconstpointer data)
+{
+        GUri *base_uri = (GUri *)data;
+        GUri *proxy_uri;
+        char *proxy_uri_str;
+        SoupSession *session;
+        SoupMessage *msg;
+        GProxyResolver *resolver;
+        GBytes *body;
+        GError *error = NULL;
+
+        /* Proxy connection will success, but CONNECT message to https will fail due to TLS errors */
+        proxy_uri = soup_uri_copy (base_uri, SOUP_URI_SCHEME, "http", NULL);
+        proxy_uri_str = g_uri_to_string (proxy_uri);
+        g_uri_unref (proxy_uri);
+
+        resolver = g_simple_proxy_resolver_new (proxy_uri_str, (char **)ignore_hosts);
+        g_free (proxy_uri_str);
+        session = soup_test_session_new ("proxy-resolver", resolver, NULL);
+        g_object_unref (resolver);
+
+        msg = soup_message_new_from_uri (SOUP_METHOD_GET, base_uri);
+        body = soup_test_session_async_send (session, msg, NULL, &error);
+        g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED);
+
+        g_error_free (error);
+        g_bytes_unref (body);
+        g_object_unref (msg);
+        soup_test_session_abort_unref (session);
+}
+
 int
 main (int argc, char **argv)
 {
        SoupServer *server;
-       GUri *base_uri;
+       GUri *base_uri, *base_https_uri;
        char *path;
        int i, ret;
 
@@ -359,6 +391,7 @@ main (int argc, char **argv)
        server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
        soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
        base_uri = soup_test_server_get_uri (server, "http", NULL);
+        base_https_uri = soup_test_server_get_uri (server, "https", NULL);
 
        for (i = 0; i < ntests; i++) {
                path = g_strdup_printf ("/proxy/%s", tests[i].explanation);
@@ -369,10 +402,12 @@ main (int argc, char **argv)
        g_test_add_data_func ("/proxy/fragment", base_uri, do_proxy_fragment_test);
        g_test_add_func ("/proxy/redirect", do_proxy_redirect_test);
        g_test_add_func ("/proxy/auth-cache", do_proxy_auth_cache_test);
+        g_test_add_data_func ("/proxy/connect-error", base_https_uri, do_proxy_connect_error_test);
 
        ret = g_test_run ();
 
        g_uri_unref (base_uri);
+        g_uri_unref (base_https_uri);
        soup_test_server_quit_unref (server);
        for (i = 0; i < 3; i++)
                g_object_unref (proxy_resolvers[i]);


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