[master] 64f609dbd h2: Send GOAWAY frames in a dedicated function

Simon Stridsberg simon.stridsberg at varnish-software.com
Mon Mar 18 18:32:06 UTC 2024


commit 64f609dbdaeb4d9f574424a374100b06f8f40398
Author: Dridi Boukelmoune <dridi.boukelmoune at gmail.com>
Date:   Tue Jan 18 10:08:33 2022 +0100

    h2: Send GOAWAY frames in a dedicated function
    
    And after issuing or receiving a goaway, stop processing frames when
    there are no streams left.
    
    Initially submitted as part of listen sockets management.
    
    Refs #3959

diff --git a/bin/varnishd/http2/cache_http2.h b/bin/varnishd/http2/cache_http2.h
index 0ca9eeb78..11e957d49 100644
--- a/bin/varnishd/http2/cache_http2.h
+++ b/bin/varnishd/http2/cache_http2.h
@@ -165,6 +165,7 @@ struct h2_sess {
 	int				refcnt;
 	unsigned			open_streams;
 	uint32_t			highest_stream;
+	int				goaway;
 	int				bogosity;
 	int				do_sweep;
 
diff --git a/bin/varnishd/http2/cache_http2_proto.c b/bin/varnishd/http2/cache_http2_proto.c
index 454a78cbe..eaa6b1b7a 100644
--- a/bin/varnishd/http2/cache_http2_proto.c
+++ b/bin/varnishd/http2/cache_http2_proto.c
@@ -389,6 +389,7 @@ h2_rx_goaway(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
 	CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
 	assert(r2 == h2->req0);
 
+	h2->goaway = 1;
 	h2->goaway_last_stream = vbe32dec(h2->rxf_data);
 	h2->error = h2_connectionerror(vbe32dec(h2->rxf_data + 4));
 	Lck_Lock(&h2->sess->mtx);
@@ -397,6 +398,25 @@ h2_rx_goaway(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
 	return (h2->error);
 }
 
+static void
+h2_tx_goaway(struct worker *wrk, struct h2_sess *h2, h2_error h2e)
+{
+	char b[8];
+
+	ASSERT_RXTHR(h2);
+	AN(h2e);
+
+	if (h2->goaway)
+		return;
+
+	h2->goaway = 1;
+	vbe32enc(b, h2->highest_stream);
+	vbe32enc(b + 4, h2e->val);
+	H2_Send_Get(wrk, h2, h2->req0);
+	H2_Send_Frame(wrk, h2, H2_F_GOAWAY, 0, 8, 0, b);
+	H2_Send_Rel(h2, h2->req0);
+}
+
 /**********************************************************************
  */
 
@@ -1411,9 +1431,12 @@ h2_rxframe(struct worker *wrk, struct h2_sess *h2)
 	h2_frame h2f;
 	h2_error h2e;
 	const char *s = NULL;
-	char b[8];
 
 	ASSERT_RXTHR(h2);
+
+	if (h2->goaway && h2->open_streams == 0)
+		return (0);
+
 	VTCP_blocking(*h2->htc->rfd);
 	h2->sess->t_idle = VTIM_real();
 	hs = HTC_RxStuff(h2->htc, h2_frame_complete,
@@ -1491,11 +1514,7 @@ h2_rxframe(struct worker *wrk, struct h2_sess *h2)
 	h2e = h2_procframe(wrk, h2, h2f);
 	if (h2->error == NULL && h2e != NULL) {
 		h2->error = h2e;
-		vbe32enc(b, h2->highest_stream);
-		vbe32enc(b + 4, h2e->val);
-		H2_Send_Get(wrk, h2, h2->req0);
-		H2_Send_Frame(wrk, h2, H2_F_GOAWAY, 0, 8, 0, b);
-		H2_Send_Rel(h2, h2->req0);
+		h2_tx_goaway(wrk, h2, h2e);
 	}
 
 	return (h2->error != NULL ? 0 : 1);


More information about the varnish-commit mailing list