MEDIUM: hlua/applet: Use the sedesc to report and detect end of processing

There are 3 kinds of applet in lua: The co-sockets, the TCP services and the
HTTP services. The three are refactored to use the SE descriptor instead of
the channel to report error and end-of-stream.
This commit is contained in:
Christopher Faulet 2023-03-31 11:13:48 +02:00
parent d550d26a39
commit 31572229ed

View File

@ -2000,12 +2000,17 @@ static void hlua_socket_handler(struct appctx *appctx)
struct hlua_csk_ctx *ctx = appctx->svcctx; struct hlua_csk_ctx *ctx = appctx->svcctx;
struct stconn *sc = appctx_sc(appctx); struct stconn *sc = appctx_sc(appctx);
if (ctx->die) { if (unlikely(se_fl_test(appctx->sedesc, (SE_FL_EOS|SE_FL_ERROR|SE_FL_SHR|SE_FL_SHW)))) {
sc_shutw(sc);
sc_shutr(sc);
notification_wake(&ctx->wake_on_read); notification_wake(&ctx->wake_on_read);
notification_wake(&ctx->wake_on_write); notification_wake(&ctx->wake_on_write);
stream_shutdown(__sc_strm(sc), SF_ERR_KILLED); return;
}
if (ctx->die) {
se_fl_set(appctx->sedesc, SE_FL_EOI|SE_FL_EOS);
notification_wake(&ctx->wake_on_read);
notification_wake(&ctx->wake_on_write);
return;
} }
/* If we can't write, wakeup the pending write signals. */ /* If we can't write, wakeup the pending write signals. */
@ -2037,12 +2042,6 @@ static void hlua_socket_handler(struct appctx *appctx)
if (!channel_is_empty(sc_oc(sc))) if (!channel_is_empty(sc_oc(sc)))
notification_wake(&ctx->wake_on_read); notification_wake(&ctx->wake_on_read);
/* Some data were injected in the buffer, notify the stream
* interface.
*/
if (!channel_is_empty(sc_ic(sc)))
sc_update(sc);
/* If write notifications are registered, we considers we want /* If write notifications are registered, we considers we want
* to write, so we clear the blocking flag. * to write, so we clear the blocking flag.
*/ */
@ -9421,33 +9420,26 @@ void hlua_applet_tcp_fct(struct appctx *ctx)
struct proxy *px = strm->be; struct proxy *px = strm->be;
struct hlua *hlua = tcp_ctx->hlua; struct hlua *hlua = tcp_ctx->hlua;
/* The applet execution is already done. */ if (unlikely(se_fl_test(ctx->sedesc, (SE_FL_EOS|SE_FL_ERROR|SE_FL_SHR|SE_FL_SHW))))
if (tcp_ctx->flags & APPLET_DONE) { goto out;
/* eat the whole request */
co_skip(sc_oc(sc), co_data(sc_oc(sc)));
return;
}
/* If the stream is disconnect or closed, ldo nothing. */ /* The applet execution is already done. */
if (unlikely(sc->state == SC_ST_DIS || sc->state == SC_ST_CLO)) if (tcp_ctx->flags & APPLET_DONE)
return; goto out;
/* Execute the function. */ /* Execute the function. */
switch (hlua_ctx_resume(hlua, 1)) { switch (hlua_ctx_resume(hlua, 1)) {
/* finished. */ /* finished. */
case HLUA_E_OK: case HLUA_E_OK:
tcp_ctx->flags |= APPLET_DONE; tcp_ctx->flags |= APPLET_DONE;
se_fl_set(ctx->sedesc, SE_FL_EOI|SE_FL_EOS);
/* eat the whole request */ break;
co_skip(sc_oc(sc), co_data(sc_oc(sc)));
sc_shutr(sc);
return;
/* yield. */ /* yield. */
case HLUA_E_AGAIN: case HLUA_E_AGAIN:
if (hlua->wake_time != TICK_ETERNITY) if (hlua->wake_time != TICK_ETERNITY)
task_schedule(tcp_ctx->task, hlua->wake_time); task_schedule(tcp_ctx->task, hlua->wake_time);
return; break;
/* finished with error. */ /* finished with error. */
case HLUA_E_ERRMSG: case HLUA_E_ERRMSG:
@ -9482,12 +9474,15 @@ void hlua_applet_tcp_fct(struct appctx *ctx)
goto error; goto error;
} }
error: out:
/* eat the whole request */
co_skip(sc_oc(sc), co_data(sc_oc(sc)));
return;
/* For all other cases, just close the stream. */ error:
sc_shutw(sc); se_fl_set(ctx->sedesc, SE_FL_ERROR);
sc_shutr(sc);
tcp_ctx->flags |= APPLET_DONE; tcp_ctx->flags |= APPLET_DONE;
goto out;
} }
static void hlua_applet_tcp_release(struct appctx *ctx) static void hlua_applet_tcp_release(struct appctx *ctx)
@ -9620,8 +9615,11 @@ void hlua_applet_http_fct(struct appctx *ctx)
res_htx = htx_from_buf(&res->buf); res_htx = htx_from_buf(&res->buf);
/* If the stream is disconnect or closed, ldo nothing. */ if (unlikely(se_fl_test(ctx->sedesc, (SE_FL_EOS|SE_FL_ERROR|SE_FL_SHR|SE_FL_SHW))))
if (unlikely(sc->state == SC_ST_DIS || sc->state == SC_ST_CLO)) goto out;
/* The applet execution is already done. */
if (http_ctx->flags & APPLET_DONE)
goto out; goto out;
/* Check if the input buffer is available. */ /* Check if the input buffer is available. */
@ -9629,9 +9627,6 @@ void hlua_applet_http_fct(struct appctx *ctx)
sc_need_room(sc); sc_need_room(sc);
goto out; goto out;
} }
/* check that the output is not closed */
if (res->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_SHUTR))
http_ctx->flags |= APPLET_DONE;
/* Set the currently running flag. */ /* Set the currently running flag. */
if (!HLUA_IS_RUNNING(hlua) && if (!HLUA_IS_RUNNING(hlua) &&
@ -9642,11 +9637,8 @@ void hlua_applet_http_fct(struct appctx *ctx)
} }
} }
/* Executes The applet if it is not done. */ /* Execute the function. */
if (!(http_ctx->flags & APPLET_DONE)) { switch (hlua_ctx_resume(hlua, 1)) {
/* Execute the function. */
switch (hlua_ctx_resume(hlua, 1)) {
/* finished. */ /* finished. */
case HLUA_E_OK: case HLUA_E_OK:
http_ctx->flags |= APPLET_DONE; http_ctx->flags |= APPLET_DONE;
@ -9662,39 +9654,38 @@ void hlua_applet_http_fct(struct appctx *ctx)
case HLUA_E_ERRMSG: case HLUA_E_ERRMSG:
/* Display log. */ /* Display log. */
SEND_ERR(px, "Lua applet http '%s': %s.\n", SEND_ERR(px, "Lua applet http '%s': %s.\n",
rule->arg.hlua_rule->fcn->name, lua_tostring(hlua->T, -1)); rule->arg.hlua_rule->fcn->name, lua_tostring(hlua->T, -1));
lua_pop(hlua->T, 1); lua_pop(hlua->T, 1);
goto error; goto error;
case HLUA_E_ETMOUT: case HLUA_E_ETMOUT:
SEND_ERR(px, "Lua applet http '%s': execution timeout.\n", SEND_ERR(px, "Lua applet http '%s': execution timeout.\n",
rule->arg.hlua_rule->fcn->name); rule->arg.hlua_rule->fcn->name);
goto error; goto error;
case HLUA_E_NOMEM: case HLUA_E_NOMEM:
SEND_ERR(px, "Lua applet http '%s': out of memory error.\n", SEND_ERR(px, "Lua applet http '%s': out of memory error.\n",
rule->arg.hlua_rule->fcn->name); rule->arg.hlua_rule->fcn->name);
goto error; goto error;
case HLUA_E_YIELD: /* unexpected */ case HLUA_E_YIELD: /* unexpected */
SEND_ERR(px, "Lua applet http '%s': yield not allowed.\n", SEND_ERR(px, "Lua applet http '%s': yield not allowed.\n",
rule->arg.hlua_rule->fcn->name); rule->arg.hlua_rule->fcn->name);
goto error; goto error;
case HLUA_E_ERR: case HLUA_E_ERR:
/* Display log. */ /* Display log. */
SEND_ERR(px, "Lua applet http '%s' return an unknown error.\n", SEND_ERR(px, "Lua applet http '%s' return an unknown error.\n",
rule->arg.hlua_rule->fcn->name); rule->arg.hlua_rule->fcn->name);
goto error; goto error;
default: default:
goto error; goto error;
}
} }
if (http_ctx->flags & APPLET_DONE) { if (http_ctx->flags & APPLET_DONE) {
if (http_ctx->flags & APPLET_RSP_SENT) if (http_ctx->flags & APPLET_RSP_SENT)
goto done; goto out;
if (!(http_ctx->flags & APPLET_HDR_SENT)) if (!(http_ctx->flags & APPLET_HDR_SENT))
goto error; goto error;
@ -9713,26 +9704,19 @@ void hlua_applet_http_fct(struct appctx *ctx)
} }
res_htx->flags |= HTX_FL_EOM; res_htx->flags |= HTX_FL_EOM;
se_fl_set(ctx->sedesc, SE_FL_EOI); se_fl_set(ctx->sedesc, SE_FL_EOI|SE_FL_EOS);
strm->txn->status = http_ctx->status; strm->txn->status = http_ctx->status;
http_ctx->flags |= APPLET_RSP_SENT; http_ctx->flags |= APPLET_RSP_SENT;
} }
done:
if (http_ctx->flags & APPLET_DONE) {
if (!(res->flags & CF_SHUTR))
sc_shutr(sc);
/* eat the whole request */
if (co_data(req)) {
req_htx = htx_from_buf(&req->buf);
co_htx_skip(req, req_htx, co_data(req));
htx_to_buf(req_htx, &req->buf);
}
}
out: out:
htx_to_buf(res_htx, &res->buf); htx_to_buf(res_htx, &res->buf);
/* eat the whole request */
if (co_data(req)) {
req_htx = htx_from_buf(&req->buf);
co_htx_skip(req, req_htx, co_data(req));
htx_to_buf(req_htx, &req->buf);
}
return; return;
error: error:
@ -9750,11 +9734,15 @@ void hlua_applet_http_fct(struct appctx *ctx)
memcpy(res->buf.area, b_head(err), b_data(err)); memcpy(res->buf.area, b_head(err), b_data(err));
res_htx = htx_from_buf(&res->buf); res_htx = htx_from_buf(&res->buf);
channel_add_input(res, res_htx->data); channel_add_input(res, res_htx->data);
se_fl_set(ctx->sedesc, SE_FL_EOI|SE_FL_EOS);
} }
else
se_fl_set(ctx->sedesc, SE_FL_ERROR);
if (!(strm->flags & SF_ERR_MASK)) if (!(strm->flags & SF_ERR_MASK))
strm->flags |= SF_ERR_RESOURCE; strm->flags |= SF_ERR_RESOURCE;
http_ctx->flags |= APPLET_DONE; http_ctx->flags |= APPLET_DONE;
goto done; goto out;
} }
static void hlua_applet_http_release(struct appctx *ctx) static void hlua_applet_http_release(struct appctx *ctx)