mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-07 23:56:57 +02:00
MINOR: h2: implement h2_send_rst_stream() to send RST_STREAM frames
This one sends an RST_STREAM for a given stream, using the current demux stream ID. It's also used to send RST_STREAM for streams which have lost their CS part (ie were aborted).
This commit is contained in:
parent
26f95954fe
commit
27a84c90ce
71
src/mux_h2.c
71
src/mux_h2.c
@ -753,6 +753,64 @@ static int h2c_send_goaway_error(struct h2c *h2c, struct h2s *h2s)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* try to send an RST_STREAM frame on the connection for the current demuxed
|
||||
* stream to report an error, with h2s->errcode as the error code. Returns > 0
|
||||
* on success or zero if nothing was done. It uses h2c->dsi as the stream ID
|
||||
* and h2s->errcode for the error code. In case of lack of room to write the
|
||||
* message, it subscribes the requester (either <h2s> or <h2c>) to future
|
||||
* notifications. It's worth mentionning that an RST may even be sent for a
|
||||
* closed stream with error 0 in this case.
|
||||
*/
|
||||
static int h2c_send_rst_stream(struct h2c *h2c, struct h2s *h2s)
|
||||
{
|
||||
struct buffer *res;
|
||||
char str[13];
|
||||
int ret;
|
||||
|
||||
if (h2c_mux_busy(h2c, h2s)) {
|
||||
if (h2s)
|
||||
h2s->flags |= H2_SF_BLK_MBUSY;
|
||||
else
|
||||
h2c->flags |= H2_CF_DEM_MBUSY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
res = h2_get_mbuf(h2c);
|
||||
if (!res) {
|
||||
h2c->flags |= H2_CF_MUX_MALLOC;
|
||||
if (h2s)
|
||||
h2s->flags |= H2_SF_BLK_MROOM;
|
||||
else
|
||||
h2c->flags |= H2_CF_DEM_MROOM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* len: 4, type: 3, flags: none */
|
||||
memcpy(str, "\x00\x00\x04\x03\x00", 5);
|
||||
write_n32(str + 5, h2c->dsi);
|
||||
write_n32(str + 9, (h2s->st > H2_SS_IDLE && h2s->st < H2_SS_RESET) ?
|
||||
h2s->errcode : H2_ERR_STREAM_CLOSED);
|
||||
ret = bo_istput(res, ist2(str, 13));
|
||||
if (unlikely(ret <= 0)) {
|
||||
if (!ret) {
|
||||
h2c->flags |= H2_CF_MUX_MFULL;
|
||||
if (h2s)
|
||||
h2s->flags |= H2_SF_BLK_MROOM;
|
||||
else
|
||||
h2c->flags |= H2_CF_DEM_MROOM;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
h2c_error(h2c, H2_ERR_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (h2s)
|
||||
h2s->flags |= H2_SF_RST_SENT;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Increase all streams' outgoing window size by the difference passed in
|
||||
* argument. This is needed upon receipt of the settings frame if the initial
|
||||
* window size is different. The difference may be negative and the resulting
|
||||
@ -1158,6 +1216,15 @@ static void h2_process_demux(struct h2c *h2c)
|
||||
ret = h2c->dfl == 0;
|
||||
}
|
||||
|
||||
/* RST are sent similarly to frame acks */
|
||||
if (h2s->st == H2_SS_ERROR) {
|
||||
if (h2c->st0 == H2_CS_FRAME_P)
|
||||
h2c->st0 = H2_CS_FRAME_A;
|
||||
|
||||
if (h2c->st0 == H2_CS_FRAME_A)
|
||||
ret = h2c_send_rst_stream(h2c, h2s);
|
||||
}
|
||||
|
||||
/* error or missing data condition met above ? */
|
||||
if (ret <= 0)
|
||||
break;
|
||||
@ -1203,6 +1270,8 @@ static int h2_process_mux(struct h2c *h2c)
|
||||
if (h2s->cs) {
|
||||
h2s->cs->data_cb->send(h2s->cs);
|
||||
h2s->cs->data_cb->wake(h2s->cs);
|
||||
} else {
|
||||
h2c_send_rst_stream(h2c, h2s);
|
||||
}
|
||||
|
||||
/* depending on callee's blocking reasons, we may queue in send
|
||||
@ -1239,6 +1308,8 @@ static int h2_process_mux(struct h2c *h2c)
|
||||
if (h2s->cs) {
|
||||
h2s->cs->data_cb->send(h2s->cs);
|
||||
h2s->cs->data_cb->wake(h2s->cs);
|
||||
} else {
|
||||
h2c_send_rst_stream(h2c, h2s);
|
||||
}
|
||||
/* depending on callee's blocking reasons, we may queue in fctl
|
||||
* list or completely dequeue.
|
||||
|
Loading…
Reference in New Issue
Block a user