MINOR: spoe: Add status code in error variable instead of hardcoded value
Now, when option "set-on-error" is enabled, we set a status code representing
the error occurred instead of "true". For values under 256, it represents an
error coming from the engine. Below 256, it reports a SPOP error. In this case,
to retrieve the right SPOP status code, you must remove 256 to this value. Here
are possible values:
* 1: a timeout occurred during the event processing.
* 2: an error was triggered during the ressources allocation.
* 255: an unknown error occurred during the event processing.
* 256+N: a SPOP error occurred during the event processing.
diff --git a/doc/SPOE.txt b/doc/SPOE.txt
index d716c6b..81376e0 100644
--- a/doc/SPOE.txt
+++ b/doc/SPOE.txt
@@ -217,9 +217,22 @@
prefixed. So, if your variable name is "error" and your prefix is
"my_spoe_pfx", the variable will be "txn.my_spoe_pfx.error".
- When set, the variable is the boolean "true". Note that if "option
- continue-on-error" is set, the variable is not automatically removed between
- events processing.
+ When set, the variable is an integer representing the error reason. For values
+ under 256, it represents an error coming from the engine. Below 256, it
+ reports a SPOP error. In this case, to retrieve the right SPOP status code,
+ you must remove 256 to this value. Here are possible values:
+
+ * 1 a timeout occurred during the event processing.
+
+ * 2 an error was triggered during the ressources allocation.
+
+ * 255 an unknown error occurred during the event processing.
+
+ * 256+N a SPOP error occurred during the event processing (see section
+ "Errors & timeouts").
+
+ Note that if "option continue-on-error" is set, the variable is not
+ automatically removed between events processing.
See also: "option continue-on-error", "option var-prefix".
@@ -341,7 +354,7 @@
- on-backend-http-request
- on-http-response
- See section 3.5 about Events.
+ See section "Events & Messages".
2.4. Example
-------------
diff --git a/src/flt_spoe.c b/src/flt_spoe.c
index 6b8c799..1b04598 100644
--- a/src/flt_spoe.c
+++ b/src/flt_spoe.c
@@ -119,6 +119,15 @@
SPOE_EV_EVENTS
};
+/* Errors triggered by streams */
+enum spoe_context_error {
+ SPOE_CTX_ERR_NONE = 0,
+ SPOE_CTX_ERR_TOUT,
+ SPOE_CTX_ERR_RES,
+ SPOE_CTX_ERR_UNKNOWN = 255,
+ SPOE_CTX_ERRS,
+};
+
/* Errors triggerd by SPOE applet */
enum spoe_frame_error {
SPOE_FRM_ERR_NONE = 0,
@@ -243,6 +252,7 @@
enum spoe_ctx_state state; /* SPOE_CTX_ST_* */
unsigned int flags; /* SPOE_CTX_FL_* */
+ unsigned int status_code; /* SPOE_CTX_ERR_* */
unsigned int stream_id; /* stream_id and frame_id are used */
unsigned int frame_id; /* to map NOTIFY and ACK frames */
@@ -259,6 +269,7 @@
unsigned int max_frame_size; /* the negotiated max-frame-size value */
unsigned int flags; /* SPOE_APPCTX_FL_* */
+ unsigned int status_code; /* SPOE_FRM_ERR_* */
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 */
};
@@ -793,8 +804,10 @@
+ 1 + SLEN(CAPABILITIES_KEY) + 1 + 1 + SLEN(CAPABILITIES_VAL)
+ 1 + SLEN(ENGINE_ID_KEY) + 1 + 1 + 36);
- if (size < max)
+ if (size < max) {
+ spoe_status_code = SPOE_FRM_ERR_TOO_BIG;
return -1;
+ }
/* Frame type */
frame[idx++] = SPOE_FRM_T_HAPROXY_HELLO;
@@ -890,9 +903,6 @@
{
int idx = 0;
- if (size < SPOE_APPCTX(appctx)->max_frame_size)
- return -1;
-
frame[idx++] = SPOE_FRM_T_HAPROXY_NOTIFY;
/* No flags for now */
@@ -904,8 +914,10 @@
idx += encode_spoe_varint(ctx->frame_id, frame+idx);
/* Copy encoded messages */
- if (idx + ctx->buffer->i > size)
+ if (idx + ctx->buffer->i > size) {
+ spoe_status_code = SPOE_FRM_ERR_TOO_BIG;
return 0;
+ }
/* Copy encoded messages */
memcpy(frame+idx, ctx->buffer->p, ctx->buffer->i);
@@ -1218,7 +1230,7 @@
return 0;
found:
- if (acquire_spoe_buffer(ctx) <= 0)
+ if (!acquire_spoe_buffer(ctx))
return 1; /* Retry later */
/* Copy encoded actions */
@@ -1327,6 +1339,7 @@
if (ret <= 0) {
if (ret == -1)
return 1; /* retry */
+ spoe_status_code = SPOE_FRM_ERR_IO;
return -1; /* error */
}
return framesz;
@@ -1411,6 +1424,8 @@
si_shutr(si);
si_ic(si)->flags |= CF_READ_NULL;
appctx->st0 = SPOE_APPCTX_ST_END;
+ if (SPOE_APPCTX(appctx)->status_code == SPOE_FRM_ERR_NONE)
+ SPOE_APPCTX(appctx)->status_code = SPOE_FRM_ERR_IO;
}
if (SPOE_APPCTX(appctx)->task) {
@@ -1422,6 +1437,7 @@
LIST_DEL(&ctx->list);
LIST_INIT(&ctx->list);
ctx->state = SPOE_CTX_ST_ERROR;
+ ctx->status_code = (SPOE_APPCTX(appctx)->status_code + 0x100);
task_wakeup(ctx->strm->task, TASK_WOKEN_MSG);
}
@@ -1434,6 +1450,7 @@
LIST_DEL(&ctx->list);
LIST_INIT(&ctx->list);
ctx->state = SPOE_CTX_ST_ERROR;
+ ctx->status_code = (SPOE_APPCTX(appctx)->status_code + 0x100);
task_wakeup(ctx->strm->task, TASK_WOKEN_MSG);
}
@@ -1441,6 +1458,7 @@
LIST_DEL(&ctx->list);
LIST_INIT(&ctx->list);
ctx->state = SPOE_CTX_ST_ERROR;
+ ctx->status_code = (SPOE_APPCTX(appctx)->status_code + 0x100);
task_wakeup(ctx->strm->task, TASK_WOKEN_MSG);
}
}
@@ -1458,12 +1476,15 @@
task_wakeup(si_strm(si)->task, TASK_WOKEN_MSG);
goto stop;
}
- if (si->state != SI_ST_EST)
+ if (si->state != SI_ST_EST) {
+ spoe_status_code = SPOE_FRM_ERR_IO;
goto exit;
+ }
if (appctx->st1 == SPOE_APPCTX_ERR_TOUT) {
SPOE_PRINTF(stderr, "%d.%06d [SPOE/%-15s] %s: appctx=%p - Connection timed out\n",
(int)now.tv_sec, (int)now.tv_usec, agent->id, __FUNCTION__, appctx);
+ spoe_status_code = SPOE_FRM_ERR_TOUT;
goto exit;
}
@@ -1495,6 +1516,7 @@
stop:
return 1;
exit:
+ SPOE_APPCTX(appctx)->status_code = spoe_status_code;
appctx->st0 = SPOE_APPCTX_ST_EXIT;
return 0;
}
@@ -1508,12 +1530,15 @@
int ret, framesz = 0;
- if (si->state == SI_ST_CLO || si_opposite(si)->state == SI_ST_CLO)
+ if (si->state == SI_ST_CLO || si_opposite(si)->state == SI_ST_CLO) {
+ spoe_status_code = SPOE_FRM_ERR_IO;
goto exit;
+ }
if (appctx->st1 == SPOE_APPCTX_ERR_TOUT) {
SPOE_PRINTF(stderr, "%d.%06d [SPOE/%-15s] %s: appctx=%p - Connection timed out\n",
(int)now.tv_sec, (int)now.tv_usec, agent->id, __FUNCTION__, appctx);
+ spoe_status_code = SPOE_FRM_ERR_TOUT;
goto exit;
}
@@ -1562,6 +1587,7 @@
stop:
return 1;
exit:
+ SPOE_APPCTX(appctx)->status_code = spoe_status_code;
appctx->st0 = SPOE_APPCTX_ST_EXIT;
return 0;
}
@@ -1576,8 +1602,10 @@
unsigned int fpa = 0;
int ret, framesz = 0, skip_sending = 0, skip_receiving = 0;
- if (si->state == SI_ST_CLO || si_opposite(si)->state == SI_ST_CLO)
+ if (si->state == SI_ST_CLO || si_opposite(si)->state == SI_ST_CLO) {
+ spoe_status_code = SPOE_FRM_ERR_IO;
goto exit;
+ }
if (appctx->st1 == SPOE_APPCTX_ERR_TOUT) {
spoe_status_code = SPOE_FRM_ERR_TOUT;
@@ -1617,6 +1645,7 @@
case 0: /* ignore */
agent->sending_rate++;
ctx->state = SPOE_CTX_ST_ERROR;
+ ctx->status_code = (spoe_status_code + 0x100);
release_spoe_buffer(ctx);
task_wakeup(ctx->strm->task, TASK_WOKEN_MSG);
LIST_DEL(&ctx->list);
@@ -1702,6 +1731,7 @@
return 1;
exit:
+ SPOE_APPCTX(appctx)->status_code = spoe_status_code;
appctx->st0 = SPOE_APPCTX_ST_EXIT;
return 0;
}
@@ -1714,6 +1744,8 @@
char *frame = trash.str;
int ret;
+ SPOE_APPCTX(appctx)->status_code = spoe_status_code;
+
if (si->state == SI_ST_CLO || si_opposite(si)->state == SI_ST_CLO)
goto exit;
@@ -1763,11 +1795,15 @@
char *frame = trash.str;
int ret, framesz = 0;
- if (si->state == SI_ST_CLO || si_opposite(si)->state == SI_ST_CLO)
+ if (si->state == SI_ST_CLO || si_opposite(si)->state == SI_ST_CLO) {
+ spoe_status_code = SPOE_FRM_ERR_IO;
goto exit;
+ }
- if (appctx->st1 == SPOE_APPCTX_ERR_TOUT)
+ if (appctx->st1 == SPOE_APPCTX_ERR_TOUT) {
+ spoe_status_code = SPOE_FRM_ERR_TOUT;
goto exit;
+ }
framesz = 0;
ret = recv_spoe_frame(appctx, frame, SPOE_APPCTX(appctx)->max_frame_size);
@@ -1813,6 +1849,8 @@
stop:
return 1;
exit:
+ if (SPOE_APPCTX(appctx)->status_code == SPOE_FRM_ERR_NONE)
+ SPOE_APPCTX(appctx)->status_code = spoe_status_code;
appctx->st0 = SPOE_APPCTX_ST_EXIT;
return 0;
}
@@ -1824,6 +1862,8 @@
struct stream_interface *si = appctx->owner;
struct spoe_agent *agent = SPOE_APPCTX(appctx)->agent;
+ spoe_status_code = SPOE_FRM_ERR_NONE;
+
switchstate:
SPOE_PRINTF(stderr, "%d.%06d [SPOE/%-15s] %s: appctx=%p"
" - appctx-state=%s\n",
@@ -1832,7 +1872,6 @@
switch (appctx->st0) {
case SPOE_APPCTX_ST_CONNECT:
- spoe_status_code = SPOE_FRM_ERR_NONE;
if (handle_connect_spoe_applet(appctx))
goto out;
goto switchstate;
@@ -1923,6 +1962,7 @@
SPOE_APPCTX(appctx)->version = 0;
SPOE_APPCTX(appctx)->max_frame_size = conf->agent->max_frame_size;
SPOE_APPCTX(appctx)->flags = 0;
+ SPOE_APPCTX(appctx)->status_code = SPOE_FRM_ERR_NONE;
LIST_INIT(&SPOE_APPCTX(appctx)->list);
LIST_INIT(&SPOE_APPCTX(appctx)->waiting_queue);
@@ -2330,15 +2370,13 @@
static int
start_event_processing(struct spoe_context *ctx, int dir)
{
- int ret;
/* If a process is already started for this SPOE context, retry
* later. */
if (ctx->flags & SPOE_CTX_FL_PROCESS)
goto wait;
- ret = acquire_spoe_buffer(ctx);
- if (ret <= 0)
- return ret;
+ if (!acquire_spoe_buffer(ctx))
+ goto wait;
/* Set the right flag to prevent request and response processing
* in same time. */
@@ -2358,6 +2396,8 @@
/* Reset the flag to allow next processing */
ctx->flags &= ~SPOE_CTX_FL_PROCESS;
+ ctx->status_code = 0;
+
/* Reset processing timer */
ctx->process_exp = TICK_ETERNITY;
@@ -2405,6 +2445,7 @@
send_log(ctx->strm->be, LOG_WARNING,
"failed to process event '%s': timeout.\n",
spoe_event_str[ev]);
+ ctx->status_code = SPOE_CTX_ERR_TOUT;
goto error;
}
@@ -2425,20 +2466,16 @@
ctx->process_exp);
}
ret = start_event_processing(ctx, dir);
- if (ret <= 0) {
- if (!ret)
- goto out;
- goto error;
- }
+ if (!ret)
+ goto out;
ret = process_spoe_messages(s, ctx, &(ctx->messages[ev]), dir);
- if (ret <= 0) {
- if (!ret)
- goto skip;
- goto error;
- }
+ if (!ret)
+ goto skip;
- if (!queue_spoe_context(ctx))
+ if (!queue_spoe_context(ctx)) {
+ ctx->status_code = SPOE_CTX_ERR_RES;
goto error;
+ }
ctx->state = SPOE_CTX_ST_SENDING_MSGS;
/* fall through */
@@ -2452,11 +2489,8 @@
if (ctx->state == SPOE_CTX_ST_DONE) {
ret = process_spoe_actions(s, ctx, ev, dir);
- if (ret <= 0) {
- if (!ret)
- goto skip;
- goto error;
- }
+ if (!ret)
+ goto skip;
ctx->frame_id++;
ctx->state = SPOE_CTX_ST_READY;
goto end;
@@ -2475,7 +2509,7 @@
// FIXME: Get the error code here
memset(&smp, 0, sizeof(smp));
smp_set_owner(&smp, s->be, s->sess, s, dir|SMP_OPT_FINAL);
- smp.data.u.sint = 1;
+ smp.data.u.sint = ctx->status_code;
smp.data.type = SMP_T_BOOL;
set_spoe_var(ctx, "txn", agent->var_on_error,
@@ -2484,7 +2518,7 @@
ctx->state = ((agent->flags & SPOE_FL_CONT_ON_ERR)
? SPOE_CTX_ST_READY
- : SPOE_CTX_ST_ERROR);
+ : SPOE_CTX_ST_NONE);
ret = 1;
goto end;
@@ -2550,11 +2584,12 @@
return NULL;
}
memset(ctx, 0, sizeof(*ctx));
- ctx->filter = filter;
- ctx->state = SPOE_CTX_ST_NONE;
- ctx->flags = 0;
- ctx->messages = conf->agent->messages;
- ctx->buffer = &buf_empty;
+ ctx->filter = filter;
+ ctx->state = SPOE_CTX_ST_NONE;
+ ctx->status_code = SPOE_CTX_ERR_NONE;
+ ctx->flags = 0;
+ ctx->messages = conf->agent->messages;
+ ctx->buffer = &buf_empty;
LIST_INIT(&ctx->buffer_wait.list);
ctx->buffer_wait.target = ctx;
ctx->buffer_wait.wakeup_cb = (int (*)(void *))wakeup_spoe_context;
@@ -2791,6 +2826,9 @@
((struct spoe_config *)FLT_CONF(filter))->agent->id,
__FUNCTION__, s, spoe_ctx_state_str[ctx->state], ctx->flags);
+ if (ctx->state == SPOE_CTX_ST_NONE)
+ goto out;
+
if (!(chn->flags & CF_ISRESP)) {
if (filter->pre_analyzers & AN_REQ_INSPECT_FE)
chn->analysers |= AN_REQ_INSPECT_FE;
@@ -2801,11 +2839,9 @@
goto out;
ctx->stream_id = s->uniq_id;
- if (ctx->state != SPOE_CTX_ST_NONE && ctx->state != SPOE_CTX_ST_ERROR) {
- ret = process_spoe_event(s, ctx, SPOE_EV_ON_CLIENT_SESS);
- if (ret != 1)
- goto out;
- }
+ ret = process_spoe_event(s, ctx, SPOE_EV_ON_CLIENT_SESS);
+ if (!ret)
+ goto out;
ctx->flags |= SPOE_CTX_FL_CLI_CONNECTED;
}
else {
@@ -2815,16 +2851,13 @@
if (ctx->flags & SPOE_CTX_FL_SRV_CONNECTED)
goto out;
- if (ctx->state != SPOE_CTX_ST_NONE && ctx->state != SPOE_CTX_ST_ERROR) {
- ret = process_spoe_event(s, ctx, SPOE_EV_ON_SERVER_SESS);
- if (ret != 1)
- goto out;
- }
- ctx->flags |= SPOE_CTX_FL_SRV_CONNECTED;
+ ret = process_spoe_event(s, ctx, SPOE_EV_ON_SERVER_SESS);
if (!ret) {
channel_dont_read(chn);
channel_dont_close(chn);
+ goto out;
}
+ ctx->flags |= SPOE_CTX_FL_SRV_CONNECTED;
}
out:
@@ -2846,7 +2879,7 @@
__FUNCTION__, s, spoe_ctx_state_str[ctx->state],
ctx->flags, an_bit);
- if (ctx->state == SPOE_CTX_ST_NONE || ctx->state == SPOE_CTX_ST_ERROR)
+ if (ctx->state == SPOE_CTX_ST_NONE)
goto out;
switch (an_bit) {