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.
This commit is contained in:
Christopher Faulet 2024-01-26 15:41:46 +01:00
parent 868205943c
commit ee53d8421f
6 changed files with 88 additions and 67 deletions

View File

@ -61,8 +61,8 @@ struct applet {
int (*init)(struct appctx *); /* callback to init resources, may be NULL. int (*init)(struct appctx *); /* callback to init resources, may be NULL.
expect 0 if ok, -1 if an error occurs. */ expect 0 if ok, -1 if an error occurs. */
void (*fct)(struct appctx *); /* internal I/O handler, may never be NULL */ 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 (*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 stconn *sc, struct buffer *buf, size_t count, unsigned int flags); /* Called from the upper layet to put 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 */ 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 */ void (*release)(struct appctx *); /* callback to release resources, may be NULL */
unsigned int timeout; /* execution timeout. */ unsigned int timeout; /* execution timeout. */

View File

@ -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_on_early_error(struct appctx *appctx);
void appctx_free(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_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); 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); 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) static inline struct appctx *appctx_new_here(struct applet *applet, struct sedesc *sedesc)

View File

@ -452,6 +452,45 @@ int appctx_buf_available(void *arg)
return 1; 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) size_t appctx_rcv_buf(struct stconn *sc, struct buffer *buf, size_t count, unsigned int flags)
{ {
struct appctx *appctx = __sc_appctx(sc); 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; goto end;
} }
if (IS_HTX_SC(sc)) { ret = appctx->applet->rcv_buf(appctx, buf, count, flags);
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:
if (ret) if (ret)
applet_fl_clr(appctx, APPCTX_FL_OUTBLK_FULL); 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; 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) size_t appctx_snd_buf(struct stconn *sc, struct buffer *buf, size_t count, unsigned int flags)
{ {
struct appctx *appctx = __sc_appctx(sc); 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) if (!count)
goto end; goto end;
if (IS_HTX_SC(sc)) { ret = appctx->applet->snd_buf(appctx, buf, count, flags);
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:
if (ret < count) { if (ret < count) {
applet_fl_set(appctx, APPCTX_FL_INBLK_FULL); applet_fl_set(appctx, APPCTX_FL_INBLK_FULL);
appctx_wakeup(appctx); appctx_wakeup(appctx);

View File

@ -3159,8 +3159,8 @@ struct applet http_cache_applet = {
.obj_type = OBJ_TYPE_APPLET, .obj_type = OBJ_TYPE_APPLET,
.name = "<CACHE>", /* used for logging */ .name = "<CACHE>", /* used for logging */
.fct = http_cache_io_handler, .fct = http_cache_io_handler,
.rcv_buf = appctx_rcv_buf, .rcv_buf = appctx_htx_rcv_buf,
.snd_buf = appctx_snd_buf, .snd_buf = appctx_htx_snd_buf,
.fastfwd = http_cache_fastfwd, .fastfwd = http_cache_fastfwd,
.release = http_cache_applet_release, .release = http_cache_applet_release,
}; };

View File

@ -5539,8 +5539,8 @@ struct applet http_stats_applet = {
.obj_type = OBJ_TYPE_APPLET, .obj_type = OBJ_TYPE_APPLET,
.name = "<STATS>", /* used for logging */ .name = "<STATS>", /* used for logging */
.fct = http_stats_io_handler, .fct = http_stats_io_handler,
.rcv_buf = appctx_rcv_buf, .rcv_buf = appctx_htx_rcv_buf,
.snd_buf = appctx_snd_buf, .snd_buf = appctx_htx_snd_buf,
.fastfwd = http_stats_fastfwd, .fastfwd = http_stats_fastfwd,
.release = NULL, .release = NULL,
}; };

View File

@ -1968,7 +1968,7 @@ int sc_applet_recv(struct stconn *sc)
* SE_FL_RCV_MORE on the SC if more space is needed. * SE_FL_RCV_MORE on the SC if more space is needed.
*/ */
max = channel_recv_max(ic); 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)) { if (sc_ep_test(sc, SE_FL_WANT_ROOM)) {
/* SE_FL_WANT_ROOM must not be reported if the channel's /* SE_FL_WANT_ROOM must not be reported if the channel's
* buffer is empty. * buffer is empty.
@ -2120,7 +2120,6 @@ int sc_applet_sync_recv(struct stconn *sc)
*/ */
int sc_applet_send(struct stconn *sc) int sc_applet_send(struct stconn *sc)
{ {
struct appctx *appctx = __sc_appctx(sc);
struct stconn *sco = sc_opposite(sc); struct stconn *sco = sc_opposite(sc);
struct channel *oc = sc_oc(sc); struct channel *oc = sc_oc(sc);
size_t ret; size_t ret;
@ -2146,7 +2145,7 @@ int sc_applet_send(struct stconn *sc)
BUG_ON(sc_ep_have_ff_data(sc)); BUG_ON(sc_ep_have_ff_data(sc));
if (co_data(oc)) { 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) { if (ret > 0) {
did_send = 1; did_send = 1;
c_rew(oc, ret); c_rew(oc, ret);