]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: hlua: add an optional timeout to AppletTCP:receive()
authorWilly Tarreau <w@1wt.eu>
Mon, 17 Mar 2025 15:19:34 +0000 (16:19 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 17 Mar 2025 15:19:34 +0000 (16:19 +0100)
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
src/hlua.c

index e0afaffcd136c9f7345cd5dcb6e9936399c3e928..11de93882e04cca2cdd5b88b449ad84593f704a8 100644 (file)
@@ -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.
index f3ed8999a6d93ac66c11aacd5c978d40050ee5a7..8c58e498d327c5d808682f275a398d51d1ca146b 100644 (file)
@@ -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);