]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: spoe: Set the parent stream for SPOE streams
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 17 Jul 2024 15:06:00 +0000 (17:06 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 18 Jul 2024 15:06:12 +0000 (17:06 +0200)
When a SPOE applet is created to send a message to an agent, the parent of
the associated stream is set to the one filtered. And the relationship
between the streams is removed when the applet is released or when the
processing on main stream is finished.

In the mean time, it is possible to get variables of the parent stream from
the SPOE one. It is not a huge change but this will be amazingly useful. For
instance, it is now possible to be sticky on a server using a critera of the
main streem. Here is an example using the client source address:

  listen http
    bind *:80
    tcp-request content set-var(txn.client_src) src
    filter spoe engine {SPOE-NAME} config /{SPOE-CONFIG}
    http-request send-spoe-group {SPOE-NAME} {SPOE-MSG}
    server www 127.0.0.1:8000

  backend spoe-backend
    mode spop
    timeout server 10s

    stick-table type ip size 200k expire 30m
    stick on var(ptxn.client_src)

    server srv1 ...
    server srv2 ...
    server srv3 ...
    server srv4 ...

Of course, the feature is not limited to stick-tables. Everywhere variables
are used, it is now possible to get the value set on the parent stream from
the SPOE stream.

src/flt_spoe.c

index 6b4fa1527b7fb4f07167bf1124e2fc700a9af1d2..f11d2068c081341a84a03ba1ccc6695fd5716569 100644 (file)
@@ -392,6 +392,7 @@ static int spoe_init_appctx(struct appctx *appctx)
 
        s->do_log = NULL;
        s->scb->flags |= SC_FL_RCV_ONCE;
+       s->parent = spoe_appctx->spoe_ctx->strm;
 
        appctx->st0 = SPOE_APPCTX_ST_WAITING_ACK;
        appctx_wakeup(appctx);
@@ -422,6 +423,7 @@ static void spoe_release_appctx(struct appctx *appctx)
                return;
 
        appctx->svcctx = NULL;
+       appctx_strm(appctx)->parent = NULL;
 
        /* Shutdown the server connection, if needed */
        if (appctx->st0 != SPOE_APPCTX_ST_END) {
@@ -459,8 +461,6 @@ static int spoe_handle_receiving_frame_appctx(struct appctx *appctx)
        if (b_data(&appctx->inbuf) > spoe_appctx->agent->max_frame_size) {
                spoe_ctx->state = SPOE_CTX_ST_ERROR;
                spoe_ctx->status_code = (spoe_appctx->status_code + 0x100);
-               spoe_ctx->spoe_appctx = NULL;
-               spoe_appctx->spoe_ctx = NULL;
                spoe_appctx->status_code = SPOP_ERR_TOO_BIG;
                appctx->st0 = SPOE_APPCTX_ST_EXIT;
                task_wakeup(spoe_ctx->strm->task, TASK_WOKEN_MSG);
@@ -945,6 +945,7 @@ static inline void spoe_stop_processing(struct spoe_agent *agent, struct spoe_co
                if (sa->status_code == SPOP_ERR_NONE)
                        sa->status_code = spoe_ctx_err_to_spop_err(ctx->status_code);
                sa->spoe_ctx = NULL;
+               appctx_strm(sa->owner)->parent = NULL;
                appctx_wakeup(sa->owner);
        }