From 19e48f237f864347678845f03eb5e01c08130efe Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Mon, 17 Mar 2025 16:19:34 +0100 Subject: [PATCH] MINOR: hlua: add an optional timeout to AppletTCP:receive() TCP services might want to be interactive, and without a timeout on receive(), the possibilities are a bit limited. Let's add an optional timeout in the 3rd argument to possibly limit the wait time. In this case if the timeout strikes before the requested size is complete, a possibly incomplete block will be returned. --- doc/lua-api/index.rst | 6 ++++-- src/hlua.c | 36 ++++++++++++++++++++++++++++++------ 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/doc/lua-api/index.rst b/doc/lua-api/index.rst index e0afaffcd1..11de93882e 100644 --- a/doc/lua-api/index.rst +++ b/doc/lua-api/index.rst @@ -3886,11 +3886,13 @@ AppletTCP class :param class_AppletTCP applet: An :ref:`applettcp_class` :returns: a string. The string can be empty if we reach the end of the stream. -.. js:function:: AppletTCP.receive(applet, [size]) +.. js:function:: AppletTCP.receive(applet, [size, [timeout]]) Reads data from the TCP stream, according to the specified read *size*. If the *size* is missing, the function tries to read all the content of the stream - until the end. + until the end. An optional timeout may be specified in milliseconds. In this + case the function will return no longer than this delay, with the amount of + available data (possibly none). :param class_AppletTCP applet: An :ref:`applettcp_class` :param integer size: the required read size. diff --git a/src/hlua.c b/src/hlua.c index f3ed8999a6..8c58e498d3 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -5321,6 +5321,7 @@ __LJMP static int hlua_applet_tcp_recv_yield(lua_State *L, int status, lua_KCont struct hlua_appctx *luactx = MAY_LJMP(hlua_checkapplet_tcp(L, 1)); struct stconn *sc = appctx_sc(luactx->appctx); size_t len = MAY_LJMP(luaL_checkinteger(L, 2)); + int exp_date = MAY_LJMP(luaL_checkinteger(L, -1)); int ret; const char *blk1; size_t len1; @@ -5335,8 +5336,14 @@ __LJMP static int hlua_applet_tcp_recv_yield(lua_State *L, int status, lua_KCont /* Data not yet available. return yield. */ if (ret == 0) { + if (tick_is_expired(exp_date, now_ms)) { + /* return the result. */ + luaL_pushresult(&luactx->b); + return 1; + } + applet_need_more_data(luactx->appctx); - MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_recv_yield, TICK_ETERNITY, 0)); + MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_recv_yield, exp_date, 0)); } /* End of data: commit the total strings and return. */ @@ -5361,8 +5368,15 @@ __LJMP static int hlua_applet_tcp_recv_yield(lua_State *L, int status, lua_KCont b_del(&luactx->appctx->inbuf, len1 + len2); else co_skip(sc_oc(sc), len1 + len2); + + if (tick_is_expired(exp_date, now_ms)) { + /* return the result. */ + luaL_pushresult(&luactx->b); + return 1; + } + applet_need_more_data(luactx->appctx); - MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_recv_yield, TICK_ETERNITY, 0)); + MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_recv_yield, exp_date, 0)); } else { @@ -5384,11 +5398,11 @@ __LJMP static int hlua_applet_tcp_recv_yield(lua_State *L, int status, lua_KCont co_skip(sc_oc(sc), len1 + len2); /* If there is no other data available, yield waiting for new data. */ - if (len > 0) { + if (len > 0 && !tick_is_expired(exp_date, now_ms)) { lua_pushinteger(L, len); lua_replace(L, 2); applet_need_more_data(luactx->appctx); - MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_recv_yield, TICK_ETERNITY, 0)); + MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_recv_yield, exp_date, 0)); } /* return the result. */ @@ -5406,11 +5420,17 @@ __LJMP static int hlua_applet_tcp_recv_yield(lua_State *L, int status, lua_KCont __LJMP static int hlua_applet_tcp_recv(lua_State *L) { struct hlua_appctx *luactx = MAY_LJMP(hlua_checkapplet_tcp(L, 1)); + int exp_date; + int delay = 0; int len = -1; - if (lua_gettop(L) > 2) - WILL_LJMP(luaL_error(L, "The 'recv' function requires between 1 and 2 arguments.")); + if (lua_gettop(L) > 3) + WILL_LJMP(luaL_error(L, "The 'recv' function requires between 1 and 3 arguments.")); if (lua_gettop(L) >= 2) { + if (lua_gettop(L) >= 3) { + delay = MAY_LJMP(luaL_checkinteger(L, 3)); + lua_pop(L, 1); + } len = MAY_LJMP(luaL_checkinteger(L, 2)); lua_pop(L, 1); } @@ -5418,6 +5438,10 @@ __LJMP static int hlua_applet_tcp_recv(lua_State *L) /* Confirm or set the required length */ lua_pushinteger(L, len); + /* set the expiration date */ + exp_date = delay ? tick_add(now_ms, delay) : TICK_ETERNITY; + lua_pushinteger(L, exp_date); + /* Initialise the string catenation. */ luaL_buffinit(L, &luactx->b); -- 2.39.5