/* Flags indicating why reading input data are blocked. */
#define H1C_F_IN_ALLOC 0x00000010 /* mux is blocked on lack of input buffer */
#define H1C_F_IN_FULL 0x00000020 /* mux is blocked on input buffer full */
-#define H1C_F_IN_BUSY 0x00000040 /* mux is blocked on input waiting the other side */
/* 0x00000040 - 0x00000800 unused */
/* Flags indicating the connection state */
#define H1C_F_CO_MSG_MORE 0x00040000 /* set if CO_SFL_MSG_MORE must be set when calling xprt->snd_buf() */
#define H1C_F_CO_STREAMER 0x00080000 /* set if CO_SFL_STREAMER must be set when calling xprt->snd_buf() */
+#define H1C_F_WAIT_OPPOSITE 0x00100000 /* Don't read more data for now, waiting sync with opposite side */
/*
* H1 Stream flags (32 bits)
*/
return 0;
}
- if (conn_is_back(h1c->conn) && h1c->h1s && h1c->h1s->req.state == H1_MSG_RQBEFORE) {
- TRACE_DEVEL("recv not allowed because back and request not sent yet", H1_EV_H1C_RECV|H1_EV_H1C_BLK, h1c->conn);
+ if (h1c->flags & H1C_F_WAIT_OPPOSITE) {
+ TRACE_DEVEL("recv not allowed (wait_opposite)", H1_EV_H1C_RECV|H1_EV_H1C_BLK, h1c->conn);
return 0;
}
- if (!(h1c->flags & (H1C_F_IN_ALLOC|H1C_F_IN_FULL|H1C_F_IN_BUSY)))
+ if (!(h1c->flags & (H1C_F_IN_ALLOC|H1C_F_IN_FULL)))
return 1;
TRACE_DEVEL("recv not allowed because input is blocked", H1_EV_H1C_RECV|H1_EV_H1C_BLK, h1c->conn);
if (h1s->subs)
h1s->subs->events = 0;
- h1c->flags &= ~H1C_F_IN_BUSY;
+ h1c->flags &= ~H1C_F_WAIT_OPPOSITE;
if (h1s->flags & (H1S_F_REQ_ERROR|H1S_F_RES_ERROR)) {
h1c->flags |= H1C_F_CS_ERROR;
TRACE_STATE("h1s on error, set error on h1c", H1_EV_H1C_ERR, h1c->conn, h1s);
h1c->wait_event.events = 0;
if (conn_is_back(conn)) {
+ h1c->flags |= H1C_F_WAIT_OPPOSITE;
h1c->shut_timeout = h1c->timeout = proxy->timeout.server;
if (tick_isset(proxy->timeout.serverfin))
h1c->shut_timeout = proxy->timeout.serverfin;
task_queue(t);
/* Try to read, if nothing is available yet we'll just subscribe */
- h1c->conn->xprt->subscribe(h1c->conn, h1c->conn->xprt_ctx, SUB_RETRY_RECV, &h1c->wait_event);
+ if (!h1_recv_allowed(h1c))
+ h1c->conn->xprt->subscribe(h1c->conn, h1c->conn->xprt_ctx, SUB_RETRY_RECV, &h1c->wait_event);
/* mux->wake will be called soon to complete the operation */
TRACE_LEAVE(H1_EV_H1C_NEW, conn, h1c->h1s);
if (!conn_is_back(h1s->h1c->conn)) {
h1s->flags &= ~H1S_F_PARSING_DONE;
if (h1s->res.state < H1_MSG_DONE) {
- h1s->h1c->flags |= H1C_F_IN_BUSY;
- TRACE_STATE("switch h1c in busy mode", H1_EV_RX_DATA|H1_EV_H1C_BLK, h1s->h1c->conn, h1s);
+ h1s->h1c->flags |= H1C_F_WAIT_OPPOSITE;
+ TRACE_STATE("Disable read on h1c (wait_opposite)", H1_EV_RX_DATA|H1_EV_H1C_BLK, h1s->h1c->conn, h1s);
}
}
- else if (h1s->h1c->flags & H1C_F_IN_BUSY) {
- h1s->h1c->flags &= ~H1C_F_IN_BUSY;
+ else if (h1s->h1c->flags & H1C_F_WAIT_OPPOSITE) {
+ h1s->h1c->flags &= ~H1C_F_WAIT_OPPOSITE;
tasklet_wakeup(h1s->h1c->wait_event.tasklet);
- TRACE_STATE("h1c no more busy", H1_EV_RX_DATA|H1_EV_H1C_BLK|H1_EV_H1C_WAKE, h1s->h1c->conn, h1s);
+ TRACE_STATE("Re-enable read on h1c", H1_EV_RX_DATA|H1_EV_H1C_BLK|H1_EV_H1C_WAKE, h1s->h1c->conn, h1s);
}
}
* it in tunnel mode.
*/
if (h1s->req.state < H1_MSG_DONE) {
- h1s->h1c->flags |= H1C_F_IN_BUSY;
- TRACE_STATE("switch h1c in busy mode", H1_EV_RX_DATA|H1_EV_H1C_BLK, h1s->h1c->conn, h1s);
+ h1s->h1c->flags |= H1C_F_WAIT_OPPOSITE;
+ TRACE_STATE("Disable read on h1c (wait_opposite)", H1_EV_RX_DATA|H1_EV_H1C_BLK, h1s->h1c->conn, h1s);
}
else if (h1s->status == 101 && h1s->req.state == H1_MSG_DONE) {
h1s->req.flags &= ~(H1_MF_XFER_LEN|H1_MF_CLEN|H1_MF_CHNK);
TRACE_STATE("switch H1 request in tunnel mode", H1_EV_TX_DATA|H1_EV_TX_HDRS, h1s->h1c->conn, h1s);
}
}
- else if (h1s->h1c->flags & H1C_F_IN_BUSY) {
- h1s->h1c->flags &= ~H1C_F_IN_BUSY;
+ else if (h1s->h1c->flags & H1C_F_WAIT_OPPOSITE) {
+ h1s->h1c->flags &= ~H1C_F_WAIT_OPPOSITE;
tasklet_wakeup(h1s->h1c->wait_event.tasklet);
- TRACE_STATE("h1c no more busy", H1_EV_RX_DATA|H1_EV_H1C_BLK|H1_EV_H1C_WAKE, h1s->h1c->conn, h1s);
+ TRACE_STATE("Re-enable read on h1c", H1_EV_RX_DATA|H1_EV_H1C_BLK|H1_EV_H1C_WAKE, h1s->h1c->conn, h1s);
}
}
if (!(h1m->flags & H1_MF_RESP) && h1s->status == 101)
h1_set_req_tunnel_mode(h1s);
else if (h1s->req.state < H1_MSG_DONE || h1s->res.state < H1_MSG_DONE) {
- h1c->flags |= H1C_F_IN_BUSY;
- TRACE_STATE("switch h1c in busy mode", H1_EV_RX_DATA|H1_EV_H1C_BLK, h1c->conn, h1s);
+ h1c->flags |= H1C_F_WAIT_OPPOSITE;
+ TRACE_STATE("Disable read on h1c (wait_opposite)", H1_EV_RX_DATA|H1_EV_H1C_BLK, h1c->conn, h1s);
break;
}
else
if (sl->flags & HTX_SL_F_BODYLESS)
h1m->flags |= H1_MF_CLEN;
h1m->state = H1_MSG_HDR_FIRST;
+ if (h1c->flags & H1C_F_WAIT_OPPOSITE) {
+ h1c->flags &= ~H1C_F_WAIT_OPPOSITE;
+ h1c->conn->xprt->subscribe(h1c->conn, h1c->conn->xprt_ctx, SUB_RETRY_RECV, &h1c->wait_event);
+ TRACE_STATE("Re-enable read on h1c", H1_EV_TX_DATA|H1_EV_H1C_BLK|H1_EV_H1C_WAKE, h1c->conn, h1s);
+ }
break;
case H1_MSG_RPBEFORE:
h1_set_req_tunnel_mode(h1s);
TRACE_STATE("switch H1 request in tunnel mode", H1_EV_TX_DATA|H1_EV_TX_HDRS, h1c->conn, h1s);
}
- else if (h1s->h1c->flags & H1C_F_IN_BUSY) {
- h1s->h1c->flags &= ~H1C_F_IN_BUSY;
+ else if (h1s->h1c->flags & H1C_F_WAIT_OPPOSITE) {
+ h1s->h1c->flags &= ~H1C_F_WAIT_OPPOSITE;
h1c->conn->xprt->subscribe(h1c->conn, h1c->conn->xprt_ctx, SUB_RETRY_RECV, &h1c->wait_event);
- TRACE_STATE("h1c no more busy", H1_EV_TX_DATA|H1_EV_H1C_BLK|H1_EV_H1C_WAKE, h1c->conn, h1s);
+ TRACE_STATE("Re-enable read on h1c", H1_EV_TX_DATA|H1_EV_H1C_BLK|H1_EV_H1C_WAKE, h1c->conn, h1s);
}
TRACE_USER((!(h1m->flags & H1_MF_RESP) ? "H1 request fully xferred" : "H1 response fully xferred"),