From 02bdea2bce46b7833133f5e2c2dfa34630fe047c Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Mon, 2 Jun 2025 15:47:03 -0600 Subject: [PATCH] lua/streaming: provide streaming buffer as argument When setting up a Lua output script for streaming data, we're explicitly requesting stream data. Just pass the streaming data as arguments, rather than requiring the script to make an extra call to get the stream data. The streaming data will be passed in the "stream" field of the args passed to the log function. Eliminates the SCStreamingBuffer Lua function. --- doc/userguide/lua/lua-functions.rst | 28 +++++++++------- src/output-lua.c | 30 ++++++++++++----- src/util-lua-common.c | 52 ++++++++++------------------- src/util-lua-common.h | 3 ++ 4 files changed, 58 insertions(+), 55 deletions(-) diff --git a/doc/userguide/lua/lua-functions.rst b/doc/userguide/lua/lua-functions.rst index 9f87197670..de38f03aed 100644 --- a/doc/userguide/lua/lua-functions.rst +++ b/doc/userguide/lua/lua-functions.rst @@ -236,20 +236,24 @@ In case of HTTP body data, the bodies are unzipped and dechunked if applicable. return needs end -SCStreamingBuffer -~~~~~~~~~~~~~~~~~ - -:: +The streaming data will be provided in the ``args`` to the log +function within a ``stream`` subtable:: function log(args) - -- sb_ts and sb_tc are bools indicating the direction of the data - data, sb_open, sb_close, sb_ts, sb_tc = SCStreamingBuffer() - if sb_ts then - print("->") - else - print("<-") - end - hex_dump(data) + -- The data (buffer) + local data = args["stream"]["data"] + + -- Buffer open? + local open = args["stream"]["open"] + + -- Buffer closed? + local close = args["stream"]["close"] + + -- To server? + local ts = args["stream"]["toserver"] + + -- To client? + local tc = args["stream"]["toclient"] end Flow variables diff --git a/src/output-lua.c b/src/output-lua.c index 7d737ab3f2..77597220ab 100644 --- a/src/output-lua.c +++ b/src/output-lua.c @@ -126,23 +126,37 @@ static int LuaStreamingLogger(ThreadVars *tv, void *thread_data, const Flow *f, } LogLuaThreadCtx *td = (LogLuaThreadCtx *)thread_data; + lua_State *luastate = td->lua_ctx->luastate; SCMutexLock(&td->lua_ctx->m); - LuaStateSetThreadVars(td->lua_ctx->luastate, tv); + LuaStateSetThreadVars(luastate, tv); if (flags & OUTPUT_STREAMING_FLAG_TRANSACTION) - LuaStateSetTX(td->lua_ctx->luastate, txptr, tx_id); - LuaStateSetFlow(td->lua_ctx->luastate, (Flow *)f); - LuaStateSetStreamingBuffer(td->lua_ctx->luastate, &b); + LuaStateSetTX(luastate, txptr, tx_id); + LuaStateSetFlow(luastate, (Flow *)f); + LuaStateSetStreamingBuffer(luastate, &b); /* prepare data to pass to script */ - lua_getglobal(td->lua_ctx->luastate, "log"); - lua_newtable(td->lua_ctx->luastate); + lua_getglobal(luastate, "log"); + lua_newtable(luastate); if (flags & OUTPUT_STREAMING_FLAG_TRANSACTION) - LuaPushTableKeyValueInt(td->lua_ctx->luastate, "tx_id", (int)(tx_id)); + LuaPushTableKeyValueInt(luastate, "tx_id", (int)(tx_id)); - int retval = lua_pcall(td->lua_ctx->luastate, 1, 0, 0); + /* create the "stream" subtable */ + lua_pushstring(luastate, "stream"); + lua_newtable(luastate); + + LuaPushTableKeyValueLString(luastate, "data", (const char *)data, data_len); + LuaPushTableKeyValueBoolean(luastate, "open", flags & OUTPUT_STREAMING_FLAG_OPEN); + LuaPushTableKeyValueBoolean(luastate, "close", flags & OUTPUT_STREAMING_FLAG_CLOSE); + LuaPushTableKeyValueBoolean(luastate, "to_server", flags & OUTPUT_STREAMING_FLAG_TOSERVER); + LuaPushTableKeyValueBoolean(luastate, "to_client", flags & OUTPUT_STREAMING_FLAG_TOCLIENT); + + /* set the "stream" subtable into the main args table */ + lua_settable(luastate, -3); + + int retval = lua_pcall(luastate, 1, 0, 0); if (retval != 0) { SCLogInfo("failed to run script: %s", lua_tostring(td->lua_ctx->luastate, -1)); } diff --git a/src/util-lua-common.c b/src/util-lua-common.c index ca9b9915fd..9498b9b9f2 100644 --- a/src/util-lua-common.c +++ b/src/util-lua-common.c @@ -63,6 +63,13 @@ void LuaPushTableKeyValueInt(lua_State *luastate, const char *key, int value) lua_settable(luastate, -3); } +void LuaPushTableKeyValueBoolean(lua_State *luastate, const char *key, bool value) +{ + lua_pushstring(luastate, key); + lua_pushboolean(luastate, value); + lua_settable(luastate, -3); +} + /** \brief Push a key plus string value to the stack * * If value is NULL, string "(null")" will be put on the stack. @@ -74,43 +81,22 @@ void LuaPushTableKeyValueString(lua_State *luastate, const char *key, const char lua_settable(luastate, -3); } -void LuaPushTableKeyValueArray(lua_State *luastate, const char *key, const uint8_t *value, size_t len) +/** \brief Push a key plus string value with length to the stack. + */ +void LuaPushTableKeyValueLString( + lua_State *luastate, const char *key, const char *value, size_t len) { lua_pushstring(luastate, key); - LuaPushStringBuffer(luastate, value, len); + lua_pushlstring(luastate, value, len); lua_settable(luastate, -3); } -/** \internal - * \brief fill lua stack with payload - * \param luastate the lua state - * \param p packet - * \retval cnt number of data items placed on the stack - * - * Places: payload (string), open (bool), close (bool), toserver (bool), toclient (bool) - */ -static int LuaCallbackStreamingBufferPushToStack(lua_State *luastate, const LuaStreamingBuffer *b) +void LuaPushTableKeyValueArray( + lua_State *luastate, const char *key, const uint8_t *value, size_t len) { - //PrintRawDataFp(stdout, (uint8_t *)b->data, b->data_len); - lua_pushlstring (luastate, (const char *)b->data, b->data_len); - lua_pushboolean (luastate, (b->flags & OUTPUT_STREAMING_FLAG_OPEN)); - lua_pushboolean (luastate, (b->flags & OUTPUT_STREAMING_FLAG_CLOSE)); - lua_pushboolean (luastate, (b->flags & OUTPUT_STREAMING_FLAG_TOSERVER)); - lua_pushboolean (luastate, (b->flags & OUTPUT_STREAMING_FLAG_TOCLIENT)); - return 5; -} - -/** \internal - * \brief Wrapper for getting payload into a lua script - * \retval cnt number of items placed on the stack - */ -static int LuaCallbackStreamingBuffer(lua_State *luastate) -{ - const LuaStreamingBuffer *b = LuaStateGetStreamingBuffer(luastate); - if (b == NULL) - return LuaCallbackError(luastate, "internal error: no buffer"); - - return LuaCallbackStreamingBufferPushToStack(luastate, b); + lua_pushstring(luastate, key); + LuaPushStringBuffer(luastate, value, len); + lua_settable(luastate, -3); } /** \internal @@ -145,10 +131,6 @@ static int LuaCallbackThreadInfo(lua_State *luastate) int LuaRegisterFunctions(lua_State *luastate) { - /* registration of the callbacks */ - lua_pushcfunction(luastate, LuaCallbackStreamingBuffer); - lua_setglobal(luastate, "SCStreamingBuffer"); - lua_pushcfunction(luastate, LuaCallbackThreadInfo); lua_setglobal(luastate, "SCThreadInfo"); return 0; diff --git a/src/util-lua-common.h b/src/util-lua-common.h index fe90dffe2b..ddeca01b48 100644 --- a/src/util-lua-common.h +++ b/src/util-lua-common.h @@ -31,7 +31,10 @@ int LuaCallbackError(lua_State *luastate, const char *msg); const char *LuaGetStringArgument(lua_State *luastate, int argc); void LuaPushTableKeyValueInt(lua_State *luastate, const char *key, int value); +void LuaPushTableKeyValueBoolean(lua_State *luastate, const char *key, bool value); void LuaPushTableKeyValueString(lua_State *luastate, const char *key, const char *value); +void LuaPushTableKeyValueLString( + lua_State *luastate, const char *key, const char *value, size_t len); void LuaPushTableKeyValueArray(lua_State *luastate, const char *key, const uint8_t *value, size_t len); int LuaRegisterFunctions(lua_State *luastate);