: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.
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;
/* 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. */
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 {
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. */
__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);
}
/* 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);