This is an automated email from the ASF dual-hosted git repository.
kichan pushed a commit to branch 8.1.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/8.1.x by this push:
new 32cbd5baad Add support for vconn start handler for lua plugin (#10575)
32cbd5baad is described below
commit 32cbd5baadc946fc87c78b1b3a8b778a081ff3c7
Author: Kit Chan <[email protected]>
AuthorDate: Mon Oct 9 15:43:42 2023 -0300
Add support for vconn start handler for lua plugin (#10575)
* add support for vconn start for lua plugin
* fix clang format
---
doc/admin-guide/plugins/lua.en.rst | 84 +++++++++++++++++++++++
plugins/lua/Makefile.inc | 1 +
plugins/lua/example/test_vconn.lua | 40 +++++++++++
plugins/lua/ts_lua.c | 87 ++++++++++++++++++++++++
plugins/lua/ts_lua_common.h | 17 +++++
plugins/lua/ts_lua_fetch.c | 4 ++
plugins/lua/ts_lua_hook.c | 10 +++
plugins/lua/ts_lua_http.c | 131 ++++++++++++++++++++++++++++++++++++
plugins/lua/ts_lua_http_intercept.c | 2 +
plugins/lua/ts_lua_misc.c | 6 ++
plugins/lua/ts_lua_util.c | 92 +++++++++++++++++++++++++
plugins/lua/ts_lua_util.h | 25 +++++--
plugins/lua/ts_lua_vconn.c | 87 ++++++++++++++++++++++++
plugins/lua/ts_lua_vconn.h | 21 ++++++
14 files changed, 602 insertions(+), 5 deletions(-)
diff --git a/doc/admin-guide/plugins/lua.en.rst
b/doc/admin-guide/plugins/lua.en.rst
index 8cf69b17ba..3e27e1ba44 100644
--- a/doc/admin-guide/plugins/lua.en.rst
+++ b/doc/admin-guide/plugins/lua.en.rst
@@ -96,6 +96,7 @@ script, and we can write this in remap.config:
This module can also act as a global plugin of Traffic Server. In this case we
should provide one of these functions in
each lua script:
+- **'do_global_vconn_start'**
- **'do_global_txn_start'**
- **'do_global_txn_close'**
- **'do_global_os_dns'**
@@ -478,6 +479,7 @@ Hook point constants
::
+ TS_LUA_HOOK_VCONN_START
TS_LUA_HOOK_OS_DNS
TS_LUA_HOOK_PRE_REMAP
TS_LUA_HOOK_READ_CACHE_HDR
@@ -501,6 +503,8 @@ Additional Information:
| | | do_remap() via |
do_os_response() | global context via |
| | | ts.hook()? |
via ts.hook()? | ts.hook()? |
+=======================+===========================+======================+====================+======================+
+| TS_VCONN_START_HOOK | TS_LUA_HOOK_VCONN_START | NO |
NO | YES |
++-----------------------+---------------------------+----------------------+--------------------+----------------------+
| TS_HTTP_TXN | TS_LUA_HOOK | NO |
NO | YES |
| _START_HOOK | _TXN_START | |
| |
+-----------------------+---------------------------+----------------------+--------------------+----------------------+
@@ -2745,6 +2749,66 @@ Here is an example
`TOP <#ts-lua-plugin>`_
+ts.http.get_ssn_remote_addr
+---------------------------
+**syntax:** *ts.http.get_ssn_remote_addr()*
+
+**context:** after do_global_read_reqest
+
+**description:** This function can be used to get the remote address (IP,
port, family) of the session.
+
+`TOP <#ts-lua-plugin>`_
+
+ts.http.get_client_received_error
+---------------------------------
+**syntax:** *ts.http.get_client_received_error()*
+
+**context:** after do_global_txn_close
+
+**description:** This function can be used to get the client received error
from transaction.
+
+Here is an example
+
+::
+
+ function do_global_txn_close()
+ local class, code = ts.http.get_client_received_error()
+ ts.debug('txn_close: '..class)
+ ts.debug('txn_close: '..code)
+ end
+
+`TOP <#ts-lua-plugin>`_
+
+ts.http.get_client_sent_error
+-----------------------------
+**syntax:** *ts.http.get_client_sent_error()*
+
+**context:** after do_global_txn_close
+
+**description:** This function can be used to get the client sent error from
transaction.
+
+`TOP <#ts-lua-plugin>`_
+
+ts.http.get_server_received_error
+---------------------------------
+**syntax:** *ts.http.get_server_received_error()*
+
+**context:** after do_global_txn_close
+
+**description:** This function can be used to get the server received error
from transaction.
+
+`TOP <#ts-lua-plugin>`_
+
+ts.http.get_server_sent_error
+-----------------------------
+**syntax:** *ts.http.get_server_sent_error()*
+
+**context:** after do_global_txn_close
+
+**description:** This function can be used to get the server sent error from
transaction.
+
+`TOP <#ts-lua-plugin>`_
+
ts.add_package_path
-------------------
**syntax:** *ts.add_package_path(lua-style-path-str)*
@@ -3847,6 +3911,26 @@ be returned with 4 functions to increment, decrement,
get and set the value. Tha
`TOP <#ts-lua-plugin>`_
+ts.vconn.get_fd
+---------------
+**syntax:** *ts.vconn.get_fd()*
+
+**context:** do_global_vconn_start
+
+**description:** This function can be used to get the file descriptor of the
virtual connection.
+
+`TOP <#ts-lua-plugin>`_
+
+ts.vconn.get_remote_addr
+------------------------
+**syntax:** *ts.vconn.get_remote_addr()*
+
+**context:** do_global_vconn_start
+
+**description:** This function can be used to get the remote address (IP,
port, family) of the virtual connection.
+
+`TOP <#ts-lua-plugin>`_
+
Todo
====
* ts.cache_xxx
diff --git a/plugins/lua/Makefile.inc b/plugins/lua/Makefile.inc
index adcdde5e87..cfae2e89a4 100644
--- a/plugins/lua/Makefile.inc
+++ b/plugins/lua/Makefile.inc
@@ -26,6 +26,7 @@ lua_tslua_la_SOURCES = \
lua/ts_lua_client_response.c \
lua/ts_lua_context.c \
lua/ts_lua_hook.c \
+ lua/ts_lua_vconn.c \
lua/ts_lua_http.c \
lua/ts_lua_http_intercept.c \
lua/ts_lua_log.c \
diff --git a/plugins/lua/example/test_vconn.lua
b/plugins/lua/example/test_vconn.lua
new file mode 100644
index 0000000000..70175ef171
--- /dev/null
+++ b/plugins/lua/example/test_vconn.lua
@@ -0,0 +1,40 @@
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements. See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership. The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+function do_global_vconn_start()
+ ts.debug('vconn_start')
+
+ ip, port, family = ts.vconn.get_remote_addr()
+ ts.debug('vconn: '..ip) -- 192.168.231.17
+ ts.debug('vconn: '..port) -- 17786
+ ts.debug('vconn: '..family) -- 2(AF_INET)
+
+ fd = ts.vconn.get_fd()
+ ts.debug('vconn: '..fd)
+end
+
+function do_global_txn_close()
+ ts.debug('txn_close')
+
+ ip, port, family = ts.http.get_ssn_remote_addr()
+ ts.debug('txn_close: '..ip) -- 192.168.231.17
+ ts.debug('txn_close: '..port) -- 17786
+ ts.debug('txn_close: '..family) -- 2(AF_INET)
+
+ class, code = ts.http.get_client_received_error()
+ ts.debug('txn_close: '..class)
+ ts.debug('txn_close: '..code)
+end
diff --git a/plugins/lua/ts_lua.c b/plugins/lua/ts_lua.c
index 2a4cbc34f3..2e758e55b5 100644
--- a/plugins/lua/ts_lua.c
+++ b/plugins/lua/ts_lua.c
@@ -555,6 +555,73 @@ configHandler(TSCont contp, TSEvent event ATS_UNUSED, void
*edata ATS_UNUSED)
return 0;
}
+static int
+vconnHookHandler(TSCont contp, TSEvent event, void *edata)
+{
+ TSVConn vconn = (TSVConn)edata;
+
+ int ret;
+ uint64_t req_id;
+
+ lua_State *l;
+
+ ts_lua_main_ctx *main_ctx;
+ ts_lua_vconn_ctx *vconn_ctx;
+
+ ts_lua_instance_conf *conf = (ts_lua_instance_conf *)TSContDataGet(contp);
+
+ req_id = __sync_fetch_and_add(&ts_lua_g_http_next_id, 1);
+
+ main_ctx = &ts_lua_g_main_ctx_array[req_id % conf->states];
+
+ TSDebug(TS_LUA_DEBUG_TAG, "[%s] req_id: %" PRId64, __FUNCTION__, req_id);
+
+ TSMutexLock(main_ctx->mutexp);
+
+ vconn_ctx = ts_lua_create_vconn_ctx(main_ctx, conf);
+ vconn_ctx->vconn = vconn;
+ l = vconn_ctx->lua;
+
+ switch (event) {
+ case TS_EVENT_VCONN_START:
+ lua_getglobal(l, TS_LUA_FUNCTION_G_VCONN_START);
+ break;
+
+ default:
+ ts_lua_destroy_vconn_ctx(vconn_ctx);
+ TSMutexUnlock(main_ctx->mutexp);
+ TSVConnReenable(vconn);
+ return 0;
+ }
+
+ if (lua_type(l, -1) != LUA_TFUNCTION) {
+ lua_pop(l, 1);
+ ts_lua_destroy_vconn_ctx(vconn_ctx);
+ TSMutexUnlock(main_ctx->mutexp);
+
+ TSVConnReenable(vconn);
+ return 0;
+ }
+
+ if (lua_pcall(l, 0, 1, 0) != 0) {
+ TSError("[ts_lua][%s] lua_pcall failed: %s", __FUNCTION__, lua_tostring(l,
-1));
+ }
+
+ ret = lua_tointeger(l, -1);
+ lua_pop(l, 1);
+
+ ts_lua_destroy_vconn_ctx(vconn_ctx);
+
+ TSMutexUnlock(main_ctx->mutexp);
+ if (ret) {
+ TSError("[ts_lua][%s] error returned", __FUNCTION__);
+ } else {
+ TSDebug(TS_LUA_DEBUG_TAG, "[%s] no error returned", __FUNCTION__);
+ }
+ TSVConnReenable(vconn);
+ return 0;
+}
+
static int
globalHookHandler(TSCont contp, TSEvent event ATS_UNUSED, void *edata)
{
@@ -908,6 +975,26 @@ TSPluginInit(int argc, const char *argv[])
ts_lua_destroy_http_ctx(http_ctx);
+ TSCont vconn_contp = TSContCreate(vconnHookHandler, NULL);
+ if (!vconn_contp) {
+ TSError("[ts_lua][%s] could not create vconn continuation", __FUNCTION__);
+ return;
+ }
+ TSContDataSet(vconn_contp, conf);
+
+ // adding hook based on whther the lua global vconn function exists
+ ts_lua_vconn_ctx *vconn_ctx = ts_lua_create_vconn_ctx(main_ctx, conf);
+ lua_State *vl = vconn_ctx->lua;
+
+ lua_getglobal(vl, TS_LUA_FUNCTION_G_VCONN_START);
+ if (lua_type(vl, -1) == LUA_TFUNCTION) {
+ TSHttpHookAdd(TS_VCONN_START_HOOK, vconn_contp);
+ TSDebug(TS_LUA_DEBUG_TAG, "vconn_start_hook added");
+ }
+ lua_pop(vl, 1);
+
+ ts_lua_destroy_vconn_ctx(vconn_ctx);
+
// support for reload as global plugin
if (reload) {
TSCont config_contp = TSContCreate(configHandler, NULL);
diff --git a/plugins/lua/ts_lua_common.h b/plugins/lua/ts_lua_common.h
index dba8b7d77e..3cec245363 100644
--- a/plugins/lua/ts_lua_common.h
+++ b/plugins/lua/ts_lua_common.h
@@ -58,6 +58,9 @@
#define TS_LUA_FUNCTION_G_READ_CACHE "do_global_read_cache"
#define TS_LUA_FUNCTION_G_TXN_CLOSE "do_global_txn_close"
+// TLS hooks can only be global
+#define TS_LUA_FUNCTION_G_VCONN_START "do_global_vconn_start"
+
#define TS_LUA_DEBUG_TAG "ts_lua"
#define TS_LUA_EVENT_COROUTINE_CONT 20000
@@ -100,6 +103,20 @@ typedef struct {
int init_func;
} ts_lua_instance_conf;
+/* lua state for vconn */
+typedef struct {
+ int ref;
+
+ ts_lua_main_ctx *mctx;
+
+ lua_State *lua;
+
+ TSVConn vconn;
+
+ ts_lua_instance_conf *instance_conf;
+
+} ts_lua_vconn_ctx;
+
/* lua state for http request */
typedef struct {
ts_lua_cont_info cinfo;
diff --git a/plugins/lua/ts_lua_fetch.c b/plugins/lua/ts_lua_fetch.c
index f76e990d06..d27fd66a18 100644
--- a/plugins/lua/ts_lua_fetch.c
+++ b/plugins/lua/ts_lua_fetch.c
@@ -60,6 +60,8 @@ ts_lua_fetch(lua_State *L)
ci = ts_lua_get_cont_info(L);
if (ci == NULL) {
+ TSError("[ts_lua][%s] no cont info found", __FUNCTION__);
+ TSReleaseAssert(!"Unexpected fetch of cont info");
return 0;
}
@@ -124,6 +126,8 @@ ts_lua_fetch_multi(lua_State *L)
ci = ts_lua_get_cont_info(L);
if (ci == NULL) {
+ TSError("[ts_lua][%s] no cont info found", __FUNCTION__);
+ TSReleaseAssert(!"Unexpected fetch of cont info");
return 0;
}
diff --git a/plugins/lua/ts_lua_hook.c b/plugins/lua/ts_lua_hook.c
index 81e32983ce..227a0f4335 100644
--- a/plugins/lua/ts_lua_hook.c
+++ b/plugins/lua/ts_lua_hook.c
@@ -35,6 +35,7 @@ typedef enum {
TS_LUA_HOOK_TXN_CLOSE,
TS_LUA_REQUEST_TRANSFORM,
TS_LUA_RESPONSE_TRANSFORM,
+ TS_LUA_HOOK_VCONN_START,
TS_LUA_HOOK_LAST
} TSLuaHookID;
@@ -52,6 +53,7 @@ char *ts_lua_hook_id_string[] = {"TS_LUA_HOOK_DUMMY",
"TS_LUA_HOOK_TXN_CLOSE",
"TS_LUA_REQUEST_TRANSFORM",
"TS_LUA_RESPONSE_TRANSFORM",
+ "TS_LUA_HOOK_VCONN_START",
"TS_LUA_HOOK_LAST"};
static int ts_lua_add_hook(lua_State *L);
@@ -240,6 +242,14 @@ ts_lua_add_hook(lua_State *L)
}
break;
+ case TS_LUA_HOOK_VCONN_START:
+ if (http_ctx) {
+ TSError("[ts_lua][%s] VCONN_START handler can only be global",
__FUNCTION__);
+ } else {
+ lua_pushvalue(L, 2);
+ lua_setglobal(L, TS_LUA_FUNCTION_G_VCONN_START);
+ }
+
default:
break;
}
diff --git a/plugins/lua/ts_lua_http.c b/plugins/lua/ts_lua_http.c
index b10fefba1c..2e9f7cf674 100644
--- a/plugins/lua/ts_lua_http.c
+++ b/plugins/lua/ts_lua_http.c
@@ -16,6 +16,8 @@
limitations under the License.
*/
+#include <netinet/in.h>
+#include <arpa/inet.h>
#include "ts_lua_util.h"
#include "ts_lua_http_intercept.h"
#include "ts_lua_http_config.h"
@@ -101,6 +103,13 @@ static int ts_lua_http_get_remap_to_url(lua_State *L);
static int ts_lua_http_get_server_fd(lua_State *L);
static int ts_lua_http_get_client_fd(lua_State *L);
+static int ts_lua_http_get_client_received_error(lua_State *L);
+static int ts_lua_http_get_client_sent_error(lua_State *L);
+static int ts_lua_http_get_server_received_error(lua_State *L);
+static int ts_lua_http_get_server_sent_error(lua_State *L);
+
+static int ts_lua_http_get_ssn_remote_addr(lua_State *L);
+
static void ts_lua_inject_server_state_variables(lua_State *L);
static void ts_lua_inject_http_resp_transform_api(lua_State *L);
@@ -257,6 +266,21 @@ ts_lua_inject_http_misc_api(lua_State *L)
lua_pushcfunction(L, ts_lua_http_get_client_fd);
lua_setfield(L, -2, "get_client_fd");
+ lua_pushcfunction(L, ts_lua_http_get_client_received_error);
+ lua_setfield(L, -2, "get_client_received_error");
+
+ lua_pushcfunction(L, ts_lua_http_get_client_sent_error);
+ lua_setfield(L, -2, "get_client_sent_error");
+
+ lua_pushcfunction(L, ts_lua_http_get_server_received_error);
+ lua_setfield(L, -2, "get_server_received_error");
+
+ lua_pushcfunction(L, ts_lua_http_get_server_sent_error);
+ lua_setfield(L, -2, "get_server_sent_error");
+
+ lua_pushcfunction(L, ts_lua_http_get_ssn_remote_addr);
+ lua_setfield(L, -2, "get_ssn_remote_addr");
+
ts_lua_inject_server_state_variables(L);
}
@@ -876,6 +900,109 @@ ts_lua_http_get_client_fd(lua_State *L)
return 1;
}
+static int
+ts_lua_http_get_client_received_error(lua_State *L)
+{
+ uint32_t class = 0;
+ uint64_t code = 0;
+ ts_lua_http_ctx *http_ctx;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ TSHttpTxnClientReceivedErrorGet(http_ctx->txnp, &class, &code);
+ lua_pushnumber(L, class);
+ lua_pushnumber(L, code);
+
+ return 2;
+}
+
+static int
+ts_lua_http_get_client_sent_error(lua_State *L)
+{
+ uint32_t class = 0;
+ uint64_t code = 0;
+ ts_lua_http_ctx *http_ctx;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ TSHttpTxnClientSentErrorGet(http_ctx->txnp, &class, &code);
+ lua_pushnumber(L, class);
+ lua_pushnumber(L, code);
+
+ return 2;
+}
+
+static int
+ts_lua_http_get_server_received_error(lua_State *L)
+{
+ uint32_t class = 0;
+ uint64_t code = 0;
+ ts_lua_http_ctx *http_ctx;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ TSHttpTxnServerReceivedErrorGet(http_ctx->txnp, &class, &code);
+ lua_pushnumber(L, class);
+ lua_pushnumber(L, code);
+
+ return 2;
+}
+
+static int
+ts_lua_http_get_server_sent_error(lua_State *L)
+{
+ uint32_t class = 0;
+ uint64_t code = 0;
+ ts_lua_http_ctx *http_ctx;
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ TSHttpTxnServerSentErrorGet(http_ctx->txnp, &class, &code);
+ lua_pushnumber(L, class);
+ lua_pushnumber(L, code);
+
+ return 2;
+}
+
+static int
+ts_lua_http_get_ssn_remote_addr(lua_State *L)
+{
+ struct sockaddr const *client_ip;
+ ts_lua_http_ctx *http_ctx;
+ int port;
+ int family;
+ char cip[128];
+
+ GET_HTTP_CONTEXT(http_ctx, L);
+
+ TSHttpSsn ssn = TSHttpTxnSsnGet(http_ctx->txnp);
+ TSVConn vconn = TSHttpSsnClientVConnGet(ssn);
+ client_ip = TSNetVConnRemoteAddrGet(vconn);
+
+ if (client_ip == NULL) {
+ lua_pushnil(L);
+ lua_pushnil(L);
+ lua_pushnil(L);
+
+ } else {
+ if (client_ip->sa_family == AF_INET) {
+ port = ntohs(((struct sockaddr_in *)client_ip)->sin_port);
+ inet_ntop(AF_INET, (const void *)&((struct sockaddr_in
*)client_ip)->sin_addr, cip, sizeof(cip));
+ family = AF_INET;
+ } else {
+ port = ntohs(((struct sockaddr_in6 *)client_ip)->sin6_port);
+ inet_ntop(AF_INET6, (const void *)&((struct sockaddr_in6
*)client_ip)->sin6_addr, cip, sizeof(cip));
+ family = AF_INET6;
+ }
+
+ lua_pushstring(L, cip);
+ lua_pushnumber(L, port);
+ lua_pushnumber(L, family);
+ }
+
+ return 3;
+}
+
static int
ts_lua_http_resp_transform_get_upstream_bytes(lua_State *L)
{
@@ -884,6 +1011,7 @@ ts_lua_http_resp_transform_get_upstream_bytes(lua_State *L)
transform_ctx = ts_lua_get_http_transform_ctx(L);
if (transform_ctx == NULL) {
TSError("[ts_lua] missing transform_ctx");
+ TSReleaseAssert(!"Unexpected fetch of transform_ctx");
return 0;
}
@@ -900,6 +1028,7 @@
ts_lua_http_resp_transform_get_upstream_watermark_bytes(lua_State *L)
transform_ctx = ts_lua_get_http_transform_ctx(L);
if (transform_ctx == NULL) {
TSError("[ts_lua] missing transform_ctx");
+ TSReleaseAssert(!"Unexpected fetch of transform_ctx");
return 0;
}
@@ -917,6 +1046,7 @@
ts_lua_http_resp_transform_set_upstream_watermark_bytes(lua_State *L)
transform_ctx = ts_lua_get_http_transform_ctx(L);
if (transform_ctx == NULL) {
TSError("[ts_lua] missing transform_ctx");
+ TSReleaseAssert(!"Unexpected fetch of transform_ctx");
return 0;
}
@@ -936,6 +1066,7 @@ ts_lua_http_resp_transform_set_downstream_bytes(lua_State
*L)
transform_ctx = ts_lua_get_http_transform_ctx(L);
if (transform_ctx == NULL) {
TSError("[ts_lua] missing transform_ctx");
+ TSReleaseAssert(!"Unexpected fetch of transform_ctx");
return 0;
}
diff --git a/plugins/lua/ts_lua_http_intercept.c
b/plugins/lua/ts_lua_http_intercept.c
index 048f52d918..deec525266 100644
--- a/plugins/lua/ts_lua_http_intercept.c
+++ b/plugins/lua/ts_lua_http_intercept.c
@@ -358,6 +358,7 @@ ts_lua_say(lua_State *L)
ictx = ts_lua_get_http_intercept_ctx(L);
if (ictx == NULL) {
TSError("[ts_lua] missing ictx");
+ TSReleaseAssert(!"Unexpected fetch of intercept_ctx");
return 0;
}
@@ -380,6 +381,7 @@ ts_lua_flush(lua_State *L)
ictx = ts_lua_get_http_intercept_ctx(L);
if (ictx == NULL) {
TSError("[ts_lua] missing ictx");
+ TSReleaseAssert(!"Unexpected fetch of intercept_ctx");
return 0;
}
diff --git a/plugins/lua/ts_lua_misc.c b/plugins/lua/ts_lua_misc.c
index 8da3a160aa..f2800fd050 100644
--- a/plugins/lua/ts_lua_misc.c
+++ b/plugins/lua/ts_lua_misc.c
@@ -180,6 +180,8 @@ ts_lua_schedule(lua_State *L)
ci = ts_lua_get_cont_info(L);
if (ci == NULL) {
+ TSError("[ts_lua][%s] no cont info found", __FUNCTION__);
+ TSReleaseAssert(!"Unexpected fetch of cont info");
return 0;
}
@@ -278,6 +280,8 @@ ts_lua_sleep(lua_State *L)
ci = ts_lua_get_cont_info(L);
if (ci == NULL) {
+ TSError("[ts_lua][%s] no cont info found", __FUNCTION__);
+ TSReleaseAssert(!"Unexpected fetch of cont info");
return 0;
}
@@ -338,6 +342,8 @@ ts_lua_host_lookup(lua_State *L)
ci = ts_lua_get_cont_info(L);
if (ci == NULL) {
+ TSError("[ts_lua][%s] no cont info found", __FUNCTION__);
+ TSReleaseAssert(!"Unexpected fetch of cont info");
return 0;
}
diff --git a/plugins/lua/ts_lua_util.c b/plugins/lua/ts_lua_util.c
index 76d86fd88c..ee08617d38 100644
--- a/plugins/lua/ts_lua_util.c
+++ b/plugins/lua/ts_lua_util.c
@@ -26,6 +26,7 @@
#include "ts_lua_cached_response.h"
#include "ts_lua_context.h"
#include "ts_lua_hook.h"
+#include "ts_lua_vconn.h"
#include "ts_lua_http.h"
#include "ts_lua_misc.h"
#include "ts_lua_log.h"
@@ -454,6 +455,8 @@ ts_lua_inject_ts_api(lua_State *L)
ts_lua_inject_context_api(L);
ts_lua_inject_hook_api(L);
+ ts_lua_inject_vconn_api(L);
+
ts_lua_inject_http_api(L);
ts_lua_inject_intercept_api(L);
ts_lua_inject_misc_api(L);
@@ -576,6 +579,95 @@ ts_lua_destroy_async_ctx(ts_lua_http_ctx *http_ctx)
TSfree(http_ctx);
}
+void
+ts_lua_set_vconn_ctx(lua_State *L, ts_lua_vconn_ctx *ctx)
+{
+ lua_pushliteral(L, "__ts_vconn_ctx");
+ lua_pushlightuserdata(L, ctx);
+ lua_rawset(L, LUA_GLOBALSINDEX);
+}
+
+ts_lua_vconn_ctx *
+ts_lua_get_vconn_ctx(lua_State *L)
+{
+ ts_lua_vconn_ctx *ctx;
+
+ lua_pushliteral(L, "__ts_vconn_ctx");
+ lua_rawget(L, LUA_GLOBALSINDEX);
+ ctx = lua_touserdata(L, -1);
+
+ lua_pop(L, 1); // pop the ctx out
+
+ return ctx;
+}
+
+ts_lua_vconn_ctx *
+ts_lua_create_vconn_ctx(ts_lua_main_ctx *main_ctx, ts_lua_instance_conf *conf)
+{
+ ts_lua_vconn_ctx *vconn_ctx;
+
+ vconn_ctx = TSmalloc(sizeof(ts_lua_vconn_ctx));
+ memset(vconn_ctx, 0, sizeof(*vconn_ctx));
+
+ lua_State *L = main_ctx->lua;
+ lua_State *l = lua_newthread(L);
+
+ lua_pushlightuserdata(L, conf);
+ lua_rawget(L, LUA_REGISTRYINDEX);
+
+ /* new globals table for coroutine */
+ lua_newtable(l);
+ lua_pushvalue(l, -1);
+ lua_setfield(l, -2, "_G");
+ lua_newtable(l);
+ lua_xmove(L, l, 1);
+ lua_setfield(l, -2, "__index");
+ lua_setmetatable(l, -2);
+
+ lua_replace(l, LUA_GLOBALSINDEX);
+
+ // init coroutine
+ vconn_ctx->ref = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ vconn_ctx->lua = l;
+ vconn_ctx->mctx = main_ctx;
+
+ // update thread stats
+ ts_lua_ctx_stats *const stats = main_ctx->stats;
+
+ TSMutexLock(stats->mutexp);
+ ++stats->threads;
+ if (stats->threads_max < stats->threads) {
+ stats->threads_max = stats->threads;
+ }
+ TSMutexUnlock(stats->mutexp);
+
+ vconn_ctx->instance_conf = conf;
+
+ ts_lua_set_vconn_ctx(l, vconn_ctx);
+ ts_lua_create_context_table(l);
+
+ return vconn_ctx;
+}
+
+void
+ts_lua_destroy_vconn_ctx(ts_lua_vconn_ctx *vconn_ctx)
+{
+ // update thread stats
+ ts_lua_main_ctx *const main_ctx = vconn_ctx->mctx;
+ ts_lua_ctx_stats *const stats = main_ctx->stats;
+
+ TSMutexLock(stats->mutexp);
+ --stats->threads;
+ TSMutexUnlock(stats->mutexp);
+
+ if (vconn_ctx->lua) {
+ luaL_unref(vconn_ctx->lua, LUA_REGISTRYINDEX, vconn_ctx->ref);
+ }
+
+ TSfree(vconn_ctx);
+}
+
void
ts_lua_set_http_ctx(lua_State *L, ts_lua_http_ctx *ctx)
{
diff --git a/plugins/lua/ts_lua_util.h b/plugins/lua/ts_lua_util.h
index d75db9f188..b35890db17 100644
--- a/plugins/lua/ts_lua_util.h
+++ b/plugins/lua/ts_lua_util.h
@@ -46,16 +46,31 @@ void ts_lua_destroy_async_ctx(ts_lua_http_ctx *http_ctx);
void ts_lua_set_http_ctx(lua_State *L, ts_lua_http_ctx *ctx);
ts_lua_http_ctx *ts_lua_get_http_ctx(lua_State *L);
-#define GET_HTTP_CONTEXT(ctx, list) \
- ctx = ts_lua_get_http_ctx(list); \
- if (ctx == NULL) { \
- TSError("[ts_lua] missing http_ctx"); \
- return 0; \
+#define GET_HTTP_CONTEXT(ctx, list) \
+ ctx = ts_lua_get_http_ctx(list); \
+ if (ctx == NULL) { \
+ TSError("[ts_lua] missing http_ctx"); \
+ TSReleaseAssert(!"Unexpected fetch of http_ctx"); \
+ return 0; \
+ }
+
+#define GET_VCONN_CONTEXT(ctx, list) \
+ ctx = ts_lua_get_vconn_ctx(list); \
+ if (ctx == NULL) { \
+ TSError("[ts_lua] missing vconn_ctx"); \
+ TSReleaseAssert(!"Unexpected fetch of vconn_ctx"); \
+ return 0; \
}
ts_lua_http_ctx *ts_lua_create_http_ctx(ts_lua_main_ctx *mctx,
ts_lua_instance_conf *conf);
void ts_lua_destroy_http_ctx(ts_lua_http_ctx *http_ctx);
+void ts_lua_set_vconn_ctx(lua_State *L, ts_lua_vconn_ctx *ctx);
+ts_lua_vconn_ctx *ts_lua_get_vconn_ctx(lua_State *L);
+
+ts_lua_vconn_ctx *ts_lua_create_vconn_ctx(ts_lua_main_ctx *mctx,
ts_lua_instance_conf *conf);
+void ts_lua_destroy_vconn_ctx(ts_lua_vconn_ctx *vconn_ctx);
+
ts_lua_http_transform_ctx *ts_lua_create_http_transform_ctx(ts_lua_http_ctx
*http_ctx, TSVConn connp);
void ts_lua_destroy_http_transform_ctx(ts_lua_http_transform_ctx
*transform_ctx);
void ts_lua_set_http_transform_ctx(lua_State *L, ts_lua_http_transform_ctx
*tctx);
diff --git a/plugins/lua/ts_lua_vconn.c b/plugins/lua/ts_lua_vconn.c
new file mode 100644
index 0000000000..dd1e4b5381
--- /dev/null
+++ b/plugins/lua/ts_lua_vconn.c
@@ -0,0 +1,87 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "ts_lua_util.h"
+
+static int ts_lua_vconn_get_remote_addr(lua_State *L);
+static int ts_lua_vconn_get_fd(lua_State *L);
+
+void
+ts_lua_inject_vconn_api(lua_State *L)
+{
+ lua_newtable(L);
+
+ lua_pushcfunction(L, ts_lua_vconn_get_remote_addr);
+ lua_setfield(L, -2, "get_remote_addr");
+
+ lua_pushcfunction(L, ts_lua_vconn_get_fd);
+ lua_setfield(L, -2, "get_fd");
+
+ lua_setfield(L, -2, "vconn");
+}
+
+static int
+ts_lua_vconn_get_remote_addr(lua_State *L)
+{
+ ts_lua_vconn_ctx *vconn_ctx;
+ int port;
+ int family;
+ char sip[128];
+
+ GET_VCONN_CONTEXT(vconn_ctx, L);
+
+ struct sockaddr const *addr = TSNetVConnRemoteAddrGet(vconn_ctx->vconn);
+
+ if (addr == NULL) {
+ lua_pushnil(L);
+ lua_pushnil(L);
+ lua_pushnil(L);
+ } else {
+ if (addr->sa_family == AF_INET) {
+ port = ntohs(((struct sockaddr_in *)addr)->sin_port);
+ inet_ntop(AF_INET, (const void *)&((struct sockaddr_in
*)addr)->sin_addr, sip, sizeof(sip));
+ family = AF_INET;
+ } else {
+ port = ntohs(((struct sockaddr_in6 *)addr)->sin6_port);
+ inet_ntop(AF_INET6, (const void *)&((struct sockaddr_in6
*)addr)->sin6_addr, sip, sizeof(sip));
+ family = AF_INET6;
+ }
+
+ lua_pushstring(L, sip);
+ lua_pushnumber(L, port);
+ lua_pushnumber(L, family);
+ }
+
+ return 3;
+}
+
+static int
+ts_lua_vconn_get_fd(lua_State *L)
+{
+ int fd = 0;
+ ts_lua_vconn_ctx *vconn_ctx;
+
+ GET_VCONN_CONTEXT(vconn_ctx, L);
+
+ fd = TSVConnFdGet(vconn_ctx->vconn);
+
+ lua_pushnumber(L, fd);
+
+ return 1;
+}
diff --git a/plugins/lua/ts_lua_vconn.h b/plugins/lua/ts_lua_vconn.h
new file mode 100644
index 0000000000..6239f86435
--- /dev/null
+++ b/plugins/lua/ts_lua_vconn.h
@@ -0,0 +1,21 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#pragma once
+
+#include "ts_lua_common.h"
+
+void ts_lua_inject_vconn_api(lua_State *L);