From: Willy Tarreau Date: Fri, 2 Mar 2018 12:55:01 +0000 (+0100) Subject: MEDIUM: conn_stream: add cs_recv() as a default rcv_buf() function X-Git-Tag: v1.9-dev1~51 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=11c9aa424e2e4fd3e14f96559a68527550561cc1;p=thirdparty%2Fhaproxy.git MEDIUM: conn_stream: add cs_recv() as a default rcv_buf() function This function is generic and is able to automatically transfer data from a conn_stream's rx buffer to the destination buffer. It does this automatically if the mux doesn't define another rcv_buf() function. --- diff --git a/include/proto/connection.h b/include/proto/connection.h index ce7ef38119..dba7fca991 100644 --- a/include/proto/connection.h +++ b/include/proto/connection.h @@ -44,6 +44,9 @@ int init_connection(); */ void conn_fd_handler(int fd); +/* conn_stream functions */ +size_t __cs_recv(struct conn_stream *cs, struct buffer *buf, size_t count, int flags); + /* receive a PROXY protocol header over a connection */ int conn_recv_proxy(struct connection *conn, int flag); int make_proxy_line(char *buf, int buf_len, struct server *srv, struct connection *remote); @@ -300,6 +303,17 @@ static inline void cs_update_mux_polling(struct conn_stream *cs) conn->mux->update_poll(cs); } +/* conn_stream receive function. Uses mux->rcv_buf() if defined, otherwise + * falls back to __cs_recv(). + */ +static inline size_t cs_recv(struct conn_stream *cs, struct buffer *buf, size_t count, int flags) +{ + if (cs->conn->mux->rcv_buf) + return cs->conn->mux->rcv_buf(cs, buf, count, flags); + else + return __cs_recv(cs, buf, count, flags); +} + /***** Event manipulation primitives for use by DATA I/O callbacks *****/ /* The __conn_* versions do not propagate to lower layers and are only meant * to be used by handlers called by the connection handler. The other ones diff --git a/src/checks.c b/src/checks.c index af6ddd453a..b965ee6937 100644 --- a/src/checks.c +++ b/src/checks.c @@ -850,7 +850,7 @@ static void event_srv_chk_r(struct conn_stream *cs) done = 0; - conn->mux->rcv_buf(cs, &check->bi, b_size(&check->bi), 0); + cs_recv(cs, &check->bi, b_size(&check->bi), 0); if (conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH) || cs->flags & CS_FL_ERROR) { done = 1; if ((conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR) && !b_data(&check->bi)) { @@ -2918,7 +2918,7 @@ static int tcpcheck_main(struct check *check) goto out_end_tcpcheck; __cs_want_recv(cs); - if (conn->mux->rcv_buf(cs, &check->bi, b_size(&check->bi), 0) <= 0) { + if (cs_recv(cs, &check->bi, b_size(&check->bi), 0) <= 0) { if (conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH) || cs->flags & CS_FL_ERROR) { done = 1; if ((conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR) && !b_data(&check->bi)) { diff --git a/src/connection.c b/src/connection.c index e02129093a..4b1e066edb 100644 --- a/src/connection.c +++ b/src/connection.c @@ -383,6 +383,33 @@ int conn_sock_drain(struct connection *conn) return 1; } +/* + * default conn_stream recv() : this one is used when cs->rcv_buf == NULL. + * It reads up to bytes from cs->rxbuf, puts them into and + * returns the count. It possibly sets/clears CS_FL_RCV_MORE depending on the + * buffer's state, and may set CS_FL_EOS. The number of bytes transferred is + * returned. is not touched if is null, but cs flags will be + * updated to indicate any RCV_MORE or EOS. + */ +size_t __cs_recv(struct conn_stream *cs, struct buffer *buf, size_t count, int flags) +{ + size_t ret = 0; + + /* transfer possibly pending data to the upper layer */ + ret = b_xfer(buf, &cs->rxbuf, count); + + if (b_data(&cs->rxbuf)) + cs->flags |= CS_FL_RCV_MORE; + else { + cs->flags &= ~CS_FL_RCV_MORE; + if (cs->flags & CS_FL_REOS) + cs->flags |= CS_FL_EOS; + cs_drop_rxbuf(cs); + } + + return ret; +} + /* * Get data length from tlv */ diff --git a/src/stream_interface.c b/src/stream_interface.c index f1b52c176b..a0c73bca2f 100644 --- a/src/stream_interface.c +++ b/src/stream_interface.c @@ -1236,7 +1236,7 @@ static void si_cs_recv_cb(struct conn_stream *cs) break; } - ret = conn->mux->rcv_buf(cs, &ic->buf, max, co_data(ic) ? CO_RFL_BUF_WET : 0); + ret = cs_recv(cs, &ic->buf, max, co_data(ic) ? CO_RFL_BUF_WET : 0); if (cs->flags & CS_FL_RCV_MORE) si->flags |= SI_FL_WAIT_ROOM;