xref: /trafficserver/plugins/lua/ts_lua_misc.c (revision 7236e78f)
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 "tscore/ink_platform.h"
20 #include <netinet/in.h>
21 #include "ts_lua_util.h"
22 
23 static int ts_lua_get_process_id(lua_State *L);
24 static int ts_lua_get_now_time(lua_State *L);
25 static int ts_lua_debug(lua_State *L);
26 static int ts_lua_error(lua_State *L);
27 static int ts_lua_emergency(lua_State *L);
28 static int ts_lua_fatal(lua_State *L);
29 static int ts_lua_sleep(lua_State *L);
30 static int ts_lua_host_lookup(lua_State *L);
31 static int ts_lua_schedule(lua_State *L);
32 static int ts_lua_get_install_dir(lua_State *L);
33 static int ts_lua_get_config_dir(lua_State *L);
34 static int ts_lua_get_runtime_dir(lua_State *L);
35 static int ts_lua_get_plugin_dir(lua_State *L);
36 static int ts_lua_get_traffic_server_version(lua_State *L);
37 
38 static int ts_lua_sleep_cleanup(ts_lua_async_item *ai);
39 static int ts_lua_sleep_handler(TSCont contp, TSEvent event, void *edata);
40 static int ts_lua_host_lookup_cleanup(ts_lua_async_item *ai);
41 static int ts_lua_host_lookup_handler(TSCont contp, TSEvent event, void *edata);
42 static int ts_lua_schedule_handler(TSCont contp, TSEvent event, void *edata);
43 
44 static void ts_lua_inject_misc_variables(lua_State *L);
45 
46 void
ts_lua_inject_misc_api(lua_State * L)47 ts_lua_inject_misc_api(lua_State *L)
48 {
49   lua_newtable(L);
50 
51   /* ts.process.uuid() */
52   lua_pushcfunction(L, ts_lua_get_process_id);
53   lua_setfield(L, -2, "uuid");
54 
55   lua_setfield(L, -2, "process");
56 
57   /* ts.now() */
58   lua_pushcfunction(L, ts_lua_get_now_time);
59   lua_setfield(L, -2, "now");
60 
61   /* ts.debug(...) */
62   lua_pushcfunction(L, ts_lua_debug);
63   lua_setfield(L, -2, "debug");
64 
65   /* ts.error(...) */
66   lua_pushcfunction(L, ts_lua_error);
67   lua_setfield(L, -2, "error");
68 
69   /* ts.emergency(...) */
70   lua_pushcfunction(L, ts_lua_emergency);
71   lua_setfield(L, -2, "emergency");
72 
73   /* ts.fatal(...) */
74   lua_pushcfunction(L, ts_lua_fatal);
75   lua_setfield(L, -2, "fatal");
76 
77   /* ts.sleep(...) */
78   lua_pushcfunction(L, ts_lua_sleep);
79   lua_setfield(L, -2, "sleep");
80 
81   /* ts.schedule(...) */
82   lua_pushcfunction(L, ts_lua_schedule);
83   lua_setfield(L, -2, "schedule");
84 
85   /* ts.host_lookup(...) */
86   lua_pushcfunction(L, ts_lua_host_lookup);
87   lua_setfield(L, -2, "host_lookup");
88 
89   /* ts.get_install_dir(...) */
90   lua_pushcfunction(L, ts_lua_get_install_dir);
91   lua_setfield(L, -2, "get_install_dir");
92 
93   /* ts.get_config_dir(...) */
94   lua_pushcfunction(L, ts_lua_get_config_dir);
95   lua_setfield(L, -2, "get_config_dir");
96 
97   /* ts.get_runtime_dir(...) */
98   lua_pushcfunction(L, ts_lua_get_runtime_dir);
99   lua_setfield(L, -2, "get_runtime_dir");
100 
101   /* ts.get_plugin_dir(...) */
102   lua_pushcfunction(L, ts_lua_get_plugin_dir);
103   lua_setfield(L, -2, "get_plugin_dir");
104 
105   /* ts.get_traffic_server_version(...) */
106   lua_pushcfunction(L, ts_lua_get_traffic_server_version);
107   lua_setfield(L, -2, "get_traffic_server_version");
108 
109   ts_lua_inject_misc_variables(L);
110 }
111 
112 static void
ts_lua_inject_misc_variables(lua_State * L)113 ts_lua_inject_misc_variables(lua_State *L)
114 {
115   lua_pushinteger(L, TS_THREAD_POOL_NET);
116   lua_setglobal(L, "TS_LUA_THREAD_POOL_NET");
117   lua_pushinteger(L, TS_THREAD_POOL_TASK);
118   lua_setglobal(L, "TS_LUA_THREAD_POOL_TASK");
119 }
120 
121 static int
ts_lua_get_process_id(lua_State * L)122 ts_lua_get_process_id(lua_State *L)
123 {
124   const char *s;
125   TSUuid process = TSProcessUuidGet();
126   if (process) {
127     s = TSUuidStringGet(process);
128   } else {
129     return luaL_error(L, "not able to get process uuid");
130   }
131   lua_pushstring(L, s);
132   return 1;
133 }
134 
135 static int
ts_lua_get_now_time(lua_State * L)136 ts_lua_get_now_time(lua_State *L)
137 {
138   lua_Number now;
139 
140   // Return fractional seconds.
141   now = ((lua_Number)TShrtime()) / 1000000000.0;
142   lua_pushnumber(L, now);
143   return 1;
144 }
145 
146 static int
ts_lua_debug(lua_State * L)147 ts_lua_debug(lua_State *L)
148 {
149   const char *msg;
150   const char *flag;
151   size_t msg_len = 0, flag_len = 0;
152 
153   if (lua_gettop(L) == 2) {
154     msg  = luaL_checklstring(L, 2, &msg_len);
155     flag = luaL_checklstring(L, 1, &flag_len);
156     TSDebug(flag, "%.*s", (int)msg_len, msg);
157   } else {
158     msg = luaL_checklstring(L, 1, &msg_len);
159     TSDebug(TS_LUA_DEBUG_TAG, "%.*s", (int)msg_len, msg);
160   }
161 
162   return 0;
163 }
164 
165 static int
ts_lua_error(lua_State * L)166 ts_lua_error(lua_State *L)
167 {
168   const char *msg;
169   size_t len = 0;
170 
171   msg = luaL_checklstring(L, 1, &len);
172   TSError("%.*s", (int)len, msg);
173   return 0;
174 }
175 
176 static int
ts_lua_emergency(lua_State * L)177 ts_lua_emergency(lua_State *L)
178 {
179   const char *msg;
180   size_t len = 0;
181 
182   msg = luaL_checklstring(L, 1, &len);
183   TSEmergency("%.*s", (int)len, msg);
184   return 0;
185 }
186 
187 static int
ts_lua_fatal(lua_State * L)188 ts_lua_fatal(lua_State *L)
189 {
190   const char *msg;
191   size_t len = 0;
192 
193   msg = luaL_checklstring(L, 1, &len);
194   TSFatal("%.*s", (int)len, msg);
195   return 0;
196 }
197 
198 static int
ts_lua_schedule(lua_State * L)199 ts_lua_schedule(lua_State *L)
200 {
201   int sec;
202   int type;
203   int entry;
204 
205   ts_lua_http_ctx *actx;
206 
207   int n;
208 
209   TSCont contp;
210   ts_lua_cont_info *ci;
211   ts_lua_cont_info *nci;
212 
213   ci = ts_lua_get_cont_info(L);
214   if (ci == NULL) {
215     return 0;
216   }
217 
218   entry = lua_tointeger(L, 1);
219 
220   sec = luaL_checknumber(L, 2);
221   if (sec < 1) {
222     sec = 0;
223   }
224 
225   type = lua_type(L, 3);
226   if (type != LUA_TFUNCTION)
227     return 0;
228 
229   n = lua_gettop(L);
230 
231   if (n < 3) {
232     TSError("[ts_lua][%s] ts.schedule need at least three parameters", __FUNCTION__);
233     return 0;
234   }
235 
236   // TO-DO unset the original context in L
237   actx = ts_lua_create_async_ctx(L, ci, n);
238 
239   contp = TSContCreate(ts_lua_schedule_handler, ci->mutex);
240   TSContDataSet(contp, actx);
241 
242   nci        = &actx->cinfo;
243   nci->contp = contp;
244   nci->mutex = ci->mutex;
245 
246   TSContScheduleOnPool(contp, sec * 1000, entry);
247 
248   return 0;
249 }
250 
251 static int
ts_lua_schedule_handler(TSCont contp,TSEvent ev,void * edata)252 ts_lua_schedule_handler(TSCont contp, TSEvent ev, void *edata)
253 {
254   lua_State *L;
255   ts_lua_cont_info *ci;
256   ts_lua_coroutine *crt;
257   int event, n, ret;
258   ts_lua_http_ctx *actx;
259   ts_lua_main_ctx *main_ctx;
260 
261   event = (int)ev;
262   TSDebug(TS_LUA_DEBUG_TAG, "getting actx and other info");
263   actx = (ts_lua_http_ctx *)TSContDataGet(contp);
264 
265   TSDebug(TS_LUA_DEBUG_TAG, "getting http_Ctx");
266   ci  = &actx->cinfo;
267   crt = &ci->routine;
268 
269   main_ctx = crt->mctx;
270   L        = crt->lua;
271 
272   TSMutexLock(main_ctx->mutexp);
273   ts_lua_set_cont_info(L, ci);
274 
275   if (event == TS_LUA_EVENT_COROUTINE_CONT) {
276     TSDebug(TS_LUA_DEBUG_TAG, "event is coroutine_cont");
277     n   = (intptr_t)edata;
278     ret = lua_resume(L, n);
279   } else {
280     TSDebug(TS_LUA_DEBUG_TAG, "event is not coroutine_cont");
281     n   = lua_gettop(L);
282     ret = lua_resume(L, n - 1);
283   }
284 
285   if (ret == LUA_YIELD) {
286     TSMutexUnlock(main_ctx->mutexp);
287     goto done;
288   }
289 
290   if (ret != 0) {
291     TSError("[ts_lua][%s] lua_resume failed: %s", __FUNCTION__, lua_tostring(L, -1));
292   }
293 
294   lua_pop(L, lua_gettop(L));
295   TSMutexUnlock(main_ctx->mutexp);
296   ts_lua_destroy_async_ctx(actx);
297 
298 done:
299   return 0;
300 }
301 
302 static int
ts_lua_sleep(lua_State * L)303 ts_lua_sleep(lua_State *L)
304 {
305   int sec;
306   TSAction action;
307   TSCont contp;
308   ts_lua_async_item *ai;
309   ts_lua_cont_info *ci;
310 
311   ci = ts_lua_get_cont_info(L);
312   if (ci == NULL) {
313     return 0;
314   }
315 
316   sec = luaL_checknumber(L, 1);
317   if (sec < 1) {
318     sec = 1;
319   }
320 
321   contp  = TSContCreate(ts_lua_sleep_handler, ci->mutex);
322   action = TSContScheduleOnPool(contp, sec * 1000, TS_THREAD_POOL_NET);
323 
324   ai = ts_lua_async_create_item(contp, ts_lua_sleep_cleanup, (void *)action, ci);
325   TSContDataSet(contp, ai);
326 
327   return lua_yield(L, 0);
328 }
329 
330 static int
ts_lua_sleep_handler(TSCont contp,TSEvent event ATS_UNUSED,void * edata ATS_UNUSED)331 ts_lua_sleep_handler(TSCont contp, TSEvent event ATS_UNUSED, void *edata ATS_UNUSED)
332 {
333   ts_lua_async_item *ai;
334   ts_lua_cont_info *ci;
335 
336   ai = TSContDataGet(contp);
337   ci = ai->cinfo;
338 
339   ai->data = NULL;
340   ts_lua_sleep_cleanup(ai);
341 
342   TSContCall(ci->contp, TS_LUA_EVENT_COROUTINE_CONT, 0);
343 
344   return 0;
345 }
346 
347 static int
ts_lua_sleep_cleanup(ts_lua_async_item * ai)348 ts_lua_sleep_cleanup(ts_lua_async_item *ai)
349 {
350   if (ai->data) {
351     TSActionCancel((TSAction)ai->data);
352     ai->data = NULL;
353   }
354 
355   TSContDestroy(ai->contp);
356   ai->deleted = 1;
357 
358   return 0;
359 }
360 
361 static int
ts_lua_host_lookup(lua_State * L)362 ts_lua_host_lookup(lua_State *L)
363 {
364   const char *host;
365   size_t host_len = 0;
366   TSAction action;
367   TSCont contp;
368   ts_lua_async_item *ai;
369   ts_lua_cont_info *ci;
370 
371   ci = ts_lua_get_cont_info(L);
372   if (ci == NULL) {
373     return 0;
374   }
375 
376   if (lua_gettop(L) != 1) {
377     TSError("[ts_lua][%s] ts.host_lookup need at least one parameter", __FUNCTION__);
378     return 0;
379   }
380 
381   host = luaL_checklstring(L, 1, &host_len);
382 
383   contp  = TSContCreate(ts_lua_host_lookup_handler, ci->mutex);
384   action = TSHostLookup(contp, host, host_len);
385 
386   ai = ts_lua_async_create_item(contp, ts_lua_host_lookup_cleanup, (void *)action, ci);
387   TSContDataSet(contp, ai);
388 
389   return lua_yield(L, 0);
390 }
391 
392 static int
ts_lua_host_lookup_handler(TSCont contp,TSEvent event,void * edata)393 ts_lua_host_lookup_handler(TSCont contp, TSEvent event, void *edata)
394 {
395   ts_lua_async_item *ai;
396   ts_lua_cont_info *ci;
397   struct sockaddr const *addr;
398   char cip[128];
399   lua_State *L;
400   ts_lua_coroutine *crt;
401 
402   ai  = TSContDataGet(contp);
403   ci  = ai->cinfo;
404   crt = &ci->routine;
405   L   = crt->lua;
406 
407   ai->data = NULL;
408   ts_lua_host_lookup_cleanup(ai);
409 
410   if (event != TS_EVENT_HOST_LOOKUP) {
411     TSError("[ts_lua][%s] ts.host_lookup receives unknown event", __FUNCTION__);
412     lua_pushnil(L);
413   } else if (!edata) {
414     lua_pushnil(L);
415   } else {
416     TSHostLookupResult result = (TSHostLookupResult)edata;
417     addr                      = TSHostLookupResultAddrGet(result);
418     if (addr->sa_family == AF_INET) {
419       inet_ntop(AF_INET, (const void *)&((struct sockaddr_in *)addr)->sin_addr, cip, sizeof(cip));
420     } else {
421       inet_ntop(AF_INET6, (const void *)&((struct sockaddr_in6 *)addr)->sin6_addr, cip, sizeof(cip));
422     }
423     lua_pushstring(L, cip);
424   }
425 
426   TSContCall(ci->contp, TS_LUA_EVENT_COROUTINE_CONT, (void *)1);
427 
428   return 0;
429 }
430 
431 static int
ts_lua_host_lookup_cleanup(ts_lua_async_item * ai)432 ts_lua_host_lookup_cleanup(ts_lua_async_item *ai)
433 {
434   if (ai->data) {
435     TSActionCancel((TSAction)ai->data);
436     ai->data = NULL;
437   }
438 
439   TSContDestroy(ai->contp);
440   ai->deleted = 1;
441 
442   return 0;
443 }
444 
445 static int
ts_lua_get_install_dir(lua_State * L)446 ts_lua_get_install_dir(lua_State *L)
447 {
448   const char *s = TSInstallDirGet();
449   lua_pushstring(L, s);
450   return 1;
451 }
452 
453 static int
ts_lua_get_config_dir(lua_State * L)454 ts_lua_get_config_dir(lua_State *L)
455 {
456   const char *s = TSConfigDirGet();
457   lua_pushstring(L, s);
458   return 1;
459 }
460 
461 static int
ts_lua_get_runtime_dir(lua_State * L)462 ts_lua_get_runtime_dir(lua_State *L)
463 {
464   const char *s = TSRuntimeDirGet();
465   lua_pushstring(L, s);
466   return 1;
467 }
468 
469 static int
ts_lua_get_plugin_dir(lua_State * L)470 ts_lua_get_plugin_dir(lua_State *L)
471 {
472   const char *s = TSPluginDirGet();
473   lua_pushstring(L, s);
474   return 1;
475 }
476 
477 static int
ts_lua_get_traffic_server_version(lua_State * L)478 ts_lua_get_traffic_server_version(lua_State *L)
479 {
480   const char *s = TSTrafficServerVersionGet();
481   lua_pushstring(L, s);
482   return 1;
483 }
484