[libsoup/libsoup-3-0] message: make it possible to force http/2 too



commit f6e05d7762297f4912965184f4b88277c5490938
Author: Carlos Garcia Campos <cgarcia igalia com>
Date:   Wed Apr 13 10:19:51 2022 +0200

    message: make it possible to force http/2 too
    
    Now that apache supports http/2 for tests, we need a way to force http/2
    because http1 is still the preferred protocol. This changes the API to
    force http1 into force http version. It's not exactly the same because
    force http1 also included http 1.0, but forcing http 1.1 should just
    work too.

 libsoup/soup-connection.c      | 45 +++++++++++++++++++++++++++---------------
 libsoup/soup-message-private.h |  6 +++---
 libsoup/soup-message.c         | 19 +++++++++++-------
 libsoup/soup-session.c         | 15 ++++++--------
 4 files changed, 50 insertions(+), 35 deletions(-)
---
diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c
index 38a91e46..a6e784b7 100644
--- a/libsoup/soup-connection.c
+++ b/libsoup/soup-connection.c
@@ -31,7 +31,7 @@ typedef struct {
        SoupSocketProperties *socket_props;
         guint64 id;
         GSocketAddress *remote_address;
-        gboolean force_http1;
+        guint8 force_http_version;
 
        GUri *proxy_uri;
        gboolean ssl;
@@ -75,7 +75,7 @@ enum {
        PROP_TLS_CERTIFICATE_ERRORS,
         PROP_TLS_PROTOCOL_VERSION,
         PROP_TLS_CIPHERSUITE_NAME,
-        PROP_FORCE_HTTP1,
+        PROP_FORCE_HTTP_VERSION,
 
        LAST_PROPERTY
 };
@@ -95,6 +95,7 @@ soup_connection_init (SoupConnection *conn)
         SoupConnectionPrivate *priv = soup_connection_get_instance_private (conn);
 
         priv->http_version = SOUP_HTTP_1_1;
+        priv->force_http_version = G_MAXUINT8;
 }
 
 static void
@@ -156,8 +157,8 @@ soup_connection_set_property (GObject *object, guint prop_id,
        case PROP_ID:
                priv->id = g_value_get_uint64 (value);
                break;
-       case PROP_FORCE_HTTP1:
-               priv->force_http1 = g_value_get_boolean (value);
+       case PROP_FORCE_HTTP_VERSION:
+               priv->force_http_version = g_value_get_uchar (value);
                break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -202,8 +203,8 @@ soup_connection_get_property (GObject *object, guint prop_id,
         case PROP_TLS_CIPHERSUITE_NAME:
                 g_value_set_string (value, soup_connection_get_tls_ciphersuite_name (SOUP_CONNECTION 
(object)));
                 break;
-       case PROP_FORCE_HTTP1:
-               g_value_set_boolean (value, priv->force_http1);
+       case PROP_FORCE_HTTP_VERSION:
+               g_value_set_uchar (value, priv->force_http_version);
                break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -344,12 +345,13 @@ soup_connection_class_init (SoupConnectionClass *connection_class)
                                      NULL,
                                      G_PARAM_READABLE |
                                      G_PARAM_STATIC_STRINGS);
-        properties[PROP_FORCE_HTTP1] =
-                g_param_spec_boolean ("force-http1",
-                                      "Force HTTP 1.x",
-                                      "Force connection to use HTTP 1.x",
-                                      FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-                                      G_PARAM_STATIC_STRINGS);
+        properties[PROP_FORCE_HTTP_VERSION] =
+                g_param_spec_uchar ("force-http-version",
+                                    "Force HTTP version",
+                                    "Force connection to use a specific HTTP version",
+                                    0, G_MAXUINT8, G_MAXUINT8,
+                                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+                                    G_PARAM_STATIC_STRINGS);
 
         g_object_class_install_properties (object_class, LAST_PROPERTY, properties);
 }
@@ -568,11 +570,22 @@ new_tls_connection (SoupConnection    *conn,
         GPtrArray *advertised_protocols = g_ptr_array_sized_new (4);
 
         // https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
-        if (!priv->force_http1)
+        switch (priv->force_http_version) {
+        case SOUP_HTTP_1_0:
+                g_ptr_array_add (advertised_protocols, "http/1.0");
+                break;
+        case SOUP_HTTP_1_1:
+                g_ptr_array_add (advertised_protocols, "http/1.1");
+                break;
+        case SOUP_HTTP_2_0:
                 g_ptr_array_add (advertised_protocols, "h2");
-
-        g_ptr_array_add (advertised_protocols, "http/1.1");
-        g_ptr_array_add (advertised_protocols, "http/1.0");
+                break;
+        default:
+                g_ptr_array_add (advertised_protocols, "h2");
+                g_ptr_array_add (advertised_protocols, "http/1.1");
+                g_ptr_array_add (advertised_protocols, "http/1.0");
+                break;
+        }
         g_ptr_array_add (advertised_protocols, NULL);
 
         tls_interaction = priv->socket_props->tls_interaction ? g_object_ref 
(priv->socket_props->tls_interaction) : soup_tls_interaction_new (conn);
diff --git a/libsoup/soup-message-private.h b/libsoup/soup-message-private.h
index 8b3ad56f..c036630e 100644
--- a/libsoup/soup-message-private.h
+++ b/libsoup/soup-message-private.h
@@ -147,10 +147,10 @@ void soup_message_update_request_host_if_needed (SoupMessage *msg);
 
 void soup_message_force_keep_alive_if_needed    (SoupMessage *msg);
 
-void soup_message_set_force_http1               (SoupMessage *msg,
-                                                 gboolean     force_http1);
+void     soup_message_set_force_http_version    (SoupMessage *msg,
+                                                 guint8       version);
 
-gboolean soup_message_get_force_http1           (SoupMessage *msg);
+guint8   soup_message_get_force_http_version    (SoupMessage *msg);
 
 void     soup_message_set_is_misdirected_retry  (SoupMessage *msg,
                                                  gboolean     is_misdirected_retry);
diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c
index 73671819..e7d9b3ab 100644
--- a/libsoup/soup-message.c
+++ b/libsoup/soup-message.c
@@ -103,9 +103,9 @@ typedef struct {
        gboolean is_top_level_navigation;
         gboolean is_options_ping;
         gboolean is_preconnect;
-        gboolean force_http1;
         gboolean is_misdirected_retry;
         guint    last_connection_id;
+        guint8   force_http_version;
         GSocketAddress *remote_address;
 
         SoupMessageMetrics *metrics;
@@ -173,6 +173,7 @@ soup_message_init (SoupMessage *msg)
 
        priv->http_version = priv->orig_http_version = SOUP_HTTP_1_1;
        priv->priority = SOUP_MESSAGE_PRIORITY_NORMAL;
+        priv->force_http_version = G_MAXUINT8;
 
        priv->request_headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_REQUEST);
        priv->response_headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_RESPONSE);
