]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: spoe: Remove SPOE details from the appctx structure
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 4 Jan 2017 13:14:19 +0000 (14:14 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 9 Mar 2017 14:32:55 +0000 (15:32 +0100)
Now, as for peers, we use an opaque pointer to store information related to the
SPOE filter in appctx structure. These information are now stored in a dedicated
structure (spoe_appctx) and allocated, using a pool, when the applet is created.

This removes the dependency between applets and the SPOE filter and avoids to
eventually inflate the appctx structure.

include/types/applet.h
src/flt_spoe.c

index 851948b4a37e2664d263d44f2919676532a58654..90484f6070ed6c70ee294f0b83d9b2e071e18a93 100644 (file)
@@ -84,13 +84,7 @@ struct appctx {
                        struct task *task;
                } hlua_apphttp;                 /* used by the Lua HTTP services */
                struct {
-                       struct task *task;
-                       void        *agent;
-                       unsigned int version;
-                       unsigned int max_frame_size;
-                       unsigned int flags;
-                       struct list  waiting_queue;
-                       struct list  list;
+                       void *ptr;              /* private pointer for SPOE filter */
                } spoe;                         /* used by SPOE filter */
                struct {
                        const char *msg;        /* pointer to a persistent message to be returned in CLI_ST_PRINT state */
index 17290d2cc4a5674edc577fa5388bccf09c11aaeb..6b8c799957e4afcbefdad423e44fbaf088f9723e 100644 (file)
@@ -49,9 +49,6 @@
 #define SPOE_PRINTF(x...)
 #endif
 
-/* Helper to get ctx inside an appctx */
-#define APPCTX_SPOE(appctx) ((appctx)->ctx.spoe)
-
 /* Minimal size for a frame */
 #define MIN_FRAME_SIZE 256
 
@@ -252,6 +249,22 @@ struct spoe_context {
        unsigned int        process_exp;  /* expiration date to process an event */
 };
 
+/* SPOE context inside a appctx */
+struct spoe_appctx {
+       struct appctx      *owner;          /* the owner */
+       struct task        *task;           /* task to handle applet timeouts */
+       struct spoe_agent  *agent;          /* agent on which the applet is attached */
+
+       unsigned int        version;        /* the negotiated version */
+       unsigned int        max_frame_size; /* the negotiated max-frame-size value */
+       unsigned int        flags;          /* SPOE_APPCTX_FL_* */
+
+       struct list         waiting_queue;  /* list of streams waiting for a ACK frame, in sync and pipelining mode */
+       struct list         list;           /* next spoe appctx for the same agent */
+};
+
+#define SPOE_APPCTX(appctx) ((struct spoe_appctx *)((appctx)->ctx.spoe.ptr))
+
 /* SPOE filter id. Used to identify SPOE filters */
 const char *spoe_filter_id = "SPOE filter";
 
@@ -274,8 +287,9 @@ struct spoe_message *curmsg = NULL;
 struct list curmsgs;
 struct list curmps;
 
-/* Pool used to allocate new SPOE contexts */
+/* Pools used to allocate SPOE structs */
 static struct pool_head *pool2_spoe_ctx = NULL;
+static struct pool_head *pool2_spoe_appctx = NULL;
 
 /* Temporary variables used to ease error processing */
 int  spoe_status_code = SPOE_FRM_ERR_NONE;
@@ -771,7 +785,7 @@ skip_spoe_action(char *frame, char *end)
 static int
 prepare_spoe_hahello_frame(struct appctx *appctx, char *frame, size_t size)
 {
-       struct spoe_agent *agent = APPCTX_SPOE(appctx).agent;
+       struct spoe_agent *agent = SPOE_APPCTX(appctx)->agent;
        int      idx = 0;
        size_t   max = (7   /* TYPE + METADATA */
                        + 1 + SLEN(SUPPORTED_VERSIONS_KEY) + 1 + 1 + SLEN(SUPPORTED_VERSIONS_VAL)
@@ -804,7 +818,7 @@ prepare_spoe_hahello_frame(struct appctx *appctx, char *frame, size_t size)
        /* "max-fram-size" K/V item */
        idx += encode_spoe_string(MAX_FRAME_SIZE_KEY, SLEN(MAX_FRAME_SIZE_KEY), frame+idx);
        frame[idx++] = SPOE_DATA_T_UINT32;
-       idx += encode_spoe_varint(APPCTX_SPOE(appctx).max_frame_size, frame+idx);
+       idx += encode_spoe_varint(SPOE_APPCTX(appctx)->max_frame_size, frame+idx);
 
        /* "capabilities" K/V item */
        idx += encode_spoe_string(CAPABILITIES_KEY, SLEN(CAPABILITIES_KEY), frame+idx);
@@ -876,7 +890,7 @@ prepare_spoe_hanotify_frame(struct appctx *appctx, struct spoe_context *ctx,
 {
        int idx = 0;
 
-       if (size < APPCTX_SPOE(appctx).max_frame_size)
+       if (size < SPOE_APPCTX(appctx)->max_frame_size)
                return -1;
 
        frame[idx++] = SPOE_FRM_T_HAPROXY_NOTIFY;
@@ -992,7 +1006,7 @@ handle_spoe_agenthello_frame(struct appctx *appctx, char *frame, size_t size)
                                return -1;
                        }
                        idx += i;
-                       if (sz < MIN_FRAME_SIZE || sz > APPCTX_SPOE(appctx).max_frame_size) {
+                       if (sz < MIN_FRAME_SIZE || sz > SPOE_APPCTX(appctx)->max_frame_size) {
                                spoe_status_code = SPOE_FRM_ERR_BAD_FRAME_SIZE;
                                return -1;
                        }
@@ -1054,9 +1068,9 @@ handle_spoe_agenthello_frame(struct appctx *appctx, char *frame, size_t size)
                return -1;
        }
 
-       APPCTX_SPOE(appctx).version        = (unsigned int)vsn;
-       APPCTX_SPOE(appctx).max_frame_size = (unsigned int)max_frame_size;
-       APPCTX_SPOE(appctx).flags         |= flags;
+       SPOE_APPCTX(appctx)->version        = (unsigned int)vsn;
+       SPOE_APPCTX(appctx)->max_frame_size = (unsigned int)max_frame_size;
+       SPOE_APPCTX(appctx)->flags         |= flags;
        return idx;
 }
 
@@ -1159,7 +1173,7 @@ handle_spoe_agentdiscon_frame(struct appctx *appctx, char *frame, size_t size)
 static int
 handle_spoe_agentack_frame(struct appctx *appctx, char *frame, size_t size)
 {
-       struct spoe_agent    *agent = APPCTX_SPOE(appctx).agent;
+       struct spoe_agent    *agent = SPOE_APPCTX(appctx)->agent;
        struct spoe_context  *ctx, *back;
        uint64_t              stream_id, frame_id;
        int                   i, idx = 0;
@@ -1185,7 +1199,7 @@ handle_spoe_agentack_frame(struct appctx *appctx, char *frame, size_t size)
                return 0;
        idx += i;
 
-       if (APPCTX_SPOE(appctx).flags & SPOE_APPCTX_FL_ASYNC) {
+       if (SPOE_APPCTX(appctx)->flags & SPOE_APPCTX_FL_ASYNC) {
                list_for_each_entry_safe(ctx, back, &agent->waiting_queue, list) {
                        if (ctx->stream_id == (unsigned int)stream_id &&
                            ctx->frame_id  == (unsigned int)frame_id)
@@ -1193,7 +1207,7 @@ handle_spoe_agentack_frame(struct appctx *appctx, char *frame, size_t size)
                }
        }
        else {
-               list_for_each_entry_safe(ctx, back, &APPCTX_SPOE(appctx).waiting_queue, list) {
+               list_for_each_entry_safe(ctx, back, &SPOE_APPCTX(appctx)->waiting_queue, list) {
                        if (ctx->stream_id == (unsigned int)stream_id &&
                            ctx->frame_id  == (unsigned int)frame_id)
                                goto found;
@@ -1226,17 +1240,21 @@ handle_spoe_agentack_frame(struct appctx *appctx, char *frame, size_t size)
 int
 prepare_spoe_healthcheck_request(char **req, int *len)
 {
-       struct appctx a;
-       char          *frame, buf[global.tune.bufsize];
-       unsigned int  framesz;
-       int           idx;
-
-       memset(&a, 0, sizeof(a));
+       struct appctx       appctx;
+       struct spoe_appctx  spoe_appctx;
+       char               *frame, buf[global.tune.bufsize];
+       unsigned int        framesz;
+       int                 idx;
+
+       memset(&appctx, 0, sizeof(appctx));
+       memset(&spoe_appctx, 0, sizeof(spoe_appctx));
        memset(buf, 0, sizeof(buf));
-       APPCTX_SPOE(&a).max_frame_size = global.tune.bufsize-4;
+
+       appctx.ctx.spoe.ptr = &spoe_appctx;
+       SPOE_APPCTX(&appctx)->max_frame_size = global.tune.bufsize-4;
 
        frame = buf+4;
-       idx = prepare_spoe_hahello_frame(&a, frame, global.tune.bufsize-4);
+       idx = prepare_spoe_hahello_frame(&appctx, frame, global.tune.bufsize-4);
        if (idx <= 0)
                return -1;
        if (idx + SLEN(HEALTHCHECK_KEY) + 1 > global.tune.bufsize-4)
@@ -1262,15 +1280,19 @@ prepare_spoe_healthcheck_request(char **req, int *len)
 int
 handle_spoe_healthcheck_response(char *frame, size_t size, char *err, int errlen)
 {
-       struct appctx a;
-       int           r;
+       struct appctx      appctx;
+       struct spoe_appctx spoe_appctx;
+       int                r;
+
+       memset(&appctx, 0, sizeof(appctx));
+       memset(&spoe_appctx, 0, sizeof(spoe_appctx));
 
-       memset(&a, 0, sizeof(a));
-       APPCTX_SPOE(&a).max_frame_size = global.tune.bufsize-4;
+       appctx.ctx.spoe.ptr = &spoe_appctx;
+       SPOE_APPCTX(&appctx)->max_frame_size = global.tune.bufsize-4;
 
-       if (handle_spoe_agentdiscon_frame(&a, frame, size) != 0)
+       if (handle_spoe_agentdiscon_frame(&appctx, frame, size) != 0)
                goto error;
-       if ((r = handle_spoe_agenthello_frame(&a, frame, size)) <= 0) {
+       if ((r = handle_spoe_agenthello_frame(&appctx, frame, size)) <= 0) {
                if (r == 0)
                        spoe_status_code = SPOE_FRM_ERR_INVALID;
                goto error;
@@ -1326,7 +1348,7 @@ recv_spoe_frame(struct appctx *appctx, char *buf, size_t framesz)
        ret = bo_getblk(si_oc(si), (char *)&netint, 4, 0);
        if (ret > 0) {
                framesz = ntohl(netint);
-               if (framesz > APPCTX_SPOE(appctx).max_frame_size) {
+               if (framesz > SPOE_APPCTX(appctx)->max_frame_size) {
                        spoe_status_code = SPOE_FRM_ERR_TOO_BIG;
                        return -1;
                }
@@ -1368,7 +1390,7 @@ static void
 release_spoe_applet(struct appctx *appctx)
 {
        struct stream_interface *si    = appctx->owner;
-       struct spoe_agent       *agent = APPCTX_SPOE(appctx).agent;
+       struct spoe_agent       *agent = SPOE_APPCTX(appctx)->agent;
        struct spoe_context     *ctx, *back;
 
        SPOE_PRINTF(stderr, "%d.%06d [SPOE/%-15s] %s: appctx=%p\n",
@@ -1376,9 +1398,9 @@ release_spoe_applet(struct appctx *appctx)
                    __FUNCTION__, appctx);
 
        agent->applets_act--;
-       if (!LIST_ISEMPTY(&APPCTX_SPOE(appctx).list)) {
-               LIST_DEL(&APPCTX_SPOE(appctx).list);
-               LIST_INIT(&APPCTX_SPOE(appctx).list);
+       if (!LIST_ISEMPTY(&SPOE_APPCTX(appctx)->list)) {
+               LIST_DEL(&SPOE_APPCTX(appctx)->list);
+               LIST_INIT(&SPOE_APPCTX(appctx)->list);
        }
 
        if (appctx->st0 != SPOE_APPCTX_ST_END) {
@@ -1391,18 +1413,20 @@ release_spoe_applet(struct appctx *appctx)
                appctx->st0 = SPOE_APPCTX_ST_END;
        }
 
-       if (APPCTX_SPOE(appctx).task) {
-               task_delete(APPCTX_SPOE(appctx).task);
-               task_free(APPCTX_SPOE(appctx).task);
+       if (SPOE_APPCTX(appctx)->task) {
+               task_delete(SPOE_APPCTX(appctx)->task);
+               task_free(SPOE_APPCTX(appctx)->task);
        }
 
-       list_for_each_entry_safe(ctx, back, &APPCTX_SPOE(appctx).waiting_queue, list) {
+       list_for_each_entry_safe(ctx, back, &SPOE_APPCTX(appctx)->waiting_queue, list) {
                LIST_DEL(&ctx->list);
                LIST_INIT(&ctx->list);
                ctx->state = SPOE_CTX_ST_ERROR;
                task_wakeup(ctx->strm->task, TASK_WOKEN_MSG);
        }
 
+       pool_free2(pool2_spoe_appctx, SPOE_APPCTX(appctx));
+
        if (!LIST_ISEMPTY(&agent->applets))
                return;
 
@@ -1425,7 +1449,7 @@ static int
 handle_connect_spoe_applet(struct appctx *appctx)
 {
        struct stream_interface *si    = appctx->owner;
-       struct spoe_agent       *agent = APPCTX_SPOE(appctx).agent;
+       struct spoe_agent       *agent = SPOE_APPCTX(appctx)->agent;
        char *frame = trash.str;
        int   ret;
 
@@ -1443,10 +1467,10 @@ handle_connect_spoe_applet(struct appctx *appctx)
                goto exit;
        }
 
-       if (APPCTX_SPOE(appctx).task->expire == TICK_ETERNITY)
-               APPCTX_SPOE(appctx).task->expire = tick_add_ifset(now_ms, agent->timeout.hello);
+       if (SPOE_APPCTX(appctx)->task->expire == TICK_ETERNITY)
+               SPOE_APPCTX(appctx)->task->expire = tick_add_ifset(now_ms, agent->timeout.hello);
 
-       ret = prepare_spoe_hahello_frame(appctx, frame+4, APPCTX_SPOE(appctx).max_frame_size);
+       ret = prepare_spoe_hahello_frame(appctx, frame+4, SPOE_APPCTX(appctx)->max_frame_size);
        if (ret > 1)
                ret = send_spoe_frame(appctx, frame, ret);
 
@@ -1479,7 +1503,7 @@ static int
 handle_connecting_spoe_applet(struct appctx *appctx)
 {
        struct stream_interface *si     = appctx->owner;
-       struct spoe_agent       *agent  = APPCTX_SPOE(appctx).agent;
+       struct spoe_agent       *agent  = SPOE_APPCTX(appctx)->agent;
        char *frame = trash.str;
        int   ret, framesz = 0;
 
@@ -1493,7 +1517,7 @@ handle_connecting_spoe_applet(struct appctx *appctx)
                goto exit;
        }
 
-       ret = recv_spoe_frame(appctx, frame, APPCTX_SPOE(appctx).max_frame_size);
+       ret = recv_spoe_frame(appctx, frame, SPOE_APPCTX(appctx)->max_frame_size);
        if (ret > 1) {
                if (*frame == SPOE_FRM_T_AGENT_DISCON) {
                        appctx->st0 = SPOE_APPCTX_ST_DISCONNECTING;
@@ -1527,11 +1551,13 @@ handle_connecting_spoe_applet(struct appctx *appctx)
                                bo_skip(si_oc(si), framesz+4);
                        agent->applets_idle++;
                        appctx->st0 = SPOE_APPCTX_ST_IDLE;
+                       LIST_DEL(&SPOE_APPCTX(appctx)->list);
+                       LIST_ADD(&agent->applets, &SPOE_APPCTX(appctx)->list);
                        goto next;
        }
 
   next:
-       APPCTX_SPOE(appctx).task->expire = tick_add_ifset(now_ms, agent->timeout.idle);
+       SPOE_APPCTX(appctx)->task->expire = tick_add_ifset(now_ms, agent->timeout.idle);
        return 0;
   stop:
        return 1;
@@ -1544,7 +1570,7 @@ static int
 handle_processing_spoe_applet(struct appctx *appctx)
 {
        struct stream_interface *si    = appctx->owner;
-       struct spoe_agent       *agent = APPCTX_SPOE(appctx).agent;
+       struct spoe_agent       *agent = SPOE_APPCTX(appctx)->agent;
        struct spoe_context     *ctx;
        char         *frame = trash.str;
        unsigned int  fpa = 0;
@@ -1566,8 +1592,8 @@ handle_processing_spoe_applet(struct appctx *appctx)
 
        /* Frames must be handled synchronously and a the applet is waiting for
         * a ACK frame */
-       if (!(APPCTX_SPOE(appctx).flags & (SPOE_APPCTX_FL_ASYNC|SPOE_APPCTX_FL_PIPELINING)) &&
-           !LIST_ISEMPTY(&APPCTX_SPOE(appctx).waiting_queue)) {
+       if (!(SPOE_APPCTX(appctx)->flags & (SPOE_APPCTX_FL_ASYNC|SPOE_APPCTX_FL_PIPELINING)) &&
+           !LIST_ISEMPTY(&SPOE_APPCTX(appctx)->waiting_queue)) {
                if (skip_receiving)
                        goto stop;
                goto recv_frame;
@@ -1579,7 +1605,7 @@ handle_processing_spoe_applet(struct appctx *appctx)
        }
 
        ctx = LIST_NEXT(&agent->sending_queue, typeof(ctx), list);
-       ret = prepare_spoe_hanotify_frame(appctx, ctx, frame+4, APPCTX_SPOE(appctx).max_frame_size);
+       ret = prepare_spoe_hanotify_frame(appctx, ctx, frame+4, SPOE_APPCTX(appctx)->max_frame_size);
        if (ret > 1)
                ret = send_spoe_frame(appctx, frame, ret);
 
@@ -1609,10 +1635,10 @@ handle_processing_spoe_applet(struct appctx *appctx)
                        release_spoe_buffer(ctx);
                        LIST_DEL(&ctx->list);
                        LIST_INIT(&ctx->list);
-                       if (APPCTX_SPOE(appctx).flags & SPOE_APPCTX_FL_ASYNC)
+                       if (SPOE_APPCTX(appctx)->flags & SPOE_APPCTX_FL_ASYNC)
                                LIST_ADDQ(&agent->waiting_queue, &ctx->list);
                        else
-                               LIST_ADDQ(&APPCTX_SPOE(appctx).waiting_queue, &ctx->list);
+                               LIST_ADDQ(&SPOE_APPCTX(appctx)->waiting_queue, &ctx->list);
                        fpa++;
        }
 
@@ -1624,7 +1650,7 @@ handle_processing_spoe_applet(struct appctx *appctx)
                goto process;
 
        framesz = 0;
-       ret = recv_spoe_frame(appctx, frame, APPCTX_SPOE(appctx).max_frame_size);
+       ret = recv_spoe_frame(appctx, frame, SPOE_APPCTX(appctx)->max_frame_size);
        if (ret > 1) {
                if (*frame == SPOE_FRM_T_AGENT_DISCON) {
                        appctx->st0 = SPOE_APPCTX_ST_DISCONNECTING;
@@ -1659,19 +1685,19 @@ handle_processing_spoe_applet(struct appctx *appctx)
        goto process;
 
   next:
-       APPCTX_SPOE(appctx).task->expire = tick_add_ifset(now_ms, agent->timeout.idle);
+       SPOE_APPCTX(appctx)->task->expire = tick_add_ifset(now_ms, agent->timeout.idle);
        return 0;
   stop:
-       if ((APPCTX_SPOE(appctx).flags & (SPOE_APPCTX_FL_ASYNC|SPOE_APPCTX_FL_PIPELINING)) ||
-           LIST_ISEMPTY(&APPCTX_SPOE(appctx).waiting_queue)) {
+       if ((SPOE_APPCTX(appctx)->flags & (SPOE_APPCTX_FL_ASYNC|SPOE_APPCTX_FL_PIPELINING)) ||
+           LIST_ISEMPTY(&SPOE_APPCTX(appctx)->waiting_queue)) {
                agent->applets_idle++;
                appctx->st0 = SPOE_APPCTX_ST_IDLE;
        }
-       if (fpa || (APPCTX_SPOE(appctx).flags & SPOE_APPCTX_FL_PERSIST)) {
-               LIST_DEL(&APPCTX_SPOE(appctx).list);
-               LIST_ADD(&agent->applets, &APPCTX_SPOE(appctx).list);
+       if (fpa || (SPOE_APPCTX(appctx)->flags & SPOE_APPCTX_FL_PERSIST)) {
+               LIST_DEL(&SPOE_APPCTX(appctx)->list);
+               LIST_ADD(&agent->applets, &SPOE_APPCTX(appctx)->list);
                if (fpa)
-                       APPCTX_SPOE(appctx).task->expire = tick_add_ifset(now_ms, agent->timeout.idle);
+                       SPOE_APPCTX(appctx)->task->expire = tick_add_ifset(now_ms, agent->timeout.idle);
        }
        return 1;
 
@@ -1684,7 +1710,7 @@ static int
 handle_disconnect_spoe_applet(struct appctx *appctx)
 {
        struct stream_interface *si    = appctx->owner;
-       struct spoe_agent       *agent = APPCTX_SPOE(appctx).agent;
+       struct spoe_agent       *agent = SPOE_APPCTX(appctx)->agent;
        char *frame = trash.str;
        int ret;
 
@@ -1694,7 +1720,7 @@ handle_disconnect_spoe_applet(struct appctx *appctx)
        if (appctx->st1 == SPOE_APPCTX_ERR_TOUT)
                goto exit;
 
-       ret = prepare_spoe_hadiscon_frame(appctx, frame+4, APPCTX_SPOE(appctx).max_frame_size);
+       ret = prepare_spoe_hadiscon_frame(appctx, frame+4, SPOE_APPCTX(appctx)->max_frame_size);
        if (ret > 1)
                ret = send_spoe_frame(appctx, frame, ret);
 
@@ -1721,7 +1747,7 @@ handle_disconnect_spoe_applet(struct appctx *appctx)
        }
 
   next:
-       APPCTX_SPOE(appctx).task->expire = tick_add_ifset(now_ms, agent->timeout.idle);
+       SPOE_APPCTX(appctx)->task->expire = tick_add_ifset(now_ms, agent->timeout.idle);
        return 0;
   stop:
        return 1;
@@ -1744,7 +1770,7 @@ handle_disconnecting_spoe_applet(struct appctx *appctx)
                goto exit;
 
        framesz = 0;
-       ret = recv_spoe_frame(appctx, frame, APPCTX_SPOE(appctx).max_frame_size);
+       ret = recv_spoe_frame(appctx, frame, SPOE_APPCTX(appctx)->max_frame_size);
        if (ret > 1) {
                framesz = ret;
                ret = handle_spoe_agentdiscon_frame(appctx, frame, framesz);
@@ -1757,7 +1783,7 @@ handle_disconnecting_spoe_applet(struct appctx *appctx)
                        SPOE_PRINTF(stderr, "%d.%06d [SPOE/%-15s] %s: appctx=%p"
                                    " - error on frame (%s)\n",
                                    (int)now.tv_sec, (int)now.tv_usec,
-                                   ((struct spoe_agent *)APPCTX_SPOE(appctx).agent)->id,
+                                   ((struct spoe_agent *)SPOE_APPCTX(appctx)->agent)->id,
                                    __FUNCTION__, appctx,
                                    spoe_frm_err_reasons[spoe_status_code]);
                        goto exit;
@@ -1776,7 +1802,7 @@ handle_disconnecting_spoe_applet(struct appctx *appctx)
                        SPOE_PRINTF(stderr, "%d.%06d [SPOE/%-15s] %s: appctx=%p"
                                    " - disconnected by peer (%d): %s\n",
                                    (int)now.tv_sec, (int)now.tv_usec,
-                                   ((struct spoe_agent *)APPCTX_SPOE(appctx).agent)->id,
+                                   ((struct spoe_agent *)SPOE_APPCTX(appctx)->agent)->id,
                                    __FUNCTION__, appctx, spoe_status_code,
                                    spoe_reason);
                        goto exit;
@@ -1796,7 +1822,7 @@ static void
 handle_spoe_applet(struct appctx *appctx)
 {
        struct stream_interface *si    = appctx->owner;
-       struct spoe_agent       *agent = APPCTX_SPOE(appctx).agent;
+       struct spoe_agent       *agent = SPOE_APPCTX(appctx)->agent;
 
   switchstate:
        SPOE_PRINTF(stderr, "%d.%06d [SPOE/%-15s] %s: appctx=%p"
@@ -1819,8 +1845,8 @@ handle_spoe_applet(struct appctx *appctx)
                case SPOE_APPCTX_ST_IDLE:
                        if (stopping &&
                            LIST_ISEMPTY(&agent->sending_queue) &&
-                           LIST_ISEMPTY(&APPCTX_SPOE(appctx).waiting_queue)) {
-                               APPCTX_SPOE(appctx).task->expire = tick_add_ifset(now_ms, agent->timeout.idle);
+                           LIST_ISEMPTY(&SPOE_APPCTX(appctx)->waiting_queue)) {
+                               SPOE_APPCTX(appctx)->task->expire = tick_add_ifset(now_ms, agent->timeout.idle);
                                appctx->st0 = SPOE_APPCTX_ST_DISCONNECT;
                                goto switchstate;
                        }
@@ -1848,15 +1874,15 @@ handle_spoe_applet(struct appctx *appctx)
                        si_shutr(si);
                        si_ic(si)->flags |= CF_READ_NULL;
                        appctx->st0 = SPOE_APPCTX_ST_END;
-                       APPCTX_SPOE(appctx).task->expire = TICK_ETERNITY;
+                       SPOE_APPCTX(appctx)->task->expire = TICK_ETERNITY;
                        /* fall through */
 
                case SPOE_APPCTX_ST_END:
                        return;
        }
   out:
-       if (APPCTX_SPOE(appctx).task->expire != TICK_ETERNITY)
-               task_queue(APPCTX_SPOE(appctx).task);
+       if (SPOE_APPCTX(appctx)->task->expire != TICK_ETERNITY)
+               task_queue(SPOE_APPCTX(appctx)->task);
        si_oc(si)->flags |= CF_READ_DONTWAIT;
        task_wakeup(si_strm(si)->task, TASK_WOKEN_IO);
 }
@@ -1881,19 +1907,25 @@ create_spoe_appctx(struct spoe_config *conf)
        if ((appctx = appctx_new(&spoe_applet)) == NULL)
                goto out_error;
 
-       appctx->st0 = SPOE_APPCTX_ST_CONNECT;
-       if ((APPCTX_SPOE(appctx).task = task_new()) == NULL)
+       appctx->ctx.spoe.ptr = pool_alloc_dirty(pool2_spoe_appctx);
+       if (SPOE_APPCTX(appctx) == NULL)
                goto out_free_appctx;
-       APPCTX_SPOE(appctx).task->process   = process_spoe_applet;
-       APPCTX_SPOE(appctx).task->expire    = TICK_ETERNITY;//tick_add_ifset(now_ms, conf->agent->timeout.hello);
-       APPCTX_SPOE(appctx).task->context   = appctx;
-       APPCTX_SPOE(appctx).agent           = conf->agent;
-       APPCTX_SPOE(appctx).version         = 0;
-       APPCTX_SPOE(appctx).max_frame_size  = conf->agent->max_frame_size;
-       APPCTX_SPOE(appctx).flags           = 0;
 
-       LIST_INIT(&APPCTX_SPOE(appctx).list);
-       LIST_INIT(&APPCTX_SPOE(appctx).waiting_queue);
+       appctx->st0 = SPOE_APPCTX_ST_CONNECT;
+       if ((SPOE_APPCTX(appctx)->task = task_new()) == NULL)
+               goto out_free_spoe_appctx;
+
+       SPOE_APPCTX(appctx)->owner           = appctx;
+       SPOE_APPCTX(appctx)->task->process   = process_spoe_applet;
+       SPOE_APPCTX(appctx)->task->expire    = TICK_ETERNITY;
+       SPOE_APPCTX(appctx)->task->context   = appctx;
+       SPOE_APPCTX(appctx)->agent           = conf->agent;
+       SPOE_APPCTX(appctx)->version         = 0;
+       SPOE_APPCTX(appctx)->max_frame_size  = conf->agent->max_frame_size;
+       SPOE_APPCTX(appctx)->flags           = 0;
+
+       LIST_INIT(&SPOE_APPCTX(appctx)->list);
+       LIST_INIT(&SPOE_APPCTX(appctx)->waiting_queue);
 
        sess = session_new(&conf->agent_fe, NULL, &appctx->obj_type);
        if (!sess)
@@ -1918,8 +1950,8 @@ create_spoe_appctx(struct spoe_config *conf)
        jobs++;
        totalconn++;
 
-       task_wakeup(APPCTX_SPOE(appctx).task, TASK_WOKEN_INIT);
-       LIST_ADDQ(&conf->agent->applets, &APPCTX_SPOE(appctx).list);
+       task_wakeup(SPOE_APPCTX(appctx)->task, TASK_WOKEN_INIT);
+       LIST_ADDQ(&conf->agent->applets, &SPOE_APPCTX(appctx)->list);
        conf->agent->applets_act++;
        return appctx;
 
@@ -1929,7 +1961,9 @@ create_spoe_appctx(struct spoe_config *conf)
  out_free_sess:
        session_free(sess);
  out_free_spoe:
-       task_free(APPCTX_SPOE(appctx).task);
+       task_free(SPOE_APPCTX(appctx)->task);
+ out_free_spoe_appctx:
+       pool_free2(pool2_spoe_appctx, SPOE_APPCTX(appctx));
  out_free_appctx:
        appctx_free(appctx);
  out_error:
@@ -1942,6 +1976,7 @@ queue_spoe_context(struct spoe_context *ctx)
        struct spoe_config *conf = FLT_CONF(ctx->filter);
        struct spoe_agent  *agent = conf->agent;
        struct appctx      *appctx;
+       struct spoe_appctx *spoe_appctx;
        unsigned int        min_applets;
 
        min_applets = min_applets_act(agent);
@@ -1986,7 +2021,7 @@ queue_spoe_context(struct spoe_context *ctx)
                goto end;
        }
        if (agent->applets_act <= min_applets)
-               APPCTX_SPOE(appctx).flags |= SPOE_APPCTX_FL_PERSIST;
+               SPOE_APPCTX(appctx)->flags |= SPOE_APPCTX_FL_PERSIST;
 
        /* Increase the per-process number of cumulated connections */
        if (agent->cps_max > 0)
@@ -2011,13 +2046,14 @@ queue_spoe_context(struct spoe_context *ctx)
 
        /* Finally try to wakeup the first IDLE applet found and move it at the
         * end of the list. */
-       list_for_each_entry(appctx, &agent->applets, ctx.spoe.list) {
+       list_for_each_entry(spoe_appctx, &agent->applets, list) {
+               appctx = spoe_appctx->owner;
                if (appctx->st0 == SPOE_APPCTX_ST_IDLE) {
                        si_applet_want_get(appctx->owner);
                        si_applet_want_put(appctx->owner);
                        appctx_wakeup(appctx);
-                       LIST_DEL(&APPCTX_SPOE(appctx).list);
-                       LIST_ADDQ(&agent->applets, &APPCTX_SPOE(appctx).list);
+                       LIST_DEL(&spoe_appctx->list);
+                       LIST_ADDQ(&agent->applets, &spoe_appctx->list);
                        break;
                }
        }
@@ -2569,6 +2605,7 @@ sig_stop_spoe(struct sig_handler *sh)
                        struct spoe_config *conf;
                        struct spoe_agent  *agent;
                        struct appctx      *appctx;
+                       struct spoe_appctx *spoe_appctx;
 
                        if (fconf->id != spoe_filter_id)
                                continue;
@@ -2576,7 +2613,8 @@ sig_stop_spoe(struct sig_handler *sh)
                        conf  = fconf->conf;
                        agent = conf->agent;
 
-                       list_for_each_entry(appctx, &agent->applets, ctx.spoe.list) {
+                       list_for_each_entry(spoe_appctx, &agent->applets, list) {
+                               appctx = spoe_appctx->owner;
                                si_applet_want_get(appctx->owner);
                                si_applet_want_put(appctx->owner);
                                appctx_wakeup(appctx);
@@ -3491,6 +3529,7 @@ static void __spoe_init(void)
        LIST_INIT(&curmsgs);
        LIST_INIT(&curmps);
        pool2_spoe_ctx = create_pool("spoe_ctx", sizeof(struct spoe_context), MEM_F_SHARED);
+       pool2_spoe_appctx = create_pool("spoe_appctx", sizeof(struct spoe_appctx), MEM_F_SHARED);
 }
 
 __attribute__((destructor))
@@ -3498,4 +3537,5 @@ static void
 __spoe_deinit(void)
 {
        pool_destroy2(pool2_spoe_ctx);
+       pool_destroy2(pool2_spoe_appctx);
 }