Commit 64f609db authored by Dridi Boukelmoune's avatar Dridi Boukelmoune Committed by Simon Stridsberg

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
parent 7ce5f508
...@@ -165,6 +165,7 @@ struct h2_sess { ...@@ -165,6 +165,7 @@ struct h2_sess {
int refcnt; int refcnt;
unsigned open_streams; unsigned open_streams;
uint32_t highest_stream; uint32_t highest_stream;
int goaway;
int bogosity; int bogosity;
int do_sweep; int do_sweep;
......
...@@ -389,6 +389,7 @@ h2_rx_goaway(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2) ...@@ -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); CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
assert(r2 == h2->req0); assert(r2 == h2->req0);
h2->goaway = 1;
h2->goaway_last_stream = vbe32dec(h2->rxf_data); h2->goaway_last_stream = vbe32dec(h2->rxf_data);
h2->error = h2_connectionerror(vbe32dec(h2->rxf_data + 4)); h2->error = h2_connectionerror(vbe32dec(h2->rxf_data + 4));
Lck_Lock(&h2->sess->mtx); Lck_Lock(&h2->sess->mtx);
...@@ -397,6 +398,25 @@ h2_rx_goaway(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2) ...@@ -397,6 +398,25 @@ h2_rx_goaway(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
return (h2->error); 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) ...@@ -1411,9 +1431,12 @@ h2_rxframe(struct worker *wrk, struct h2_sess *h2)
h2_frame h2f; h2_frame h2f;
h2_error h2e; h2_error h2e;
const char *s = NULL; const char *s = NULL;
char b[8];
ASSERT_RXTHR(h2); ASSERT_RXTHR(h2);
if (h2->goaway && h2->open_streams == 0)
return (0);
VTCP_blocking(*h2->htc->rfd); VTCP_blocking(*h2->htc->rfd);
h2->sess->t_idle = VTIM_real(); h2->sess->t_idle = VTIM_real();
hs = HTC_RxStuff(h2->htc, h2_frame_complete, hs = HTC_RxStuff(h2->htc, h2_frame_complete,
...@@ -1491,11 +1514,7 @@ h2_rxframe(struct worker *wrk, struct h2_sess *h2) ...@@ -1491,11 +1514,7 @@ h2_rxframe(struct worker *wrk, struct h2_sess *h2)
h2e = h2_procframe(wrk, h2, h2f); h2e = h2_procframe(wrk, h2, h2f);
if (h2->error == NULL && h2e != NULL) { if (h2->error == NULL && h2e != NULL) {
h2->error = h2e; h2->error = h2e;
vbe32enc(b, h2->highest_stream); h2_tx_goaway(wrk, h2, h2e);
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);
} }
return (h2->error != NULL ? 0 : 1); return (h2->error != NULL ? 0 : 1);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment