]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: early data: Don't rely on CO_FL_EARLY_DATA to wake up streams.
authorOlivier Houchard <ohouchard@haproxy.com>
Mon, 27 Nov 2017 17:41:32 +0000 (18:41 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 5 Feb 2018 13:24:50 +0000 (14:24 +0100)
Instead of looking for CO_FL_EARLY_DATA to know if we have to try to wake
up a stream, because it is waiting for a SSL handshake, instead add a new
conn_stream flag, CS_FL_WAIT_FOR_HS. This way we don't have to rely on
CO_FL_EARLY_DATA, and we will only wake streams that are actually waiting.

include/types/connection.h
src/mux_h2.c
src/ssl_sock.c
src/stream_interface.c

index 4bcac6079bffa61c9c6bef7eb83e7694164cce84..cea61f55975979eed58fb430de002c4eb994e50b 100644 (file)
@@ -70,6 +70,7 @@ enum {
        CS_FL_ERROR         = 0x00000100,  /* a fatal error was reported */
        CS_FL_RCV_MORE      = 0x00000200,  /* more bytes to receive but not enough room */
        CS_FL_EOS           = 0x00001000,  /* End of stream */
+       CS_FL_WAIT_FOR_HS   = 0x00010000,  /* This stream is waiting for handhskae */
 };
 
 /* cs_shutr() modes */
index 7bb51ea4185da9408ef835f78c611b7095bab20d..6c63b86125922cf823dc924982d1f0092f20f3ac 100644 (file)
@@ -59,6 +59,7 @@ static struct pool_head *pool_head_h2s;
 /* other flags */
 #define H2_CF_GOAWAY_SENT       0x00000100  // a GOAWAY frame was successfully sent
 #define H2_CF_GOAWAY_FAILED     0x00000200  // a GOAWAY frame failed to be sent
+#define H2_CF_WAIT_FOR_HS       0x00000400  // We did check that at least a stream was waiting for handshake
 
 
 /* H2 connection state, in h2c->st0 */
@@ -2275,14 +2276,25 @@ static int h2_wake(struct connection *conn)
        }
 
        /*
-        * If we received early data, try to wake any stream, just in case
-        * at least one of them was waiting for the handshake
+        * If we received early data, and the handshake is done, wake
+        * any stream that was waiting for it.
         */
-       if ((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA | CO_FL_HANDSHAKE)) ==
-           CO_FL_EARLY_DATA) {
-               h2_wake_some_streams(h2c, 0, 0);
-               conn->flags &= ~CO_FL_EARLY_DATA;
+       if (!(h2c->flags & H2_CF_WAIT_FOR_HS) &&
+           (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE | CO_FL_EARLY_DATA)) == CO_FL_EARLY_DATA) {
+               struct eb32_node *node;
+               struct h2s *h2s;
+
+               h2c->flags |= H2_CF_WAIT_FOR_HS;
+               node = eb32_lookup_ge(&h2c->streams_by_id, 1);
+
+               while (node) {
+                       h2s = container_of(node, struct h2s, by_id);
+                       if (h2s->cs->flags & CS_FL_WAIT_FOR_HS)
+                               h2s->cs->data_cb->wake(h2s->cs);
+                       node = eb32_next(node);
+               }
        }
+
        if (conn->flags & CO_FL_ERROR || conn_xprt_read0_pending(conn) ||
            h2c->st0 == H2_CS_ERROR2 || h2c->flags & H2_CF_GOAWAY_FAILED ||
            (eb_is_empty(&h2c->streams_by_id) && h2c->last_sid >= 0 &&
index c2fa45f52df71cccb4889291554b0c6b6c52d264..76f842528b42af42033875afdea6730edbbd682d 100644 (file)
@@ -8711,11 +8711,14 @@ enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
                                        struct session *sess, struct stream *s, int flags)
 {
        struct connection *conn;
+       struct conn_stream *cs;
 
        conn = objt_conn(sess->origin);
+       cs = objt_cs(s->si[0].end);
 
-       if (conn) {
+       if (conn && cs) {
                if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
+                       cs->flags |= CS_FL_WAIT_FOR_HS;
                        s->req.flags |= CF_READ_NULL;
                        return ACT_RET_YIELD;
                }
index 9f61a7510589e79f225845de04f07fa34bab010f..a78694f78454a9f8b1086420fc4e21e271f3a1dd 100644 (file)
@@ -584,7 +584,9 @@ static int si_cs_wake_cb(struct conn_stream *cs)
         * in the event there's an analyser waiting for the end of
         * the handshake.
         */
-       if ((conn->flags & (CO_FL_EARLY_DATA | CO_FL_EARLY_SSL_HS)) == CO_FL_EARLY_DATA) {
+       if (!(conn->flags & (CO_FL_HANDSHAKE | CO_FL_EARLY_SSL_HS)) &&
+           (cs->flags & CS_FL_WAIT_FOR_HS)) {
+               cs->flags &= ~CS_FL_WAIT_FOR_HS;
                task_wakeup(si_task(si), TASK_WOKEN_MSG);
        }