1 /*
2 Licensed to the Apache Software Foundation (ASF) under one
3 or more contributor license agreements. See the NOTICE file
4 distributed with this work for additional information
5 regarding copyright ownership. The ASF licenses this file
6 to you under the Apache License, Version 2.0 (the
7 "License"); you may not use this file except in compliance
8 with the License. You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 */
18
19 #include "ts_lua_hook.h"
20 #include "ts_lua_transform.h"
21 #include "ts_lua_util.h"
22
23 typedef enum {
24 TS_LUA_HOOK_DUMMY = 0,
25 TS_LUA_HOOK_CACHE_LOOKUP_COMPLETE,
26 TS_LUA_HOOK_SEND_REQUEST_HDR,
27 TS_LUA_HOOK_READ_RESPONSE_HDR,
28 TS_LUA_HOOK_SEND_RESPONSE_HDR,
29 TS_LUA_HOOK_READ_REQUEST_HDR,
30 TS_LUA_HOOK_TXN_START,
31 TS_LUA_HOOK_PRE_REMAP,
32 TS_LUA_HOOK_POST_REMAP,
33 TS_LUA_HOOK_OS_DNS,
34 TS_LUA_HOOK_READ_CACHE_HDR,
35 TS_LUA_HOOK_TXN_CLOSE,
36 TS_LUA_REQUEST_TRANSFORM,
37 TS_LUA_RESPONSE_TRANSFORM,
38 TS_LUA_HOOK_LAST
39 } TSLuaHookID;
40
41 char *ts_lua_hook_id_string[] = {"TS_LUA_HOOK_DUMMY",
42 "TS_LUA_HOOK_CACHE_LOOKUP_COMPLETE",
43 "TS_LUA_HOOK_SEND_REQUEST_HDR",
44 "TS_LUA_HOOK_READ_RESPONSE_HDR",
45 "TS_LUA_HOOK_SEND_RESPONSE_HDR",
46 "TS_LUA_HOOK_READ_REQUEST_HDR",
47 "TS_LUA_HOOK_TXN_START",
48 "TS_LUA_HOOK_PRE_REMAP",
49 "TS_LUA_HOOK_POST_REMAP",
50 "TS_LUA_HOOK_OS_DNS",
51 "TS_LUA_HOOK_READ_CACHE_HDR",
52 "TS_LUA_HOOK_TXN_CLOSE",
53 "TS_LUA_REQUEST_TRANSFORM",
54 "TS_LUA_RESPONSE_TRANSFORM",
55 "TS_LUA_HOOK_LAST"};
56
57 static int ts_lua_add_hook(lua_State *L);
58 static void ts_lua_inject_hook_variables(lua_State *L);
59
60 void
ts_lua_inject_hook_api(lua_State * L)61 ts_lua_inject_hook_api(lua_State *L)
62 {
63 lua_pushcfunction(L, ts_lua_add_hook);
64 lua_setfield(L, -2, "hook");
65
66 ts_lua_inject_hook_variables(L);
67 }
68
69 static void
ts_lua_inject_hook_variables(lua_State * L)70 ts_lua_inject_hook_variables(lua_State *L)
71 {
72 size_t i;
73
74 for (i = 0; i < sizeof(ts_lua_hook_id_string) / sizeof(char *); i++) {
75 lua_pushinteger(L, (lua_Integer)i);
76 lua_setglobal(L, ts_lua_hook_id_string[i]);
77 }
78 }
79
80 static int
ts_lua_add_hook(lua_State * L)81 ts_lua_add_hook(lua_State *L)
82 {
83 int type;
84 int entry;
85
86 TSVConn connp;
87 ts_lua_http_ctx *http_ctx;
88
89 http_ctx = ts_lua_get_http_ctx(L);
90
91 entry = lua_tointeger(L, 1); // get hook id
92
93 type = lua_type(L, 2);
94 if (type != LUA_TFUNCTION)
95 return 0;
96
97 switch (entry) {
98 case TS_LUA_HOOK_CACHE_LOOKUP_COMPLETE:
99 if (http_ctx) {
100 TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, http_ctx->cinfo.contp);
101 http_ctx->has_hook = 1;
102 lua_pushvalue(L, 2);
103 lua_setglobal(L, TS_LUA_FUNCTION_CACHE_LOOKUP_COMPLETE);
104 } else {
105 lua_pushvalue(L, 2);
106 lua_setglobal(L, TS_LUA_FUNCTION_G_CACHE_LOOKUP_COMPLETE);
107 }
108 break;
109
110 case TS_LUA_HOOK_SEND_REQUEST_HDR:
111 if (http_ctx) {
112 TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_SEND_REQUEST_HDR_HOOK, http_ctx->cinfo.contp);
113 http_ctx->has_hook = 1;
114 lua_pushvalue(L, 2);
115 lua_setglobal(L, TS_LUA_FUNCTION_SEND_REQUEST);
116 } else {
117 lua_pushvalue(L, 2);
118 lua_setglobal(L, TS_LUA_FUNCTION_G_SEND_REQUEST);
119 }
120 break;
121
122 case TS_LUA_HOOK_READ_RESPONSE_HDR:
123 if (http_ctx) {
124 TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_READ_RESPONSE_HDR_HOOK, http_ctx->cinfo.contp);
125 http_ctx->has_hook = 1;
126 lua_pushvalue(L, 2);
127 lua_setglobal(L, TS_LUA_FUNCTION_READ_RESPONSE);
128 } else {
129 lua_pushvalue(L, 2);
130 lua_setglobal(L, TS_LUA_FUNCTION_G_READ_RESPONSE);
131 }
132 break;
133
134 case TS_LUA_HOOK_SEND_RESPONSE_HDR:
135 if (http_ctx) {
136 TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, http_ctx->cinfo.contp);
137 http_ctx->has_hook = 1;
138 lua_pushvalue(L, 2);
139 lua_setglobal(L, TS_LUA_FUNCTION_SEND_RESPONSE);
140 } else {
141 lua_pushvalue(L, 2);
142 lua_setglobal(L, TS_LUA_FUNCTION_G_SEND_RESPONSE);
143 }
144 break;
145
146 case TS_LUA_HOOK_READ_REQUEST_HDR:
147 if (http_ctx) {
148 TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_READ_REQUEST_HDR_HOOK, http_ctx->cinfo.contp);
149 http_ctx->has_hook = 1;
150 lua_pushvalue(L, 2);
151 lua_setglobal(L, TS_LUA_FUNCTION_READ_REQUEST);
152 } else {
153 lua_pushvalue(L, 2);
154 lua_setglobal(L, TS_LUA_FUNCTION_G_READ_REQUEST);
155 }
156 break;
157
158 case TS_LUA_HOOK_TXN_START:
159 if (http_ctx) {
160 TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_TXN_START_HOOK, http_ctx->cinfo.contp);
161 http_ctx->has_hook = 1;
162 lua_pushvalue(L, 2);
163 lua_setglobal(L, TS_LUA_FUNCTION_TXN_START);
164 } else {
165 lua_pushvalue(L, 2);
166 lua_setglobal(L, TS_LUA_FUNCTION_G_TXN_START);
167 }
168 break;
169
170 case TS_LUA_HOOK_PRE_REMAP:
171 if (http_ctx) {
172 TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_PRE_REMAP_HOOK, http_ctx->cinfo.contp);
173 http_ctx->has_hook = 1;
174 lua_pushvalue(L, 2);
175 lua_setglobal(L, TS_LUA_FUNCTION_PRE_REMAP);
176 } else {
177 lua_pushvalue(L, 2);
178 lua_setglobal(L, TS_LUA_FUNCTION_G_PRE_REMAP);
179 }
180 break;
181
182 case TS_LUA_HOOK_POST_REMAP:
183 if (http_ctx) {
184 TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_POST_REMAP_HOOK, http_ctx->cinfo.contp);
185 http_ctx->has_hook = 1;
186 lua_pushvalue(L, 2);
187 lua_setglobal(L, TS_LUA_FUNCTION_POST_REMAP);
188 } else {
189 lua_pushvalue(L, 2);
190 lua_setglobal(L, TS_LUA_FUNCTION_G_POST_REMAP);
191 }
192 break;
193
194 case TS_LUA_HOOK_OS_DNS:
195 if (http_ctx) {
196 TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_OS_DNS_HOOK, http_ctx->cinfo.contp);
197 http_ctx->has_hook = 1;
198 lua_pushvalue(L, 2);
199 lua_setglobal(L, TS_LUA_FUNCTION_OS_DNS);
200 } else {
201 lua_pushvalue(L, 2);
202 lua_setglobal(L, TS_LUA_FUNCTION_G_OS_DNS);
203 }
204 break;
205
206 case TS_LUA_HOOK_READ_CACHE_HDR:
207 if (http_ctx) {
208 TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_READ_CACHE_HDR_HOOK, http_ctx->cinfo.contp);
209 http_ctx->has_hook = 1;
210 lua_pushvalue(L, 2);
211 lua_setglobal(L, TS_LUA_FUNCTION_READ_CACHE);
212 } else {
213 lua_pushvalue(L, 2);
214 lua_setglobal(L, TS_LUA_FUNCTION_G_READ_CACHE);
215 }
216 break;
217
218 case TS_LUA_HOOK_TXN_CLOSE:
219 if (http_ctx) {
220 // we don't need to add a hook because we already have added one by default
221 lua_pushvalue(L, 2);
222 lua_setglobal(L, TS_LUA_FUNCTION_TXN_CLOSE);
223 } else {
224 lua_pushvalue(L, 2);
225 lua_setglobal(L, TS_LUA_FUNCTION_G_TXN_CLOSE);
226 }
227 break;
228
229 case TS_LUA_REQUEST_TRANSFORM:
230 case TS_LUA_RESPONSE_TRANSFORM:
231 if (http_ctx) {
232 connp = TSTransformCreate(ts_lua_transform_entry, http_ctx->txnp);
233 ts_lua_create_http_transform_ctx(http_ctx, connp);
234
235 if (entry == TS_LUA_REQUEST_TRANSFORM) {
236 TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_REQUEST_TRANSFORM_HOOK, connp);
237 } else {
238 TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_RESPONSE_TRANSFORM_HOOK, connp);
239 }
240 }
241 break;
242
243 default:
244 break;
245 }
246
247 return 0;
248 }
249