diff --git a/dev/flags/flags.c b/dev/flags/flags.c index b645e35f2..eb98b6856 100644 --- a/dev/flags/flags.c +++ b/dev/flags/flags.c @@ -187,6 +187,15 @@ void show_endp_flags(unsigned int f) printf("0\n"); return; } + SHOW_FLAG(f, CS_EP_KILL_CONN); + SHOW_FLAG(f, CS_EP_WAIT_FOR_HS); + SHOW_FLAG(f, CS_EP_MAY_SPLICE); + SHOW_FLAG(f, CS_EP_WEBSOCKET); + SHOW_FLAG(f, CS_EP_NOT_FIRST); + SHOW_FLAG(f, CS_EP_SHWS); + SHOW_FLAG(f, CS_EP_SHWN); + SHOW_FLAG(f, CS_EP_SHRR); + SHOW_FLAG(f, CS_EP_SHRD); SHOW_FLAG(f, CS_EP_T_APPLET); SHOW_FLAG(f, CS_EP_T_MUX); @@ -202,21 +211,12 @@ void show_cs_flags(unsigned int f) printf("0\n"); return; } - SHOW_FLAG(f, CS_FL_WEBSOCKET); - SHOW_FLAG(f, CS_FL_NOT_FIRST); - SHOW_FLAG(f, CS_FL_KILL_CONN); - SHOW_FLAG(f, CS_FL_WAIT_FOR_HS); - SHOW_FLAG(f, CS_FL_MAY_SPLICE); SHOW_FLAG(f, CS_FL_EOI); SHOW_FLAG(f, CS_FL_EOS); SHOW_FLAG(f, CS_FL_ERR_PENDING); SHOW_FLAG(f, CS_FL_WANT_ROOM); SHOW_FLAG(f, CS_FL_RCV_MORE); SHOW_FLAG(f, CS_FL_ERROR); - SHOW_FLAG(f, CS_FL_SHWS); - SHOW_FLAG(f, CS_FL_SHWN); - SHOW_FLAG(f, CS_FL_SHRR); - SHOW_FLAG(f, CS_FL_SHRD); if (f) { printf("EXTRA(0x%08x)", f); diff --git a/include/haproxy/conn_stream-t.h b/include/haproxy/conn_stream-t.h index 56a4ab299..e76a8c339 100644 --- a/include/haproxy/conn_stream-t.h +++ b/include/haproxy/conn_stream-t.h @@ -34,19 +34,36 @@ struct stream_interface; /* Endpoint types */ CS_EP_T_MUX = 0x00000001, /* The endpoint is a mux (the target may be NULL before the mux init) */ CS_EP_T_APPLET = 0x00000002, /* The endpoint is an applet */ + + /* unused: 0x00000004 .. 0x00000080 */ + + CS_EP_SHRD = 0x00000100, /* read shut, draining extra data */ + CS_EP_SHRR = 0x00000200, /* read shut, resetting extra data */ + CS_EP_SHR = CS_EP_SHRD | CS_EP_SHRR, /* read shut status */ + + CS_EP_SHWN = 0x00000400, /* write shut, verbose mode */ + CS_EP_SHWS = 0x00000800, /* write shut, silent mode */ + CS_EP_SHW = CS_EP_SHWN | CS_EP_SHWS, /* write shut status */ + + /* following flags are supposed to be set by the endpoint and read by + * the app layer : + */ + CS_EP_NOT_FIRST = 0x00001000, /* This conn-stream is not the first one for the endpoint */ + CS_EP_WEBSOCKET = 0x00002000, /* The endpoint uses the websocket proto */ + CS_EP_MAY_SPLICE = 0x00004000, /* The endpoint may use the kernel splicing to forward data to the other side (implies CS_EP_CAN_SPLICE) */ + + /* unused: 0x00008000 */ + + /* following flags are supposed to be set by the app layer and read by + * the endpoint : + */ + CS_EP_WAIT_FOR_HS = 0x00010000, /* This stream is waiting for handhskae */ + CS_EP_KILL_CONN = 0x00020000, /* must kill the connection when the CS closes */ }; /* conn_stream flags */ enum { CS_FL_NONE = 0x00000000, /* Just for initialization purposes */ - CS_FL_SHRD = 0x00000010, /* read shut, draining extra data */ - CS_FL_SHRR = 0x00000020, /* read shut, resetting extra data */ - CS_FL_SHR = CS_FL_SHRD | CS_FL_SHRR, /* read shut status */ - - CS_FL_SHWN = 0x00000040, /* write shut, verbose mode */ - CS_FL_SHWS = 0x00000080, /* write shut, silent mode */ - CS_FL_SHW = CS_FL_SHWN | CS_FL_SHWS, /* write shut status */ - CS_FL_ERROR = 0x00000100, /* a fatal error was reported */ CS_FL_RCV_MORE = 0x00000200, /* We may have more bytes to transfer */ @@ -55,17 +72,6 @@ enum { CS_FL_EOS = 0x00001000, /* End of stream delivered to data layer */ /* unused: 0x00002000 */ CS_FL_EOI = 0x00004000, /* end-of-input reached */ - CS_FL_MAY_SPLICE = 0x00008000, /* caller may use rcv_pipe() only if this flag is set */ - CS_FL_WAIT_FOR_HS = 0x00010000, /* This stream is waiting for handhskae */ - CS_FL_KILL_CONN = 0x00020000, /* must kill the connection when the CS closes */ - - /* following flags are supposed to be set by the mux and read/unset by - * the stream-interface : - */ - CS_FL_NOT_FIRST = 0x00100000, /* this stream is not the first one */ - - /* flags set by the mux relayed to the stream */ - CS_FL_WEBSOCKET = 0x00200000, /* websocket stream */ }; /* cs_shutr() modes */ diff --git a/include/haproxy/conn_stream.h b/include/haproxy/conn_stream.h index 7a6866809..cb7c4cbea 100644 --- a/include/haproxy/conn_stream.h +++ b/include/haproxy/conn_stream.h @@ -162,14 +162,14 @@ static inline void cs_shutr(struct conn_stream *cs, enum cs_shr_mode mode) { const struct mux_ops *mux; - if (!cs_conn(cs) || cs->flags & CS_FL_SHR) + if (!cs_conn(cs) || cs->endp->flags & CS_EP_SHR) return; /* clean data-layer shutdown */ mux = cs_conn_mux(cs); if (mux && mux->shutr) mux->shutr(cs, mode); - cs->flags |= (mode == CS_SHR_DRAIN) ? CS_FL_SHRD : CS_FL_SHRR; + cs->endp->flags |= (mode == CS_SHR_DRAIN) ? CS_EP_SHRD : CS_EP_SHRR; } /* shut write */ @@ -177,14 +177,14 @@ static inline void cs_shutw(struct conn_stream *cs, enum cs_shw_mode mode) { const struct mux_ops *mux; - if (!cs_conn(cs) || cs->flags & CS_FL_SHW) + if (!cs_conn(cs) || cs->endp->flags & CS_EP_SHW) return; /* clean data-layer shutdown */ mux = cs_conn_mux(cs); if (mux && mux->shutw) mux->shutw(cs, mode); - cs->flags |= (mode == CS_SHW_NORMAL) ? CS_FL_SHWN : CS_FL_SHWS; + cs->endp->flags |= (mode == CS_SHW_NORMAL) ? CS_EP_SHWN : CS_EP_SHWS; } /* completely close a conn_stream (but do not detach it) */ diff --git a/src/backend.c b/src/backend.c index 3e1665395..2f33f37c2 100644 --- a/src/backend.c +++ b/src/backend.c @@ -1749,7 +1749,7 @@ skip_reuse: * the handshake. */ if (!(srv_conn->flags & (CO_FL_WAIT_XPRT | CO_FL_EARLY_SSL_HS))) - s->csb->flags &= ~CS_FL_WAIT_FOR_HS; + s->csb->endp->flags &= ~CS_EP_WAIT_FOR_HS; if (!si_state_in(cs_si(s->csb)->state, SI_SB_EST|SI_SB_DIS|SI_SB_CLO) && (srv_conn->flags & CO_FL_WAIT_XPRT) == 0) { diff --git a/src/h3.c b/src/h3.c index 59c1ae193..ec219a5c0 100644 --- a/src/h3.c +++ b/src/h3.c @@ -176,7 +176,7 @@ static int h3_headers_to_htx(struct qcs *qcs, struct buffer *buf, uint64_t len, cs = qc_attach_cs(qcs, &htx_buf); if (!cs) return 1; - cs->flags |= CS_FL_NOT_FIRST; + cs->endp->flags |= CS_EP_NOT_FIRST; /* buffer is transferred to conn_stream and set to NULL * except on stream creation error. diff --git a/src/http_ana.c b/src/http_ana.c index 84ddbf36b..8c477708f 100644 --- a/src/http_ana.c +++ b/src/http_ana.c @@ -5131,7 +5131,7 @@ struct http_txn *http_create_txn(struct stream *s) return NULL; s->txn = txn; - txn->flags = ((cs && cs->flags & CS_FL_NOT_FIRST) ? TX_NOT_FIRST : 0); + txn->flags = ((cs && cs->endp->flags & CS_EP_NOT_FIRST) ? TX_NOT_FIRST : 0); txn->status = -1; txn->http_reply = NULL; write_u32(txn->cache_hash, 0); diff --git a/src/mux_fcgi.c b/src/mux_fcgi.c index aadaf96b5..ea956b334 100644 --- a/src/mux_fcgi.c +++ b/src/mux_fcgi.c @@ -3117,7 +3117,7 @@ static int fcgi_process(struct fcgi_conn *fconn) while (node) { fstrm = container_of(node, struct fcgi_strm, by_id); - if (fstrm->cs && fstrm->cs->flags & CS_FL_WAIT_FOR_HS) + if (fstrm->cs && fstrm->cs->endp->flags & CS_EP_WAIT_FOR_HS) fcgi_strm_notify_recv(fstrm); node = eb32_next(node); } @@ -3854,7 +3854,7 @@ static void fcgi_shutr(struct conn_stream *cs, enum cs_shr_mode mode) struct fcgi_strm *fstrm = __cs_mux(cs); TRACE_POINT(FCGI_EV_STRM_SHUT, fstrm->fconn->conn, fstrm); - if (cs->flags & CS_FL_KILL_CONN) + if (cs->endp->flags & CS_EP_KILL_CONN) fstrm->flags |= FCGI_SF_KILL_CONN; if (!mode) @@ -3869,7 +3869,7 @@ static void fcgi_shutw(struct conn_stream *cs, enum cs_shw_mode mode) struct fcgi_strm *fstrm = __cs_mux(cs); TRACE_POINT(FCGI_EV_STRM_SHUT, fstrm->fconn->conn, fstrm); - if (cs->flags & CS_FL_KILL_CONN) + if (cs->endp->flags & CS_EP_KILL_CONN) fstrm->flags |= FCGI_SF_KILL_CONN; fcgi_do_shutw(fstrm); diff --git a/src/mux_h1.c b/src/mux_h1.c index afc09dfad..82470bc2e 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -728,10 +728,10 @@ static struct conn_stream *h1s_new_cs(struct h1s *h1s, struct buffer *input) h1s->cs = cs; if (h1s->flags & H1S_F_NOT_FIRST) - cs->flags |= CS_FL_NOT_FIRST; + cs->endp->flags |= CS_EP_NOT_FIRST; if (h1s->req.flags & H1_MF_UPG_WEBSOCKET) - cs->flags |= CS_FL_WEBSOCKET; + cs->endp->flags |= CS_EP_WEBSOCKET; if (!stream_new(h1c->conn->owner, cs, input)) { TRACE_DEVEL("leaving on stream creation failure", H1_EV_STRM_NEW|H1_EV_STRM_END|H1_EV_STRM_ERR, h1c->conn, h1s); @@ -1880,11 +1880,11 @@ static size_t h1_process_demux(struct h1c *h1c, struct buffer *buf, size_t count /* Here h1s->cs is always defined */ if (!(h1m->flags & H1_MF_CHNK) && (h1m->state == H1_MSG_DATA || (h1m->state == H1_MSG_TUNNEL))) { TRACE_STATE("notify the mux can use splicing", H1_EV_RX_DATA|H1_EV_RX_BODY, h1c->conn, h1s); - h1s->cs->flags |= CS_FL_MAY_SPLICE; + h1s->cs->endp->flags |= CS_EP_MAY_SPLICE; } else { TRACE_STATE("notify the mux can't use splicing anymore", H1_EV_RX_DATA|H1_EV_RX_BODY, h1c->conn, h1s); - h1s->cs->flags &= ~CS_FL_MAY_SPLICE; + h1s->cs->endp->flags &= ~CS_EP_MAY_SPLICE; } /* Set EOI on conn-stream in DONE state iff: @@ -3454,9 +3454,9 @@ static void h1_shutr(struct conn_stream *cs, enum cs_shr_mode mode) TRACE_ENTER(H1_EV_STRM_SHUT, h1c->conn, h1s, 0, (size_t[]){mode}); - if (cs->flags & CS_FL_SHR) + if (cs->endp->flags & CS_EP_SHR) goto end; - if (cs->flags & CS_FL_KILL_CONN) { + if (cs->endp->flags & CS_EP_KILL_CONN) { TRACE_STATE("stream wants to kill the connection", H1_EV_STRM_SHUT, h1c->conn, h1s); goto do_shutr; } @@ -3477,7 +3477,7 @@ static void h1_shutr(struct conn_stream *cs, enum cs_shr_mode mode) do_shutr: /* NOTE: Be sure to handle abort (cf. h2_shutr) */ - if (cs->flags & CS_FL_SHR) + if (cs->endp->flags & CS_EP_SHR) goto end; if (conn_xprt_ready(h1c->conn) && h1c->conn->xprt->shutr) @@ -3497,9 +3497,9 @@ static void h1_shutw(struct conn_stream *cs, enum cs_shw_mode mode) TRACE_ENTER(H1_EV_STRM_SHUT, h1c->conn, h1s, 0, (size_t[]){mode}); - if (cs->flags & CS_FL_SHW) + if (cs->endp->flags & CS_EP_SHW) goto end; - if (cs->flags & CS_FL_KILL_CONN) { + if (cs->endp->flags & CS_EP_KILL_CONN) { TRACE_STATE("stream wants to kill the connection", H1_EV_STRM_SHUT, h1c->conn, h1s); goto do_shutw; } @@ -3643,7 +3643,7 @@ static size_t h1_rcv_buf(struct conn_stream *cs, struct buffer *buf, size_t coun else TRACE_DEVEL("h1c ibuf not allocated", H1_EV_H1C_RECV|H1_EV_H1C_BLK, h1c->conn); - if ((flags & CO_RFL_BUF_FLUSH) && (cs->flags & CS_FL_MAY_SPLICE)) { + if ((flags & CO_RFL_BUF_FLUSH) && (cs->endp->flags & CS_EP_MAY_SPLICE)) { h1c->flags |= H1C_F_WANT_SPLICE; TRACE_STATE("Block xprt rcv_buf to flush stream's buffer (want_splice)", H1_EV_STRM_RECV, h1c->conn, h1s); } @@ -3783,7 +3783,7 @@ static int h1_rcv_pipe(struct conn_stream *cs, struct pipe *pipe, unsigned int c if (!(h1c->flags & H1C_F_WANT_SPLICE)) { TRACE_STATE("notify the mux can't use splicing anymore", H1_EV_STRM_RECV, h1c->conn, h1s); - cs->flags &= ~CS_FL_MAY_SPLICE; + cs->endp->flags &= ~CS_EP_MAY_SPLICE; if (!(h1c->wait_event.events & SUB_RETRY_RECV)) { TRACE_STATE("restart receiving data, subscribing", H1_EV_STRM_RECV, h1c->conn, h1s); h1c->conn->xprt->subscribe(h1c->conn, h1c->conn->xprt_ctx, SUB_RETRY_RECV, &h1c->wait_event); diff --git a/src/mux_h2.c b/src/mux_h2.c index 7e7bc66ca..82196e95f 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -1605,7 +1605,7 @@ static struct h2s *h2c_frt_stream_new(struct h2c *h2c, int id, struct buffer *in cs = cs_new(); if (!cs) goto out_close; - cs->flags |= CS_FL_NOT_FIRST; + cs->endp->flags |= CS_EP_NOT_FIRST; cs_attach_endp_mux(cs, h2s, h2c->conn); h2s->cs = cs; h2c->nb_cs++; @@ -1614,7 +1614,7 @@ static struct h2s *h2c_frt_stream_new(struct h2c *h2c, int id, struct buffer *in * be refine. */ if (flags & H2_SF_EXT_CONNECT_RCVD) - cs->flags |= CS_FL_WEBSOCKET; + cs->endp->flags |= CS_EP_WEBSOCKET; /* The stream will record the request's accept date (which is either the * end of the connection's or the date immediately after the previous @@ -4083,7 +4083,7 @@ static int h2_process(struct h2c *h2c) while (node) { h2s = container_of(node, struct h2s, by_id); - if (h2s->cs && h2s->cs->flags & CS_FL_WAIT_FOR_HS) + if (h2s->cs && h2s->cs->endp->flags & CS_EP_WAIT_FOR_HS) h2s_notify_recv(h2s); node = eb32_next(node); } @@ -4671,7 +4671,7 @@ static void h2_shutr(struct conn_stream *cs, enum cs_shr_mode mode) struct h2s *h2s = __cs_mux(cs); TRACE_ENTER(H2_EV_STRM_SHUT, h2s->h2c->conn, h2s); - if (cs->flags & CS_FL_KILL_CONN) + if (cs->endp->flags & CS_EP_KILL_CONN) h2s->flags |= H2_SF_KILL_CONN; if (mode) @@ -4686,7 +4686,7 @@ static void h2_shutw(struct conn_stream *cs, enum cs_shw_mode mode) struct h2s *h2s = __cs_mux(cs); TRACE_ENTER(H2_EV_STRM_SHUT, h2s->h2c->conn, h2s); - if (cs->flags & CS_FL_KILL_CONN) + if (cs->endp->flags & CS_EP_KILL_CONN) h2s->flags |= H2_SF_KILL_CONN; h2_do_shutw(h2s); @@ -5325,7 +5325,7 @@ static size_t h2s_frt_make_resp_headers(struct h2s *h2s, struct htx *htx) break; } - if (!h2s->cs || h2s->cs->flags & CS_FL_SHW) { + if (!h2s->cs || h2s->cs->endp->flags & CS_EP_SHW) { /* Response already closed: add END_STREAM */ es_now = 1; } @@ -5745,7 +5745,7 @@ static size_t h2s_bck_make_req_headers(struct h2s *h2s, struct htx *htx) break; } - if (!h2s->cs || h2s->cs->flags & CS_FL_SHW) { + if (!h2s->cs || h2s->cs->endp->flags & CS_EP_SHW) { /* Request already closed: add END_STREAM */ es_now = 1; } diff --git a/src/mux_pt.c b/src/mux_pt.c index 1609a74db..198c41a32 100644 --- a/src/mux_pt.c +++ b/src/mux_pt.c @@ -308,7 +308,7 @@ static int mux_pt_init(struct connection *conn, struct proxy *prx, struct sessio ctx->cs = cs; cs->flags |= CS_FL_RCV_MORE; if (global.tune.options & GTUNE_USE_SPLICE) - cs->flags |= CS_FL_MAY_SPLICE; + cs->endp->flags |= CS_EP_MAY_SPLICE; TRACE_LEAVE(PT_EV_CONN_NEW, conn, cs); return 0; @@ -449,7 +449,7 @@ static void mux_pt_shutr(struct conn_stream *cs, enum cs_shr_mode mode) TRACE_ENTER(PT_EV_STRM_SHUT, conn, cs); - if (cs->flags & CS_FL_SHR) + if (cs->endp->flags & CS_EP_SHR) return; cs->flags &= ~(CS_FL_RCV_MORE | CS_FL_WANT_ROOM); if (conn_xprt_ready(conn) && conn->xprt->shutr) @@ -457,7 +457,7 @@ static void mux_pt_shutr(struct conn_stream *cs, enum cs_shr_mode mode) (mode == CS_SHR_DRAIN)); else if (mode == CS_SHR_DRAIN) conn_ctrl_drain(conn); - if (cs->flags & CS_FL_SHW) + if (cs->endp->flags & CS_EP_SHW) conn_full_close(conn); TRACE_LEAVE(PT_EV_STRM_SHUT, conn, cs); @@ -469,12 +469,12 @@ static void mux_pt_shutw(struct conn_stream *cs, enum cs_shw_mode mode) TRACE_ENTER(PT_EV_STRM_SHUT, conn, cs); - if (cs->flags & CS_FL_SHW) + if (cs->endp->flags & CS_EP_SHW) return; if (conn_xprt_ready(conn) && conn->xprt->shutw) conn->xprt->shutw(conn, conn->xprt_ctx, (mode == CS_SHW_NORMAL)); - if (!(cs->flags & CS_FL_SHR)) + if (!(cs->endp->flags & CS_EP_SHR)) conn_sock_shutw(conn, (mode == CS_SHW_NORMAL)); else conn_full_close(conn); diff --git a/src/ssl_sock.c b/src/ssl_sock.c index c5c3df7f2..a6314f53b 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -7739,7 +7739,7 @@ enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px, if (conn && cs) { if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) { - cs->flags |= CS_FL_WAIT_FOR_HS; + cs->endp->flags |= CS_EP_WAIT_FOR_HS; s->req.flags |= CF_READ_NULL; return ACT_RET_YIELD; } diff --git a/src/stream.c b/src/stream.c index 95e6fc5cc..868a3f0cf 100644 --- a/src/stream.c +++ b/src/stream.c @@ -463,7 +463,7 @@ struct stream *stream_new(struct session *sess, struct conn_stream *cs, struct b if (likely(sess->fe->options2 & PR_O2_INDEPSTR)) cs_si(s->csb)->flags |= SI_FL_INDEP_STR; - if (cs->flags & CS_FL_WEBSOCKET) + if (cs->endp->flags & CS_EP_WEBSOCKET) s->flags |= SF_WEBSOCKET; if (cs_conn(cs)) { const struct mux_ops *mux = cs_conn_mux(cs); diff --git a/src/stream_interface.c b/src/stream_interface.c index 9396c90fc..4e2f7bb2f 100644 --- a/src/stream_interface.c +++ b/src/stream_interface.c @@ -645,8 +645,8 @@ static int si_cs_process(struct conn_stream *cs) * the handshake. */ if (!(conn->flags & (CO_FL_WAIT_XPRT | CO_FL_EARLY_SSL_HS)) && - (cs->flags & CS_FL_WAIT_FOR_HS)) { - cs->flags &= ~CS_FL_WAIT_FOR_HS; + (cs->endp->flags & CS_EP_WAIT_FOR_HS)) { + cs->endp->flags &= ~CS_EP_WAIT_FOR_HS; task_wakeup(si_task(si), TASK_WOKEN_MSG); } @@ -1072,7 +1072,7 @@ static void stream_int_shutr_conn(struct stream_interface *si) return; if (si->flags & SI_FL_KILL_CONN) - cs->flags |= CS_FL_KILL_CONN; + cs->endp->flags |= CS_EP_KILL_CONN; if (si_oc(si)->flags & CF_SHUTW) { cs_close(cs); @@ -1123,7 +1123,7 @@ static void stream_int_shutw_conn(struct stream_interface *si) * no risk so we close both sides immediately. */ if (si->flags & SI_FL_KILL_CONN) - cs->flags |= CS_FL_KILL_CONN; + cs->endp->flags |= CS_EP_KILL_CONN; if (si->flags & SI_FL_ERR) { /* quick close, the socket is already shut anyway */ @@ -1155,7 +1155,7 @@ static void stream_int_shutw_conn(struct stream_interface *si) * response buffer as shutr */ if (si->flags & SI_FL_KILL_CONN) - cs->flags |= CS_FL_KILL_CONN; + cs->endp->flags |= CS_EP_KILL_CONN; cs_close(cs); /* fall through */ case SI_ST_CER: @@ -1349,7 +1349,7 @@ static int si_cs_recv(struct conn_stream *cs) /* First, let's see if we may splice data across the channel without * using a buffer. */ - if (cs->flags & CS_FL_MAY_SPLICE && + if (cs->endp->flags & CS_EP_MAY_SPLICE && (ic->pipe || ic->to_forward >= MIN_SPLICE_FORWARD) && ic->flags & CF_KERN_SPLICING) { if (c_data(ic)) { @@ -1404,7 +1404,7 @@ static int si_cs_recv(struct conn_stream *cs) ic->pipe = NULL; } - if (ic->pipe && ic->to_forward && !(flags & CO_RFL_BUF_FLUSH) && cs->flags & CS_FL_MAY_SPLICE) { + if (ic->pipe && ic->to_forward && !(flags & CO_RFL_BUF_FLUSH) && cs->endp->flags & CS_EP_MAY_SPLICE) { /* don't break splicing by reading, but still call rcv_buf() * to pass the flag. */