@@ -1208,7 +1209,11 @@ soup_message_restarted (SoupMessage *msg)
 void
 soup_message_finished (SoupMessage *msg)
 {
+        SoupMessagePrivate *priv = soup_message_get_instance_private (msg);
+
        g_signal_emit (msg, signals[FINISHED], 0);
+
+        priv->force_http_version = G_MAXUINT8;
 }
 
 gboolean
@@ -3156,20 +3161,20 @@ soup_message_force_keep_alive_if_needed (SoupMessage *msg)
 }
 
 void
-soup_message_set_force_http1 (SoupMessage *msg,
-                              gboolean     force_http1)
+soup_message_set_force_http_version (SoupMessage *msg,
+                                     guint8       version)
 {
         SoupMessagePrivate *priv = soup_message_get_instance_private (msg);
 
-        priv->force_http1 = force_http1;
+        priv->force_http_version = version;
 }
 
-gboolean
-soup_message_get_force_http1 (SoupMessage *msg)
+guint8
+soup_message_get_force_http_version (SoupMessage *msg)
 {
         SoupMessagePrivate *priv = soup_message_get_instance_private (msg);
 
-        return priv->force_http1;
+        return priv->force_http_version;
 }
 
 void
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index 319174f3..ea0c1405 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -1806,7 +1806,7 @@ get_connection_for_host (SoupSession *session,
 {
        SoupSessionPrivate *priv = soup_session_get_instance_private (session);
        GSocketConnectable *remote_connectable;
-        gboolean force_http1;
+        guint8 force_http_version;
        SoupConnection *conn;
        GSList *conns;
 
@@ -1819,10 +1819,7 @@ get_connection_for_host (SoupSession *session,
                return conn;
        }
 
-        if (g_getenv ("SOUP_FORCE_HTTP1"))
-                force_http1 = TRUE;
-        else
-                force_http1 = soup_message_get_force_http1 (item->msg);
+        force_http_version = g_getenv ("SOUP_FORCE_HTTP1") ? SOUP_HTTP_1_1 : 
soup_message_get_force_http_version (item->msg);
 
        for (conns = host->connections; conns; conns = conns->next) {
                 SoupHTTPVersion http_version;
@@ -1830,7 +1827,7 @@ get_connection_for_host (SoupSession *session,
                conn = conns->data;
 
                 http_version = soup_connection_get_negotiated_protocol (conn);
-                if (force_http1 && http_version > SOUP_HTTP_1_1)
+                if (force_http_version <= SOUP_HTTP_1_1 && http_version > SOUP_HTTP_1_1)
                         continue;
 
                switch (soup_connection_get_state (conn)) {
@@ -1849,7 +1846,7 @@ get_connection_for_host (SoupSession *session,
                         /* Always wait if we have a pending connection as it may be
                          * an h2 connection which will be shared. http/1.x connections
                          * will only be slightly delayed. */
-                        if (!force_http1 && !need_new_connection && !item->connect_only)
+                        if (force_http_version > SOUP_HTTP_1_1 && !need_new_connection && 
!item->connect_only)
                                 return NULL;
                default:
                        break;
@@ -1884,7 +1881,7 @@ get_connection_for_host (SoupSession *session,
                             "remote-connectable", remote_connectable,
                             "ssl", soup_uri_is_https (host->uri),
                             "socket-properties", priv->socket_props,
-                             "force-http1", force_http1,
+                             "force-http-version", force_http_version,
                             NULL);
        g_object_unref (remote_connectable);
 
@@ -3935,7 +3932,7 @@ soup_session_websocket_connect_async (SoupSession          *session,
         /* WebSocket negotiation over HTTP/2 is not currently supported
          * and in practice all websocket servers support HTTP1.x with
          * HTTP/2 not providing a tangible benefit */
-        soup_message_set_force_http1 (msg, TRUE);
+        soup_message_set_force_http_version (msg, SOUP_HTTP_1_1);
 
        item = soup_session_append_queue_item (session, msg, TRUE, cancellable);
        item->io_priority = io_priority;


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