From ee53d8421f03bdbf7be44843fdaee693dfd0d3ec Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Fri, 26 Jan 2024 15:41:46 +0100 Subject: [PATCH] MEDIUM: applet: Simplify a bit API to exchange data with applets Default .rcv_buf and .snd_buf functions that applets can use are now specialized to manipulate raw buffers or HTX buffers. Thus a TCP applet should use appctx_raw_rcv_buf() and appctx_raw_snd_buf() while HTTP applet should use appctx_htx_rcv_buf() and appctx_htx_snd_buf(). Note that the appctx is now directly passed to these functions instead of the SC. --- include/haproxy/applet-t.h | 4 +- include/haproxy/applet.h | 6 ++ src/applet.c | 132 +++++++++++++++++++++---------------- src/cache.c | 4 +- src/stats.c | 4 +- src/stconn.c | 5 +- 6 files changed, 88 insertions(+), 67 deletions(-) diff --git a/include/haproxy/applet-t.h b/include/haproxy/applet-t.h index 86e08c3195..9ee8f5d9cf 100644 --- a/include/haproxy/applet-t.h +++ b/include/haproxy/applet-t.h @@ -61,8 +61,8 @@ struct applet { int (*init)(struct appctx *); /* callback to init resources, may be NULL. expect 0 if ok, -1 if an error occurs. */ void (*fct)(struct appctx *); /* internal I/O handler, may never be NULL */ - size_t (*rcv_buf)(struct stconn *sc, struct buffer *buf, size_t count, unsigned int flags); /* called from the upper layer to get data */ - size_t (*snd_buf)(struct stconn *sc, struct buffer *buf, size_t count, unsigned int flags); /* Called from the upper layet to put data */ + size_t (*rcv_buf)(struct appctx *appctx, struct buffer *buf, size_t count, unsigned int flags); /* called from the upper layer to get data */ + size_t (*snd_buf)(struct appctx *appctx, struct buffer *buf, size_t count, unsigned int flags); /* Called from the upper layet to put data */ size_t (*fastfwd)(struct appctx *appctx, struct buffer *buf, size_t count, unsigned int flags); /* Callback to fast-forward data */ void (*release)(struct appctx *); /* callback to release resources, may be NULL */ unsigned int timeout; /* execution timeout. */ diff --git a/include/haproxy/applet.h b/include/haproxy/applet.h index 2f84a11684..17222c5244 100644 --- a/include/haproxy/applet.h +++ b/include/haproxy/applet.h @@ -49,8 +49,14 @@ int appctx_finalize_startup(struct appctx *appctx, struct proxy *px, struct buff void appctx_free_on_early_error(struct appctx *appctx); void appctx_free(struct appctx *appctx); +size_t appctx_htx_rcv_buf(struct appctx *appctx, struct buffer *buf, size_t count, unsigned int flags); +size_t appctx_raw_rcv_buf(struct appctx *appctx, struct buffer *buf, size_t count, unsigned int flags); size_t appctx_rcv_buf(struct stconn *sc, struct buffer *buf, size_t count, unsigned int flags); + +size_t appctx_htx_snd_buf(struct appctx *appctx, struct buffer *buf, size_t count, unsigned int flags); +size_t appctx_raw_snd_buf(struct appctx *appctx, struct buffer *buf, size_t count, unsigned int flags); size_t appctx_snd_buf(struct stconn *sc, struct buffer *buf, size_t count, unsigned int flags); + int appctx_fastfwd(struct stconn *sc, unsigned int count, unsigned int flags); static inline struct appctx *appctx_new_here(struct applet *applet, struct sedesc *sedesc) diff --git a/src/applet.c b/src/applet.c index 7b302f9768..91232cceb5 100644 --- a/src/applet.c +++ b/src/applet.c @@ -452,6 +452,45 @@ int appctx_buf_available(void *arg) return 1; } +size_t appctx_htx_rcv_buf(struct appctx *appctx, struct buffer *buf, size_t count, unsigned int flags) +{ + struct htx *appctx_htx = htx_from_buf(&appctx->outbuf); + struct htx *buf_htx = NULL; + size_t ret = 0; + + if (htx_is_empty(appctx_htx)) { + htx_to_buf(appctx_htx, &appctx->outbuf); + goto out; + } + + ret = appctx_htx->data; + buf_htx = htx_from_buf(buf); + if (htx_is_empty(buf_htx) && htx_used_space(appctx_htx) <= count) { + htx_to_buf(buf_htx, buf); + htx_to_buf(appctx_htx, &appctx->outbuf); + b_xfer(buf, &appctx->outbuf, b_data(&appctx->outbuf)); + goto out; + } + + htx_xfer_blks(buf_htx, appctx_htx, count, HTX_BLK_UNUSED); + buf_htx->flags |= (appctx_htx->flags & (HTX_FL_PARSING_ERROR|HTX_FL_PROCESSING_ERROR)); + if (htx_is_empty(appctx_htx)) { + buf_htx->flags |= (appctx_htx->flags & HTX_FL_EOM); + } + buf_htx->extra = (appctx_htx->extra ? (appctx_htx->data + appctx_htx->extra) : 0); + htx_to_buf(buf_htx, buf); + htx_to_buf(appctx_htx, &appctx->inbuf); + ret -= appctx_htx->data; + + out: + return ret; +} + +size_t appctx_raw_rcv_buf(struct appctx *appctx, struct buffer *buf, size_t count, unsigned int flags) +{ + return b_xfer(buf, &appctx->outbuf, MAX(count, b_data(&appctx->outbuf))); +} + size_t appctx_rcv_buf(struct stconn *sc, struct buffer *buf, size_t count, unsigned int flags) { struct appctx *appctx = __sc_appctx(sc); @@ -471,38 +510,7 @@ size_t appctx_rcv_buf(struct stconn *sc, struct buffer *buf, size_t count, unsig goto end; } - if (IS_HTX_SC(sc)) { - struct htx *appctx_htx = htx_from_buf(&appctx->outbuf); - struct htx *buf_htx = NULL; - - if (htx_is_empty(appctx_htx)) { - htx_to_buf(appctx_htx, &appctx->outbuf); - goto done; - } - - ret = appctx_htx->data; - buf_htx = htx_from_buf(buf); - if (htx_is_empty(buf_htx) && htx_used_space(appctx_htx) <= count) { - htx_to_buf(buf_htx, buf); - htx_to_buf(appctx_htx, &appctx->outbuf); - b_xfer(buf, &appctx->outbuf, b_data(&appctx->outbuf)); - goto done; - } - - htx_xfer_blks(buf_htx, appctx_htx, count, HTX_BLK_UNUSED); - buf_htx->flags |= (appctx_htx->flags & (HTX_FL_PARSING_ERROR|HTX_FL_PROCESSING_ERROR)); - if (htx_is_empty(appctx_htx)) { - buf_htx->flags |= (appctx_htx->flags & HTX_FL_EOM); - } - buf_htx->extra = (appctx_htx->extra ? (appctx_htx->data + appctx_htx->extra) : 0); - htx_to_buf(buf_htx, buf); - htx_to_buf(appctx_htx, &appctx->inbuf); - ret -= appctx_htx->data; - } - else - ret = b_xfer(buf, &appctx->outbuf, MAX(count, b_data(&appctx->outbuf))); - - done: + ret = appctx->applet->rcv_buf(appctx, buf, count, flags); if (ret) applet_fl_clr(appctx, APPCTX_FL_OUTBLK_FULL); @@ -531,6 +539,39 @@ size_t appctx_rcv_buf(struct stconn *sc, struct buffer *buf, size_t count, unsig return ret; } +size_t appctx_htx_snd_buf(struct appctx *appctx, struct buffer *buf, size_t count, unsigned int flags) +{ + struct htx *appctx_htx = htx_from_buf(&appctx->inbuf); + struct htx *buf_htx = htx_from_buf(buf); + size_t ret = 0; + + ret = buf_htx->data; + if (htx_is_empty(appctx_htx) && buf_htx->data == count) { + htx_to_buf(appctx_htx, &appctx->inbuf); + htx_to_buf(buf_htx, buf); + b_xfer(&appctx->inbuf, buf, b_data(buf)); + goto end; + } + + htx_xfer_blks(appctx_htx, buf_htx, count, HTX_BLK_UNUSED); + if (htx_is_empty(buf_htx)) { + appctx_htx->flags |= (buf_htx->flags & HTX_FL_EOM); + } + + appctx_htx->extra = (buf_htx->extra ? (buf_htx->data + buf_htx->extra) : 0); + htx_to_buf(appctx_htx, &appctx->outbuf); + htx_to_buf(buf_htx, buf); + ret -= buf_htx->data; + +end: + return ret; +} + +size_t appctx_raw_snd_buf(struct appctx *appctx, struct buffer *buf, size_t count, unsigned flags) +{ + return b_xfer(&appctx->inbuf, buf, MIN(b_room(&appctx->inbuf), count)); +} + size_t appctx_snd_buf(struct stconn *sc, struct buffer *buf, size_t count, unsigned int flags) { struct appctx *appctx = __sc_appctx(sc); @@ -553,32 +594,7 @@ size_t appctx_snd_buf(struct stconn *sc, struct buffer *buf, size_t count, unsig if (!count) goto end; - if (IS_HTX_SC(sc)) { - struct htx *appctx_htx = htx_from_buf(&appctx->inbuf); - struct htx *buf_htx = htx_from_buf(buf); - - ret = buf_htx->data; - if (htx_is_empty(appctx_htx) && buf_htx->data == count) { - htx_to_buf(appctx_htx, &appctx->inbuf); - htx_to_buf(buf_htx, buf); - b_xfer(&appctx->inbuf, buf, b_data(buf)); - goto done; - } - - htx_xfer_blks(appctx_htx, buf_htx, count, HTX_BLK_UNUSED); - if (htx_is_empty(buf_htx)) { - appctx_htx->flags |= (buf_htx->flags & HTX_FL_EOM); - } - - appctx_htx->extra = (buf_htx->extra ? (buf_htx->data + buf_htx->extra) : 0); - htx_to_buf(appctx_htx, &appctx->outbuf); - htx_to_buf(buf_htx, buf); - ret -= buf_htx->data; - } - else - ret = b_xfer(&appctx->inbuf, buf, MIN(b_room(&appctx->inbuf), count)); - - done: + ret = appctx->applet->snd_buf(appctx, buf, count, flags); if (ret < count) { applet_fl_set(appctx, APPCTX_FL_INBLK_FULL); appctx_wakeup(appctx); diff --git a/src/cache.c b/src/cache.c index 43df8a6b57..385fcefadb 100644 --- a/src/cache.c +++ b/src/cache.c @@ -3159,8 +3159,8 @@ struct applet http_cache_applet = { .obj_type = OBJ_TYPE_APPLET, .name = "", /* used for logging */ .fct = http_cache_io_handler, - .rcv_buf = appctx_rcv_buf, - .snd_buf = appctx_snd_buf, + .rcv_buf = appctx_htx_rcv_buf, + .snd_buf = appctx_htx_snd_buf, .fastfwd = http_cache_fastfwd, .release = http_cache_applet_release, }; diff --git a/src/stats.c b/src/stats.c index 65a54f6b2e..d2e56ec698 100644 --- a/src/stats.c +++ b/src/stats.c @@ -5539,8 +5539,8 @@ struct applet http_stats_applet = { .obj_type = OBJ_TYPE_APPLET, .name = "", /* used for logging */ .fct = http_stats_io_handler, - .rcv_buf = appctx_rcv_buf, - .snd_buf = appctx_snd_buf, + .rcv_buf = appctx_htx_rcv_buf, + .snd_buf = appctx_htx_snd_buf, .fastfwd = http_stats_fastfwd, .release = NULL, }; diff --git a/src/stconn.c b/src/stconn.c index 3817e7b4d2..70f27db816 100644 --- a/src/stconn.c +++ b/src/stconn.c @@ -1968,7 +1968,7 @@ int sc_applet_recv(struct stconn *sc) * SE_FL_RCV_MORE on the SC if more space is needed. */ max = channel_recv_max(ic); - ret = appctx->applet->rcv_buf(sc, &ic->buf, max, flags); + ret = appctx_rcv_buf(sc, &ic->buf, max, flags); if (sc_ep_test(sc, SE_FL_WANT_ROOM)) { /* SE_FL_WANT_ROOM must not be reported if the channel's * buffer is empty. @@ -2120,7 +2120,6 @@ int sc_applet_sync_recv(struct stconn *sc) */ int sc_applet_send(struct stconn *sc) { - struct appctx *appctx = __sc_appctx(sc); struct stconn *sco = sc_opposite(sc); struct channel *oc = sc_oc(sc); size_t ret; @@ -2146,7 +2145,7 @@ int sc_applet_send(struct stconn *sc) BUG_ON(sc_ep_have_ff_data(sc)); if (co_data(oc)) { - ret = appctx->applet->snd_buf(sc, &oc->buf, co_data(oc), 0); + ret = appctx_snd_buf(sc, &oc->buf, co_data(oc), 0); if (ret > 0) { did_send = 1; c_rew(oc, ret); -- 2.39.5