blob: 3bb46bb049e82114678a84f7ae50584f939bd1ba [file] [log] [blame]
Thierry Fourniere726b142016-02-11 17:57:57 +01001/*
2 * Lua unsafe core engine
3 *
4 * Copyright 2015-2016 Thierry Fournier <tfournier@arpalert.org>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +010013#include <ctype.h>
Thierry FOURNIERbabae282015-09-17 11:36:37 +020014#include <setjmp.h>
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +010015
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +010016#include <lauxlib.h>
17#include <lua.h>
18#include <lualib.h>
19
Thierry FOURNIER463119c2015-03-10 00:35:36 +010020#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 503
21#error "Requires Lua 5.3 or later."
Cyril Bontédc0306e2015-03-02 00:08:40 +010022#endif
23
Thierry FOURNIER380d0932015-01-23 14:27:52 +010024#include <ebpttree.h>
25
26#include <common/cfgparse.h>
Thierry FOURNIER2da788e2017-09-11 18:37:23 +020027#include <common/xref.h>
Thierry FOURNIER61ba0e22017-07-12 11:41:21 +020028#include <common/hathreads.h>
Thierry FOURNIER380d0932015-01-23 14:27:52 +010029
William Lallemand9ed62032016-11-21 17:49:11 +010030#include <types/cli.h>
Thierry FOURNIER380d0932015-01-23 14:27:52 +010031#include <types/hlua.h>
32#include <types/proxy.h>
William Lallemand9ed62032016-11-21 17:49:11 +010033#include <types/stats.h>
Thierry FOURNIER380d0932015-01-23 14:27:52 +010034
Thierry FOURNIER55da1652015-01-23 11:36:30 +010035#include <proto/arg.h>
Willy Tarreau8a8d83b2015-04-13 13:24:54 +020036#include <proto/applet.h>
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +010037#include <proto/channel.h>
William Lallemand9ed62032016-11-21 17:49:11 +010038#include <proto/cli.h>
Willy Tarreaua71f6422016-11-16 17:00:14 +010039#include <proto/connection.h>
William Lallemand9ed62032016-11-21 17:49:11 +010040#include <proto/stats.h>
Thierry FOURNIER9a819e72015-02-16 20:22:55 +010041#include <proto/hdr_idx.h>
Thierry FOURNIERa097fdf2015-03-03 15:17:35 +010042#include <proto/hlua.h>
Thierry Fournierfb0b5462016-01-21 09:28:58 +010043#include <proto/hlua_fcn.h>
Thierry FOURNIER3def3932015-04-07 11:27:54 +020044#include <proto/map.h>
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +010045#include <proto/obj_type.h>
Thierry FOURNIER83758bb2015-02-04 13:21:04 +010046#include <proto/pattern.h>
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +010047#include <proto/payload.h>
48#include <proto/proto_http.h>
49#include <proto/sample.h>
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +010050#include <proto/server.h>
Willy Tarreaufeb76402015-04-03 14:10:06 +020051#include <proto/session.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020052#include <proto/stream.h>
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +010053#include <proto/stream_interface.h>
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +010054#include <proto/task.h>
Willy Tarreau39713102016-11-25 15:49:32 +010055#include <proto/tcp_rules.h>
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +020056#include <proto/vars.h>
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +010057
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +010058/* Lua uses longjmp to perform yield or throwing errors. This
59 * macro is used only for identifying the function that can
60 * not return because a longjmp is executed.
61 * __LJMP marks a prototype of hlua file that can use longjmp.
62 * WILL_LJMP() marks an lua function that will use longjmp.
63 * MAY_LJMP() marks an lua function that may use longjmp.
64 */
65#define __LJMP
66#define WILL_LJMP(func) func
67#define MAY_LJMP(func) func
68
Thierry FOURNIERbabae282015-09-17 11:36:37 +020069/* This couple of function executes securely some Lua calls outside of
70 * the lua runtime environment. Each Lua call can return a longjmp
71 * if it encounter a memory error.
72 *
73 * Lua documentation extract:
74 *
75 * If an error happens outside any protected environment, Lua calls
76 * a panic function (see lua_atpanic) and then calls abort, thus
77 * exiting the host application. Your panic function can avoid this
78 * exit by never returning (e.g., doing a long jump to your own
79 * recovery point outside Lua).
80 *
81 * The panic function runs as if it were a message handler (see
82 * §2.3); in particular, the error message is at the top of the
83 * stack. However, there is no guarantee about stack space. To push
84 * anything on the stack, the panic function must first check the
85 * available space (see §4.2).
86 *
87 * We must check all the Lua entry point. This includes:
88 * - The include/proto/hlua.h exported functions
89 * - the task wrapper function
90 * - The action wrapper function
91 * - The converters wrapper function
92 * - The sample-fetch wrapper functions
93 *
94 * It is tolerated that the initilisation function returns an abort.
95 * Before each Lua abort, an error message is writed on stderr.
96 *
97 * The macro SET_SAFE_LJMP initialise the longjmp. The Macro
98 * RESET_SAFE_LJMP reset the longjmp. These function must be macro
99 * because they must be exists in the program stack when the longjmp
100 * is called.
Thierry FOURNIER61ba0e22017-07-12 11:41:21 +0200101 *
102 * Note that the Lua processing is not really thread safe. It provides
103 * heavy system which consists to add our own lock function in the Lua
104 * code and recompile the library. This system will probably not accepted
105 * by maintainers of various distribs.
106 *
107 * Our main excution point of the Lua is the function lua_resume(). A
108 * quick looking on the Lua sources displays a lua_lock() a the start
109 * of function and a lua_unlock() at the end of the function. So I
110 * conclude that the Lua thread safe mode just perform a mutex around
111 * all execution. So I prefer to do this in the HAProxy code, it will be
112 * easier for distro maintainers.
113 *
114 * Note that the HAProxy lua functions rounded by the macro SET_SAFE_LJMP
115 * and RESET_SAFE_LJMP manipulates the Lua stack, so it will be careful
116 * to set mutex around these functions.
Thierry FOURNIERbabae282015-09-17 11:36:37 +0200117 */
Thierry FOURNIER61ba0e22017-07-12 11:41:21 +0200118#ifdef USE_THREAD
119HA_SPINLOCK_T hlua_global_lock;
120#endif
Thierry FOURNIERffbad792017-07-12 11:39:04 +0200121THREAD_LOCAL jmp_buf safe_ljmp_env;
Thierry FOURNIERbabae282015-09-17 11:36:37 +0200122static int hlua_panic_safe(lua_State *L) { return 0; }
123static int hlua_panic_ljmp(lua_State *L) { longjmp(safe_ljmp_env, 1); }
124
125#define SET_SAFE_LJMP(__L) \
126 ({ \
127 int ret; \
Thierry FOURNIER61ba0e22017-07-12 11:41:21 +0200128 SPIN_LOCK(LUA_LOCK, &hlua_global_lock); \
Thierry FOURNIERbabae282015-09-17 11:36:37 +0200129 if (setjmp(safe_ljmp_env) != 0) { \
130 lua_atpanic(__L, hlua_panic_safe); \
131 ret = 0; \
Thierry FOURNIER61ba0e22017-07-12 11:41:21 +0200132 SPIN_UNLOCK(LUA_LOCK, &hlua_global_lock); \
Thierry FOURNIERbabae282015-09-17 11:36:37 +0200133 } else { \
134 lua_atpanic(__L, hlua_panic_ljmp); \
135 ret = 1; \
136 } \
137 ret; \
138 })
139
140/* If we are the last function catching Lua errors, we
141 * must reset the panic function.
142 */
143#define RESET_SAFE_LJMP(__L) \
144 do { \
145 lua_atpanic(__L, hlua_panic_safe); \
Thierry FOURNIER61ba0e22017-07-12 11:41:21 +0200146 SPIN_UNLOCK(LUA_LOCK, &hlua_global_lock); \
Thierry FOURNIERbabae282015-09-17 11:36:37 +0200147 } while(0)
148
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +0200149/* Applet status flags */
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +0200150#define APPLET_DONE 0x01 /* applet processing is done. */
151#define APPLET_100C 0x02 /* 100 continue expected. */
152#define APPLET_HDR_SENT 0x04 /* Response header sent. */
153#define APPLET_CHUNKED 0x08 /* Use transfer encoding chunked. */
154#define APPLET_LAST_CHK 0x10 /* Last chunk sent. */
Thierry FOURNIERd93ea2b2015-12-20 19:14:52 +0100155#define APPLET_HTTP11 0x20 /* Last chunk sent. */
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +0200156
157#define HTTP_100C "HTTP/1.1 100 Continue\r\n\r\n"
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +0200158
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100159/* The main Lua execution context. */
160struct hlua gL;
161
Thierry FOURNIERebed6e92016-12-16 11:54:07 +0100162/* This is the memory pool containing struct lua for applets
163 * (including cli).
164 */
165struct pool_head *pool2_hlua;
166
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +0100167/* Used for Socket connection. */
168static struct proxy socket_proxy;
169static struct server socket_tcp;
170#ifdef USE_OPENSSL
171static struct server socket_ssl;
172#endif
173
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +0100174/* List head of the function called at the initialisation time. */
175struct list hlua_init_functions = LIST_HEAD_INIT(hlua_init_functions);
176
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +0100177/* The following variables contains the reference of the different
178 * Lua classes. These references are useful for identify metadata
179 * associated with an object.
180 */
Thierry FOURNIER65f34c62015-02-16 20:11:43 +0100181static int class_txn_ref;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +0100182static int class_socket_ref;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +0100183static int class_channel_ref;
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +0100184static int class_fetches_ref;
Thierry FOURNIER594afe72015-03-10 23:58:30 +0100185static int class_converters_ref;
Thierry FOURNIER08504f42015-03-16 14:17:08 +0100186static int class_http_ref;
Thierry FOURNIER3def3932015-04-07 11:27:54 +0200187static int class_map_ref;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +0200188static int class_applet_tcp_ref;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +0200189static int class_applet_http_ref;
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +0100190
Thierry FOURNIERbd413492015-03-03 16:52:26 +0100191/* Global Lua execution timeout. By default Lua, execution linked
Willy Tarreau87b09662015-04-03 00:22:06 +0200192 * with stream (actions, sample-fetches and converters) have a
Thierry FOURNIERbd413492015-03-03 16:52:26 +0100193 * short timeout. Lua linked with tasks doesn't have a timeout
194 * because a task may remain alive during all the haproxy execution.
195 */
196static unsigned int hlua_timeout_session = 4000; /* session timeout. */
197static unsigned int hlua_timeout_task = TICK_ETERNITY; /* task timeout. */
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +0200198static unsigned int hlua_timeout_applet = 4000; /* applet timeout. */
Thierry FOURNIERbd413492015-03-03 16:52:26 +0100199
Thierry FOURNIERee9f8022015-03-03 17:37:37 +0100200/* Interrupts the Lua processing each "hlua_nb_instruction" instructions.
201 * it is used for preventing infinite loops.
202 *
203 * I test the scheer with an infinite loop containing one incrementation
204 * and one test. I run this loop between 10 seconds, I raise a ceil of
205 * 710M loops from one interrupt each 9000 instructions, so I fix the value
206 * to one interrupt each 10 000 instructions.
207 *
208 * configured | Number of
209 * instructions | loops executed
210 * between two | in milions
211 * forced yields |
212 * ---------------+---------------
213 * 10 | 160
214 * 500 | 670
215 * 1000 | 680
216 * 5000 | 700
217 * 7000 | 700
218 * 8000 | 700
219 * 9000 | 710 <- ceil
220 * 10000 | 710
221 * 100000 | 710
222 * 1000000 | 710
223 *
224 */
225static unsigned int hlua_nb_instruction = 10000;
226
Willy Tarreau32f61e22015-03-18 17:54:59 +0100227/* Descriptor for the memory allocation state. If limit is not null, it will
228 * be enforced on any memory allocation.
229 */
230struct hlua_mem_allocator {
231 size_t allocated;
232 size_t limit;
233};
234
235static struct hlua_mem_allocator hlua_global_allocator;
236
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +0200237static const char error_500[] =
Jarno Huuskonen16ad94a2017-01-09 14:17:10 +0200238 "HTTP/1.0 500 Internal Server Error\r\n"
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +0200239 "Cache-Control: no-cache\r\n"
240 "Connection: close\r\n"
241 "Content-Type: text/html\r\n"
242 "\r\n"
Jarno Huuskonen16ad94a2017-01-09 14:17:10 +0200243 "<html><body><h1>500 Internal Server Error</h1>\nAn internal server error occured.\n</body></html>\n";
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +0200244
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100245/* These functions converts types between HAProxy internal args or
246 * sample and LUA types. Another function permits to check if the
247 * LUA stack contains arguments according with an required ARG_T
248 * format.
249 */
250static int hlua_arg2lua(lua_State *L, const struct arg *arg);
251static int hlua_lua2arg(lua_State *L, int ud, struct arg *arg);
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100252__LJMP static int hlua_lua2arg_check(lua_State *L, int first, struct arg *argp,
David Carlier0c437f42016-04-27 16:21:56 +0100253 uint64_t mask, struct proxy *p);
Willy Tarreau5eadada2015-03-10 17:28:54 +0100254static int hlua_smp2lua(lua_State *L, struct sample *smp);
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100255static int hlua_smp2lua_str(lua_State *L, struct sample *smp);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100256static int hlua_lua2smp(lua_State *L, int ud, struct sample *smp);
257
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +0200258__LJMP static int hlua_http_get_headers(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg);
259
Thierry FOURNIER23bc3752015-09-11 19:15:43 +0200260#define SEND_ERR(__be, __fmt, __args...) \
261 do { \
262 send_log(__be, LOG_ERR, __fmt, ## __args); \
263 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) \
264 Alert(__fmt, ## __args); \
265 } while (0)
266
Thierry FOURNIERe8b9a402015-02-25 18:48:12 +0100267/* Used to check an Lua function type in the stack. It creates and
268 * returns a reference of the function. This function throws an
269 * error if the rgument is not a "function".
270 */
271__LJMP unsigned int hlua_checkfunction(lua_State *L, int argno)
272{
273 if (!lua_isfunction(L, argno)) {
274 const char *msg = lua_pushfstring(L, "function expected, got %s", luaL_typename(L, -1));
275 WILL_LJMP(luaL_argerror(L, argno, msg));
276 }
277 lua_pushvalue(L, argno);
278 return luaL_ref(L, LUA_REGISTRYINDEX);
279}
280
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +0200281/* Return the string that is of the top of the stack. */
282const char *hlua_get_top_error_string(lua_State *L)
283{
284 if (lua_gettop(L) < 1)
285 return "unknown error";
286 if (lua_type(L, -1) != LUA_TSTRING)
287 return "unknown error";
288 return lua_tostring(L, -1);
289}
290
Thierry FOURNIERe8b9a402015-02-25 18:48:12 +0100291/* This function check the number of arguments available in the
292 * stack. If the number of arguments available is not the same
293 * then <nb> an error is throwed.
294 */
295__LJMP static inline void check_args(lua_State *L, int nb, char *fcn)
296{
297 if (lua_gettop(L) == nb)
298 return;
299 WILL_LJMP(luaL_error(L, "'%s' needs %d arguments", fcn, nb));
300}
301
Thierry FOURNIERe8b9a402015-02-25 18:48:12 +0100302/* This fucntion push an error string prefixed by the file name
303 * and the line number where the error is encountered.
304 */
305static int hlua_pusherror(lua_State *L, const char *fmt, ...)
306{
307 va_list argp;
308 va_start(argp, fmt);
309 luaL_where(L, 1);
310 lua_pushvfstring(L, fmt, argp);
311 va_end(argp);
312 lua_concat(L, 2);
313 return 1;
314}
315
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100316/* This functions is used with sample fetch and converters. It
317 * converts the HAProxy configuration argument in a lua stack
318 * values.
319 *
320 * It takes an array of "arg", and each entry of the array is
321 * converted and pushed in the LUA stack.
322 */
323static int hlua_arg2lua(lua_State *L, const struct arg *arg)
324{
325 switch (arg->type) {
326 case ARGT_SINT:
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100327 case ARGT_TIME:
328 case ARGT_SIZE:
Thierry FOURNIERf90838b2015-03-06 13:48:32 +0100329 lua_pushinteger(L, arg->data.sint);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100330 break;
331
332 case ARGT_STR:
333 lua_pushlstring(L, arg->data.str.str, arg->data.str.len);
334 break;
335
336 case ARGT_IPV4:
337 case ARGT_IPV6:
338 case ARGT_MSK4:
339 case ARGT_MSK6:
340 case ARGT_FE:
341 case ARGT_BE:
342 case ARGT_TAB:
343 case ARGT_SRV:
344 case ARGT_USR:
345 case ARGT_MAP:
346 default:
347 lua_pushnil(L);
348 break;
349 }
350 return 1;
351}
352
353/* This function take one entrie in an LUA stack at the index "ud",
354 * and try to convert it in an HAProxy argument entry. This is useful
355 * with sample fetch wrappers. The input arguments are gived to the
356 * lua wrapper and converted as arg list by thi function.
357 */
358static int hlua_lua2arg(lua_State *L, int ud, struct arg *arg)
359{
360 switch (lua_type(L, ud)) {
361
362 case LUA_TNUMBER:
363 case LUA_TBOOLEAN:
364 arg->type = ARGT_SINT;
365 arg->data.sint = lua_tointeger(L, ud);
366 break;
367
368 case LUA_TSTRING:
369 arg->type = ARGT_STR;
370 arg->data.str.str = (char *)lua_tolstring(L, ud, (size_t *)&arg->data.str.len);
371 break;
372
373 case LUA_TUSERDATA:
374 case LUA_TNIL:
375 case LUA_TTABLE:
376 case LUA_TFUNCTION:
377 case LUA_TTHREAD:
378 case LUA_TLIGHTUSERDATA:
379 arg->type = ARGT_SINT;
Thierry FOURNIERbf65cd42015-07-20 17:45:02 +0200380 arg->data.sint = 0;
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100381 break;
382 }
383 return 1;
384}
385
386/* the following functions are used to convert a struct sample
387 * in Lua type. This useful to convert the return of the
388 * fetchs or converters.
389 */
Willy Tarreau5eadada2015-03-10 17:28:54 +0100390static int hlua_smp2lua(lua_State *L, struct sample *smp)
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100391{
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200392 switch (smp->data.type) {
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100393 case SMP_T_SINT:
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100394 case SMP_T_BOOL:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200395 lua_pushinteger(L, smp->data.u.sint);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100396 break;
397
398 case SMP_T_BIN:
399 case SMP_T_STR:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200400 lua_pushlstring(L, smp->data.u.str.str, smp->data.u.str.len);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100401 break;
402
403 case SMP_T_METH:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200404 switch (smp->data.u.meth.meth) {
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100405 case HTTP_METH_OPTIONS: lua_pushstring(L, "OPTIONS"); break;
406 case HTTP_METH_GET: lua_pushstring(L, "GET"); break;
407 case HTTP_METH_HEAD: lua_pushstring(L, "HEAD"); break;
408 case HTTP_METH_POST: lua_pushstring(L, "POST"); break;
409 case HTTP_METH_PUT: lua_pushstring(L, "PUT"); break;
410 case HTTP_METH_DELETE: lua_pushstring(L, "DELETE"); break;
411 case HTTP_METH_TRACE: lua_pushstring(L, "TRACE"); break;
412 case HTTP_METH_CONNECT: lua_pushstring(L, "CONNECT"); break;
413 case HTTP_METH_OTHER:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200414 lua_pushlstring(L, smp->data.u.meth.str.str, smp->data.u.meth.str.len);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100415 break;
416 default:
417 lua_pushnil(L);
418 break;
419 }
420 break;
421
422 case SMP_T_IPV4:
423 case SMP_T_IPV6:
424 case SMP_T_ADDR: /* This type is never used to qualify a sample. */
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200425 if (sample_casts[smp->data.type][SMP_T_STR] &&
426 sample_casts[smp->data.type][SMP_T_STR](smp))
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200427 lua_pushlstring(L, smp->data.u.str.str, smp->data.u.str.len);
Willy Tarreau5eadada2015-03-10 17:28:54 +0100428 else
429 lua_pushnil(L);
430 break;
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100431 default:
432 lua_pushnil(L);
433 break;
434 }
435 return 1;
436}
437
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100438/* the following functions are used to convert a struct sample
439 * in Lua strings. This is useful to convert the return of the
440 * fetchs or converters.
441 */
442static int hlua_smp2lua_str(lua_State *L, struct sample *smp)
443{
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200444 switch (smp->data.type) {
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100445
446 case SMP_T_BIN:
447 case SMP_T_STR:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200448 lua_pushlstring(L, smp->data.u.str.str, smp->data.u.str.len);
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100449 break;
450
451 case SMP_T_METH:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200452 switch (smp->data.u.meth.meth) {
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100453 case HTTP_METH_OPTIONS: lua_pushstring(L, "OPTIONS"); break;
454 case HTTP_METH_GET: lua_pushstring(L, "GET"); break;
455 case HTTP_METH_HEAD: lua_pushstring(L, "HEAD"); break;
456 case HTTP_METH_POST: lua_pushstring(L, "POST"); break;
457 case HTTP_METH_PUT: lua_pushstring(L, "PUT"); break;
458 case HTTP_METH_DELETE: lua_pushstring(L, "DELETE"); break;
459 case HTTP_METH_TRACE: lua_pushstring(L, "TRACE"); break;
460 case HTTP_METH_CONNECT: lua_pushstring(L, "CONNECT"); break;
461 case HTTP_METH_OTHER:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200462 lua_pushlstring(L, smp->data.u.meth.str.str, smp->data.u.meth.str.len);
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100463 break;
464 default:
465 lua_pushstring(L, "");
466 break;
467 }
468 break;
469
470 case SMP_T_SINT:
471 case SMP_T_BOOL:
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100472 case SMP_T_IPV4:
473 case SMP_T_IPV6:
474 case SMP_T_ADDR: /* This type is never used to qualify a sample. */
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200475 if (sample_casts[smp->data.type][SMP_T_STR] &&
476 sample_casts[smp->data.type][SMP_T_STR](smp))
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200477 lua_pushlstring(L, smp->data.u.str.str, smp->data.u.str.len);
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100478 else
479 lua_pushstring(L, "");
480 break;
481 default:
482 lua_pushstring(L, "");
483 break;
484 }
485 return 1;
486}
487
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100488/* the following functions are used to convert an Lua type in a
489 * struct sample. This is useful to provide data from a converter
490 * to the LUA code.
491 */
492static int hlua_lua2smp(lua_State *L, int ud, struct sample *smp)
493{
494 switch (lua_type(L, ud)) {
495
496 case LUA_TNUMBER:
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200497 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200498 smp->data.u.sint = lua_tointeger(L, ud);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100499 break;
500
501
502 case LUA_TBOOLEAN:
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200503 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200504 smp->data.u.sint = lua_toboolean(L, ud);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100505 break;
506
507 case LUA_TSTRING:
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200508 smp->data.type = SMP_T_STR;
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100509 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200510 smp->data.u.str.str = (char *)lua_tolstring(L, ud, (size_t *)&smp->data.u.str.len);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100511 break;
512
513 case LUA_TUSERDATA:
514 case LUA_TNIL:
515 case LUA_TTABLE:
516 case LUA_TFUNCTION:
517 case LUA_TTHREAD:
518 case LUA_TLIGHTUSERDATA:
Thierry FOURNIER93405e12015-08-26 14:19:03 +0200519 case LUA_TNONE:
520 default:
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200521 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200522 smp->data.u.sint = 0;
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100523 break;
524 }
525 return 1;
526}
527
528/* This function check the "argp" builded by another conversion function
529 * is in accord with the expected argp defined by the "mask". The fucntion
530 * returns true or false. It can be adjust the types if there compatibles.
Thierry FOURNIER3caa0392015-03-13 13:38:17 +0100531 *
532 * This function assumes thant the argp argument contains ARGM_NBARGS + 1
533 * entries.
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100534 */
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100535__LJMP int hlua_lua2arg_check(lua_State *L, int first, struct arg *argp,
David Carlier0c437f42016-04-27 16:21:56 +0100536 uint64_t mask, struct proxy *p)
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100537{
538 int min_arg;
539 int idx;
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100540 struct proxy *px;
541 char *sname, *pname;
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100542
543 idx = 0;
544 min_arg = ARGM(mask);
545 mask >>= ARGM_BITS;
546
547 while (1) {
548
549 /* Check oversize. */
550 if (idx >= ARGM_NBARGS && argp[idx].type != ARGT_STOP) {
Cyril Bonté577a36a2015-03-02 00:08:38 +0100551 WILL_LJMP(luaL_argerror(L, first + idx, "Malformed argument mask"));
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100552 }
553
554 /* Check for mandatory arguments. */
555 if (argp[idx].type == ARGT_STOP) {
Thierry FOURNIER3caa0392015-03-13 13:38:17 +0100556 if (idx < min_arg) {
557
558 /* If miss other argument than the first one, we return an error. */
559 if (idx > 0)
560 WILL_LJMP(luaL_argerror(L, first + idx, "Mandatory argument expected"));
561
562 /* If first argument have a certain type, some default values
563 * may be used. See the function smp_resolve_args().
564 */
565 switch (mask & ARGT_MASK) {
566
567 case ARGT_FE:
568 if (!(p->cap & PR_CAP_FE))
569 WILL_LJMP(luaL_argerror(L, first + idx, "Mandatory argument expected"));
570 argp[idx].data.prx = p;
571 argp[idx].type = ARGT_FE;
572 argp[idx+1].type = ARGT_STOP;
573 break;
574
575 case ARGT_BE:
576 if (!(p->cap & PR_CAP_BE))
577 WILL_LJMP(luaL_argerror(L, first + idx, "Mandatory argument expected"));
578 argp[idx].data.prx = p;
579 argp[idx].type = ARGT_BE;
580 argp[idx+1].type = ARGT_STOP;
581 break;
582
583 case ARGT_TAB:
584 argp[idx].data.prx = p;
585 argp[idx].type = ARGT_TAB;
586 argp[idx+1].type = ARGT_STOP;
587 break;
588
589 default:
590 WILL_LJMP(luaL_argerror(L, first + idx, "Mandatory argument expected"));
591 break;
592 }
593 }
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100594 return 0;
595 }
596
597 /* Check for exceed the number of requiered argument. */
598 if ((mask & ARGT_MASK) == ARGT_STOP &&
599 argp[idx].type != ARGT_STOP) {
600 WILL_LJMP(luaL_argerror(L, first + idx, "Last argument expected"));
601 }
602
603 if ((mask & ARGT_MASK) == ARGT_STOP &&
604 argp[idx].type == ARGT_STOP) {
605 return 0;
606 }
607
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100608 /* Convert some argument types. */
609 switch (mask & ARGT_MASK) {
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100610 case ARGT_SINT:
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100611 if (argp[idx].type != ARGT_SINT)
612 WILL_LJMP(luaL_argerror(L, first + idx, "integer expected"));
613 argp[idx].type = ARGT_SINT;
614 break;
615
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100616 case ARGT_TIME:
617 if (argp[idx].type != ARGT_SINT)
618 WILL_LJMP(luaL_argerror(L, first + idx, "integer expected"));
Thierry FOURNIER29176f32015-07-07 00:41:29 +0200619 argp[idx].type = ARGT_TIME;
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100620 break;
621
622 case ARGT_SIZE:
623 if (argp[idx].type != ARGT_SINT)
624 WILL_LJMP(luaL_argerror(L, first + idx, "integer expected"));
Thierry FOURNIER29176f32015-07-07 00:41:29 +0200625 argp[idx].type = ARGT_SIZE;
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100626 break;
627
628 case ARGT_FE:
629 if (argp[idx].type != ARGT_STR)
630 WILL_LJMP(luaL_argerror(L, first + idx, "string expected"));
631 memcpy(trash.str, argp[idx].data.str.str, argp[idx].data.str.len);
632 trash.str[argp[idx].data.str.len] = 0;
Willy Tarreau9e0bb102015-05-26 11:24:42 +0200633 argp[idx].data.prx = proxy_fe_by_name(trash.str);
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100634 if (!argp[idx].data.prx)
635 WILL_LJMP(luaL_argerror(L, first + idx, "frontend doesn't exist"));
636 argp[idx].type = ARGT_FE;
637 break;
638
639 case ARGT_BE:
640 if (argp[idx].type != ARGT_STR)
641 WILL_LJMP(luaL_argerror(L, first + idx, "string expected"));
642 memcpy(trash.str, argp[idx].data.str.str, argp[idx].data.str.len);
643 trash.str[argp[idx].data.str.len] = 0;
Willy Tarreau9e0bb102015-05-26 11:24:42 +0200644 argp[idx].data.prx = proxy_be_by_name(trash.str);
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100645 if (!argp[idx].data.prx)
646 WILL_LJMP(luaL_argerror(L, first + idx, "backend doesn't exist"));
647 argp[idx].type = ARGT_BE;
648 break;
649
650 case ARGT_TAB:
651 if (argp[idx].type != ARGT_STR)
652 WILL_LJMP(luaL_argerror(L, first + idx, "string expected"));
653 memcpy(trash.str, argp[idx].data.str.str, argp[idx].data.str.len);
654 trash.str[argp[idx].data.str.len] = 0;
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +0200655 argp[idx].data.prx = proxy_tbl_by_name(trash.str);
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100656 if (!argp[idx].data.prx)
657 WILL_LJMP(luaL_argerror(L, first + idx, "table doesn't exist"));
658 argp[idx].type = ARGT_TAB;
659 break;
660
661 case ARGT_SRV:
662 if (argp[idx].type != ARGT_STR)
663 WILL_LJMP(luaL_argerror(L, first + idx, "string expected"));
664 memcpy(trash.str, argp[idx].data.str.str, argp[idx].data.str.len);
665 trash.str[argp[idx].data.str.len] = 0;
666 sname = strrchr(trash.str, '/');
667 if (sname) {
668 *sname++ = '\0';
669 pname = trash.str;
Willy Tarreau9e0bb102015-05-26 11:24:42 +0200670 px = proxy_be_by_name(pname);
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100671 if (!px)
672 WILL_LJMP(luaL_argerror(L, first + idx, "backend doesn't exist"));
673 }
674 else {
675 sname = trash.str;
676 px = p;
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100677 }
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100678 argp[idx].data.srv = findserver(px, sname);
679 if (!argp[idx].data.srv)
680 WILL_LJMP(luaL_argerror(L, first + idx, "server doesn't exist"));
681 argp[idx].type = ARGT_SRV;
682 break;
683
684 case ARGT_IPV4:
685 memcpy(trash.str, argp[idx].data.str.str, argp[idx].data.str.len);
686 trash.str[argp[idx].data.str.len] = 0;
687 if (inet_pton(AF_INET, trash.str, &argp[idx].data.ipv4))
688 WILL_LJMP(luaL_argerror(L, first + idx, "invalid IPv4 address"));
689 argp[idx].type = ARGT_IPV4;
690 break;
691
692 case ARGT_MSK4:
693 memcpy(trash.str, argp[idx].data.str.str, argp[idx].data.str.len);
694 trash.str[argp[idx].data.str.len] = 0;
695 if (!str2mask(trash.str, &argp[idx].data.ipv4))
696 WILL_LJMP(luaL_argerror(L, first + idx, "invalid IPv4 mask"));
697 argp[idx].type = ARGT_MSK4;
698 break;
699
700 case ARGT_IPV6:
701 memcpy(trash.str, argp[idx].data.str.str, argp[idx].data.str.len);
702 trash.str[argp[idx].data.str.len] = 0;
703 if (inet_pton(AF_INET6, trash.str, &argp[idx].data.ipv6))
704 WILL_LJMP(luaL_argerror(L, first + idx, "invalid IPv6 address"));
705 argp[idx].type = ARGT_IPV6;
706 break;
707
708 case ARGT_MSK6:
709 case ARGT_MAP:
710 case ARGT_REG:
711 case ARGT_USR:
712 WILL_LJMP(luaL_argerror(L, first + idx, "type not yet supported"));
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100713 break;
714 }
715
716 /* Check for type of argument. */
717 if ((mask & ARGT_MASK) != argp[idx].type) {
718 const char *msg = lua_pushfstring(L, "'%s' expected, got '%s'",
719 arg_type_names[(mask & ARGT_MASK)],
720 arg_type_names[argp[idx].type & ARGT_MASK]);
721 WILL_LJMP(luaL_argerror(L, first + idx, msg));
722 }
723
724 /* Next argument. */
725 mask >>= ARGT_BITS;
726 idx++;
727 }
728}
729
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100730/*
731 * The following functions are used to make correspondance between the the
732 * executed lua pointer and the "struct hlua *" that contain the context.
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100733 *
734 * - hlua_gethlua : return the hlua context associated with an lua_State.
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100735 * - hlua_sethlua : create the association between hlua context and lua_state.
736 */
737static inline struct hlua *hlua_gethlua(lua_State *L)
738{
Thierry FOURNIER38c5fd62015-03-10 02:40:29 +0100739 struct hlua **hlua = lua_getextraspace(L);
740 return *hlua;
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100741}
742static inline void hlua_sethlua(struct hlua *hlua)
743{
Thierry FOURNIER38c5fd62015-03-10 02:40:29 +0100744 struct hlua **hlua_store = lua_getextraspace(hlua->T);
745 *hlua_store = hlua;
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100746}
747
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +0100748/* This function is used to send logs. It try to send on screen (stderr)
749 * and on the default syslog server.
750 */
751static inline void hlua_sendlog(struct proxy *px, int level, const char *msg)
752{
753 struct tm tm;
754 char *p;
755
756 /* Cleanup the log message. */
757 p = trash.str;
758 for (; *msg != '\0'; msg++, p++) {
Thierry FOURNIERccf00632015-09-16 12:47:03 +0200759 if (p >= trash.str + trash.size - 1) {
760 /* Break the message if exceed the buffer size. */
761 *(p-4) = ' ';
762 *(p-3) = '.';
763 *(p-2) = '.';
764 *(p-1) = '.';
765 break;
766 }
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +0100767 if (isprint(*msg))
768 *p = *msg;
769 else
770 *p = '.';
771 }
772 *p = '\0';
773
Thierry FOURNIER5554e292015-09-09 11:21:37 +0200774 send_log(px, level, "%s\n", trash.str);
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +0100775 if (!(global.mode & MODE_QUIET) || (global.mode & (MODE_VERBOSE | MODE_STARTING))) {
Willy Tarreaua678b432015-08-28 10:14:59 +0200776 get_localtime(date.tv_sec, &tm);
777 fprintf(stderr, "[%s] %03d/%02d%02d%02d (%d) : %s\n",
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +0100778 log_levels[level], tm.tm_yday, tm.tm_hour, tm.tm_min, tm.tm_sec,
779 (int)getpid(), trash.str);
780 fflush(stderr);
781 }
782}
783
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +0100784/* This function just ensure that the yield will be always
785 * returned with a timeout and permit to set some flags
786 */
787__LJMP void hlua_yieldk(lua_State *L, int nresults, int ctx,
Thierry FOURNIERf90838b2015-03-06 13:48:32 +0100788 lua_KFunction k, int timeout, unsigned int flags)
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +0100789{
790 struct hlua *hlua = hlua_gethlua(L);
791
792 /* Set the wake timeout. If timeout is required, we set
793 * the expiration time.
794 */
Thierry FOURNIER10770fa2015-09-29 01:59:42 +0200795 hlua->wake_time = timeout;
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +0100796
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +0100797 hlua->flags |= flags;
798
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +0100799 /* Process the yield. */
800 WILL_LJMP(lua_yieldk(L, nresults, ctx, k));
801}
802
Willy Tarreau87b09662015-04-03 00:22:06 +0200803/* This function initialises the Lua environment stored in the stream.
804 * It must be called at the start of the stream. This function creates
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100805 * an LUA coroutine. It can not be use to crete the main LUA context.
Thierry FOURNIERbabae282015-09-17 11:36:37 +0200806 *
807 * This function is particular. it initialises a new Lua thread. If the
808 * initialisation fails (example: out of memory error), the lua function
809 * throws an error (longjmp).
810 *
811 * This function manipulates two Lua stack: the main and the thread. Only
812 * the main stack can fail. The thread is not manipulated. This function
813 * MUST NOT manipulate the created thread stack state, because is not
814 * proctected agains error throwed by the thread stack.
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100815 */
816int hlua_ctx_init(struct hlua *lua, struct task *task)
817{
Thierry FOURNIERbabae282015-09-17 11:36:37 +0200818 if (!SET_SAFE_LJMP(gL.T)) {
819 lua->Tref = LUA_REFNIL;
820 return 0;
821 }
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100822 lua->Mref = LUA_REFNIL;
Thierry FOURNIERa097fdf2015-03-03 15:17:35 +0100823 lua->flags = 0;
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +0100824 LIST_INIT(&lua->com);
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100825 lua->T = lua_newthread(gL.T);
826 if (!lua->T) {
827 lua->Tref = LUA_REFNIL;
Thierry FOURNIER0a976202017-07-12 11:18:00 +0200828 RESET_SAFE_LJMP(gL.T);
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100829 return 0;
830 }
831 hlua_sethlua(lua);
832 lua->Tref = luaL_ref(gL.T, LUA_REGISTRYINDEX);
833 lua->task = task;
Thierry FOURNIERbabae282015-09-17 11:36:37 +0200834 RESET_SAFE_LJMP(gL.T);
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100835 return 1;
836}
837
Willy Tarreau87b09662015-04-03 00:22:06 +0200838/* Used to destroy the Lua coroutine when the attached stream or task
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100839 * is destroyed. The destroy also the memory context. The struct "lua"
840 * is not freed.
841 */
842void hlua_ctx_destroy(struct hlua *lua)
843{
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +0100844 if (!lua)
Thierry FOURNIERa718b292015-03-04 16:48:34 +0100845 return;
846
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +0100847 if (!lua->T)
848 goto end;
849
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +0100850 /* Purge all the pending signals. */
Thierry FOURNIERd6975962017-07-12 14:31:10 +0200851 notification_purge(&lua->com);
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +0100852
Thierry FOURNIER75d02082017-07-12 13:41:33 +0200853 if (!SET_SAFE_LJMP(lua->T))
854 return;
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100855 luaL_unref(lua->T, LUA_REGISTRYINDEX, lua->Mref);
Thierry FOURNIER75d02082017-07-12 13:41:33 +0200856 RESET_SAFE_LJMP(lua->T);
Thierry FOURNIER5a50a852015-09-23 16:59:28 +0200857
Thierry FOURNIER75d02082017-07-12 13:41:33 +0200858 if (!SET_SAFE_LJMP(gL.T))
859 return;
860 luaL_unref(gL.T, LUA_REGISTRYINDEX, lua->Tref);
861 RESET_SAFE_LJMP(gL.T);
Thierry FOURNIER5a50a852015-09-23 16:59:28 +0200862 /* Forces a garbage collecting process. If the Lua program is finished
863 * without error, we run the GC on the thread pointer. Its freed all
864 * the unused memory.
865 * If the thread is finnish with an error or is currently yielded,
866 * it seems that the GC applied on the thread doesn't clean anything,
867 * so e run the GC on the main thread.
868 * NOTE: maybe this action locks all the Lua threads untiml the en of
869 * the garbage collection.
870 */
Thierry FOURNIER7c39ab42015-09-27 22:53:33 +0200871 if (lua->flags & HLUA_MUST_GC) {
Thierry FOURNIER7bd10d52017-07-17 00:44:40 +0200872 if (!SET_SAFE_LJMP(gL.T))
Thierry FOURNIER75d02082017-07-12 13:41:33 +0200873 return;
Thierry FOURNIER7bd10d52017-07-17 00:44:40 +0200874 lua_gc(gL.T, LUA_GCCOLLECT, 0);
875 RESET_SAFE_LJMP(gL.T);
Thierry FOURNIER7c39ab42015-09-27 22:53:33 +0200876 }
Thierry FOURNIER5a50a852015-09-23 16:59:28 +0200877
Thierry FOURNIERa7b536b2015-09-21 22:50:24 +0200878 lua->T = NULL;
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +0100879
880end:
881 pool_free2(pool2_hlua, lua);
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100882}
883
884/* This function is used to restore the Lua context when a coroutine
885 * fails. This function copy the common memory between old coroutine
886 * and the new coroutine. The old coroutine is destroyed, and its
887 * replaced by the new coroutine.
888 * If the flag "keep_msg" is set, the last entry of the old is assumed
889 * as string error message and it is copied in the new stack.
890 */
891static int hlua_ctx_renew(struct hlua *lua, int keep_msg)
892{
893 lua_State *T;
894 int new_ref;
895
896 /* Renew the main LUA stack doesn't have sense. */
897 if (lua == &gL)
898 return 0;
899
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100900 /* New Lua coroutine. */
901 T = lua_newthread(gL.T);
902 if (!T)
903 return 0;
904
905 /* Copy last error message. */
906 if (keep_msg)
907 lua_xmove(lua->T, T, 1);
908
909 /* Copy data between the coroutines. */
910 lua_rawgeti(lua->T, LUA_REGISTRYINDEX, lua->Mref);
911 lua_xmove(lua->T, T, 1);
912 new_ref = luaL_ref(T, LUA_REGISTRYINDEX); /* Valur poped. */
913
914 /* Destroy old data. */
915 luaL_unref(lua->T, LUA_REGISTRYINDEX, lua->Mref);
916
917 /* The thread is garbage collected by Lua. */
918 luaL_unref(gL.T, LUA_REGISTRYINDEX, lua->Tref);
919
920 /* Fill the struct with the new coroutine values. */
921 lua->Mref = new_ref;
922 lua->T = T;
923 lua->Tref = luaL_ref(gL.T, LUA_REGISTRYINDEX);
924
925 /* Set context. */
926 hlua_sethlua(lua);
927
928 return 1;
929}
930
Thierry FOURNIERee9f8022015-03-03 17:37:37 +0100931void hlua_hook(lua_State *L, lua_Debug *ar)
932{
Thierry FOURNIERcae49c92015-03-06 14:05:24 +0100933 struct hlua *hlua = hlua_gethlua(L);
934
935 /* Lua cannot yield when its returning from a function,
936 * so, we can fix the interrupt hook to 1 instruction,
937 * expecting that the function is finnished.
938 */
939 if (lua_gethookmask(L) & LUA_MASKRET) {
940 lua_sethook(hlua->T, hlua_hook, LUA_MASKCOUNT, 1);
941 return;
942 }
943
944 /* restore the interrupt condition. */
945 lua_sethook(hlua->T, hlua_hook, LUA_MASKCOUNT, hlua_nb_instruction);
946
947 /* If we interrupt the Lua processing in yieldable state, we yield.
948 * If the state is not yieldable, trying yield causes an error.
949 */
950 if (lua_isyieldable(L))
951 WILL_LJMP(hlua_yieldk(L, 0, 0, NULL, TICK_ETERNITY, HLUA_CTRLYIELD));
952
Thierry FOURNIERa85cfb12015-03-13 14:50:06 +0100953 /* If we cannot yield, update the clock and check the timeout. */
954 tv_update_date(0, 1);
Thierry FOURNIER10770fa2015-09-29 01:59:42 +0200955 hlua->run_time += now_ms - hlua->start_time;
956 if (hlua->max_time && hlua->run_time >= hlua->max_time) {
Thierry FOURNIERcae49c92015-03-06 14:05:24 +0100957 lua_pushfstring(L, "execution timeout");
958 WILL_LJMP(lua_error(L));
959 }
960
Thierry FOURNIER10770fa2015-09-29 01:59:42 +0200961 /* Update the start time. */
962 hlua->start_time = now_ms;
963
Thierry FOURNIERcae49c92015-03-06 14:05:24 +0100964 /* Try to interrupt the process at the end of the current
965 * unyieldable function.
966 */
967 lua_sethook(hlua->T, hlua_hook, LUA_MASKRET|LUA_MASKCOUNT, hlua_nb_instruction);
Thierry FOURNIERee9f8022015-03-03 17:37:37 +0100968}
969
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100970/* This function start or resumes the Lua stack execution. If the flag
971 * "yield_allowed" if no set and the LUA stack execution returns a yield
972 * The function return an error.
973 *
974 * The function can returns 4 values:
975 * - HLUA_E_OK : The execution is terminated without any errors.
976 * - HLUA_E_AGAIN : The execution must continue at the next associated
977 * task wakeup.
978 * - HLUA_E_ERRMSG : An error has occured, an error message is set in
979 * the top of the stack.
980 * - HLUA_E_ERR : An error has occured without error message.
981 *
982 * If an error occured, the stack is renewed and it is ready to run new
983 * LUA code.
984 */
985static enum hlua_exec hlua_ctx_resume(struct hlua *lua, int yield_allowed)
986{
987 int ret;
988 const char *msg;
989
Thierry FOURNIER10770fa2015-09-29 01:59:42 +0200990 /* Initialise run time counter. */
991 if (!HLUA_IS_RUNNING(lua))
992 lua->run_time = 0;
Thierry FOURNIERdc9ca962015-03-05 11:16:52 +0100993
Thierry FOURNIER61ba0e22017-07-12 11:41:21 +0200994 /* Lock the whole Lua execution. This lock must be before the
995 * label "resume_execution".
996 */
997 SPIN_LOCK(LUA_LOCK, &hlua_global_lock);
998
Thierry FOURNIERee9f8022015-03-03 17:37:37 +0100999resume_execution:
1000
1001 /* This hook interrupts the Lua processing each 'hlua_nb_instruction'
1002 * instructions. it is used for preventing infinite loops.
1003 */
1004 lua_sethook(lua->T, hlua_hook, LUA_MASKCOUNT, hlua_nb_instruction);
1005
Thierry FOURNIER1bfc09b2015-03-05 17:10:14 +01001006 /* Remove all flags except the running flags. */
Thierry FOURNIER2f3867f2015-09-28 01:02:01 +02001007 HLUA_SET_RUN(lua);
1008 HLUA_CLR_CTRLYIELD(lua);
1009 HLUA_CLR_WAKERESWR(lua);
1010 HLUA_CLR_WAKEREQWR(lua);
Thierry FOURNIER1bfc09b2015-03-05 17:10:14 +01001011
Thierry FOURNIER10770fa2015-09-29 01:59:42 +02001012 /* Update the start time. */
1013 lua->start_time = now_ms;
1014
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001015 /* Call the function. */
1016 ret = lua_resume(lua->T, gL.T, lua->nargs);
1017 switch (ret) {
1018
1019 case LUA_OK:
1020 ret = HLUA_E_OK;
1021 break;
1022
1023 case LUA_YIELD:
Thierry FOURNIERdc9ca962015-03-05 11:16:52 +01001024 /* Check if the execution timeout is expired. It it is the case, we
1025 * break the Lua execution.
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01001026 */
Thierry FOURNIER10770fa2015-09-29 01:59:42 +02001027 tv_update_date(0, 1);
1028 lua->run_time += now_ms - lua->start_time;
1029 if (lua->max_time && lua->run_time > lua->max_time) {
Thierry FOURNIERdc9ca962015-03-05 11:16:52 +01001030 lua_settop(lua->T, 0); /* Empty the stack. */
1031 if (!lua_checkstack(lua->T, 1)) {
1032 ret = HLUA_E_ERR;
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01001033 break;
1034 }
Thierry FOURNIERdc9ca962015-03-05 11:16:52 +01001035 lua_pushfstring(lua->T, "execution timeout");
1036 ret = HLUA_E_ERRMSG;
1037 break;
1038 }
1039 /* Process the forced yield. if the general yield is not allowed or
1040 * if no task were associated this the current Lua execution
1041 * coroutine, we resume the execution. Else we want to return in the
1042 * scheduler and we want to be waked up again, to continue the
1043 * current Lua execution. So we schedule our own task.
1044 */
1045 if (HLUA_IS_CTRLYIELDING(lua)) {
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01001046 if (!yield_allowed || !lua->task)
1047 goto resume_execution;
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01001048 task_wakeup(lua->task, TASK_WOKEN_MSG);
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01001049 }
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001050 if (!yield_allowed) {
1051 lua_settop(lua->T, 0); /* Empty the stack. */
1052 if (!lua_checkstack(lua->T, 1)) {
1053 ret = HLUA_E_ERR;
1054 break;
1055 }
1056 lua_pushfstring(lua->T, "yield not allowed");
1057 ret = HLUA_E_ERRMSG;
1058 break;
1059 }
1060 ret = HLUA_E_AGAIN;
1061 break;
1062
1063 case LUA_ERRRUN:
Thierry FOURNIER0a99b892015-08-26 00:14:17 +02001064
1065 /* Special exit case. The traditionnal exit is returned as an error
1066 * because the errors ares the only one mean to return immediately
1067 * from and lua execution.
1068 */
1069 if (lua->flags & HLUA_EXIT) {
1070 ret = HLUA_E_OK;
Thierry FOURNIERe1587b32015-08-28 09:54:13 +02001071 hlua_ctx_renew(lua, 0);
Thierry FOURNIER0a99b892015-08-26 00:14:17 +02001072 break;
1073 }
1074
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01001075 lua->wake_time = TICK_ETERNITY;
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001076 if (!lua_checkstack(lua->T, 1)) {
1077 ret = HLUA_E_ERR;
1078 break;
1079 }
1080 msg = lua_tostring(lua->T, -1);
1081 lua_settop(lua->T, 0); /* Empty the stack. */
1082 lua_pop(lua->T, 1);
1083 if (msg)
1084 lua_pushfstring(lua->T, "runtime error: %s", msg);
1085 else
1086 lua_pushfstring(lua->T, "unknown runtime error");
1087 ret = HLUA_E_ERRMSG;
1088 break;
1089
1090 case LUA_ERRMEM:
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01001091 lua->wake_time = TICK_ETERNITY;
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001092 lua_settop(lua->T, 0); /* Empty the stack. */
1093 if (!lua_checkstack(lua->T, 1)) {
1094 ret = HLUA_E_ERR;
1095 break;
1096 }
1097 lua_pushfstring(lua->T, "out of memory error");
1098 ret = HLUA_E_ERRMSG;
1099 break;
1100
1101 case LUA_ERRERR:
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01001102 lua->wake_time = TICK_ETERNITY;
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001103 if (!lua_checkstack(lua->T, 1)) {
1104 ret = HLUA_E_ERR;
1105 break;
1106 }
1107 msg = lua_tostring(lua->T, -1);
1108 lua_settop(lua->T, 0); /* Empty the stack. */
1109 lua_pop(lua->T, 1);
1110 if (msg)
1111 lua_pushfstring(lua->T, "message handler error: %s", msg);
1112 else
1113 lua_pushfstring(lua->T, "message handler error");
1114 ret = HLUA_E_ERRMSG;
1115 break;
1116
1117 default:
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01001118 lua->wake_time = TICK_ETERNITY;
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001119 lua_settop(lua->T, 0); /* Empty the stack. */
1120 if (!lua_checkstack(lua->T, 1)) {
1121 ret = HLUA_E_ERR;
1122 break;
1123 }
1124 lua_pushfstring(lua->T, "unknonwn error");
1125 ret = HLUA_E_ERRMSG;
1126 break;
1127 }
1128
Thierry FOURNIER6ab4d8e2015-09-27 22:17:19 +02001129 /* This GC permits to destroy some object when a Lua timeout strikes. */
Thierry FOURNIER7c39ab42015-09-27 22:53:33 +02001130 if (lua->flags & HLUA_MUST_GC &&
1131 ret != HLUA_E_AGAIN)
Thierry FOURNIER6ab4d8e2015-09-27 22:17:19 +02001132 lua_gc(lua->T, LUA_GCCOLLECT, 0);
1133
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001134 switch (ret) {
1135 case HLUA_E_AGAIN:
1136 break;
1137
1138 case HLUA_E_ERRMSG:
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001139 notification_purge(&lua->com);
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001140 hlua_ctx_renew(lua, 1);
Thierry FOURNIERa097fdf2015-03-03 15:17:35 +01001141 HLUA_CLR_RUN(lua);
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001142 break;
1143
1144 case HLUA_E_ERR:
Thierry FOURNIERa097fdf2015-03-03 15:17:35 +01001145 HLUA_CLR_RUN(lua);
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001146 notification_purge(&lua->com);
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001147 hlua_ctx_renew(lua, 0);
1148 break;
1149
1150 case HLUA_E_OK:
Thierry FOURNIERa097fdf2015-03-03 15:17:35 +01001151 HLUA_CLR_RUN(lua);
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001152 notification_purge(&lua->com);
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001153 break;
1154 }
1155
Thierry FOURNIER61ba0e22017-07-12 11:41:21 +02001156 /* This is the main exit point, remove the Lua lock. */
1157 SPIN_UNLOCK(LUA_LOCK, &hlua_global_lock);
1158
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001159 return ret;
1160}
1161
Thierry FOURNIER0a99b892015-08-26 00:14:17 +02001162/* This function exit the current code. */
1163__LJMP static int hlua_done(lua_State *L)
1164{
1165 struct hlua *hlua = hlua_gethlua(L);
1166
1167 hlua->flags |= HLUA_EXIT;
1168 WILL_LJMP(lua_error(L));
1169
1170 return 0;
1171}
1172
Thierry FOURNIER83758bb2015-02-04 13:21:04 +01001173/* This function is an LUA binding. It provides a function
1174 * for deleting ACL from a referenced ACL file.
1175 */
1176__LJMP static int hlua_del_acl(lua_State *L)
1177{
1178 const char *name;
1179 const char *key;
1180 struct pat_ref *ref;
1181
1182 MAY_LJMP(check_args(L, 2, "del_acl"));
1183
1184 name = MAY_LJMP(luaL_checkstring(L, 1));
1185 key = MAY_LJMP(luaL_checkstring(L, 2));
1186
1187 ref = pat_ref_lookup(name);
1188 if (!ref)
Vincent Bernata72db182015-10-06 16:05:59 +02001189 WILL_LJMP(luaL_error(L, "'del_acl': unknown acl file '%s'", name));
Thierry FOURNIER83758bb2015-02-04 13:21:04 +01001190
1191 pat_ref_delete(ref, key);
1192 return 0;
1193}
1194
1195/* This function is an LUA binding. It provides a function
1196 * for deleting map entry from a referenced map file.
1197 */
1198static int hlua_del_map(lua_State *L)
1199{
1200 const char *name;
1201 const char *key;
1202 struct pat_ref *ref;
1203
1204 MAY_LJMP(check_args(L, 2, "del_map"));
1205
1206 name = MAY_LJMP(luaL_checkstring(L, 1));
1207 key = MAY_LJMP(luaL_checkstring(L, 2));
1208
1209 ref = pat_ref_lookup(name);
1210 if (!ref)
Vincent Bernata72db182015-10-06 16:05:59 +02001211 WILL_LJMP(luaL_error(L, "'del_map': unknown acl file '%s'", name));
Thierry FOURNIER83758bb2015-02-04 13:21:04 +01001212
1213 pat_ref_delete(ref, key);
1214 return 0;
1215}
1216
1217/* This function is an LUA binding. It provides a function
1218 * for adding ACL pattern from a referenced ACL file.
1219 */
1220static int hlua_add_acl(lua_State *L)
1221{
1222 const char *name;
1223 const char *key;
1224 struct pat_ref *ref;
1225
1226 MAY_LJMP(check_args(L, 2, "add_acl"));
1227
1228 name = MAY_LJMP(luaL_checkstring(L, 1));
1229 key = MAY_LJMP(luaL_checkstring(L, 2));
1230
1231 ref = pat_ref_lookup(name);
1232 if (!ref)
Vincent Bernata72db182015-10-06 16:05:59 +02001233 WILL_LJMP(luaL_error(L, "'add_acl': unknown acl file '%s'", name));
Thierry FOURNIER83758bb2015-02-04 13:21:04 +01001234
1235 if (pat_ref_find_elt(ref, key) == NULL)
1236 pat_ref_add(ref, key, NULL, NULL);
1237 return 0;
1238}
1239
1240/* This function is an LUA binding. It provides a function
1241 * for setting map pattern and sample from a referenced map
1242 * file.
1243 */
1244static int hlua_set_map(lua_State *L)
1245{
1246 const char *name;
1247 const char *key;
1248 const char *value;
1249 struct pat_ref *ref;
1250
1251 MAY_LJMP(check_args(L, 3, "set_map"));
1252
1253 name = MAY_LJMP(luaL_checkstring(L, 1));
1254 key = MAY_LJMP(luaL_checkstring(L, 2));
1255 value = MAY_LJMP(luaL_checkstring(L, 3));
1256
1257 ref = pat_ref_lookup(name);
1258 if (!ref)
Vincent Bernata72db182015-10-06 16:05:59 +02001259 WILL_LJMP(luaL_error(L, "'set_map': unknown map file '%s'", name));
Thierry FOURNIER83758bb2015-02-04 13:21:04 +01001260
1261 if (pat_ref_find_elt(ref, key) != NULL)
1262 pat_ref_set(ref, key, value, NULL);
1263 else
1264 pat_ref_add(ref, key, value, NULL);
1265 return 0;
1266}
1267
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01001268/* A class is a lot of memory that contain data. This data can be a table,
1269 * an integer or user data. This data is associated with a metatable. This
1270 * metatable have an original version registred in the global context with
1271 * the name of the object (_G[<name>] = <metable> ).
1272 *
1273 * A metable is a table that modify the standard behavior of a standard
1274 * access to the associated data. The entries of this new metatable are
1275 * defined as is:
1276 *
1277 * http://lua-users.org/wiki/MetatableEvents
1278 *
1279 * __index
1280 *
1281 * we access an absent field in a table, the result is nil. This is
1282 * true, but it is not the whole truth. Actually, such access triggers
1283 * the interpreter to look for an __index metamethod: If there is no
1284 * such method, as usually happens, then the access results in nil;
1285 * otherwise, the metamethod will provide the result.
1286 *
1287 * Control 'prototype' inheritance. When accessing "myTable[key]" and
1288 * the key does not appear in the table, but the metatable has an __index
1289 * property:
1290 *
1291 * - if the value is a function, the function is called, passing in the
1292 * table and the key; the return value of that function is returned as
1293 * the result.
1294 *
1295 * - if the value is another table, the value of the key in that table is
1296 * asked for and returned (and if it doesn't exist in that table, but that
1297 * table's metatable has an __index property, then it continues on up)
1298 *
1299 * - Use "rawget(myTable,key)" to skip this metamethod.
1300 *
1301 * http://www.lua.org/pil/13.4.1.html
1302 *
1303 * __newindex
1304 *
1305 * Like __index, but control property assignment.
1306 *
1307 * __mode - Control weak references. A string value with one or both
1308 * of the characters 'k' and 'v' which specifies that the the
1309 * keys and/or values in the table are weak references.
1310 *
1311 * __call - Treat a table like a function. When a table is followed by
1312 * parenthesis such as "myTable( 'foo' )" and the metatable has
1313 * a __call key pointing to a function, that function is invoked
1314 * (passing any specified arguments) and the return value is
1315 * returned.
1316 *
1317 * __metatable - Hide the metatable. When "getmetatable( myTable )" is
1318 * called, if the metatable for myTable has a __metatable
1319 * key, the value of that key is returned instead of the
1320 * actual metatable.
1321 *
1322 * __tostring - Control string representation. When the builtin
1323 * "tostring( myTable )" function is called, if the metatable
1324 * for myTable has a __tostring property set to a function,
1325 * that function is invoked (passing myTable to it) and the
1326 * return value is used as the string representation.
1327 *
1328 * __len - Control table length. When the table length is requested using
1329 * the length operator ( '#' ), if the metatable for myTable has
1330 * a __len key pointing to a function, that function is invoked
1331 * (passing myTable to it) and the return value used as the value
1332 * of "#myTable".
1333 *
1334 * __gc - Userdata finalizer code. When userdata is set to be garbage
1335 * collected, if the metatable has a __gc field pointing to a
1336 * function, that function is first invoked, passing the userdata
1337 * to it. The __gc metamethod is not called for tables.
1338 * (See http://lua-users.org/lists/lua-l/2006-11/msg00508.html)
1339 *
1340 * Special metamethods for redefining standard operators:
1341 * http://www.lua.org/pil/13.1.html
1342 *
1343 * __add "+"
1344 * __sub "-"
1345 * __mul "*"
1346 * __div "/"
1347 * __unm "!"
1348 * __pow "^"
1349 * __concat ".."
1350 *
1351 * Special methods for redfining standar relations
1352 * http://www.lua.org/pil/13.2.html
1353 *
1354 * __eq "=="
1355 * __lt "<"
1356 * __le "<="
1357 */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001358
1359/*
1360 *
1361 *
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001362 * Class Map
1363 *
1364 *
1365 */
1366
1367/* Returns a struct hlua_map if the stack entry "ud" is
1368 * a class session, otherwise it throws an error.
1369 */
1370__LJMP static struct map_descriptor *hlua_checkmap(lua_State *L, int ud)
1371{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001372 return MAY_LJMP(hlua_checkudata(L, ud, class_map_ref));
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001373}
1374
1375/* This function is the map constructor. It don't need
1376 * the class Map object. It creates and return a new Map
1377 * object. It must be called only during "body" or "init"
1378 * context because it process some filesystem accesses.
1379 */
1380__LJMP static int hlua_map_new(struct lua_State *L)
1381{
1382 const char *fn;
1383 int match = PAT_MATCH_STR;
1384 struct sample_conv conv;
1385 const char *file = "";
1386 int line = 0;
1387 lua_Debug ar;
1388 char *err = NULL;
1389 struct arg args[2];
1390
1391 if (lua_gettop(L) < 1 || lua_gettop(L) > 2)
1392 WILL_LJMP(luaL_error(L, "'new' needs at least 1 argument."));
1393
1394 fn = MAY_LJMP(luaL_checkstring(L, 1));
1395
1396 if (lua_gettop(L) >= 2) {
1397 match = MAY_LJMP(luaL_checkinteger(L, 2));
1398 if (match < 0 || match >= PAT_MATCH_NUM)
1399 WILL_LJMP(luaL_error(L, "'new' needs a valid match method."));
1400 }
1401
1402 /* Get Lua filename and line number. */
1403 if (lua_getstack(L, 1, &ar)) { /* check function at level */
1404 lua_getinfo(L, "Sl", &ar); /* get info about it */
1405 if (ar.currentline > 0) { /* is there info? */
1406 file = ar.short_src;
1407 line = ar.currentline;
1408 }
1409 }
1410
1411 /* fill fake sample_conv struct. */
1412 conv.kw = ""; /* unused. */
1413 conv.process = NULL; /* unused. */
1414 conv.arg_mask = 0; /* unused. */
1415 conv.val_args = NULL; /* unused. */
1416 conv.out_type = SMP_T_STR;
1417 conv.private = (void *)(long)match;
1418 switch (match) {
1419 case PAT_MATCH_STR: conv.in_type = SMP_T_STR; break;
1420 case PAT_MATCH_BEG: conv.in_type = SMP_T_STR; break;
1421 case PAT_MATCH_SUB: conv.in_type = SMP_T_STR; break;
1422 case PAT_MATCH_DIR: conv.in_type = SMP_T_STR; break;
1423 case PAT_MATCH_DOM: conv.in_type = SMP_T_STR; break;
1424 case PAT_MATCH_END: conv.in_type = SMP_T_STR; break;
1425 case PAT_MATCH_REG: conv.in_type = SMP_T_STR; break;
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02001426 case PAT_MATCH_INT: conv.in_type = SMP_T_SINT; break;
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001427 case PAT_MATCH_IP: conv.in_type = SMP_T_ADDR; break;
1428 default:
1429 WILL_LJMP(luaL_error(L, "'new' doesn't support this match mode."));
1430 }
1431
1432 /* fill fake args. */
1433 args[0].type = ARGT_STR;
1434 args[0].data.str.str = (char *)fn;
1435 args[1].type = ARGT_STOP;
1436
1437 /* load the map. */
1438 if (!sample_load_map(args, &conv, file, line, &err)) {
1439 /* error case: we cant use luaL_error because we must
1440 * free the err variable.
1441 */
1442 luaL_where(L, 1);
1443 lua_pushfstring(L, "'new': %s.", err);
1444 lua_concat(L, 2);
1445 free(err);
1446 WILL_LJMP(lua_error(L));
1447 }
1448
1449 /* create the lua object. */
1450 lua_newtable(L);
1451 lua_pushlightuserdata(L, args[0].data.map);
1452 lua_rawseti(L, -2, 0);
1453
1454 /* Pop a class Map metatable and affect it to the userdata. */
1455 lua_rawgeti(L, LUA_REGISTRYINDEX, class_map_ref);
1456 lua_setmetatable(L, -2);
1457
1458
1459 return 1;
1460}
1461
1462__LJMP static inline int _hlua_map_lookup(struct lua_State *L, int str)
1463{
1464 struct map_descriptor *desc;
1465 struct pattern *pat;
1466 struct sample smp;
1467
1468 MAY_LJMP(check_args(L, 2, "lookup"));
1469 desc = MAY_LJMP(hlua_checkmap(L, 1));
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02001470 if (desc->pat.expect_type == SMP_T_SINT) {
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02001471 smp.data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02001472 smp.data.u.sint = MAY_LJMP(luaL_checkinteger(L, 2));
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001473 }
1474 else {
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02001475 smp.data.type = SMP_T_STR;
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001476 smp.flags = SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02001477 smp.data.u.str.str = (char *)MAY_LJMP(luaL_checklstring(L, 2, (size_t *)&smp.data.u.str.len));
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001478 }
1479
1480 pat = pattern_exec_match(&desc->pat, &smp, 1);
Thierry FOURNIER503bb092015-08-19 08:35:43 +02001481 if (!pat || !pat->data) {
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001482 if (str)
1483 lua_pushstring(L, "");
1484 else
1485 lua_pushnil(L);
1486 return 1;
1487 }
1488
1489 /* The Lua pattern must return a string, so we can't check the returned type */
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02001490 lua_pushlstring(L, pat->data->u.str.str, pat->data->u.str.len);
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001491 return 1;
1492}
1493
1494__LJMP static int hlua_map_lookup(struct lua_State *L)
1495{
1496 return _hlua_map_lookup(L, 0);
1497}
1498
1499__LJMP static int hlua_map_slookup(struct lua_State *L)
1500{
1501 return _hlua_map_lookup(L, 1);
1502}
1503
1504/*
1505 *
1506 *
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001507 * Class Socket
1508 *
1509 *
1510 */
1511
1512__LJMP static struct hlua_socket *hlua_checksocket(lua_State *L, int ud)
1513{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001514 return MAY_LJMP(hlua_checkudata(L, ud, class_socket_ref));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001515}
1516
1517/* This function is the handler called for each I/O on the established
1518 * connection. It is used for notify space avalaible to send or data
1519 * received.
1520 */
Willy Tarreau00a37f02015-04-13 12:05:19 +02001521static void hlua_socket_handler(struct appctx *appctx)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001522{
Willy Tarreau00a37f02015-04-13 12:05:19 +02001523 struct stream_interface *si = appctx->owner;
Willy Tarreau50fe03b2014-11-28 13:59:31 +01001524 struct connection *c = objt_conn(si_opposite(si)->end);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001525
Thierry FOURNIERb13b20a2017-07-16 20:48:54 +02001526 if (appctx->ctx.hlua_cosocket.die) {
1527 si_shutw(si);
1528 si_shutr(si);
1529 si_ic(si)->flags |= CF_READ_NULL;
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001530 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_read);
1531 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_write);
Thierry FOURNIERb13b20a2017-07-16 20:48:54 +02001532 stream_shutdown(si_strm(si), SF_ERR_KILLED);
1533 }
1534
Thierry FOURNIER6d695e62015-09-27 19:29:38 +02001535 /* If the connection object is not avalaible, close all the
1536 * streams and wakeup everithing waiting for.
1537 */
1538 if (!c) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001539 si_shutw(si);
1540 si_shutr(si);
Willy Tarreau2bb4a962014-11-28 11:11:05 +01001541 si_ic(si)->flags |= CF_READ_NULL;
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001542 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_read);
1543 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_write);
Willy Tarreaud4da1962015-04-20 01:31:23 +02001544 return;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001545 }
1546
Thierry FOURNIER6d695e62015-09-27 19:29:38 +02001547 /* If we cant write, wakeup the pending write signals. */
1548 if (channel_output_closed(si_ic(si)))
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001549 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_write);
Thierry FOURNIER6d695e62015-09-27 19:29:38 +02001550
1551 /* If we cant read, wakeup the pending read signals. */
1552 if (channel_input_closed(si_oc(si)))
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001553 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_read);
Thierry FOURNIER6d695e62015-09-27 19:29:38 +02001554
Thierry FOURNIER316e3192015-09-04 18:25:53 +02001555 /* if the connection is not estabkished, inform the stream that we want
1556 * to be notified whenever the connection completes.
1557 */
1558 if (!(c->flags & CO_FL_CONNECTED)) {
1559 si_applet_cant_get(si);
1560 si_applet_cant_put(si);
Willy Tarreaud4da1962015-04-20 01:31:23 +02001561 return;
Thierry FOURNIER316e3192015-09-04 18:25:53 +02001562 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001563
1564 /* This function is called after the connect. */
Thierry FOURNIER18d09902016-12-16 09:25:38 +01001565 appctx->ctx.hlua_cosocket.connected = 1;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001566
1567 /* Wake the tasks which wants to write if the buffer have avalaible space. */
Thierry FOURNIEReba6f642015-09-26 22:01:07 +02001568 if (channel_may_recv(si_ic(si)))
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001569 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_write);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001570
1571 /* Wake the tasks which wants to read if the buffer contains data. */
Thierry FOURNIEReba6f642015-09-26 22:01:07 +02001572 if (!channel_is_empty(si_oc(si)))
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001573 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_read);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001574}
1575
Willy Tarreau87b09662015-04-03 00:22:06 +02001576/* This function is called when the "struct stream" is destroyed.
1577 * Remove the link from the object to this stream.
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001578 * Wake all the pending signals.
1579 */
Willy Tarreau00a37f02015-04-13 12:05:19 +02001580static void hlua_socket_release(struct appctx *appctx)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001581{
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001582 /* Remove my link in the original object. */
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001583 xref_disconnect(&appctx->ctx.hlua_cosocket.xref);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001584
1585 /* Wake all the task waiting for me. */
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001586 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_read);
1587 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_write);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001588}
1589
1590/* If the garbage collectio of the object is launch, nobody
Willy Tarreau87b09662015-04-03 00:22:06 +02001591 * uses this object. If the stream does not exists, just quit.
1592 * Send the shutdown signal to the stream. In some cases,
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001593 * pending signal can rest in the read and write lists. destroy
1594 * it.
1595 */
1596__LJMP static int hlua_socket_gc(lua_State *L)
1597{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001598 struct hlua_socket *socket;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001599 struct appctx *appctx;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001600 struct xref *peer;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001601
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001602 MAY_LJMP(check_args(L, 1, "__gc"));
1603
1604 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001605 peer = xref_get_peer(&socket->xref);
1606 if (!peer) {
1607 xref_disconnect(&socket->xref);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001608 return 0;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001609 }
1610 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001611
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001612 /* Set the flag which destroy the session. */
Thierry FOURNIERb13b20a2017-07-16 20:48:54 +02001613 appctx->ctx.hlua_cosocket.die = 1;
1614 appctx_wakeup(appctx);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001615
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001616 /* Remove all reference between the Lua stack and the coroutine stream. */
1617 xref_disconnect(&socket->xref);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001618 return 0;
1619}
1620
1621/* The close function send shutdown signal and break the
Willy Tarreau87b09662015-04-03 00:22:06 +02001622 * links between the stream and the object.
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001623 */
1624__LJMP static int hlua_socket_close(lua_State *L)
1625{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001626 struct hlua_socket *socket;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001627 struct appctx *appctx;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001628 struct xref *peer;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001629
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001630 MAY_LJMP(check_args(L, 1, "close"));
1631
1632 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001633 peer = xref_get_peer(&socket->xref);
1634 if (!peer) {
1635 xref_disconnect(&socket->xref);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001636 return 0;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001637 }
1638 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001639
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001640 /* Set the flag which destroy the session. */
Thierry FOURNIERb13b20a2017-07-16 20:48:54 +02001641 appctx->ctx.hlua_cosocket.die = 1;
1642 appctx_wakeup(appctx);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001643
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001644 /* Remove all reference between the Lua stack and the coroutine stream. */
1645 xref_disconnect(&socket->xref);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001646 return 0;
1647}
1648
1649/* This Lua function assumes that the stack contain three parameters.
1650 * 1 - USERDATA containing a struct socket
1651 * 2 - INTEGER with values of the macro defined below
1652 * If the integer is -1, we must read at most one line.
1653 * If the integer is -2, we ust read all the data until the
1654 * end of the stream.
1655 * If the integer is positive value, we must read a number of
1656 * bytes corresponding to this value.
1657 */
1658#define HLSR_READ_LINE (-1)
1659#define HLSR_READ_ALL (-2)
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01001660__LJMP static int hlua_socket_receive_yield(struct lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001661{
1662 struct hlua_socket *socket = MAY_LJMP(hlua_checksocket(L, 1));
1663 int wanted = lua_tointeger(L, 2);
1664 struct hlua *hlua = hlua_gethlua(L);
1665 struct appctx *appctx;
1666 int len;
1667 int nblk;
1668 char *blk1;
1669 int len1;
1670 char *blk2;
1671 int len2;
Thierry FOURNIER00543922015-03-09 18:35:06 +01001672 int skip_at_end = 0;
Willy Tarreau81389672015-03-10 12:03:52 +01001673 struct channel *oc;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001674 struct stream_interface *si;
1675 struct stream *s;
1676 struct xref *peer;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001677
1678 /* Check if this lua stack is schedulable. */
1679 if (!hlua || !hlua->task)
1680 WILL_LJMP(luaL_error(L, "The 'receive' function is only allowed in "
1681 "'frontend', 'backend' or 'task'"));
1682
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001683 /* check for connection break. If some data where read, return it. */
1684 peer = xref_get_peer(&socket->xref);
1685 if (!peer) {
1686 xref_disconnect(&socket->xref);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001687 goto connection_closed;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001688 }
1689 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
1690 si = appctx->owner;
1691 s = si_strm(si);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001692
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001693 oc = &s->res;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001694 if (wanted == HLSR_READ_LINE) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001695 /* Read line. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02001696 nblk = co_getline_nc(oc, &blk1, &len1, &blk2, &len2);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001697 if (nblk < 0) /* Connection close. */
1698 goto connection_closed;
1699 if (nblk == 0) /* No data avalaible. */
1700 goto connection_empty;
Thierry FOURNIER00543922015-03-09 18:35:06 +01001701
1702 /* remove final \r\n. */
1703 if (nblk == 1) {
1704 if (blk1[len1-1] == '\n') {
1705 len1--;
1706 skip_at_end++;
1707 if (blk1[len1-1] == '\r') {
1708 len1--;
1709 skip_at_end++;
1710 }
1711 }
1712 }
1713 else {
1714 if (blk2[len2-1] == '\n') {
1715 len2--;
1716 skip_at_end++;
1717 if (blk2[len2-1] == '\r') {
1718 len2--;
1719 skip_at_end++;
1720 }
1721 }
1722 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001723 }
1724
1725 else if (wanted == HLSR_READ_ALL) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001726 /* Read all the available data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02001727 nblk = co_getblk_nc(oc, &blk1, &len1, &blk2, &len2);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001728 if (nblk < 0) /* Connection close. */
1729 goto connection_closed;
1730 if (nblk == 0) /* No data avalaible. */
1731 goto connection_empty;
1732 }
1733
1734 else {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001735 /* Read a block of data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02001736 nblk = co_getblk_nc(oc, &blk1, &len1, &blk2, &len2);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001737 if (nblk < 0) /* Connection close. */
1738 goto connection_closed;
1739 if (nblk == 0) /* No data avalaible. */
1740 goto connection_empty;
1741
1742 if (len1 > wanted) {
1743 nblk = 1;
1744 len1 = wanted;
1745 } if (nblk == 2 && len1 + len2 > wanted)
1746 len2 = wanted - len1;
1747 }
1748
1749 len = len1;
1750
1751 luaL_addlstring(&socket->b, blk1, len1);
1752 if (nblk == 2) {
1753 len += len2;
1754 luaL_addlstring(&socket->b, blk2, len2);
1755 }
1756
1757 /* Consume data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02001758 co_skip(oc, len + skip_at_end);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001759
1760 /* Don't wait anything. */
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001761 stream_int_notify(&s->si[0]);
1762 stream_int_update_applet(&s->si[0]);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001763
1764 /* If the pattern reclaim to read all the data
1765 * in the connection, got out.
1766 */
1767 if (wanted == HLSR_READ_ALL)
1768 goto connection_empty;
1769 else if (wanted >= 0 && len < wanted)
1770 goto connection_empty;
1771
1772 /* Return result. */
1773 luaL_pushresult(&socket->b);
1774 return 1;
1775
1776connection_closed:
1777
1778 /* If the buffer containds data. */
1779 if (socket->b.n > 0) {
1780 luaL_pushresult(&socket->b);
1781 return 1;
1782 }
1783 lua_pushnil(L);
1784 lua_pushstring(L, "connection closed.");
1785 return 2;
1786
1787connection_empty:
1788
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001789 appctx = objt_appctx(s->si[0].end);
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001790 if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_read, hlua->task))
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001791 WILL_LJMP(luaL_error(L, "out of memory"));
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +01001792 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_receive_yield, TICK_ETERNITY, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001793 return 0;
1794}
1795
1796/* This Lus function gets two parameters. The first one can be string
1797 * or a number. If the string is "*l", the user require one line. If
1798 * the string is "*a", the user require all the content of the stream.
1799 * If the value is a number, the user require a number of bytes equal
1800 * to the value. The default value is "*l" (a line).
1801 *
1802 * This paraeter with a variable type is converted in integer. This
1803 * integer takes this values:
1804 * -1 : read a line
1805 * -2 : read all the stream
1806 * >0 : amount if bytes.
1807 *
1808 * The second parameter is optinal. It contains a string that must be
1809 * concatenated with the read data.
1810 */
1811__LJMP static int hlua_socket_receive(struct lua_State *L)
1812{
1813 int wanted = HLSR_READ_LINE;
1814 const char *pattern;
1815 int type;
1816 char *error;
1817 size_t len;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001818 struct hlua_socket *socket;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001819
1820 if (lua_gettop(L) < 1 || lua_gettop(L) > 3)
1821 WILL_LJMP(luaL_error(L, "The 'receive' function requires between 1 and 3 arguments."));
1822
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001823 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001824
1825 /* check for pattern. */
1826 if (lua_gettop(L) >= 2) {
1827 type = lua_type(L, 2);
1828 if (type == LUA_TSTRING) {
1829 pattern = lua_tostring(L, 2);
1830 if (strcmp(pattern, "*a") == 0)
1831 wanted = HLSR_READ_ALL;
1832 else if (strcmp(pattern, "*l") == 0)
1833 wanted = HLSR_READ_LINE;
1834 else {
1835 wanted = strtoll(pattern, &error, 10);
1836 if (*error != '\0')
1837 WILL_LJMP(luaL_error(L, "Unsupported pattern."));
1838 }
1839 }
1840 else if (type == LUA_TNUMBER) {
1841 wanted = lua_tointeger(L, 2);
1842 if (wanted < 0)
1843 WILL_LJMP(luaL_error(L, "Unsupported size."));
1844 }
1845 }
1846
1847 /* Set pattern. */
1848 lua_pushinteger(L, wanted);
1849 lua_replace(L, 2);
1850
1851 /* init bufffer, and fiil it wih prefix. */
1852 luaL_buffinit(L, &socket->b);
1853
1854 /* Check prefix. */
1855 if (lua_gettop(L) >= 3) {
1856 if (lua_type(L, 3) != LUA_TSTRING)
1857 WILL_LJMP(luaL_error(L, "Expect a 'string' for the prefix"));
1858 pattern = lua_tolstring(L, 3, &len);
1859 luaL_addlstring(&socket->b, pattern, len);
1860 }
1861
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01001862 return __LJMP(hlua_socket_receive_yield(L, 0, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001863}
1864
1865/* Write the Lua input string in the output buffer.
1866 * This fucntion returns a yield if no space are available.
1867 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01001868static int hlua_socket_write_yield(struct lua_State *L,int status, lua_KContext ctx)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001869{
1870 struct hlua_socket *socket;
1871 struct hlua *hlua = hlua_gethlua(L);
1872 struct appctx *appctx;
1873 size_t buf_len;
1874 const char *buf;
1875 int len;
1876 int send_len;
1877 int sent;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001878 struct xref *peer;
1879 struct stream_interface *si;
1880 struct stream *s;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001881
1882 /* Check if this lua stack is schedulable. */
1883 if (!hlua || !hlua->task)
1884 WILL_LJMP(luaL_error(L, "The 'write' function is only allowed in "
1885 "'frontend', 'backend' or 'task'"));
1886
1887 /* Get object */
1888 socket = MAY_LJMP(hlua_checksocket(L, 1));
1889 buf = MAY_LJMP(luaL_checklstring(L, 2, &buf_len));
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01001890 sent = MAY_LJMP(luaL_checkinteger(L, 3));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001891
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001892 /* check for connection break. If some data where read, return it. */
1893 peer = xref_get_peer(&socket->xref);
1894 if (!peer) {
1895 xref_disconnect(&socket->xref);
1896 lua_pushinteger(L, -1);
1897 return 1;
1898 }
1899 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
1900 si = appctx->owner;
1901 s = si_strm(si);
1902
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001903 /* Check for connection close. */
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001904 if (channel_output_closed(&s->req)) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001905 lua_pushinteger(L, -1);
1906 return 1;
1907 }
1908
1909 /* Update the input buffer data. */
1910 buf += sent;
1911 send_len = buf_len - sent;
1912
1913 /* All the data are sent. */
1914 if (sent >= buf_len)
1915 return 1; /* Implicitly return the length sent. */
1916
Thierry FOURNIER486d52a2015-03-09 17:51:43 +01001917 /* Check if the buffer is avalaible because HAProxy doesn't allocate
1918 * the request buffer if its not required.
1919 */
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001920 if (s->req.buf->size == 0) {
Christopher Faulet33834b12016-12-19 09:29:06 +01001921 appctx = hlua->task->context;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001922 if (!channel_alloc_buffer(&s->req, &appctx->buffer_wait))
Christopher Faulet33834b12016-12-19 09:29:06 +01001923 goto hlua_socket_write_yield_return;
Thierry FOURNIER486d52a2015-03-09 17:51:43 +01001924 }
1925
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001926 /* Check for avalaible space. */
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001927 len = buffer_total_space(s->req.buf);
Christopher Faulet33834b12016-12-19 09:29:06 +01001928 if (len <= 0) {
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001929 appctx = objt_appctx(s->si[0].end);
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001930 if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task))
Christopher Faulet33834b12016-12-19 09:29:06 +01001931 WILL_LJMP(luaL_error(L, "out of memory"));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001932 goto hlua_socket_write_yield_return;
Christopher Faulet33834b12016-12-19 09:29:06 +01001933 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001934
1935 /* send data */
1936 if (len < send_len)
1937 send_len = len;
Willy Tarreau06d80a92017-10-19 14:32:15 +02001938 len = ci_putblk(&s->req, buf+sent, send_len);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001939
1940 /* "Not enough space" (-1), "Buffer too little to contain
1941 * the data" (-2) are not expected because the available length
1942 * is tested.
1943 * Other unknown error are also not expected.
1944 */
1945 if (len <= 0) {
Willy Tarreaubc18da12015-03-13 14:00:47 +01001946 if (len == -1)
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001947 s->req.flags |= CF_WAKE_WRITE;
Willy Tarreaubc18da12015-03-13 14:00:47 +01001948
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001949 MAY_LJMP(hlua_socket_close(L));
1950 lua_pop(L, 1);
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01001951 lua_pushinteger(L, -1);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001952 return 1;
1953 }
1954
1955 /* update buffers. */
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001956 stream_int_notify(&s->si[0]);
1957 stream_int_update_applet(&s->si[0]);
Willy Tarreaude70fa12015-09-26 11:25:05 +02001958
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001959 s->req.rex = TICK_ETERNITY;
1960 s->res.wex = TICK_ETERNITY;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001961
1962 /* Update length sent. */
1963 lua_pop(L, 1);
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01001964 lua_pushinteger(L, sent + len);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001965
1966 /* All the data buffer is sent ? */
1967 if (sent + len >= buf_len)
1968 return 1;
1969
1970hlua_socket_write_yield_return:
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +01001971 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_write_yield, TICK_ETERNITY, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001972 return 0;
1973}
1974
1975/* This function initiate the send of data. It just check the input
1976 * parameters and push an integer in the Lua stack that contain the
1977 * amount of data writed in the buffer. This is used by the function
1978 * "hlua_socket_write_yield" that can yield.
1979 *
1980 * The Lua function gets between 3 and 4 parameters. The first one is
1981 * the associated object. The second is a string buffer. The third is
1982 * a facultative integer that represents where is the buffer position
1983 * of the start of the data that can send. The first byte is the
1984 * position "1". The default value is "1". The fourth argument is a
1985 * facultative integer that represents where is the buffer position
1986 * of the end of the data that can send. The default is the last byte.
1987 */
1988static int hlua_socket_send(struct lua_State *L)
1989{
1990 int i;
1991 int j;
1992 const char *buf;
1993 size_t buf_len;
1994
1995 /* Check number of arguments. */
1996 if (lua_gettop(L) < 2 || lua_gettop(L) > 4)
1997 WILL_LJMP(luaL_error(L, "'send' needs between 2 and 4 arguments"));
1998
1999 /* Get the string. */
2000 buf = MAY_LJMP(luaL_checklstring(L, 2, &buf_len));
2001
2002 /* Get and check j. */
2003 if (lua_gettop(L) == 4) {
2004 j = MAY_LJMP(luaL_checkinteger(L, 4));
2005 if (j < 0)
2006 j = buf_len + j + 1;
2007 if (j > buf_len)
2008 j = buf_len + 1;
2009 lua_pop(L, 1);
2010 }
2011 else
2012 j = buf_len;
2013
2014 /* Get and check i. */
2015 if (lua_gettop(L) == 3) {
2016 i = MAY_LJMP(luaL_checkinteger(L, 3));
2017 if (i < 0)
2018 i = buf_len + i + 1;
2019 if (i > buf_len)
2020 i = buf_len + 1;
2021 lua_pop(L, 1);
2022 } else
2023 i = 1;
2024
2025 /* Check bth i and j. */
2026 if (i > j) {
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002027 lua_pushinteger(L, 0);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002028 return 1;
2029 }
2030 if (i == 0 && j == 0) {
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002031 lua_pushinteger(L, 0);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002032 return 1;
2033 }
2034 if (i == 0)
2035 i = 1;
2036 if (j == 0)
2037 j = 1;
2038
2039 /* Pop the string. */
2040 lua_pop(L, 1);
2041
2042 /* Update the buffer length. */
2043 buf += i - 1;
2044 buf_len = j - i + 1;
2045 lua_pushlstring(L, buf, buf_len);
2046
2047 /* This unsigned is used to remember the amount of sent data. */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002048 lua_pushinteger(L, 0);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002049
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002050 return MAY_LJMP(hlua_socket_write_yield(L, 0, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002051}
2052
Willy Tarreau22b0a682015-06-17 19:43:49 +02002053#define SOCKET_INFO_MAX_LEN sizeof("[0000:0000:0000:0000:0000:0000:0000:0000]:12345")
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002054__LJMP static inline int hlua_socket_info(struct lua_State *L, struct sockaddr_storage *addr)
2055{
2056 static char buffer[SOCKET_INFO_MAX_LEN];
2057 int ret;
2058 int len;
2059 char *p;
2060
2061 ret = addr_to_str(addr, buffer+1, SOCKET_INFO_MAX_LEN-1);
2062 if (ret <= 0) {
2063 lua_pushnil(L);
2064 return 1;
2065 }
2066
2067 if (ret == AF_UNIX) {
2068 lua_pushstring(L, buffer+1);
2069 return 1;
2070 }
2071 else if (ret == AF_INET6) {
2072 buffer[0] = '[';
2073 len = strlen(buffer);
2074 buffer[len] = ']';
2075 len++;
2076 buffer[len] = ':';
2077 len++;
2078 p = buffer;
2079 }
2080 else if (ret == AF_INET) {
2081 p = buffer + 1;
2082 len = strlen(p);
2083 p[len] = ':';
2084 len++;
2085 }
2086 else {
2087 lua_pushnil(L);
2088 return 1;
2089 }
2090
2091 if (port_to_str(addr, p + len, SOCKET_INFO_MAX_LEN-1 - len) <= 0) {
2092 lua_pushnil(L);
2093 return 1;
2094 }
2095
2096 lua_pushstring(L, p);
2097 return 1;
2098}
2099
2100/* Returns information about the peer of the connection. */
2101__LJMP static int hlua_socket_getpeername(struct lua_State *L)
2102{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002103 struct hlua_socket *socket;
2104 struct connection *conn;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002105 struct xref *peer;
2106 struct appctx *appctx;
2107 struct stream_interface *si;
2108 struct stream *s;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002109
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002110 MAY_LJMP(check_args(L, 1, "getpeername"));
2111
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002112 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002113
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002114 /* check for connection break. If some data where read, return it. */
2115 peer = xref_get_peer(&socket->xref);
2116 if (!peer) {
2117 xref_disconnect(&socket->xref);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002118 lua_pushnil(L);
2119 return 1;
2120 }
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002121 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2122 si = appctx->owner;
2123 s = si_strm(si);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002124
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002125 conn = objt_conn(s->si[1].end);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002126 if (!conn) {
2127 lua_pushnil(L);
2128 return 1;
2129 }
2130
Willy Tarreaua71f6422016-11-16 17:00:14 +01002131 conn_get_to_addr(conn);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002132 if (!(conn->flags & CO_FL_ADDR_TO_SET)) {
Willy Tarreaua71f6422016-11-16 17:00:14 +01002133 lua_pushnil(L);
2134 return 1;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002135 }
2136
2137 return MAY_LJMP(hlua_socket_info(L, &conn->addr.to));
2138}
2139
2140/* Returns information about my connection side. */
2141static int hlua_socket_getsockname(struct lua_State *L)
2142{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002143 struct hlua_socket *socket;
2144 struct connection *conn;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002145 struct appctx *appctx;
2146 struct xref *peer;
2147 struct stream_interface *si;
2148 struct stream *s;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002149
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002150 MAY_LJMP(check_args(L, 1, "getsockname"));
2151
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002152 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002153
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002154 /* check for connection break. If some data where read, return it. */
2155 peer = xref_get_peer(&socket->xref);
2156 if (!peer) {
2157 xref_disconnect(&socket->xref);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002158 lua_pushnil(L);
2159 return 1;
2160 }
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002161 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2162 si = appctx->owner;
2163 s = si_strm(si);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002164
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002165 conn = objt_conn(s->si[1].end);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002166 if (!conn) {
2167 lua_pushnil(L);
2168 return 1;
2169 }
2170
Willy Tarreaua71f6422016-11-16 17:00:14 +01002171 conn_get_from_addr(conn);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002172 if (!(conn->flags & CO_FL_ADDR_FROM_SET)) {
Willy Tarreaua71f6422016-11-16 17:00:14 +01002173 lua_pushnil(L);
2174 return 1;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002175 }
2176
2177 return hlua_socket_info(L, &conn->addr.from);
2178}
2179
2180/* This struct define the applet. */
Willy Tarreau30576452015-04-13 13:50:30 +02002181static struct applet update_applet = {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002182 .obj_type = OBJ_TYPE_APPLET,
2183 .name = "<LUA_TCP>",
2184 .fct = hlua_socket_handler,
2185 .release = hlua_socket_release,
2186};
2187
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002188__LJMP static int hlua_socket_connect_yield(struct lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002189{
2190 struct hlua_socket *socket = MAY_LJMP(hlua_checksocket(L, 1));
2191 struct hlua *hlua = hlua_gethlua(L);
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002192 struct xref *peer;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002193 struct appctx *appctx;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002194 struct stream_interface *si;
2195 struct stream *s;
2196
2197 /* check for connection break. If some data where read, return it. */
2198 peer = xref_get_peer(&socket->xref);
2199 if (!peer) {
2200 xref_disconnect(&socket->xref);
2201 lua_pushnil(L);
2202 lua_pushstring(L, "Can't connect");
2203 return 2;
2204 }
2205 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2206 si = appctx->owner;
2207 s = si_strm(si);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002208
2209 /* Check for connection close. */
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002210 if (!hlua || channel_output_closed(&s->req)) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002211 lua_pushnil(L);
2212 lua_pushstring(L, "Can't connect");
2213 return 2;
2214 }
2215
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002216 appctx = objt_appctx(s->si[0].end);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002217
2218 /* Check for connection established. */
Thierry FOURNIER18d09902016-12-16 09:25:38 +01002219 if (appctx->ctx.hlua_cosocket.connected) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002220 lua_pushinteger(L, 1);
2221 return 1;
2222 }
2223
Thierry FOURNIERd6975962017-07-12 14:31:10 +02002224 if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task))
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002225 WILL_LJMP(luaL_error(L, "out of memory error"));
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +01002226 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_connect_yield, TICK_ETERNITY, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002227 return 0;
2228}
2229
2230/* This function fail or initite the connection. */
2231__LJMP static int hlua_socket_connect(struct lua_State *L)
2232{
2233 struct hlua_socket *socket;
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002234 int port = -1;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002235 const char *ip;
2236 struct connection *conn;
Thierry FOURNIER95ad96a2015-03-09 18:12:40 +01002237 struct hlua *hlua;
2238 struct appctx *appctx;
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002239 int low, high;
2240 struct sockaddr_storage *addr;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002241 struct xref *peer;
2242 struct stream_interface *si;
2243 struct stream *s;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002244
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002245 if (lua_gettop(L) < 2)
2246 WILL_LJMP(luaL_error(L, "connect: need at least 2 arguments"));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002247
2248 /* Get args. */
2249 socket = MAY_LJMP(hlua_checksocket(L, 1));
2250 ip = MAY_LJMP(luaL_checkstring(L, 2));
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002251 if (lua_gettop(L) >= 3)
2252 port = MAY_LJMP(luaL_checkinteger(L, 3));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002253
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002254 /* check for connection break. If some data where read, return it. */
2255 peer = xref_get_peer(&socket->xref);
2256 if (!peer) {
2257 xref_disconnect(&socket->xref);
2258 lua_pushnil(L);
2259 return 1;
2260 }
2261 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2262 si = appctx->owner;
2263 s = si_strm(si);
2264
2265 /* Initialise connection. */
2266 conn = si_alloc_conn(&s->si[1]);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002267 if (!conn)
2268 WILL_LJMP(luaL_error(L, "connect: internal error"));
2269
Willy Tarreau3adac082015-09-26 17:51:09 +02002270 /* needed for the connection not to be closed */
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002271 conn->target = s->target;
Willy Tarreau3adac082015-09-26 17:51:09 +02002272
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002273 /* Parse ip address. */
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002274 addr = str2sa_range(ip, NULL, &low, &high, NULL, NULL, NULL, 0);
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002275 if (!addr)
2276 WILL_LJMP(luaL_error(L, "connect: cannot parse destination address '%s'", ip));
2277 if (low != high)
2278 WILL_LJMP(luaL_error(L, "connect: port ranges not supported : address '%s'", ip));
2279 memcpy(&conn->addr.to, addr, sizeof(struct sockaddr_storage));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002280
2281 /* Set port. */
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002282 if (low == 0) {
2283 if (conn->addr.to.ss_family == AF_INET) {
2284 if (port == -1)
2285 WILL_LJMP(luaL_error(L, "connect: port missing"));
2286 ((struct sockaddr_in *)&conn->addr.to)->sin_port = htons(port);
2287 } else if (conn->addr.to.ss_family == AF_INET6) {
2288 if (port == -1)
2289 WILL_LJMP(luaL_error(L, "connect: port missing"));
2290 ((struct sockaddr_in6 *)&conn->addr.to)->sin6_port = htons(port);
2291 }
2292 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002293
Thierry FOURNIER95ad96a2015-03-09 18:12:40 +01002294 hlua = hlua_gethlua(L);
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002295 appctx = objt_appctx(s->si[0].end);
Willy Tarreaubdc97a82015-08-24 15:42:28 +02002296
2297 /* inform the stream that we want to be notified whenever the
2298 * connection completes.
2299 */
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002300 si_applet_cant_get(&s->si[0]);
2301 si_applet_cant_put(&s->si[0]);
Thierry FOURNIER8c8fbbe2015-09-26 17:02:35 +02002302 appctx_wakeup(appctx);
Willy Tarreaubdc97a82015-08-24 15:42:28 +02002303
Thierry FOURNIER7c39ab42015-09-27 22:53:33 +02002304 hlua->flags |= HLUA_MUST_GC;
2305
Thierry FOURNIERd6975962017-07-12 14:31:10 +02002306 if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task))
Thierry FOURNIER95ad96a2015-03-09 18:12:40 +01002307 WILL_LJMP(luaL_error(L, "out of memory"));
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +01002308 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_connect_yield, TICK_ETERNITY, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002309
2310 return 0;
2311}
2312
Baptiste Assmann84bb4932015-03-02 21:40:06 +01002313#ifdef USE_OPENSSL
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002314__LJMP static int hlua_socket_connect_ssl(struct lua_State *L)
2315{
2316 struct hlua_socket *socket;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002317 struct xref *peer;
2318 struct appctx *appctx;
2319 struct stream_interface *si;
2320 struct stream *s;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002321
2322 MAY_LJMP(check_args(L, 3, "connect_ssl"));
2323 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002324
2325 /* check for connection break. If some data where read, return it. */
2326 peer = xref_get_peer(&socket->xref);
2327 if (!peer) {
2328 xref_disconnect(&socket->xref);
2329 lua_pushnil(L);
2330 return 1;
2331 }
2332 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2333 si = appctx->owner;
2334 s = si_strm(si);
2335
2336 s->target = &socket_ssl.obj_type;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002337 return MAY_LJMP(hlua_socket_connect(L));
2338}
Baptiste Assmann84bb4932015-03-02 21:40:06 +01002339#endif
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002340
2341__LJMP static int hlua_socket_setoption(struct lua_State *L)
2342{
2343 return 0;
2344}
2345
2346__LJMP static int hlua_socket_settimeout(struct lua_State *L)
2347{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002348 struct hlua_socket *socket;
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002349 int tmout;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002350 struct xref *peer;
2351 struct appctx *appctx;
2352 struct stream_interface *si;
2353 struct stream *s;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002354
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002355 MAY_LJMP(check_args(L, 2, "settimeout"));
2356
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002357 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002358 tmout = MAY_LJMP(luaL_checkinteger(L, 2)) * 1000;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002359
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002360 /* check for connection break. If some data where read, return it. */
2361 peer = xref_get_peer(&socket->xref);
2362 if (!peer) {
2363 xref_disconnect(&socket->xref);
2364 hlua_pusherror(L, "socket: not yet initialised, you can't set timeouts.");
2365 WILL_LJMP(lua_error(L));
2366 return 0;
2367 }
2368 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2369 si = appctx->owner;
2370 s = si_strm(si);
2371
2372 s->req.rto = tmout;
2373 s->req.wto = tmout;
2374 s->res.rto = tmout;
2375 s->res.wto = tmout;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002376
2377 return 0;
2378}
2379
2380__LJMP static int hlua_socket_new(lua_State *L)
2381{
2382 struct hlua_socket *socket;
2383 struct appctx *appctx;
Willy Tarreau15b5e142015-04-04 14:38:25 +02002384 struct session *sess;
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002385 struct stream *strm;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002386
2387 /* Check stack size. */
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002388 if (!lua_checkstack(L, 3)) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002389 hlua_pusherror(L, "socket: full stack");
2390 goto out_fail_conf;
2391 }
2392
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002393 /* Create the object: obj[0] = userdata. */
2394 lua_newtable(L);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002395 socket = MAY_LJMP(lua_newuserdata(L, sizeof(*socket)));
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002396 lua_rawseti(L, -2, 0);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002397 memset(socket, 0, sizeof(*socket));
2398
Thierry FOURNIER4a6170c2015-03-09 17:07:10 +01002399 /* Check if the various memory pools are intialized. */
Willy Tarreau87b09662015-04-03 00:22:06 +02002400 if (!pool2_stream || !pool2_buffer) {
Thierry FOURNIER4a6170c2015-03-09 17:07:10 +01002401 hlua_pusherror(L, "socket: uninitialized pools.");
2402 goto out_fail_conf;
2403 }
2404
Willy Tarreau87b09662015-04-03 00:22:06 +02002405 /* Pop a class stream metatable and affect it to the userdata. */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002406 lua_rawgeti(L, LUA_REGISTRYINDEX, class_socket_ref);
2407 lua_setmetatable(L, -2);
2408
Willy Tarreaud420a972015-04-06 00:39:18 +02002409 /* Create the applet context */
Thierry FOURNIER4325ab72017-07-12 11:53:38 +02002410 appctx = appctx_new(&update_applet, 1UL << tid);
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002411 if (!appctx) {
2412 hlua_pusherror(L, "socket: out of memory");
Willy Tarreaufeb76402015-04-03 14:10:06 +02002413 goto out_fail_conf;
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002414 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002415
Thierry FOURNIER18d09902016-12-16 09:25:38 +01002416 appctx->ctx.hlua_cosocket.connected = 0;
Thierry FOURNIERb13b20a2017-07-16 20:48:54 +02002417 appctx->ctx.hlua_cosocket.die = 0;
Thierry FOURNIER18d09902016-12-16 09:25:38 +01002418 LIST_INIT(&appctx->ctx.hlua_cosocket.wake_on_write);
2419 LIST_INIT(&appctx->ctx.hlua_cosocket.wake_on_read);
Willy Tarreaub2bf8332015-04-04 15:58:58 +02002420
Willy Tarreaud420a972015-04-06 00:39:18 +02002421 /* Now create a session, task and stream for this applet */
2422 sess = session_new(&socket_proxy, NULL, &appctx->obj_type);
2423 if (!sess) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002424 hlua_pusherror(L, "socket: out of memory");
Willy Tarreaud420a972015-04-06 00:39:18 +02002425 goto out_fail_sess;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002426 }
2427
Willy Tarreau87787ac2017-08-28 16:22:54 +02002428 strm = stream_new(sess, &appctx->obj_type);
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002429 if (!strm) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002430 hlua_pusherror(L, "socket: out of memory");
Willy Tarreaud420a972015-04-06 00:39:18 +02002431 goto out_fail_stream;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002432 }
2433
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002434 /* Initialise cross reference between stream and Lua socket object. */
2435 xref_create(&socket->xref, &appctx->ctx.hlua_cosocket.xref);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002436
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002437 /* Configure "right" stream interface. this "si" is used to connect
2438 * and retrieve data from the server. The connection is initialized
2439 * with the "struct server".
2440 */
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002441 si_set_state(&strm->si[1], SI_ST_ASS);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002442
2443 /* Force destination server. */
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002444 strm->flags |= SF_DIRECT | SF_ASSIGNED | SF_ADDR_SET | SF_BE_ASSIGNED;
2445 strm->target = &socket_tcp.obj_type;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002446
Willy Tarreau87787ac2017-08-28 16:22:54 +02002447 task_wakeup(strm->task, TASK_WOKEN_INIT);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002448 /* Return yield waiting for connection. */
2449 return 1;
2450
Willy Tarreaud420a972015-04-06 00:39:18 +02002451 out_fail_stream:
Willy Tarreau11c36242015-04-04 15:54:03 +02002452 session_free(sess);
Willy Tarreaud420a972015-04-06 00:39:18 +02002453 out_fail_sess:
2454 appctx_free(appctx);
2455 out_fail_conf:
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002456 WILL_LJMP(lua_error(L));
2457 return 0;
2458}
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01002459
2460/*
2461 *
2462 *
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002463 * Class Channel
2464 *
2465 *
2466 */
2467
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002468/* The state between the channel data and the HTTP parser state can be
2469 * unconsistent, so reset the parser and call it again. Warning, this
2470 * action not revalidate the request and not send a 400 if the modified
2471 * resuest is not valid.
2472 *
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01002473 * This function never fails. The direction is set using dir, which equals
2474 * either SMP_OPT_DIR_REQ or SMP_OPT_DIR_RES.
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002475 */
2476static void hlua_resynchonize_proto(struct stream *stream, int dir)
2477{
2478 /* Protocol HTTP. */
2479 if (stream->be->mode == PR_MODE_HTTP) {
2480
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01002481 if (dir == SMP_OPT_DIR_REQ)
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002482 http_txn_reset_req(stream->txn);
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01002483 else if (dir == SMP_OPT_DIR_RES)
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002484 http_txn_reset_res(stream->txn);
2485
2486 if (stream->txn->hdr_idx.v)
2487 hdr_idx_init(&stream->txn->hdr_idx);
2488
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01002489 if (dir == SMP_OPT_DIR_REQ)
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002490 http_msg_analyzer(&stream->txn->req, &stream->txn->hdr_idx);
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01002491 else if (dir == SMP_OPT_DIR_RES)
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002492 http_msg_analyzer(&stream->txn->rsp, &stream->txn->hdr_idx);
2493 }
2494}
2495
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01002496/* This function is called before the Lua execution. It stores
2497 * the differents parsers state before executing some Lua code.
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002498 */
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01002499static inline void consistency_set(struct stream *stream, int opt, struct hlua_consistency *c)
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002500{
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01002501 c->mode = stream->be->mode;
2502 switch (c->mode) {
2503 case PR_MODE_HTTP:
2504 c->data.http.dir = opt & SMP_OPT_DIR;
2505 if (c->data.http.dir == SMP_OPT_DIR_REQ)
2506 c->data.http.state = stream->txn->req.msg_state;
2507 else
2508 c->data.http.state = stream->txn->rsp.msg_state;
2509 break;
2510 default:
2511 break;
2512 }
2513}
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002514
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01002515/* This function is called after the Lua execution. it
2516 * returns true if the parser state is consistent, otherwise,
2517 * it return false.
2518 *
2519 * In HTTP mode, the parser state must be in the same state
2520 * or greater when we exit the function. Even if we do a
2521 * control yield. This prevent to break the HTTP message
2522 * from the Lua code.
2523 */
2524static inline int consistency_check(struct stream *stream, int opt, struct hlua_consistency *c)
2525{
2526 if (c->mode != stream->be->mode)
2527 return 0;
2528
2529 switch (c->mode) {
2530 case PR_MODE_HTTP:
2531 if (c->data.http.dir != (opt & SMP_OPT_DIR))
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002532 return 0;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01002533 if (c->data.http.dir == SMP_OPT_DIR_REQ)
2534 return stream->txn->req.msg_state >= c->data.http.state;
2535 else
2536 return stream->txn->rsp.msg_state >= c->data.http.state;
2537 default:
2538 return 1;
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002539 }
2540 return 1;
2541}
2542
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002543/* Returns the struct hlua_channel join to the class channel in the
2544 * stack entry "ud" or throws an argument error.
2545 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002546__LJMP static struct channel *hlua_checkchannel(lua_State *L, int ud)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002547{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002548 return MAY_LJMP(hlua_checkudata(L, ud, class_channel_ref));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002549}
2550
Willy Tarreau47860ed2015-03-10 14:07:50 +01002551/* Pushes the channel onto the top of the stack. If the stask does not have a
2552 * free slots, the function fails and returns 0;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002553 */
Willy Tarreau2a71af42015-03-10 13:51:50 +01002554static int hlua_channel_new(lua_State *L, struct channel *channel)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002555{
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002556 /* Check stack size. */
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002557 if (!lua_checkstack(L, 3))
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002558 return 0;
2559
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002560 lua_newtable(L);
Willy Tarreau47860ed2015-03-10 14:07:50 +01002561 lua_pushlightuserdata(L, channel);
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002562 lua_rawseti(L, -2, 0);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002563
2564 /* Pop a class sesison metatable and affect it to the userdata. */
2565 lua_rawgeti(L, LUA_REGISTRYINDEX, class_channel_ref);
2566 lua_setmetatable(L, -2);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002567 return 1;
2568}
2569
2570/* Duplicate all the data present in the input channel and put it
2571 * in a string LUA variables. Returns -1 and push a nil value in
2572 * the stack if the channel is closed and all the data are consumed,
2573 * returns 0 if no data are available, otherwise it returns the length
2574 * of the builded string.
2575 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002576static inline int _hlua_channel_dup(struct channel *chn, lua_State *L)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002577{
2578 char *blk1;
2579 char *blk2;
2580 int len1;
2581 int len2;
2582 int ret;
2583 luaL_Buffer b;
2584
Willy Tarreau06d80a92017-10-19 14:32:15 +02002585 ret = ci_getblk_nc(chn, &blk1, &len1, &blk2, &len2);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002586 if (unlikely(ret == 0))
2587 return 0;
2588
2589 if (unlikely(ret < 0)) {
2590 lua_pushnil(L);
2591 return -1;
2592 }
2593
2594 luaL_buffinit(L, &b);
2595 luaL_addlstring(&b, blk1, len1);
2596 if (unlikely(ret == 2))
2597 luaL_addlstring(&b, blk2, len2);
2598 luaL_pushresult(&b);
2599
2600 if (unlikely(ret == 2))
2601 return len1 + len2;
2602 return len1;
2603}
2604
2605/* "_hlua_channel_dup" wrapper. If no data are available, it returns
2606 * a yield. This function keep the data in the buffer.
2607 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002608__LJMP static int hlua_channel_dup_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002609{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002610 struct channel *chn;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002611
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002612 chn = MAY_LJMP(hlua_checkchannel(L, 1));
2613
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002614 if (_hlua_channel_dup(chn, L) == 0)
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002615 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_dup_yield, TICK_ETERNITY, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002616 return 1;
2617}
2618
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002619/* Check arguments for the function "hlua_channel_dup_yield". */
2620__LJMP static int hlua_channel_dup(lua_State *L)
2621{
2622 MAY_LJMP(check_args(L, 1, "dup"));
2623 MAY_LJMP(hlua_checkchannel(L, 1));
2624 return MAY_LJMP(hlua_channel_dup_yield(L, 0, 0));
2625}
2626
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002627/* "_hlua_channel_dup" wrapper. If no data are available, it returns
2628 * a yield. This function consumes the data in the buffer. It returns
2629 * a string containing the data or a nil pointer if no data are available
2630 * and the channel is closed.
2631 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002632__LJMP static int hlua_channel_get_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002633{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002634 struct channel *chn;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002635 int ret;
2636
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002637 chn = MAY_LJMP(hlua_checkchannel(L, 1));
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002638
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002639 ret = _hlua_channel_dup(chn, L);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002640 if (unlikely(ret == 0))
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002641 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_get_yield, TICK_ETERNITY, 0));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002642
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002643 if (unlikely(ret == -1))
2644 return 1;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002645
Willy Tarreau47860ed2015-03-10 14:07:50 +01002646 chn->buf->i -= ret;
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002647 hlua_resynchonize_proto(chn_strm(chn), !!(chn->flags & CF_ISRESP));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002648 return 1;
2649}
2650
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002651/* Check arguments for the fucntion "hlua_channel_get_yield". */
2652__LJMP static int hlua_channel_get(lua_State *L)
2653{
2654 MAY_LJMP(check_args(L, 1, "get"));
2655 MAY_LJMP(hlua_checkchannel(L, 1));
2656 return MAY_LJMP(hlua_channel_get_yield(L, 0, 0));
2657}
2658
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002659/* This functions consumes and returns one line. If the channel is closed,
2660 * and the last data does not contains a final '\n', the data are returned
2661 * without the final '\n'. When no more data are avalaible, it returns nil
2662 * value.
2663 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002664__LJMP static int hlua_channel_getline_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002665{
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002666 char *blk1;
2667 char *blk2;
2668 int len1;
2669 int len2;
2670 int len;
Willy Tarreau47860ed2015-03-10 14:07:50 +01002671 struct channel *chn;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002672 int ret;
2673 luaL_Buffer b;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002674
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002675 chn = MAY_LJMP(hlua_checkchannel(L, 1));
2676
Willy Tarreau06d80a92017-10-19 14:32:15 +02002677 ret = ci_getline_nc(chn, &blk1, &len1, &blk2, &len2);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002678 if (ret == 0)
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002679 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_getline_yield, TICK_ETERNITY, 0));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002680
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002681 if (ret == -1) {
2682 lua_pushnil(L);
2683 return 1;
2684 }
2685
2686 luaL_buffinit(L, &b);
2687 luaL_addlstring(&b, blk1, len1);
2688 len = len1;
2689 if (unlikely(ret == 2)) {
2690 luaL_addlstring(&b, blk2, len2);
2691 len += len2;
2692 }
2693 luaL_pushresult(&b);
Willy Tarreau47860ed2015-03-10 14:07:50 +01002694 buffer_replace2(chn->buf, chn->buf->p, chn->buf->p + len, NULL, 0);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002695 hlua_resynchonize_proto(chn_strm(chn), !!(chn->flags & CF_ISRESP));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002696 return 1;
2697}
2698
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002699/* Check arguments for the fucntion "hlua_channel_getline_yield". */
2700__LJMP static int hlua_channel_getline(lua_State *L)
2701{
2702 MAY_LJMP(check_args(L, 1, "getline"));
2703 MAY_LJMP(hlua_checkchannel(L, 1));
2704 return MAY_LJMP(hlua_channel_getline_yield(L, 0, 0));
2705}
2706
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002707/* This function takes a string as input, and append it at the
2708 * input side of channel. If the data is too big, but a space
2709 * is probably available after sending some data, the function
2710 * yield. If the data is bigger than the buffer, or if the
2711 * channel is closed, it returns -1. otherwise, it returns the
2712 * amount of data writed.
2713 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002714__LJMP static int hlua_channel_append_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002715{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002716 struct channel *chn = MAY_LJMP(hlua_checkchannel(L, 1));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002717 size_t len;
2718 const char *str = MAY_LJMP(luaL_checklstring(L, 2, &len));
2719 int l = MAY_LJMP(luaL_checkinteger(L, 3));
2720 int ret;
2721 int max;
2722
Christopher Fauleta73e59b2016-12-09 17:30:18 +01002723 /* Check if the buffer is avalaible because HAProxy doesn't allocate
2724 * the request buffer if its not required.
2725 */
2726 if (chn->buf->size == 0) {
2727 si_applet_cant_put(chn_prod(chn));
2728 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_append_yield, TICK_ETERNITY, 0));
2729 }
2730
Willy Tarreau47860ed2015-03-10 14:07:50 +01002731 max = channel_recv_limit(chn) - buffer_len(chn->buf);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002732 if (max > len - l)
2733 max = len - l;
2734
Willy Tarreau06d80a92017-10-19 14:32:15 +02002735 ret = ci_putblk(chn, str + l, max);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002736 if (ret == -2 || ret == -3) {
2737 lua_pushinteger(L, -1);
2738 return 1;
2739 }
Willy Tarreaubc18da12015-03-13 14:00:47 +01002740 if (ret == -1) {
2741 chn->flags |= CF_WAKE_WRITE;
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002742 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_append_yield, TICK_ETERNITY, 0));
Willy Tarreaubc18da12015-03-13 14:00:47 +01002743 }
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002744 l += ret;
2745 lua_pop(L, 1);
2746 lua_pushinteger(L, l);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002747 hlua_resynchonize_proto(chn_strm(chn), !!(chn->flags & CF_ISRESP));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002748
Willy Tarreau47860ed2015-03-10 14:07:50 +01002749 max = channel_recv_limit(chn) - buffer_len(chn->buf);
2750 if (max == 0 && chn->buf->o == 0) {
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002751 /* There are no space avalaible, and the output buffer is empty.
2752 * in this case, we cannot add more data, so we cannot yield,
2753 * we return the amount of copyied data.
2754 */
2755 return 1;
2756 }
2757 if (l < len)
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002758 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_append_yield, TICK_ETERNITY, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002759 return 1;
2760}
2761
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002762/* just a wrapper of "hlua_channel_append_yield". It returns the length
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002763 * of the writed string, or -1 if the channel is closed or if the
2764 * buffer size is too little for the data.
2765 */
2766__LJMP static int hlua_channel_append(lua_State *L)
2767{
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002768 size_t len;
2769
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002770 MAY_LJMP(check_args(L, 2, "append"));
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002771 MAY_LJMP(hlua_checkchannel(L, 1));
2772 MAY_LJMP(luaL_checklstring(L, 2, &len));
2773 MAY_LJMP(luaL_checkinteger(L, 3));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002774 lua_pushinteger(L, 0);
2775
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002776 return MAY_LJMP(hlua_channel_append_yield(L, 0, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002777}
2778
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002779/* just a wrapper of "hlua_channel_append_yield". This wrapper starts
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002780 * his process by cleaning the buffer. The result is a replacement
2781 * of the current data. It returns the length of the writed string,
2782 * or -1 if the channel is closed or if the buffer size is too
2783 * little for the data.
2784 */
2785__LJMP static int hlua_channel_set(lua_State *L)
2786{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002787 struct channel *chn;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002788
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002789 MAY_LJMP(check_args(L, 2, "set"));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002790 chn = MAY_LJMP(hlua_checkchannel(L, 1));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002791 lua_pushinteger(L, 0);
2792
Willy Tarreau47860ed2015-03-10 14:07:50 +01002793 chn->buf->i = 0;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002794
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002795 return MAY_LJMP(hlua_channel_append_yield(L, 0, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002796}
2797
2798/* Append data in the output side of the buffer. This data is immediatly
2799 * sent. The fcuntion returns the ammount of data writed. If the buffer
2800 * cannot contains the data, the function yield. The function returns -1
2801 * if the channel is closed.
2802 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002803__LJMP static int hlua_channel_send_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002804{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002805 struct channel *chn = MAY_LJMP(hlua_checkchannel(L, 1));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002806 size_t len;
2807 const char *str = MAY_LJMP(luaL_checklstring(L, 2, &len));
2808 int l = MAY_LJMP(luaL_checkinteger(L, 3));
2809 int max;
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01002810 struct hlua *hlua = hlua_gethlua(L);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002811
Willy Tarreau47860ed2015-03-10 14:07:50 +01002812 if (unlikely(channel_output_closed(chn))) {
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002813 lua_pushinteger(L, -1);
2814 return 1;
2815 }
2816
Thierry FOURNIER3e3a6082015-03-05 17:06:12 +01002817 /* Check if the buffer is avalaible because HAProxy doesn't allocate
2818 * the request buffer if its not required.
2819 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002820 if (chn->buf->size == 0) {
Christopher Fauleta73e59b2016-12-09 17:30:18 +01002821 si_applet_cant_put(chn_prod(chn));
2822 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_send_yield, TICK_ETERNITY, 0));
Thierry FOURNIER3e3a6082015-03-05 17:06:12 +01002823 }
2824
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002825 /* the writed data will be immediatly sent, so we can check
2826 * the avalaible space without taking in account the reserve.
2827 * The reserve is guaranted for the processing of incoming
2828 * data, because the buffer will be flushed.
2829 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002830 max = chn->buf->size - buffer_len(chn->buf);
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002831
2832 /* If there are no space avalaible, and the output buffer is empty.
2833 * in this case, we cannot add more data, so we cannot yield,
2834 * we return the amount of copyied data.
2835 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002836 if (max == 0 && chn->buf->o == 0)
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002837 return 1;
2838
2839 /* Adjust the real required length. */
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002840 if (max > len - l)
2841 max = len - l;
2842
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002843 /* The buffer avalaible size may be not contiguous. This test
2844 * detects a non contiguous buffer and realign it.
2845 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002846 if (bi_space_for_replace(chn->buf) < max)
2847 buffer_slow_realign(chn->buf);
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002848
2849 /* Copy input data in the buffer. */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002850 max = buffer_replace2(chn->buf, chn->buf->p, chn->buf->p, str + l, max);
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002851
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002852 /* buffer replace considers that the input part is filled.
2853 * so, I must forward these new data in the output part.
2854 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002855 b_adv(chn->buf, max);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002856
2857 l += max;
2858 lua_pop(L, 1);
2859 lua_pushinteger(L, l);
2860
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002861 /* If there are no space avalaible, and the output buffer is empty.
2862 * in this case, we cannot add more data, so we cannot yield,
2863 * we return the amount of copyied data.
2864 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002865 max = chn->buf->size - buffer_len(chn->buf);
2866 if (max == 0 && chn->buf->o == 0)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002867 return 1;
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002868
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01002869 if (l < len) {
2870 /* If we are waiting for space in the response buffer, we
2871 * must set the flag WAKERESWR. This flag required the task
2872 * wake up if any activity is detected on the response buffer.
2873 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002874 if (chn->flags & CF_ISRESP)
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01002875 HLUA_SET_WAKERESWR(hlua);
Thierry FOURNIER53e08ec2015-03-06 00:35:53 +01002876 else
2877 HLUA_SET_WAKEREQWR(hlua);
2878 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_send_yield, TICK_ETERNITY, 0));
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01002879 }
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002880
2881 return 1;
2882}
2883
2884/* Just a wraper of "_hlua_channel_send". This wrapper permits
2885 * yield the LUA process, and resume it without checking the
2886 * input arguments.
2887 */
2888__LJMP static int hlua_channel_send(lua_State *L)
2889{
2890 MAY_LJMP(check_args(L, 2, "send"));
2891 lua_pushinteger(L, 0);
2892
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002893 return MAY_LJMP(hlua_channel_send_yield(L, 0, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002894}
2895
2896/* This function forward and amount of butes. The data pass from
2897 * the input side of the buffer to the output side, and can be
2898 * forwarded. This function never fails.
2899 *
2900 * The Lua function takes an amount of bytes to be forwarded in
2901 * imput. It returns the number of bytes forwarded.
2902 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002903__LJMP static int hlua_channel_forward_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002904{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002905 struct channel *chn;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002906 int len;
2907 int l;
2908 int max;
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01002909 struct hlua *hlua = hlua_gethlua(L);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002910
2911 chn = MAY_LJMP(hlua_checkchannel(L, 1));
2912 len = MAY_LJMP(luaL_checkinteger(L, 2));
2913 l = MAY_LJMP(luaL_checkinteger(L, -1));
2914
2915 max = len - l;
Willy Tarreau47860ed2015-03-10 14:07:50 +01002916 if (max > chn->buf->i)
2917 max = chn->buf->i;
2918 channel_forward(chn, max);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002919 l += max;
2920
2921 lua_pop(L, 1);
2922 lua_pushinteger(L, l);
2923
2924 /* Check if it miss bytes to forward. */
2925 if (l < len) {
2926 /* The the input channel or the output channel are closed, we
2927 * must return the amount of data forwarded.
2928 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002929 if (channel_input_closed(chn) || channel_output_closed(chn))
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002930 return 1;
2931
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01002932 /* If we are waiting for space data in the response buffer, we
2933 * must set the flag WAKERESWR. This flag required the task
2934 * wake up if any activity is detected on the response buffer.
2935 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002936 if (chn->flags & CF_ISRESP)
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01002937 HLUA_SET_WAKERESWR(hlua);
Thierry FOURNIER53e08ec2015-03-06 00:35:53 +01002938 else
2939 HLUA_SET_WAKEREQWR(hlua);
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01002940
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002941 /* Otherwise, we can yield waiting for new data in the inpout side. */
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +01002942 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_forward_yield, TICK_ETERNITY, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002943 }
2944
2945 return 1;
2946}
2947
2948/* Just check the input and prepare the stack for the previous
2949 * function "hlua_channel_forward_yield"
2950 */
2951__LJMP static int hlua_channel_forward(lua_State *L)
2952{
2953 MAY_LJMP(check_args(L, 2, "forward"));
2954 MAY_LJMP(hlua_checkchannel(L, 1));
2955 MAY_LJMP(luaL_checkinteger(L, 2));
2956
2957 lua_pushinteger(L, 0);
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002958 return MAY_LJMP(hlua_channel_forward_yield(L, 0, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002959}
2960
2961/* Just returns the number of bytes available in the input
2962 * side of the buffer. This function never fails.
2963 */
2964__LJMP static int hlua_channel_get_in_len(lua_State *L)
2965{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002966 struct channel *chn;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002967
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002968 MAY_LJMP(check_args(L, 1, "get_in_len"));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002969 chn = MAY_LJMP(hlua_checkchannel(L, 1));
Willy Tarreau47860ed2015-03-10 14:07:50 +01002970 lua_pushinteger(L, chn->buf->i);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002971 return 1;
2972}
2973
Thierry FOURNIER / OZON.IO65192f32016-11-07 15:28:40 +01002974/* Returns true if the channel is full. */
2975__LJMP static int hlua_channel_is_full(lua_State *L)
2976{
2977 struct channel *chn;
2978 int rem;
2979
2980 MAY_LJMP(check_args(L, 1, "is_full"));
2981 chn = MAY_LJMP(hlua_checkchannel(L, 1));
2982
2983 rem = chn->buf->size;
2984 rem -= chn->buf->o; /* Output size */
2985 rem -= chn->buf->i; /* Input size */
2986 rem -= global.tune.maxrewrite; /* Rewrite reserved size */
2987
2988 lua_pushboolean(L, rem <= 0);
2989 return 1;
2990}
2991
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002992/* Just returns the number of bytes available in the output
2993 * side of the buffer. This function never fails.
2994 */
2995__LJMP static int hlua_channel_get_out_len(lua_State *L)
2996{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002997 struct channel *chn;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002998
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002999 MAY_LJMP(check_args(L, 1, "get_out_len"));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01003000 chn = MAY_LJMP(hlua_checkchannel(L, 1));
Willy Tarreau47860ed2015-03-10 14:07:50 +01003001 lua_pushinteger(L, chn->buf->o);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003002 return 1;
3003}
3004
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003005/*
3006 *
3007 *
3008 * Class Fetches
3009 *
3010 *
3011 */
3012
3013/* Returns a struct hlua_session if the stack entry "ud" is
Willy Tarreau87b09662015-04-03 00:22:06 +02003014 * a class stream, otherwise it throws an error.
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003015 */
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003016__LJMP static struct hlua_smp *hlua_checkfetches(lua_State *L, int ud)
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003017{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003018 return MAY_LJMP(hlua_checkudata(L, ud, class_fetches_ref));
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003019}
3020
3021/* This function creates and push in the stack a fetch object according
3022 * with a current TXN.
3023 */
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003024static int hlua_fetches_new(lua_State *L, struct hlua_txn *txn, unsigned int flags)
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003025{
Willy Tarreau7073c472015-04-06 11:15:40 +02003026 struct hlua_smp *hsmp;
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003027
3028 /* Check stack size. */
3029 if (!lua_checkstack(L, 3))
3030 return 0;
3031
3032 /* Create the object: obj[0] = userdata.
3033 * Note that the base of the Fetches object is the
3034 * transaction object.
3035 */
3036 lua_newtable(L);
Willy Tarreau7073c472015-04-06 11:15:40 +02003037 hsmp = lua_newuserdata(L, sizeof(*hsmp));
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003038 lua_rawseti(L, -2, 0);
3039
Willy Tarreau7073c472015-04-06 11:15:40 +02003040 hsmp->s = txn->s;
3041 hsmp->p = txn->p;
Thierry FOURNIERc4eebc82015-11-02 10:01:59 +01003042 hsmp->dir = txn->dir;
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003043 hsmp->flags = flags;
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003044
3045 /* Pop a class sesison metatable and affect it to the userdata. */
3046 lua_rawgeti(L, LUA_REGISTRYINDEX, class_fetches_ref);
3047 lua_setmetatable(L, -2);
3048
3049 return 1;
3050}
3051
3052/* This function is an LUA binding. It is called with each sample-fetch.
3053 * It uses closure argument to store the associated sample-fetch. It
3054 * returns only one argument or throws an error. An error is thrown
3055 * only if an error is encountered during the argument parsing. If
3056 * the "sample-fetch" function fails, nil is returned.
3057 */
3058__LJMP static int hlua_run_sample_fetch(lua_State *L)
3059{
Willy Tarreaub2ccb562015-04-06 11:11:15 +02003060 struct hlua_smp *hsmp;
Willy Tarreau2ec22742015-03-10 14:27:20 +01003061 struct sample_fetch *f;
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003062 struct arg args[ARGM_NBARGS + 1];
3063 int i;
3064 struct sample smp;
3065
3066 /* Get closure arguments. */
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003067 f = lua_touserdata(L, lua_upvalueindex(1));
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003068
3069 /* Get traditionnal arguments. */
Willy Tarreaub2ccb562015-04-06 11:11:15 +02003070 hsmp = MAY_LJMP(hlua_checkfetches(L, 1));
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003071
Thierry FOURNIERca988662015-12-20 18:43:03 +01003072 /* Check execution authorization. */
3073 if (f->use & SMP_USE_HTTP_ANY &&
3074 !(hsmp->flags & HLUA_F_MAY_USE_HTTP)) {
3075 lua_pushfstring(L, "the sample-fetch '%s' needs an HTTP parser which "
3076 "is not available in Lua services", f->kw);
3077 WILL_LJMP(lua_error(L));
3078 }
3079
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003080 /* Get extra arguments. */
3081 for (i = 0; i < lua_gettop(L) - 1; i++) {
3082 if (i >= ARGM_NBARGS)
3083 break;
3084 hlua_lua2arg(L, i + 2, &args[i]);
3085 }
3086 args[i].type = ARGT_STOP;
David Carlierabdb00f2016-04-27 16:14:50 +01003087 args[i].data.str.str = NULL;
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003088
3089 /* Check arguments. */
Willy Tarreaub2ccb562015-04-06 11:11:15 +02003090 MAY_LJMP(hlua_lua2arg_check(L, 2, args, f->arg_mask, hsmp->p));
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003091
3092 /* Run the special args checker. */
Willy Tarreau2ec22742015-03-10 14:27:20 +01003093 if (f->val_args && !f->val_args(args, NULL)) {
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003094 lua_pushfstring(L, "error in arguments");
3095 WILL_LJMP(lua_error(L));
3096 }
3097
3098 /* Initialise the sample. */
3099 memset(&smp, 0, sizeof(smp));
3100
3101 /* Run the sample fetch process. */
Willy Tarreau1777ea62016-03-10 16:15:46 +01003102 smp_set_owner(&smp, hsmp->p, hsmp->s->sess, hsmp->s, hsmp->dir & SMP_OPT_DIR);
Thierry FOURNIER0786d052015-05-11 15:42:45 +02003103 if (!f->process(args, &smp, f->kw, f->private)) {
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003104 if (hsmp->flags & HLUA_F_AS_STRING)
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003105 lua_pushstring(L, "");
3106 else
3107 lua_pushnil(L);
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003108 return 1;
3109 }
3110
3111 /* Convert the returned sample in lua value. */
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003112 if (hsmp->flags & HLUA_F_AS_STRING)
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003113 hlua_smp2lua_str(L, &smp);
3114 else
3115 hlua_smp2lua(L, &smp);
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003116 return 1;
3117}
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003118
3119/*
3120 *
3121 *
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003122 * Class Converters
3123 *
3124 *
3125 */
3126
3127/* Returns a struct hlua_session if the stack entry "ud" is
Willy Tarreau87b09662015-04-03 00:22:06 +02003128 * a class stream, otherwise it throws an error.
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003129 */
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003130__LJMP static struct hlua_smp *hlua_checkconverters(lua_State *L, int ud)
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003131{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003132 return MAY_LJMP(hlua_checkudata(L, ud, class_converters_ref));
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003133}
3134
3135/* This function creates and push in the stack a Converters object
3136 * according with a current TXN.
3137 */
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003138static int hlua_converters_new(lua_State *L, struct hlua_txn *txn, unsigned int flags)
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003139{
Willy Tarreau7073c472015-04-06 11:15:40 +02003140 struct hlua_smp *hsmp;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003141
3142 /* Check stack size. */
3143 if (!lua_checkstack(L, 3))
3144 return 0;
3145
3146 /* Create the object: obj[0] = userdata.
3147 * Note that the base of the Converters object is the
3148 * same than the TXN object.
3149 */
3150 lua_newtable(L);
Willy Tarreau7073c472015-04-06 11:15:40 +02003151 hsmp = lua_newuserdata(L, sizeof(*hsmp));
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003152 lua_rawseti(L, -2, 0);
3153
Willy Tarreau7073c472015-04-06 11:15:40 +02003154 hsmp->s = txn->s;
3155 hsmp->p = txn->p;
Thierry FOURNIERc4eebc82015-11-02 10:01:59 +01003156 hsmp->dir = txn->dir;
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003157 hsmp->flags = flags;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003158
Willy Tarreau87b09662015-04-03 00:22:06 +02003159 /* Pop a class stream metatable and affect it to the table. */
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003160 lua_rawgeti(L, LUA_REGISTRYINDEX, class_converters_ref);
3161 lua_setmetatable(L, -2);
3162
3163 return 1;
3164}
3165
3166/* This function is an LUA binding. It is called with each converter.
3167 * It uses closure argument to store the associated converter. It
3168 * returns only one argument or throws an error. An error is thrown
3169 * only if an error is encountered during the argument parsing. If
3170 * the converter function function fails, nil is returned.
3171 */
3172__LJMP static int hlua_run_sample_conv(lua_State *L)
3173{
Willy Tarreauda5f1082015-04-06 11:17:13 +02003174 struct hlua_smp *hsmp;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003175 struct sample_conv *conv;
3176 struct arg args[ARGM_NBARGS + 1];
3177 int i;
3178 struct sample smp;
3179
3180 /* Get closure arguments. */
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003181 conv = lua_touserdata(L, lua_upvalueindex(1));
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003182
3183 /* Get traditionnal arguments. */
Willy Tarreauda5f1082015-04-06 11:17:13 +02003184 hsmp = MAY_LJMP(hlua_checkconverters(L, 1));
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003185
3186 /* Get extra arguments. */
3187 for (i = 0; i < lua_gettop(L) - 2; i++) {
3188 if (i >= ARGM_NBARGS)
3189 break;
3190 hlua_lua2arg(L, i + 3, &args[i]);
3191 }
3192 args[i].type = ARGT_STOP;
David Carlierabdb00f2016-04-27 16:14:50 +01003193 args[i].data.str.str = NULL;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003194
3195 /* Check arguments. */
Willy Tarreauda5f1082015-04-06 11:17:13 +02003196 MAY_LJMP(hlua_lua2arg_check(L, 3, args, conv->arg_mask, hsmp->p));
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003197
3198 /* Run the special args checker. */
3199 if (conv->val_args && !conv->val_args(args, conv, "", 0, NULL)) {
3200 hlua_pusherror(L, "error in arguments");
3201 WILL_LJMP(lua_error(L));
3202 }
3203
3204 /* Initialise the sample. */
3205 if (!hlua_lua2smp(L, 2, &smp)) {
3206 hlua_pusherror(L, "error in the input argument");
3207 WILL_LJMP(lua_error(L));
3208 }
3209
Willy Tarreau1777ea62016-03-10 16:15:46 +01003210 smp_set_owner(&smp, hsmp->p, hsmp->s->sess, hsmp->s, hsmp->dir & SMP_OPT_DIR);
3211
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003212 /* Apply expected cast. */
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02003213 if (!sample_casts[smp.data.type][conv->in_type]) {
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003214 hlua_pusherror(L, "invalid input argument: cannot cast '%s' to '%s'",
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02003215 smp_to_type[smp.data.type], smp_to_type[conv->in_type]);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003216 WILL_LJMP(lua_error(L));
3217 }
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02003218 if (sample_casts[smp.data.type][conv->in_type] != c_none &&
3219 !sample_casts[smp.data.type][conv->in_type](&smp)) {
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003220 hlua_pusherror(L, "error during the input argument casting");
3221 WILL_LJMP(lua_error(L));
3222 }
3223
3224 /* Run the sample conversion process. */
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02003225 if (!conv->process(args, &smp, conv->private)) {
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003226 if (hsmp->flags & HLUA_F_AS_STRING)
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003227 lua_pushstring(L, "");
3228 else
Willy Tarreaua678b432015-08-28 10:14:59 +02003229 lua_pushnil(L);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003230 return 1;
3231 }
3232
3233 /* Convert the returned sample in lua value. */
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003234 if (hsmp->flags & HLUA_F_AS_STRING)
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003235 hlua_smp2lua_str(L, &smp);
3236 else
3237 hlua_smp2lua(L, &smp);
Willy Tarreaua678b432015-08-28 10:14:59 +02003238 return 1;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003239}
3240
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003241/*
3242 *
3243 *
3244 * Class AppletTCP
3245 *
3246 *
3247 */
3248
3249/* Returns a struct hlua_txn if the stack entry "ud" is
3250 * a class stream, otherwise it throws an error.
3251 */
3252__LJMP static struct hlua_appctx *hlua_checkapplet_tcp(lua_State *L, int ud)
3253{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003254 return MAY_LJMP(hlua_checkudata(L, ud, class_applet_tcp_ref));
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003255}
3256
3257/* This function creates and push in the stack an Applet object
3258 * according with a current TXN.
3259 */
3260static int hlua_applet_tcp_new(lua_State *L, struct appctx *ctx)
3261{
3262 struct hlua_appctx *appctx;
3263 struct stream_interface *si = ctx->owner;
3264 struct stream *s = si_strm(si);
3265 struct proxy *p = s->be;
3266
3267 /* Check stack size. */
3268 if (!lua_checkstack(L, 3))
3269 return 0;
3270
3271 /* Create the object: obj[0] = userdata.
3272 * Note that the base of the Converters object is the
3273 * same than the TXN object.
3274 */
3275 lua_newtable(L);
3276 appctx = lua_newuserdata(L, sizeof(*appctx));
3277 lua_rawseti(L, -2, 0);
3278 appctx->appctx = ctx;
3279 appctx->htxn.s = s;
3280 appctx->htxn.p = p;
3281
3282 /* Create the "f" field that contains a list of fetches. */
3283 lua_pushstring(L, "f");
3284 if (!hlua_fetches_new(L, &appctx->htxn, 0))
3285 return 0;
3286 lua_settable(L, -3);
3287
3288 /* Create the "sf" field that contains a list of stringsafe fetches. */
3289 lua_pushstring(L, "sf");
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003290 if (!hlua_fetches_new(L, &appctx->htxn, HLUA_F_AS_STRING))
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003291 return 0;
3292 lua_settable(L, -3);
3293
3294 /* Create the "c" field that contains a list of converters. */
3295 lua_pushstring(L, "c");
3296 if (!hlua_converters_new(L, &appctx->htxn, 0))
3297 return 0;
3298 lua_settable(L, -3);
3299
3300 /* Create the "sc" field that contains a list of stringsafe converters. */
3301 lua_pushstring(L, "sc");
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003302 if (!hlua_converters_new(L, &appctx->htxn, HLUA_F_AS_STRING))
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003303 return 0;
3304 lua_settable(L, -3);
3305
3306 /* Pop a class stream metatable and affect it to the table. */
3307 lua_rawgeti(L, LUA_REGISTRYINDEX, class_applet_tcp_ref);
3308 lua_setmetatable(L, -2);
3309
3310 return 1;
3311}
3312
Thierry FOURNIER / OZON.IO4394a2c2016-12-12 12:31:54 +01003313__LJMP static int hlua_applet_tcp_set_var(lua_State *L)
3314{
3315 struct hlua_appctx *appctx;
3316 struct stream *s;
3317 const char *name;
3318 size_t len;
3319 struct sample smp;
3320
3321 MAY_LJMP(check_args(L, 3, "set_var"));
3322
3323 /* It is useles to retrieve the stream, but this function
3324 * runs only in a stream context.
3325 */
3326 appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3327 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3328 s = appctx->htxn.s;
3329
3330 /* Converts the third argument in a sample. */
3331 hlua_lua2smp(L, 3, &smp);
3332
3333 /* Store the sample in a variable. */
3334 smp_set_owner(&smp, s->be, s->sess, s, 0);
3335 vars_set_by_name(name, len, &smp);
3336 return 0;
3337}
3338
3339__LJMP static int hlua_applet_tcp_unset_var(lua_State *L)
3340{
3341 struct hlua_appctx *appctx;
3342 struct stream *s;
3343 const char *name;
3344 size_t len;
3345 struct sample smp;
3346
3347 MAY_LJMP(check_args(L, 2, "unset_var"));
3348
3349 /* It is useles to retrieve the stream, but this function
3350 * runs only in a stream context.
3351 */
3352 appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3353 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3354 s = appctx->htxn.s;
3355
3356 /* Unset the variable. */
3357 smp_set_owner(&smp, s->be, s->sess, s, 0);
3358 vars_unset_by_name(name, len, &smp);
3359 return 0;
3360}
3361
3362__LJMP static int hlua_applet_tcp_get_var(lua_State *L)
3363{
3364 struct hlua_appctx *appctx;
3365 struct stream *s;
3366 const char *name;
3367 size_t len;
3368 struct sample smp;
3369
3370 MAY_LJMP(check_args(L, 2, "get_var"));
3371
3372 /* It is useles to retrieve the stream, but this function
3373 * runs only in a stream context.
3374 */
3375 appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3376 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3377 s = appctx->htxn.s;
3378
3379 smp_set_owner(&smp, s->be, s->sess, s, 0);
3380 if (!vars_get_by_name(name, len, &smp)) {
3381 lua_pushnil(L);
3382 return 1;
3383 }
3384
3385 return hlua_smp2lua(L, &smp);
3386}
3387
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003388__LJMP static int hlua_applet_tcp_set_priv(lua_State *L)
3389{
3390 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3391 struct stream *s = appctx->htxn.s;
Thierry FOURNIER3b0a6d42016-12-16 08:48:32 +01003392 struct hlua *hlua;
3393
3394 /* Note that this hlua struct is from the session and not from the applet. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01003395 if (!s->hlua)
3396 return 0;
3397 hlua = s->hlua;
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003398
3399 MAY_LJMP(check_args(L, 2, "set_priv"));
3400
3401 /* Remove previous value. */
Thierry FOURNIERe068b602017-04-26 13:27:05 +02003402 luaL_unref(L, LUA_REGISTRYINDEX, hlua->Mref);
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003403
3404 /* Get and store new value. */
3405 lua_pushvalue(L, 2); /* Copy the element 2 at the top of the stack. */
3406 hlua->Mref = luaL_ref(L, LUA_REGISTRYINDEX); /* pop the previously pushed value. */
3407
3408 return 0;
3409}
3410
3411__LJMP static int hlua_applet_tcp_get_priv(lua_State *L)
3412{
3413 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3414 struct stream *s = appctx->htxn.s;
Thierry FOURNIER3b0a6d42016-12-16 08:48:32 +01003415 struct hlua *hlua;
3416
3417 /* Note that this hlua struct is from the session and not from the applet. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01003418 if (!s->hlua) {
3419 lua_pushnil(L);
3420 return 1;
3421 }
3422 hlua = s->hlua;
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003423
3424 /* Push configuration index in the stack. */
3425 lua_rawgeti(L, LUA_REGISTRYINDEX, hlua->Mref);
3426
3427 return 1;
3428}
3429
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003430/* If expected data not yet available, it returns a yield. This function
3431 * consumes the data in the buffer. It returns a string containing the
3432 * data. This string can be empty.
3433 */
3434__LJMP static int hlua_applet_tcp_getline_yield(lua_State *L, int status, lua_KContext ctx)
3435{
3436 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3437 struct stream_interface *si = appctx->appctx->owner;
3438 int ret;
3439 char *blk1;
3440 int len1;
3441 char *blk2;
3442 int len2;
3443
3444 /* Read the maximum amount of data avalaible. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02003445 ret = co_getline_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003446
3447 /* Data not yet avalaible. return yield. */
3448 if (ret == 0) {
3449 si_applet_cant_get(si);
3450 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_getline_yield, TICK_ETERNITY, 0));
3451 }
3452
3453 /* End of data: commit the total strings and return. */
3454 if (ret < 0) {
3455 luaL_pushresult(&appctx->b);
3456 return 1;
3457 }
3458
3459 /* Ensure that the block 2 length is usable. */
3460 if (ret == 1)
3461 len2 = 0;
3462
3463 /* dont check the max length read and dont check. */
3464 luaL_addlstring(&appctx->b, blk1, len1);
3465 luaL_addlstring(&appctx->b, blk2, len2);
3466
3467 /* Consume input channel output buffer data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02003468 co_skip(si_oc(si), len1 + len2);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003469 luaL_pushresult(&appctx->b);
3470 return 1;
3471}
3472
3473/* Check arguments for the fucntion "hlua_channel_get_yield". */
3474__LJMP static int hlua_applet_tcp_getline(lua_State *L)
3475{
3476 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3477
3478 /* Initialise the string catenation. */
3479 luaL_buffinit(L, &appctx->b);
3480
3481 return MAY_LJMP(hlua_applet_tcp_getline_yield(L, 0, 0));
3482}
3483
3484/* If expected data not yet available, it returns a yield. This function
3485 * consumes the data in the buffer. It returns a string containing the
3486 * data. This string can be empty.
3487 */
3488__LJMP static int hlua_applet_tcp_recv_yield(lua_State *L, int status, lua_KContext ctx)
3489{
3490 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3491 struct stream_interface *si = appctx->appctx->owner;
3492 int len = MAY_LJMP(luaL_checkinteger(L, 2));
3493 int ret;
3494 char *blk1;
3495 int len1;
3496 char *blk2;
3497 int len2;
3498
3499 /* Read the maximum amount of data avalaible. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02003500 ret = co_getblk_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003501
3502 /* Data not yet avalaible. return yield. */
3503 if (ret == 0) {
3504 si_applet_cant_get(si);
3505 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_recv_yield, TICK_ETERNITY, 0));
3506 }
3507
3508 /* End of data: commit the total strings and return. */
3509 if (ret < 0) {
3510 luaL_pushresult(&appctx->b);
3511 return 1;
3512 }
3513
3514 /* Ensure that the block 2 length is usable. */
3515 if (ret == 1)
3516 len2 = 0;
3517
3518 if (len == -1) {
3519
3520 /* If len == -1, catenate all the data avalaile and
3521 * yield because we want to get all the data until
3522 * the end of data stream.
3523 */
3524 luaL_addlstring(&appctx->b, blk1, len1);
3525 luaL_addlstring(&appctx->b, blk2, len2);
Willy Tarreau06d80a92017-10-19 14:32:15 +02003526 co_skip(si_oc(si), len1 + len2);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003527 si_applet_cant_get(si);
3528 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_recv_yield, TICK_ETERNITY, 0));
3529
3530 } else {
3531
3532 /* Copy the fisrt block caping to the length required. */
3533 if (len1 > len)
3534 len1 = len;
3535 luaL_addlstring(&appctx->b, blk1, len1);
3536 len -= len1;
3537
3538 /* Copy the second block. */
3539 if (len2 > len)
3540 len2 = len;
3541 luaL_addlstring(&appctx->b, blk2, len2);
3542 len -= len2;
3543
3544 /* Consume input channel output buffer data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02003545 co_skip(si_oc(si), len1 + len2);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003546
3547 /* If we are no other data avalaible, yield waiting for new data. */
3548 if (len > 0) {
3549 lua_pushinteger(L, len);
3550 lua_replace(L, 2);
3551 si_applet_cant_get(si);
3552 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_recv_yield, TICK_ETERNITY, 0));
3553 }
3554
3555 /* return the result. */
3556 luaL_pushresult(&appctx->b);
3557 return 1;
3558 }
3559
3560 /* we never executes this */
3561 hlua_pusherror(L, "Lua: internal error");
3562 WILL_LJMP(lua_error(L));
3563 return 0;
3564}
3565
3566/* Check arguments for the fucntion "hlua_channel_get_yield". */
3567__LJMP static int hlua_applet_tcp_recv(lua_State *L)
3568{
3569 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3570 int len = -1;
3571
3572 if (lua_gettop(L) > 2)
3573 WILL_LJMP(luaL_error(L, "The 'recv' function requires between 1 and 2 arguments."));
3574 if (lua_gettop(L) >= 2) {
3575 len = MAY_LJMP(luaL_checkinteger(L, 2));
3576 lua_pop(L, 1);
3577 }
3578
3579 /* Confirm or set the required length */
3580 lua_pushinteger(L, len);
3581
3582 /* Initialise the string catenation. */
3583 luaL_buffinit(L, &appctx->b);
3584
3585 return MAY_LJMP(hlua_applet_tcp_recv_yield(L, 0, 0));
3586}
3587
3588/* Append data in the output side of the buffer. This data is immediatly
3589 * sent. The fcuntion returns the ammount of data writed. If the buffer
3590 * cannot contains the data, the function yield. The function returns -1
3591 * if the channel is closed.
3592 */
3593__LJMP static int hlua_applet_tcp_send_yield(lua_State *L, int status, lua_KContext ctx)
3594{
3595 size_t len;
3596 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3597 const char *str = MAY_LJMP(luaL_checklstring(L, 2, &len));
3598 int l = MAY_LJMP(luaL_checkinteger(L, 3));
3599 struct stream_interface *si = appctx->appctx->owner;
3600 struct channel *chn = si_ic(si);
3601 int max;
3602
3603 /* Get the max amount of data which can write as input in the channel. */
3604 max = channel_recv_max(chn);
3605 if (max > (len - l))
3606 max = len - l;
3607
3608 /* Copy data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02003609 ci_putblk(chn, str + l, max);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003610
3611 /* update counters. */
3612 l += max;
3613 lua_pop(L, 1);
3614 lua_pushinteger(L, l);
3615
3616 /* If some data is not send, declares the situation to the
3617 * applet, and returns a yield.
3618 */
3619 if (l < len) {
3620 si_applet_cant_put(si);
3621 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_send_yield, TICK_ETERNITY, 0));
3622 }
3623
3624 return 1;
3625}
3626
3627/* Just a wraper of "hlua_applet_tcp_send_yield". This wrapper permits
3628 * yield the LUA process, and resume it without checking the
3629 * input arguments.
3630 */
3631__LJMP static int hlua_applet_tcp_send(lua_State *L)
3632{
3633 MAY_LJMP(check_args(L, 2, "send"));
3634 lua_pushinteger(L, 0);
3635
3636 return MAY_LJMP(hlua_applet_tcp_send_yield(L, 0, 0));
3637}
3638
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003639/*
3640 *
3641 *
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003642 * Class AppletHTTP
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003643 *
3644 *
3645 */
3646
3647/* Returns a struct hlua_txn if the stack entry "ud" is
Willy Tarreau87b09662015-04-03 00:22:06 +02003648 * a class stream, otherwise it throws an error.
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003649 */
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003650__LJMP static struct hlua_appctx *hlua_checkapplet_http(lua_State *L, int ud)
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003651{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003652 return MAY_LJMP(hlua_checkudata(L, ud, class_applet_http_ref));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003653}
3654
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003655/* This function creates and push in the stack an Applet object
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003656 * according with a current TXN.
3657 */
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003658static int hlua_applet_http_new(lua_State *L, struct appctx *ctx)
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003659{
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003660 struct hlua_appctx *appctx;
Thierry FOURNIER841475e2015-12-11 17:10:09 +01003661 struct hlua_txn htxn;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003662 struct stream_interface *si = ctx->owner;
3663 struct stream *s = si_strm(si);
3664 struct proxy *px = s->be;
3665 struct http_txn *txn = s->txn;
3666 const char *path;
3667 const char *end;
3668 const char *p;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003669
3670 /* Check stack size. */
3671 if (!lua_checkstack(L, 3))
3672 return 0;
3673
3674 /* Create the object: obj[0] = userdata.
3675 * Note that the base of the Converters object is the
3676 * same than the TXN object.
3677 */
3678 lua_newtable(L);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003679 appctx = lua_newuserdata(L, sizeof(*appctx));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003680 lua_rawseti(L, -2, 0);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003681 appctx->appctx = ctx;
3682 appctx->appctx->ctx.hlua_apphttp.status = 200; /* Default status code returned. */
Robin H. Johnson52f5db22017-01-01 13:10:52 -08003683 appctx->appctx->ctx.hlua_apphttp.reason = NULL; /* Use default reason based on status */
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003684 appctx->htxn.s = s;
3685 appctx->htxn.p = px;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003686
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003687 /* Create the "f" field that contains a list of fetches. */
3688 lua_pushstring(L, "f");
3689 if (!hlua_fetches_new(L, &appctx->htxn, 0))
3690 return 0;
3691 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003692
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003693 /* Create the "sf" field that contains a list of stringsafe fetches. */
3694 lua_pushstring(L, "sf");
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003695 if (!hlua_fetches_new(L, &appctx->htxn, HLUA_F_AS_STRING))
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003696 return 0;
3697 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003698
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003699 /* Create the "c" field that contains a list of converters. */
3700 lua_pushstring(L, "c");
3701 if (!hlua_converters_new(L, &appctx->htxn, 0))
3702 return 0;
3703 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003704
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003705 /* Create the "sc" field that contains a list of stringsafe converters. */
3706 lua_pushstring(L, "sc");
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003707 if (!hlua_converters_new(L, &appctx->htxn, HLUA_F_AS_STRING))
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003708 return 0;
3709 lua_settable(L, -3);
Willy Tarreaueee5b512015-04-03 23:46:31 +02003710
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003711 /* Stores the request method. */
3712 lua_pushstring(L, "method");
3713 lua_pushlstring(L, txn->req.chn->buf->p, txn->req.sl.rq.m_l);
3714 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003715
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003716 /* Stores the http version. */
3717 lua_pushstring(L, "version");
3718 lua_pushlstring(L, txn->req.chn->buf->p + txn->req.sl.rq.v, txn->req.sl.rq.v_l);
3719 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003720
Thierry FOURNIER841475e2015-12-11 17:10:09 +01003721 /* creates an array of headers. hlua_http_get_headers() crates and push
3722 * the array on the top of the stack.
3723 */
3724 lua_pushstring(L, "headers");
3725 htxn.s = s;
3726 htxn.p = px;
3727 htxn.dir = SMP_OPT_DIR_REQ;
3728 if (!hlua_http_get_headers(L, &htxn, &htxn.s->txn->req))
3729 return 0;
3730 lua_settable(L, -3);
3731
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003732 /* Get path and qs */
3733 path = http_get_path(txn);
Thierry FOURNIER7d388632017-02-22 02:06:16 +01003734 if (path) {
3735 end = txn->req.chn->buf->p + txn->req.sl.rq.u + txn->req.sl.rq.u_l;
3736 p = path;
3737 while (p < end && *p != '?')
3738 p++;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003739
Thierry FOURNIER7d388632017-02-22 02:06:16 +01003740 /* Stores the request path. */
3741 lua_pushstring(L, "path");
3742 lua_pushlstring(L, path, p - path);
3743 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003744
Thierry FOURNIER7d388632017-02-22 02:06:16 +01003745 /* Stores the query string. */
3746 lua_pushstring(L, "qs");
3747 if (*p == '?')
3748 p++;
3749 lua_pushlstring(L, p, end - p);
3750 lua_settable(L, -3);
3751 }
Thierry FOURNIER04c57b32015-03-18 13:43:10 +01003752
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003753 /* Stores the request path. */
3754 lua_pushstring(L, "length");
3755 lua_pushinteger(L, txn->req.body_len);
3756 lua_settable(L, -3);
Thierry FOURNIER04c57b32015-03-18 13:43:10 +01003757
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003758 /* Create an array of HTTP request headers. */
3759 lua_pushstring(L, "headers");
3760 MAY_LJMP(hlua_http_get_headers(L, &appctx->htxn, &appctx->htxn.s->txn->req));
3761 lua_settable(L, -3);
Thierry FOURNIER04c57b32015-03-18 13:43:10 +01003762
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003763 /* Create an empty array of HTTP request headers. */
3764 lua_pushstring(L, "response");
3765 lua_newtable(L);
3766 lua_settable(L, -3);
Thierry FOURNIER04c57b32015-03-18 13:43:10 +01003767
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003768 /* Pop a class stream metatable and affect it to the table. */
3769 lua_rawgeti(L, LUA_REGISTRYINDEX, class_applet_http_ref);
3770 lua_setmetatable(L, -2);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003771
3772 return 1;
3773}
3774
Thierry FOURNIER / OZON.IO4394a2c2016-12-12 12:31:54 +01003775__LJMP static int hlua_applet_http_set_var(lua_State *L)
3776{
3777 struct hlua_appctx *appctx;
3778 struct stream *s;
3779 const char *name;
3780 size_t len;
3781 struct sample smp;
3782
3783 MAY_LJMP(check_args(L, 3, "set_var"));
3784
3785 /* It is useles to retrieve the stream, but this function
3786 * runs only in a stream context.
3787 */
3788 appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
3789 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3790 s = appctx->htxn.s;
3791
3792 /* Converts the third argument in a sample. */
3793 hlua_lua2smp(L, 3, &smp);
3794
3795 /* Store the sample in a variable. */
3796 smp_set_owner(&smp, s->be, s->sess, s, 0);
3797 vars_set_by_name(name, len, &smp);
3798 return 0;
3799}
3800
3801__LJMP static int hlua_applet_http_unset_var(lua_State *L)
3802{
3803 struct hlua_appctx *appctx;
3804 struct stream *s;
3805 const char *name;
3806 size_t len;
3807 struct sample smp;
3808
3809 MAY_LJMP(check_args(L, 2, "unset_var"));
3810
3811 /* It is useles to retrieve the stream, but this function
3812 * runs only in a stream context.
3813 */
3814 appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
3815 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3816 s = appctx->htxn.s;
3817
3818 /* Unset the variable. */
3819 smp_set_owner(&smp, s->be, s->sess, s, 0);
3820 vars_unset_by_name(name, len, &smp);
3821 return 0;
3822}
3823
3824__LJMP static int hlua_applet_http_get_var(lua_State *L)
3825{
3826 struct hlua_appctx *appctx;
3827 struct stream *s;
3828 const char *name;
3829 size_t len;
3830 struct sample smp;
3831
3832 MAY_LJMP(check_args(L, 2, "get_var"));
3833
3834 /* It is useles to retrieve the stream, but this function
3835 * runs only in a stream context.
3836 */
3837 appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
3838 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3839 s = appctx->htxn.s;
3840
3841 smp_set_owner(&smp, s->be, s->sess, s, 0);
3842 if (!vars_get_by_name(name, len, &smp)) {
3843 lua_pushnil(L);
3844 return 1;
3845 }
3846
3847 return hlua_smp2lua(L, &smp);
3848}
3849
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003850__LJMP static int hlua_applet_http_set_priv(lua_State *L)
3851{
3852 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
3853 struct stream *s = appctx->htxn.s;
Thierry FOURNIER3b0a6d42016-12-16 08:48:32 +01003854 struct hlua *hlua;
3855
3856 /* Note that this hlua struct is from the session and not from the applet. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01003857 if (!s->hlua)
3858 return 0;
3859 hlua = s->hlua;
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003860
3861 MAY_LJMP(check_args(L, 2, "set_priv"));
3862
3863 /* Remove previous value. */
Thierry FOURNIERe068b602017-04-26 13:27:05 +02003864 luaL_unref(L, LUA_REGISTRYINDEX, hlua->Mref);
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003865
3866 /* Get and store new value. */
3867 lua_pushvalue(L, 2); /* Copy the element 2 at the top of the stack. */
3868 hlua->Mref = luaL_ref(L, LUA_REGISTRYINDEX); /* pop the previously pushed value. */
3869
3870 return 0;
3871}
3872
3873__LJMP static int hlua_applet_http_get_priv(lua_State *L)
3874{
3875 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
3876 struct stream *s = appctx->htxn.s;
Thierry FOURNIER3b0a6d42016-12-16 08:48:32 +01003877 struct hlua *hlua;
3878
3879 /* Note that this hlua struct is from the session and not from the applet. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01003880 if (!s->hlua) {
3881 lua_pushnil(L);
3882 return 1;
3883 }
3884 hlua = s->hlua;
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003885
3886 /* Push configuration index in the stack. */
3887 lua_rawgeti(L, LUA_REGISTRYINDEX, hlua->Mref);
3888
3889 return 1;
3890}
3891
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003892/* If expected data not yet available, it returns a yield. This function
3893 * consumes the data in the buffer. It returns a string containing the
3894 * data. This string can be empty.
3895 */
3896__LJMP static int hlua_applet_http_getline_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003897{
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003898 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
3899 struct stream_interface *si = appctx->appctx->owner;
3900 struct channel *chn = si_ic(si);
3901 int ret;
3902 char *blk1;
3903 int len1;
3904 char *blk2;
3905 int len2;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003906
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003907 /* Maybe we cant send a 100-continue ? */
3908 if (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_100C) {
Willy Tarreau06d80a92017-10-19 14:32:15 +02003909 ret = ci_putblk(chn, HTTP_100C, strlen(HTTP_100C));
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003910 /* if ret == -2 or -3 the channel closed or the message si too
3911 * big for the buffers. We cant send anything. So, we ignoring
3912 * the error, considers that the 100-continue is sent, and try
3913 * to receive.
3914 * If ret is -1, we dont have room in the buffer, so we yield.
3915 */
3916 if (ret == -1) {
3917 si_applet_cant_put(si);
3918 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_getline_yield, TICK_ETERNITY, 0));
3919 }
3920 appctx->appctx->ctx.hlua_apphttp.flags &= ~APPLET_100C;
3921 }
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003922
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003923 /* Check for the end of the data. */
3924 if (appctx->appctx->ctx.hlua_apphttp.left_bytes <= 0) {
3925 luaL_pushresult(&appctx->b);
3926 return 1;
3927 }
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003928
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003929 /* Read the maximum amount of data avalaible. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02003930 ret = co_getline_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003931
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003932 /* Data not yet avalaible. return yield. */
3933 if (ret == 0) {
3934 si_applet_cant_get(si);
3935 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_getline_yield, TICK_ETERNITY, 0));
3936 }
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003937
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003938 /* End of data: commit the total strings and return. */
3939 if (ret < 0) {
3940 luaL_pushresult(&appctx->b);
3941 return 1;
3942 }
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003943
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003944 /* Ensure that the block 2 length is usable. */
3945 if (ret == 1)
3946 len2 = 0;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003947
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003948 /* Copy the fisrt block caping to the length required. */
3949 if (len1 > appctx->appctx->ctx.hlua_apphttp.left_bytes)
3950 len1 = appctx->appctx->ctx.hlua_apphttp.left_bytes;
3951 luaL_addlstring(&appctx->b, blk1, len1);
3952 appctx->appctx->ctx.hlua_apphttp.left_bytes -= len1;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003953
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003954 /* Copy the second block. */
3955 if (len2 > appctx->appctx->ctx.hlua_apphttp.left_bytes)
3956 len2 = appctx->appctx->ctx.hlua_apphttp.left_bytes;
3957 luaL_addlstring(&appctx->b, blk2, len2);
3958 appctx->appctx->ctx.hlua_apphttp.left_bytes -= len2;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003959
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003960 /* Consume input channel output buffer data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02003961 co_skip(si_oc(si), len1 + len2);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003962 luaL_pushresult(&appctx->b);
3963 return 1;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003964}
3965
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003966/* Check arguments for the fucntion "hlua_channel_get_yield". */
3967__LJMP static int hlua_applet_http_getline(lua_State *L)
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003968{
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003969 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003970
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003971 /* Initialise the string catenation. */
3972 luaL_buffinit(L, &appctx->b);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003973
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003974 return MAY_LJMP(hlua_applet_http_getline_yield(L, 0, 0));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003975}
3976
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003977/* If expected data not yet available, it returns a yield. This function
3978 * consumes the data in the buffer. It returns a string containing the
3979 * data. This string can be empty.
3980 */
3981__LJMP static int hlua_applet_http_recv_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003982{
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003983 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
3984 struct stream_interface *si = appctx->appctx->owner;
3985 int len = MAY_LJMP(luaL_checkinteger(L, 2));
3986 struct channel *chn = si_ic(si);
3987 int ret;
3988 char *blk1;
3989 int len1;
3990 char *blk2;
3991 int len2;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003992
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003993 /* Maybe we cant send a 100-continue ? */
3994 if (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_100C) {
Willy Tarreau06d80a92017-10-19 14:32:15 +02003995 ret = ci_putblk(chn, HTTP_100C, strlen(HTTP_100C));
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003996 /* if ret == -2 or -3 the channel closed or the message si too
3997 * big for the buffers. We cant send anything. So, we ignoring
3998 * the error, considers that the 100-continue is sent, and try
3999 * to receive.
4000 * If ret is -1, we dont have room in the buffer, so we yield.
4001 */
4002 if (ret == -1) {
4003 si_applet_cant_put(si);
4004 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_recv_yield, TICK_ETERNITY, 0));
4005 }
4006 appctx->appctx->ctx.hlua_apphttp.flags &= ~APPLET_100C;
4007 }
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004008
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004009 /* Read the maximum amount of data avalaible. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02004010 ret = co_getblk_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004011
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004012 /* Data not yet avalaible. return yield. */
4013 if (ret == 0) {
4014 si_applet_cant_get(si);
4015 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_recv_yield, TICK_ETERNITY, 0));
4016 }
4017
4018 /* End of data: commit the total strings and return. */
4019 if (ret < 0) {
4020 luaL_pushresult(&appctx->b);
4021 return 1;
4022 }
4023
4024 /* Ensure that the block 2 length is usable. */
4025 if (ret == 1)
4026 len2 = 0;
4027
4028 /* Copy the fisrt block caping to the length required. */
4029 if (len1 > len)
4030 len1 = len;
4031 luaL_addlstring(&appctx->b, blk1, len1);
4032 len -= len1;
4033
4034 /* Copy the second block. */
4035 if (len2 > len)
4036 len2 = len;
4037 luaL_addlstring(&appctx->b, blk2, len2);
4038 len -= len2;
4039
4040 /* Consume input channel output buffer data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02004041 co_skip(si_oc(si), len1 + len2);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004042 if (appctx->appctx->ctx.hlua_apphttp.left_bytes != -1)
4043 appctx->appctx->ctx.hlua_apphttp.left_bytes -= len;
4044
4045 /* If we are no other data avalaible, yield waiting for new data. */
4046 if (len > 0) {
4047 lua_pushinteger(L, len);
4048 lua_replace(L, 2);
4049 si_applet_cant_get(si);
4050 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_recv_yield, TICK_ETERNITY, 0));
4051 }
4052
4053 /* return the result. */
4054 luaL_pushresult(&appctx->b);
4055 return 1;
4056}
4057
4058/* Check arguments for the fucntion "hlua_channel_get_yield". */
4059__LJMP static int hlua_applet_http_recv(lua_State *L)
4060{
4061 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4062 int len = -1;
4063
4064 /* Check arguments. */
4065 if (lua_gettop(L) > 2)
4066 WILL_LJMP(luaL_error(L, "The 'recv' function requires between 1 and 2 arguments."));
4067 if (lua_gettop(L) >= 2) {
4068 len = MAY_LJMP(luaL_checkinteger(L, 2));
4069 lua_pop(L, 1);
4070 }
4071
4072 /* Check the required length */
4073 if (len == -1 || len > appctx->appctx->ctx.hlua_apphttp.left_bytes)
4074 len = appctx->appctx->ctx.hlua_apphttp.left_bytes;
4075 lua_pushinteger(L, len);
4076
4077 /* Initialise the string catenation. */
4078 luaL_buffinit(L, &appctx->b);
4079
4080 return MAY_LJMP(hlua_applet_http_recv_yield(L, 0, 0));
4081}
4082
4083/* Append data in the output side of the buffer. This data is immediatly
4084 * sent. The fcuntion returns the ammount of data writed. If the buffer
4085 * cannot contains the data, the function yield. The function returns -1
4086 * if the channel is closed.
4087 */
4088__LJMP static int hlua_applet_http_send_yield(lua_State *L, int status, lua_KContext ctx)
4089{
4090 size_t len;
4091 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4092 const char *str = MAY_LJMP(luaL_checklstring(L, 2, &len));
4093 int l = MAY_LJMP(luaL_checkinteger(L, 3));
4094 struct stream_interface *si = appctx->appctx->owner;
4095 struct channel *chn = si_ic(si);
4096 int max;
4097
4098 /* Get the max amount of data which can write as input in the channel. */
4099 max = channel_recv_max(chn);
4100 if (max > (len - l))
4101 max = len - l;
4102
4103 /* Copy data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02004104 ci_putblk(chn, str + l, max);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004105
4106 /* update counters. */
4107 l += max;
4108 lua_pop(L, 1);
4109 lua_pushinteger(L, l);
4110
4111 /* If some data is not send, declares the situation to the
4112 * applet, and returns a yield.
4113 */
4114 if (l < len) {
4115 si_applet_cant_put(si);
4116 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_send_yield, TICK_ETERNITY, 0));
4117 }
4118
4119 return 1;
4120}
4121
4122/* Just a wraper of "hlua_applet_send_yield". This wrapper permits
4123 * yield the LUA process, and resume it without checking the
4124 * input arguments.
4125 */
4126__LJMP static int hlua_applet_http_send(lua_State *L)
4127{
4128 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4129 size_t len;
4130 char hex[10];
4131
4132 MAY_LJMP(luaL_checklstring(L, 2, &len));
4133
4134 /* If transfer encoding chunked is selected, we surround the data
4135 * by chunk data.
4136 */
4137 if (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_CHUNKED) {
4138 snprintf(hex, 9, "%x", (unsigned int)len);
4139 lua_pushfstring(L, "%s\r\n", hex);
4140 lua_insert(L, 2); /* swap the last 2 entries. */
4141 lua_pushstring(L, "\r\n");
4142 lua_concat(L, 3);
4143 }
4144
4145 /* This interger is used for followinf the amount of data sent. */
4146 lua_pushinteger(L, 0);
4147
4148 /* We want to send some data. Headers must be sent. */
4149 if (!(appctx->appctx->ctx.hlua_apphttp.flags & APPLET_HDR_SENT)) {
4150 hlua_pusherror(L, "Lua: 'send' you must call start_response() before sending data.");
4151 WILL_LJMP(lua_error(L));
4152 }
4153
4154 return MAY_LJMP(hlua_applet_http_send_yield(L, 0, 0));
4155}
4156
4157__LJMP static int hlua_applet_http_addheader(lua_State *L)
4158{
4159 const char *name;
4160 int ret;
4161
4162 MAY_LJMP(hlua_checkapplet_http(L, 1));
4163 name = MAY_LJMP(luaL_checkstring(L, 2));
4164 MAY_LJMP(luaL_checkstring(L, 3));
4165
4166 /* Push in the stack the "response" entry. */
4167 ret = lua_getfield(L, 1, "response");
4168 if (ret != LUA_TTABLE) {
4169 hlua_pusherror(L, "Lua: 'add_header' internal error: AppletHTTP['response'] "
4170 "is expected as an array. %s found", lua_typename(L, ret));
4171 WILL_LJMP(lua_error(L));
4172 }
4173
4174 /* check if the header is already registered if it is not
4175 * the case, register it.
4176 */
4177 ret = lua_getfield(L, -1, name);
4178 if (ret == LUA_TNIL) {
4179
4180 /* Entry not found. */
4181 lua_pop(L, 1); /* remove the nil. The "response" table is the top of the stack. */
4182
4183 /* Insert the new header name in the array in the top of the stack.
4184 * It left the new array in the top of the stack.
4185 */
4186 lua_newtable(L);
4187 lua_pushvalue(L, 2);
4188 lua_pushvalue(L, -2);
4189 lua_settable(L, -4);
4190
4191 } else if (ret != LUA_TTABLE) {
4192
4193 /* corruption error. */
4194 hlua_pusherror(L, "Lua: 'add_header' internal error: AppletHTTP['response']['%s'] "
4195 "is expected as an array. %s found", name, lua_typename(L, ret));
4196 WILL_LJMP(lua_error(L));
4197 }
4198
4199 /* Now the top od thestack is an array of values. We push
4200 * the header value as new entry.
4201 */
4202 lua_pushvalue(L, 3);
4203 ret = lua_rawlen(L, -2);
4204 lua_rawseti(L, -2, ret + 1);
4205 lua_pushboolean(L, 1);
4206 return 1;
4207}
4208
4209__LJMP static int hlua_applet_http_status(lua_State *L)
4210{
4211 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4212 int status = MAY_LJMP(luaL_checkinteger(L, 2));
Robin H. Johnson52f5db22017-01-01 13:10:52 -08004213 const char *reason = MAY_LJMP(luaL_optlstring(L, 3, NULL, NULL));
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004214
4215 if (status < 100 || status > 599) {
4216 lua_pushboolean(L, 0);
4217 return 1;
4218 }
4219
4220 appctx->appctx->ctx.hlua_apphttp.status = status;
Robin H. Johnson52f5db22017-01-01 13:10:52 -08004221 appctx->appctx->ctx.hlua_apphttp.reason = reason;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004222 lua_pushboolean(L, 1);
4223 return 1;
4224}
4225
4226/* We will build the status line and the headers of the HTTP response.
4227 * We will try send at once if its not possible, we give back the hand
4228 * waiting for more room.
4229 */
4230__LJMP static int hlua_applet_http_start_response_yield(lua_State *L, int status, lua_KContext ctx)
4231{
4232 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4233 struct stream_interface *si = appctx->appctx->owner;
4234 struct channel *chn = si_ic(si);
4235 int ret;
4236 size_t len;
4237 const char *msg;
4238
4239 /* Get the message as the first argument on the stack. */
4240 msg = MAY_LJMP(luaL_checklstring(L, 2, &len));
4241
4242 /* Send the message at once. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02004243 ret = ci_putblk(chn, msg, len);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004244
4245 /* if ret == -2 or -3 the channel closed or the message si too
4246 * big for the buffers.
4247 */
4248 if (ret == -2 || ret == -3) {
4249 hlua_pusherror(L, "Lua: 'start_response': response header block too big");
4250 WILL_LJMP(lua_error(L));
4251 }
4252
4253 /* If ret is -1, we dont have room in the buffer, so we yield. */
4254 if (ret == -1) {
4255 si_applet_cant_put(si);
4256 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_start_response_yield, TICK_ETERNITY, 0));
4257 }
4258
4259 /* Headers sent, set the flag. */
4260 appctx->appctx->ctx.hlua_apphttp.flags |= APPLET_HDR_SENT;
4261 return 0;
4262}
4263
4264__LJMP static int hlua_applet_http_start_response(lua_State *L)
4265{
4266 struct chunk *tmp = get_trash_chunk();
4267 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004268 const char *name;
Willy Tarreaua3294632017-08-23 11:24:47 +02004269 size_t name_len;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004270 const char *value;
Willy Tarreaua3294632017-08-23 11:24:47 +02004271 size_t value_len;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004272 int id;
Willy Tarreauc9f4ea02017-08-23 09:32:06 +02004273 long long hdr_contentlength = -1;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004274 int hdr_chunked = 0;
Robin H. Johnson52f5db22017-01-01 13:10:52 -08004275 const char *reason = appctx->appctx->ctx.hlua_apphttp.reason;
4276
4277 if (reason == NULL)
4278 reason = get_reason(appctx->appctx->ctx.hlua_apphttp.status);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004279
4280 /* Use the same http version than the request. */
4281 chunk_appendf(tmp, "HTTP/1.%c %d %s\r\n",
Thierry FOURNIERd93ea2b2015-12-20 19:14:52 +01004282 appctx->appctx->ctx.hlua_apphttp.flags & APPLET_HTTP11 ? '1' : '0',
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004283 appctx->appctx->ctx.hlua_apphttp.status,
Robin H. Johnson52f5db22017-01-01 13:10:52 -08004284 reason);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004285
4286 /* Get the array associated to the field "response" in the object AppletHTTP. */
4287 lua_pushvalue(L, 0);
4288 if (lua_getfield(L, 1, "response") != LUA_TTABLE) {
4289 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response'] missing.\n",
4290 appctx->appctx->rule->arg.hlua_rule->fcn.name);
4291 WILL_LJMP(lua_error(L));
4292 }
4293
4294 /* Browse the list of headers. */
4295 lua_pushnil(L);
4296 while(lua_next(L, -2) != 0) {
4297
4298 /* We expect a string as -2. */
4299 if (lua_type(L, -2) != LUA_TSTRING) {
4300 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response'][] element must be a string. got %s.\n",
4301 appctx->appctx->rule->arg.hlua_rule->fcn.name,
4302 lua_typename(L, lua_type(L, -2)));
4303 WILL_LJMP(lua_error(L));
4304 }
Willy Tarreaua3294632017-08-23 11:24:47 +02004305 name = lua_tolstring(L, -2, &name_len);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004306
4307 /* We expect an array as -1. */
4308 if (lua_type(L, -1) != LUA_TTABLE) {
4309 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response']['%s'] element must be an table. got %s.\n",
4310 appctx->appctx->rule->arg.hlua_rule->fcn.name,
4311 name,
4312 lua_typename(L, lua_type(L, -1)));
4313 WILL_LJMP(lua_error(L));
4314 }
4315
4316 /* Browse the table who is on the top of the stack. */
4317 lua_pushnil(L);
4318 while(lua_next(L, -2) != 0) {
4319
4320 /* We expect a number as -2. */
4321 if (lua_type(L, -2) != LUA_TNUMBER) {
4322 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response']['%s'][] element must be a number. got %s.\n",
4323 appctx->appctx->rule->arg.hlua_rule->fcn.name,
4324 name,
4325 lua_typename(L, lua_type(L, -2)));
4326 WILL_LJMP(lua_error(L));
4327 }
4328 id = lua_tointeger(L, -2);
4329
4330 /* We expect a string as -2. */
4331 if (lua_type(L, -1) != LUA_TSTRING) {
4332 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response']['%s'][%d] element must be a string. got %s.\n",
4333 appctx->appctx->rule->arg.hlua_rule->fcn.name,
4334 name, id,
4335 lua_typename(L, lua_type(L, -1)));
4336 WILL_LJMP(lua_error(L));
4337 }
Willy Tarreaua3294632017-08-23 11:24:47 +02004338 value = lua_tolstring(L, -1, &value_len);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004339
4340 /* Catenate a new header. */
Willy Tarreaua3294632017-08-23 11:24:47 +02004341 if (tmp->len + name_len + 2 + value_len + 2 < tmp->size) {
4342 memcpy(tmp->str + tmp->len, name, name_len);
4343 tmp->len += name_len;
4344 tmp->str[tmp->len++] = ':';
4345 tmp->str[tmp->len++] = ' ';
4346
4347 memcpy(tmp->str + tmp->len, value, value_len);
4348 tmp->len += value_len;
4349 tmp->str[tmp->len++] = '\r';
4350 tmp->str[tmp->len++] = '\n';
4351 }
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004352
4353 /* Protocol checks. */
4354
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004355 /* Copy the header content length. The length conversion
Willy Tarreauc9f4ea02017-08-23 09:32:06 +02004356 * is done without control. If it contains a bad value,
4357 * the content-length remains negative so that we can
4358 * switch to either chunked encoding or close.
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004359 */
Willy Tarreaua3294632017-08-23 11:24:47 +02004360 if (name_len == 14 && strcasecmp("content-length", name) == 0)
Willy Tarreauc9f4ea02017-08-23 09:32:06 +02004361 strl2llrc(value, strlen(value), &hdr_contentlength);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004362
4363 /* Check if the client annouces a transfer-encoding chunked it self. */
Willy Tarreaua3294632017-08-23 11:24:47 +02004364 if (name_len == 17 && value_len == 7 &&
4365 strcasecmp("transfer-encoding", name) == 0 &&
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004366 strcasecmp("chunked", value) == 0)
4367 hdr_chunked = 1;
4368
4369 /* Remove the array from the stack, and get next element with a remaining string. */
4370 lua_pop(L, 1);
4371 }
4372
4373 /* Remove the array from the stack, and get next element with a remaining string. */
4374 lua_pop(L, 1);
4375 }
4376
Willy Tarreau06c75fe2017-08-23 09:10:38 +02004377 /* If we dont have a content-length set, and the HTTP version is 1.1
4378 * and the status code implies the presence of a message body, we must
4379 * announce a transfer encoding chunked. This is required by haproxy
4380 * for the keepalive compliance. If the applet annouces a transfer-encoding
4381 * chunked itslef, don't do anything.
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004382 */
Willy Tarreauc9f4ea02017-08-23 09:32:06 +02004383 if (hdr_contentlength < 0 && hdr_chunked == 0 &&
Willy Tarreau06c75fe2017-08-23 09:10:38 +02004384 (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_HTTP11) &&
4385 appctx->appctx->ctx.hlua_apphttp.status >= 200 &&
4386 appctx->appctx->ctx.hlua_apphttp.status != 204 &&
4387 appctx->appctx->ctx.hlua_apphttp.status != 304) {
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004388 chunk_appendf(tmp, "Transfer-encoding: chunked\r\n");
4389 appctx->appctx->ctx.hlua_apphttp.flags |= APPLET_CHUNKED;
4390 }
4391
4392 /* Finalize headers. */
4393 chunk_appendf(tmp, "\r\n");
4394
4395 /* Remove the last entry and the array of headers */
4396 lua_pop(L, 2);
4397
4398 /* Push the headers block. */
4399 lua_pushlstring(L, tmp->str, tmp->len);
4400
4401 return MAY_LJMP(hlua_applet_http_start_response_yield(L, 0, 0));
4402}
4403
4404/*
4405 *
4406 *
4407 * Class HTTP
4408 *
4409 *
4410 */
4411
4412/* Returns a struct hlua_txn if the stack entry "ud" is
4413 * a class stream, otherwise it throws an error.
4414 */
4415__LJMP static struct hlua_txn *hlua_checkhttp(lua_State *L, int ud)
4416{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004417 return MAY_LJMP(hlua_checkudata(L, ud, class_http_ref));
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004418}
4419
4420/* This function creates and push in the stack a HTTP object
4421 * according with a current TXN.
4422 */
4423static int hlua_http_new(lua_State *L, struct hlua_txn *txn)
4424{
4425 struct hlua_txn *htxn;
4426
4427 /* Check stack size. */
4428 if (!lua_checkstack(L, 3))
4429 return 0;
4430
4431 /* Create the object: obj[0] = userdata.
4432 * Note that the base of the Converters object is the
4433 * same than the TXN object.
4434 */
4435 lua_newtable(L);
4436 htxn = lua_newuserdata(L, sizeof(*htxn));
4437 lua_rawseti(L, -2, 0);
4438
4439 htxn->s = txn->s;
4440 htxn->p = txn->p;
4441
4442 /* Pop a class stream metatable and affect it to the table. */
4443 lua_rawgeti(L, LUA_REGISTRYINDEX, class_http_ref);
4444 lua_setmetatable(L, -2);
4445
4446 return 1;
4447}
4448
4449/* This function creates ans returns an array of HTTP headers.
4450 * This function does not fails. It is used as wrapper with the
4451 * 2 following functions.
4452 */
4453__LJMP static int hlua_http_get_headers(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg)
4454{
4455 const char *cur_ptr, *cur_next, *p;
4456 int old_idx, cur_idx;
4457 struct hdr_idx_elem *cur_hdr;
4458 const char *hn, *hv;
4459 int hnl, hvl;
4460 int type;
4461 const char *in;
4462 char *out;
4463 int len;
4464
4465 /* Create the table. */
4466 lua_newtable(L);
4467
4468 if (!htxn->s->txn)
4469 return 1;
4470
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004471 /* Check if a valid response is parsed */
4472 if (unlikely(msg->msg_state < HTTP_MSG_BODY))
4473 return 1;
4474
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004475 /* Build array of headers. */
4476 old_idx = 0;
4477 cur_next = msg->chn->buf->p + hdr_idx_first_pos(&htxn->s->txn->hdr_idx);
4478
4479 while (1) {
4480 cur_idx = htxn->s->txn->hdr_idx.v[old_idx].next;
4481 if (!cur_idx)
4482 break;
4483 old_idx = cur_idx;
4484
4485 cur_hdr = &htxn->s->txn->hdr_idx.v[cur_idx];
4486 cur_ptr = cur_next;
4487 cur_next = cur_ptr + cur_hdr->len + cur_hdr->cr + 1;
4488
4489 /* Now we have one full header at cur_ptr of len cur_hdr->len,
4490 * and the next header starts at cur_next. We'll check
4491 * this header in the list as well as against the default
4492 * rule.
4493 */
4494
4495 /* look for ': *'. */
4496 hn = cur_ptr;
4497 for (p = cur_ptr; p < cur_ptr + cur_hdr->len && *p != ':'; p++);
4498 if (p >= cur_ptr+cur_hdr->len)
4499 continue;
4500 hnl = p - hn;
4501 p++;
4502 while (p < cur_ptr+cur_hdr->len && ( *p == ' ' || *p == '\t' ))
4503 p++;
4504 if (p >= cur_ptr+cur_hdr->len)
4505 continue;
4506 hv = p;
4507 hvl = cur_ptr+cur_hdr->len-p;
4508
4509 /* Lowercase the key. Don't check the size of trash, it have
4510 * the size of one buffer and the input data contains in one
4511 * buffer.
4512 */
4513 out = trash.str;
4514 for (in=hn; in<hn+hnl; in++, out++)
4515 *out = tolower(*in);
4516 *out = '\0';
4517
4518 /* Check for existing entry:
4519 * assume that the table is on the top of the stack, and
4520 * push the key in the stack, the function lua_gettable()
4521 * perform the lookup.
4522 */
4523 lua_pushlstring(L, trash.str, hnl);
4524 lua_gettable(L, -2);
4525 type = lua_type(L, -1);
4526
4527 switch (type) {
4528 case LUA_TNIL:
4529 /* Table not found, create it. */
4530 lua_pop(L, 1); /* remove the nil value. */
4531 lua_pushlstring(L, trash.str, hnl); /* push the header name as key. */
4532 lua_newtable(L); /* create and push empty table. */
4533 lua_pushlstring(L, hv, hvl); /* push header value. */
4534 lua_rawseti(L, -2, 0); /* index header value (pop it). */
4535 lua_rawset(L, -3); /* index new table with header name (pop the values). */
4536 break;
4537
4538 case LUA_TTABLE:
4539 /* Entry found: push the value in the table. */
4540 len = lua_rawlen(L, -1);
4541 lua_pushlstring(L, hv, hvl); /* push header value. */
4542 lua_rawseti(L, -2, len+1); /* index header value (pop it). */
4543 lua_pop(L, 1); /* remove the table (it is stored in the main table). */
4544 break;
4545
4546 default:
4547 /* Other cases are errors. */
4548 hlua_pusherror(L, "internal error during the parsing of headers.");
4549 WILL_LJMP(lua_error(L));
4550 }
4551 }
4552
4553 return 1;
4554}
4555
4556__LJMP static int hlua_http_req_get_headers(lua_State *L)
4557{
4558 struct hlua_txn *htxn;
4559
4560 MAY_LJMP(check_args(L, 1, "req_get_headers"));
4561 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4562
4563 return hlua_http_get_headers(L, htxn, &htxn->s->txn->req);
4564}
4565
4566__LJMP static int hlua_http_res_get_headers(lua_State *L)
4567{
4568 struct hlua_txn *htxn;
4569
4570 MAY_LJMP(check_args(L, 1, "res_get_headers"));
4571 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4572
4573 return hlua_http_get_headers(L, htxn, &htxn->s->txn->rsp);
4574}
4575
4576/* This function replace full header, or just a value in
4577 * the request or in the response. It is a wrapper fir the
4578 * 4 following functions.
4579 */
4580__LJMP static inline int hlua_http_rep_hdr(lua_State *L, struct hlua_txn *htxn,
4581 struct http_msg *msg, int action)
4582{
4583 size_t name_len;
4584 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
4585 const char *reg = MAY_LJMP(luaL_checkstring(L, 3));
4586 const char *value = MAY_LJMP(luaL_checkstring(L, 4));
4587 struct my_regex re;
4588
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004589 /* Check if a valid response is parsed */
4590 if (unlikely(msg->msg_state < HTTP_MSG_BODY))
4591 return 0;
4592
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004593 if (!regex_comp(reg, &re, 1, 1, NULL))
4594 WILL_LJMP(luaL_argerror(L, 3, "invalid regex"));
4595
4596 http_transform_header_str(htxn->s, msg, name, name_len, value, &re, action);
4597 regex_free(&re);
4598 return 0;
4599}
4600
4601__LJMP static int hlua_http_req_rep_hdr(lua_State *L)
4602{
4603 struct hlua_txn *htxn;
4604
4605 MAY_LJMP(check_args(L, 4, "req_rep_hdr"));
4606 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4607
4608 return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->req, ACT_HTTP_REPLACE_HDR));
4609}
4610
4611__LJMP static int hlua_http_res_rep_hdr(lua_State *L)
4612{
4613 struct hlua_txn *htxn;
4614
4615 MAY_LJMP(check_args(L, 4, "res_rep_hdr"));
4616 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4617
4618 return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->rsp, ACT_HTTP_REPLACE_HDR));
4619}
4620
4621__LJMP static int hlua_http_req_rep_val(lua_State *L)
4622{
4623 struct hlua_txn *htxn;
4624
4625 MAY_LJMP(check_args(L, 4, "req_rep_hdr"));
4626 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4627
4628 return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->req, ACT_HTTP_REPLACE_VAL));
4629}
4630
4631__LJMP static int hlua_http_res_rep_val(lua_State *L)
4632{
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004633 struct hlua_txn *htxn;
4634
4635 MAY_LJMP(check_args(L, 4, "res_rep_val"));
4636 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4637
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02004638 return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->rsp, ACT_HTTP_REPLACE_VAL));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004639}
4640
4641/* This function deletes all the occurences of an header.
4642 * It is a wrapper for the 2 following functions.
4643 */
4644__LJMP static inline int hlua_http_del_hdr(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg)
4645{
4646 size_t len;
4647 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &len));
4648 struct hdr_ctx ctx;
Willy Tarreaueee5b512015-04-03 23:46:31 +02004649 struct http_txn *txn = htxn->s->txn;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004650
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004651 /* Check if a valid response is parsed */
4652 if (unlikely(msg->msg_state < HTTP_MSG_BODY))
4653 return 0;
4654
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004655 ctx.idx = 0;
4656 while (http_find_header2(name, len, msg->chn->buf->p, &txn->hdr_idx, &ctx))
4657 http_remove_header2(msg, &txn->hdr_idx, &ctx);
4658 return 0;
4659}
4660
4661__LJMP static int hlua_http_req_del_hdr(lua_State *L)
4662{
4663 struct hlua_txn *htxn;
4664
4665 MAY_LJMP(check_args(L, 2, "req_del_hdr"));
4666 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4667
Willy Tarreaueee5b512015-04-03 23:46:31 +02004668 return hlua_http_del_hdr(L, htxn, &htxn->s->txn->req);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004669}
4670
4671__LJMP static int hlua_http_res_del_hdr(lua_State *L)
4672{
4673 struct hlua_txn *htxn;
4674
4675 MAY_LJMP(check_args(L, 2, "req_del_hdr"));
4676 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4677
Willy Tarreaueee5b512015-04-03 23:46:31 +02004678 return hlua_http_del_hdr(L, htxn, &htxn->s->txn->rsp);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004679}
4680
4681/* This function adds an header. It is a wrapper used by
4682 * the 2 following functions.
4683 */
4684__LJMP static inline int hlua_http_add_hdr(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg)
4685{
4686 size_t name_len;
4687 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
4688 size_t value_len;
4689 const char *value = MAY_LJMP(luaL_checklstring(L, 3, &value_len));
4690 char *p;
4691
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004692 /* Check if a valid message is parsed */
4693 if (unlikely(msg->msg_state < HTTP_MSG_BODY))
4694 return 0;
4695
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004696 /* Check length. */
4697 trash.len = value_len + name_len + 2;
4698 if (trash.len > trash.size)
4699 return 0;
4700
4701 /* Creates the header string. */
4702 p = trash.str;
4703 memcpy(p, name, name_len);
4704 p += name_len;
4705 *p = ':';
4706 p++;
4707 *p = ' ';
4708 p++;
4709 memcpy(p, value, value_len);
4710
Willy Tarreaueee5b512015-04-03 23:46:31 +02004711 lua_pushboolean(L, http_header_add_tail2(msg, &htxn->s->txn->hdr_idx,
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004712 trash.str, trash.len) != 0);
4713
4714 return 0;
4715}
4716
4717__LJMP static int hlua_http_req_add_hdr(lua_State *L)
4718{
4719 struct hlua_txn *htxn;
4720
4721 MAY_LJMP(check_args(L, 3, "req_add_hdr"));
4722 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4723
Willy Tarreaueee5b512015-04-03 23:46:31 +02004724 return hlua_http_add_hdr(L, htxn, &htxn->s->txn->req);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004725}
4726
4727__LJMP static int hlua_http_res_add_hdr(lua_State *L)
4728{
4729 struct hlua_txn *htxn;
4730
4731 MAY_LJMP(check_args(L, 3, "res_add_hdr"));
4732 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4733
Willy Tarreaueee5b512015-04-03 23:46:31 +02004734 return hlua_http_add_hdr(L, htxn, &htxn->s->txn->rsp);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004735}
4736
4737static int hlua_http_req_set_hdr(lua_State *L)
4738{
4739 struct hlua_txn *htxn;
4740
4741 MAY_LJMP(check_args(L, 3, "req_set_hdr"));
4742 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4743
Willy Tarreaueee5b512015-04-03 23:46:31 +02004744 hlua_http_del_hdr(L, htxn, &htxn->s->txn->req);
4745 return hlua_http_add_hdr(L, htxn, &htxn->s->txn->req);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004746}
4747
4748static int hlua_http_res_set_hdr(lua_State *L)
4749{
4750 struct hlua_txn *htxn;
4751
4752 MAY_LJMP(check_args(L, 3, "res_set_hdr"));
4753 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4754
Willy Tarreaueee5b512015-04-03 23:46:31 +02004755 hlua_http_del_hdr(L, htxn, &htxn->s->txn->rsp);
4756 return hlua_http_add_hdr(L, htxn, &htxn->s->txn->rsp);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004757}
4758
4759/* This function set the method. */
4760static int hlua_http_req_set_meth(lua_State *L)
4761{
Willy Tarreaubcb39cc2015-04-06 11:21:44 +02004762 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004763 size_t name_len;
4764 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004765
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004766 /* Check if a valid request is parsed */
4767 if (unlikely(htxn->s->txn->req.msg_state < HTTP_MSG_BODY)) {
4768 lua_pushboolean(L, 0);
4769 return 1;
4770 }
4771
Willy Tarreau987e3fb2015-04-04 01:09:08 +02004772 lua_pushboolean(L, http_replace_req_line(0, name, name_len, htxn->p, htxn->s) != -1);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004773 return 1;
4774}
4775
4776/* This function set the method. */
4777static int hlua_http_req_set_path(lua_State *L)
4778{
Willy Tarreaubcb39cc2015-04-06 11:21:44 +02004779 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004780 size_t name_len;
4781 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004782
4783 /* Check if a valid request is parsed */
4784 if (unlikely(htxn->s->txn->req.msg_state < HTTP_MSG_BODY)) {
4785 lua_pushboolean(L, 0);
4786 return 1;
4787 }
4788
Willy Tarreau987e3fb2015-04-04 01:09:08 +02004789 lua_pushboolean(L, http_replace_req_line(1, name, name_len, htxn->p, htxn->s) != -1);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004790 return 1;
4791}
4792
4793/* This function set the query-string. */
4794static int hlua_http_req_set_query(lua_State *L)
4795{
Willy Tarreaubcb39cc2015-04-06 11:21:44 +02004796 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004797 size_t name_len;
4798 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004799
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004800 /* Check if a valid request is parsed */
4801 if (unlikely(htxn->s->txn->req.msg_state < HTTP_MSG_BODY)) {
4802 lua_pushboolean(L, 0);
4803 return 1;
4804 }
4805
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004806 /* Check length. */
4807 if (name_len > trash.size - 1) {
4808 lua_pushboolean(L, 0);
4809 return 1;
4810 }
4811
4812 /* Add the mark question as prefix. */
4813 chunk_reset(&trash);
4814 trash.str[trash.len++] = '?';
4815 memcpy(trash.str + trash.len, name, name_len);
4816 trash.len += name_len;
4817
Willy Tarreau987e3fb2015-04-04 01:09:08 +02004818 lua_pushboolean(L, http_replace_req_line(2, trash.str, trash.len, htxn->p, htxn->s) != -1);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004819 return 1;
4820}
4821
4822/* This function set the uri. */
4823static int hlua_http_req_set_uri(lua_State *L)
4824{
Willy Tarreaubcb39cc2015-04-06 11:21:44 +02004825 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004826 size_t name_len;
4827 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004828
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004829 /* Check if a valid request is parsed */
4830 if (unlikely(htxn->s->txn->req.msg_state < HTTP_MSG_BODY)) {
4831 lua_pushboolean(L, 0);
4832 return 1;
4833 }
4834
Willy Tarreau987e3fb2015-04-04 01:09:08 +02004835 lua_pushboolean(L, http_replace_req_line(3, name, name_len, htxn->p, htxn->s) != -1);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004836 return 1;
4837}
4838
Robin H. Johnson52f5db22017-01-01 13:10:52 -08004839/* This function set the response code & optionally reason. */
Thierry FOURNIER35d70ef2015-08-26 16:21:56 +02004840static int hlua_http_res_set_status(lua_State *L)
4841{
4842 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4843 unsigned int code = MAY_LJMP(luaL_checkinteger(L, 2));
Robin H. Johnson52f5db22017-01-01 13:10:52 -08004844 const char *reason = MAY_LJMP(luaL_optlstring(L, 3, NULL, NULL));
Thierry FOURNIER35d70ef2015-08-26 16:21:56 +02004845
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004846 /* Check if a valid response is parsed */
4847 if (unlikely(htxn->s->txn->rsp.msg_state < HTTP_MSG_BODY))
4848 return 0;
4849
Robin H. Johnson52f5db22017-01-01 13:10:52 -08004850 http_set_status(code, reason, htxn->s);
Thierry FOURNIER35d70ef2015-08-26 16:21:56 +02004851 return 0;
4852}
4853
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004854/*
4855 *
4856 *
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01004857 * Class TXN
4858 *
4859 *
4860 */
4861
4862/* Returns a struct hlua_session if the stack entry "ud" is
Willy Tarreau87b09662015-04-03 00:22:06 +02004863 * a class stream, otherwise it throws an error.
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01004864 */
4865__LJMP static struct hlua_txn *hlua_checktxn(lua_State *L, int ud)
4866{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004867 return MAY_LJMP(hlua_checkudata(L, ud, class_txn_ref));
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01004868}
4869
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +02004870__LJMP static int hlua_set_var(lua_State *L)
4871{
4872 struct hlua_txn *htxn;
4873 const char *name;
4874 size_t len;
4875 struct sample smp;
4876
4877 MAY_LJMP(check_args(L, 3, "set_var"));
4878
4879 /* It is useles to retrieve the stream, but this function
4880 * runs only in a stream context.
4881 */
4882 htxn = MAY_LJMP(hlua_checktxn(L, 1));
4883 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
4884
4885 /* Converts the third argument in a sample. */
4886 hlua_lua2smp(L, 3, &smp);
4887
4888 /* Store the sample in a variable. */
Willy Tarreau7560dd42016-03-10 16:28:58 +01004889 smp_set_owner(&smp, htxn->p, htxn->s->sess, htxn->s, htxn->dir & SMP_OPT_DIR);
Willy Tarreau6204cd92016-03-10 16:33:04 +01004890 vars_set_by_name(name, len, &smp);
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +02004891 return 0;
4892}
4893
Christopher Faulet85d79c92016-11-09 16:54:56 +01004894__LJMP static int hlua_unset_var(lua_State *L)
4895{
4896 struct hlua_txn *htxn;
4897 const char *name;
4898 size_t len;
4899 struct sample smp;
4900
4901 MAY_LJMP(check_args(L, 2, "unset_var"));
4902
4903 /* It is useles to retrieve the stream, but this function
4904 * runs only in a stream context.
4905 */
4906 htxn = MAY_LJMP(hlua_checktxn(L, 1));
4907 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
4908
4909 /* Unset the variable. */
4910 smp_set_owner(&smp, htxn->p, htxn->s->sess, htxn->s, htxn->dir & SMP_OPT_DIR);
4911 vars_unset_by_name(name, len, &smp);
4912 return 0;
4913}
4914
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +02004915__LJMP static int hlua_get_var(lua_State *L)
4916{
4917 struct hlua_txn *htxn;
4918 const char *name;
4919 size_t len;
4920 struct sample smp;
4921
4922 MAY_LJMP(check_args(L, 2, "get_var"));
4923
4924 /* It is useles to retrieve the stream, but this function
4925 * runs only in a stream context.
4926 */
4927 htxn = MAY_LJMP(hlua_checktxn(L, 1));
4928 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
4929
Willy Tarreau7560dd42016-03-10 16:28:58 +01004930 smp_set_owner(&smp, htxn->p, htxn->s->sess, htxn->s, htxn->dir & SMP_OPT_DIR);
Willy Tarreau6204cd92016-03-10 16:33:04 +01004931 if (!vars_get_by_name(name, len, &smp)) {
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +02004932 lua_pushnil(L);
4933 return 1;
4934 }
4935
4936 return hlua_smp2lua(L, &smp);
4937}
4938
Willy Tarreau59551662015-03-10 14:23:13 +01004939__LJMP static int hlua_set_priv(lua_State *L)
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01004940{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01004941 struct hlua *hlua;
4942
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01004943 MAY_LJMP(check_args(L, 2, "set_priv"));
4944
Willy Tarreau87b09662015-04-03 00:22:06 +02004945 /* It is useles to retrieve the stream, but this function
4946 * runs only in a stream context.
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01004947 */
4948 MAY_LJMP(hlua_checktxn(L, 1));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01004949 hlua = hlua_gethlua(L);
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01004950
4951 /* Remove previous value. */
Thierry FOURNIERe068b602017-04-26 13:27:05 +02004952 luaL_unref(L, LUA_REGISTRYINDEX, hlua->Mref);
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01004953
4954 /* Get and store new value. */
4955 lua_pushvalue(L, 2); /* Copy the element 2 at the top of the stack. */
4956 hlua->Mref = luaL_ref(L, LUA_REGISTRYINDEX); /* pop the previously pushed value. */
4957
4958 return 0;
4959}
4960
Willy Tarreau59551662015-03-10 14:23:13 +01004961__LJMP static int hlua_get_priv(lua_State *L)
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01004962{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01004963 struct hlua *hlua;
4964
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01004965 MAY_LJMP(check_args(L, 1, "get_priv"));
4966
Willy Tarreau87b09662015-04-03 00:22:06 +02004967 /* It is useles to retrieve the stream, but this function
4968 * runs only in a stream context.
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01004969 */
4970 MAY_LJMP(hlua_checktxn(L, 1));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01004971 hlua = hlua_gethlua(L);
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01004972
4973 /* Push configuration index in the stack. */
4974 lua_rawgeti(L, LUA_REGISTRYINDEX, hlua->Mref);
4975
4976 return 1;
4977}
4978
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01004979/* Create stack entry containing a class TXN. This function
4980 * return 0 if the stack does not contains free slots,
4981 * otherwise it returns 1.
4982 */
Thierry FOURNIERab00df62016-07-14 11:42:37 +02004983static int hlua_txn_new(lua_State *L, struct stream *s, struct proxy *p, int dir, int flags)
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01004984{
Willy Tarreaude491382015-04-06 11:04:28 +02004985 struct hlua_txn *htxn;
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01004986
4987 /* Check stack size. */
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01004988 if (!lua_checkstack(L, 3))
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01004989 return 0;
4990
4991 /* NOTE: The allocation never fails. The failure
4992 * throw an error, and the function never returns.
4993 * if the throw is not avalaible, the process is aborted.
4994 */
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01004995 /* Create the object: obj[0] = userdata. */
4996 lua_newtable(L);
Willy Tarreaude491382015-04-06 11:04:28 +02004997 htxn = lua_newuserdata(L, sizeof(*htxn));
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01004998 lua_rawseti(L, -2, 0);
4999
Willy Tarreaude491382015-04-06 11:04:28 +02005000 htxn->s = s;
5001 htxn->p = p;
Thierry FOURNIERc4eebc82015-11-02 10:01:59 +01005002 htxn->dir = dir;
Thierry FOURNIERab00df62016-07-14 11:42:37 +02005003 htxn->flags = flags;
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01005004
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01005005 /* Create the "f" field that contains a list of fetches. */
5006 lua_pushstring(L, "f");
Thierry FOURNIERca988662015-12-20 18:43:03 +01005007 if (!hlua_fetches_new(L, htxn, HLUA_F_MAY_USE_HTTP))
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01005008 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02005009 lua_rawset(L, -3);
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01005010
5011 /* Create the "sf" field that contains a list of stringsafe fetches. */
5012 lua_pushstring(L, "sf");
Thierry FOURNIERca988662015-12-20 18:43:03 +01005013 if (!hlua_fetches_new(L, htxn, HLUA_F_MAY_USE_HTTP | HLUA_F_AS_STRING))
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01005014 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02005015 lua_rawset(L, -3);
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01005016
Thierry FOURNIER594afe72015-03-10 23:58:30 +01005017 /* Create the "c" field that contains a list of converters. */
5018 lua_pushstring(L, "c");
Willy Tarreaude491382015-04-06 11:04:28 +02005019 if (!hlua_converters_new(L, htxn, 0))
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01005020 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02005021 lua_rawset(L, -3);
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01005022
5023 /* Create the "sc" field that contains a list of stringsafe converters. */
5024 lua_pushstring(L, "sc");
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01005025 if (!hlua_converters_new(L, htxn, HLUA_F_AS_STRING))
Thierry FOURNIER594afe72015-03-10 23:58:30 +01005026 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02005027 lua_rawset(L, -3);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01005028
Thierry FOURNIER397826a2015-03-11 19:39:09 +01005029 /* Create the "req" field that contains the request channel object. */
5030 lua_pushstring(L, "req");
Willy Tarreau2a71af42015-03-10 13:51:50 +01005031 if (!hlua_channel_new(L, &s->req))
Thierry FOURNIER397826a2015-03-11 19:39:09 +01005032 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02005033 lua_rawset(L, -3);
Thierry FOURNIER397826a2015-03-11 19:39:09 +01005034
5035 /* Create the "res" field that contains the response channel object. */
5036 lua_pushstring(L, "res");
Willy Tarreau2a71af42015-03-10 13:51:50 +01005037 if (!hlua_channel_new(L, &s->res))
Thierry FOURNIER397826a2015-03-11 19:39:09 +01005038 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02005039 lua_rawset(L, -3);
Thierry FOURNIER397826a2015-03-11 19:39:09 +01005040
Thierry FOURNIER08504f42015-03-16 14:17:08 +01005041 /* Creates the HTTP object is the current proxy allows http. */
5042 lua_pushstring(L, "http");
5043 if (p->mode == PR_MODE_HTTP) {
Willy Tarreaude491382015-04-06 11:04:28 +02005044 if (!hlua_http_new(L, htxn))
Thierry FOURNIER08504f42015-03-16 14:17:08 +01005045 return 0;
5046 }
5047 else
5048 lua_pushnil(L);
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02005049 lua_rawset(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01005050
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01005051 /* Pop a class sesison metatable and affect it to the userdata. */
5052 lua_rawgeti(L, LUA_REGISTRYINDEX, class_txn_ref);
5053 lua_setmetatable(L, -2);
5054
5055 return 1;
5056}
5057
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +01005058__LJMP static int hlua_txn_deflog(lua_State *L)
5059{
5060 const char *msg;
5061 struct hlua_txn *htxn;
5062
5063 MAY_LJMP(check_args(L, 2, "deflog"));
5064 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5065 msg = MAY_LJMP(luaL_checkstring(L, 2));
5066
5067 hlua_sendlog(htxn->s->be, htxn->s->logs.level, msg);
5068 return 0;
5069}
5070
5071__LJMP static int hlua_txn_log(lua_State *L)
5072{
5073 int level;
5074 const char *msg;
5075 struct hlua_txn *htxn;
5076
5077 MAY_LJMP(check_args(L, 3, "log"));
5078 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5079 level = MAY_LJMP(luaL_checkinteger(L, 2));
5080 msg = MAY_LJMP(luaL_checkstring(L, 3));
5081
5082 if (level < 0 || level >= NB_LOG_LEVELS)
5083 WILL_LJMP(luaL_argerror(L, 1, "Invalid loglevel."));
5084
5085 hlua_sendlog(htxn->s->be, level, msg);
5086 return 0;
5087}
5088
5089__LJMP static int hlua_txn_log_debug(lua_State *L)
5090{
5091 const char *msg;
5092 struct hlua_txn *htxn;
5093
5094 MAY_LJMP(check_args(L, 2, "Debug"));
5095 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5096 msg = MAY_LJMP(luaL_checkstring(L, 2));
5097 hlua_sendlog(htxn->s->be, LOG_DEBUG, msg);
5098 return 0;
5099}
5100
5101__LJMP static int hlua_txn_log_info(lua_State *L)
5102{
5103 const char *msg;
5104 struct hlua_txn *htxn;
5105
5106 MAY_LJMP(check_args(L, 2, "Info"));
5107 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5108 msg = MAY_LJMP(luaL_checkstring(L, 2));
5109 hlua_sendlog(htxn->s->be, LOG_INFO, msg);
5110 return 0;
5111}
5112
5113__LJMP static int hlua_txn_log_warning(lua_State *L)
5114{
5115 const char *msg;
5116 struct hlua_txn *htxn;
5117
5118 MAY_LJMP(check_args(L, 2, "Warning"));
5119 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5120 msg = MAY_LJMP(luaL_checkstring(L, 2));
5121 hlua_sendlog(htxn->s->be, LOG_WARNING, msg);
5122 return 0;
5123}
5124
5125__LJMP static int hlua_txn_log_alert(lua_State *L)
5126{
5127 const char *msg;
5128 struct hlua_txn *htxn;
5129
5130 MAY_LJMP(check_args(L, 2, "Alert"));
5131 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5132 msg = MAY_LJMP(luaL_checkstring(L, 2));
5133 hlua_sendlog(htxn->s->be, LOG_ALERT, msg);
5134 return 0;
5135}
5136
Thierry FOURNIER2cce3532015-03-16 12:04:16 +01005137__LJMP static int hlua_txn_set_loglevel(lua_State *L)
5138{
5139 struct hlua_txn *htxn;
5140 int ll;
5141
5142 MAY_LJMP(check_args(L, 2, "set_loglevel"));
5143 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5144 ll = MAY_LJMP(luaL_checkinteger(L, 2));
5145
5146 if (ll < 0 || ll > 7)
5147 WILL_LJMP(luaL_argerror(L, 2, "Bad log level. It must be between 0 and 7"));
5148
5149 htxn->s->logs.level = ll;
5150 return 0;
5151}
5152
5153__LJMP static int hlua_txn_set_tos(lua_State *L)
5154{
5155 struct hlua_txn *htxn;
5156 struct connection *cli_conn;
5157 int tos;
5158
5159 MAY_LJMP(check_args(L, 2, "set_tos"));
5160 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5161 tos = MAY_LJMP(luaL_checkinteger(L, 2));
5162
Willy Tarreau9ad7bd42015-04-03 19:19:59 +02005163 if ((cli_conn = objt_conn(htxn->s->sess->origin)) && conn_ctrl_ready(cli_conn))
Willy Tarreau585744b2017-08-24 14:31:19 +02005164 inet_set_tos(cli_conn->handle.fd, &cli_conn->addr.from, tos);
Thierry FOURNIER2cce3532015-03-16 12:04:16 +01005165
5166 return 0;
5167}
5168
5169__LJMP static int hlua_txn_set_mark(lua_State *L)
5170{
5171#ifdef SO_MARK
5172 struct hlua_txn *htxn;
5173 struct connection *cli_conn;
5174 int mark;
5175
5176 MAY_LJMP(check_args(L, 2, "set_mark"));
5177 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5178 mark = MAY_LJMP(luaL_checkinteger(L, 2));
5179
Willy Tarreau9ad7bd42015-04-03 19:19:59 +02005180 if ((cli_conn = objt_conn(htxn->s->sess->origin)) && conn_ctrl_ready(cli_conn))
Willy Tarreau585744b2017-08-24 14:31:19 +02005181 setsockopt(cli_conn->handle.fd, SOL_SOCKET, SO_MARK, &mark, sizeof(mark));
Thierry FOURNIER2cce3532015-03-16 12:04:16 +01005182#endif
5183 return 0;
5184}
5185
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005186/* This function is an Lua binding that send pending data
5187 * to the client, and close the stream interface.
5188 */
Thierry FOURNIER4bb375c2015-08-26 08:42:21 +02005189__LJMP static int hlua_txn_done(lua_State *L)
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005190{
Willy Tarreaub2ccb562015-04-06 11:11:15 +02005191 struct hlua_txn *htxn;
Thierry FOURNIER9bd52d42016-07-14 11:45:33 +02005192 struct hlua *hlua;
Willy Tarreau81389672015-03-10 12:03:52 +01005193 struct channel *ic, *oc;
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005194
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005195 MAY_LJMP(check_args(L, 1, "close"));
Willy Tarreaub2ccb562015-04-06 11:11:15 +02005196 htxn = MAY_LJMP(hlua_checktxn(L, 1));
Thierry FOURNIER9bd52d42016-07-14 11:45:33 +02005197 hlua = hlua_gethlua(L);
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005198
Thierry FOURNIERab00df62016-07-14 11:42:37 +02005199 /* If the flags NOTERM is set, we cannot terminate the http
5200 * session, so we just end the execution of the current
5201 * lua code.
5202 */
5203 if (htxn->flags & HLUA_TXN_NOTERM) {
5204 WILL_LJMP(hlua_done(L));
5205 return 0;
5206 }
5207
Willy Tarreaub2ccb562015-04-06 11:11:15 +02005208 ic = &htxn->s->req;
5209 oc = &htxn->s->res;
Willy Tarreau81389672015-03-10 12:03:52 +01005210
Willy Tarreau630ef452015-08-28 10:06:15 +02005211 if (htxn->s->txn) {
5212 /* HTTP mode, let's stay in sync with the stream */
5213 bi_fast_delete(ic->buf, htxn->s->txn->req.sov);
5214 htxn->s->txn->req.next -= htxn->s->txn->req.sov;
5215 htxn->s->txn->req.sov = 0;
5216 ic->analysers &= AN_REQ_HTTP_XFER_BODY;
5217 oc->analysers = AN_RES_HTTP_XFER_BODY;
5218 htxn->s->txn->req.msg_state = HTTP_MSG_CLOSED;
5219 htxn->s->txn->rsp.msg_state = HTTP_MSG_DONE;
5220
Willy Tarreau630ef452015-08-28 10:06:15 +02005221 /* Note that if we want to support keep-alive, we need
5222 * to bypass the close/shutr_now calls below, but that
5223 * may only be done if the HTTP request was already
5224 * processed and the connection header is known (ie
5225 * not during TCP rules).
5226 */
5227 }
5228
Thierry FOURNIER10ec2142015-08-24 17:23:45 +02005229 channel_auto_read(ic);
Willy Tarreau81389672015-03-10 12:03:52 +01005230 channel_abort(ic);
5231 channel_auto_close(ic);
5232 channel_erase(ic);
Thierry FOURNIER10ec2142015-08-24 17:23:45 +02005233
5234 oc->wex = tick_add_ifset(now_ms, oc->wto);
Willy Tarreau81389672015-03-10 12:03:52 +01005235 channel_auto_read(oc);
5236 channel_auto_close(oc);
5237 channel_shutr_now(oc);
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005238
Willy Tarreau0458b082015-08-28 09:40:04 +02005239 ic->analysers = 0;
Thierry FOURNIER4bb375c2015-08-26 08:42:21 +02005240
Thierry FOURNIER9bd52d42016-07-14 11:45:33 +02005241 hlua->flags |= HLUA_STOP;
Thierry FOURNIER4bb375c2015-08-26 08:42:21 +02005242 WILL_LJMP(hlua_done(L));
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +01005243 return 0;
5244}
5245
5246__LJMP static int hlua_log(lua_State *L)
5247{
5248 int level;
5249 const char *msg;
5250
5251 MAY_LJMP(check_args(L, 2, "log"));
5252 level = MAY_LJMP(luaL_checkinteger(L, 1));
5253 msg = MAY_LJMP(luaL_checkstring(L, 2));
5254
5255 if (level < 0 || level >= NB_LOG_LEVELS)
5256 WILL_LJMP(luaL_argerror(L, 1, "Invalid loglevel."));
5257
5258 hlua_sendlog(NULL, level, msg);
5259 return 0;
5260}
5261
5262__LJMP static int hlua_log_debug(lua_State *L)
5263{
5264 const char *msg;
5265
5266 MAY_LJMP(check_args(L, 1, "debug"));
5267 msg = MAY_LJMP(luaL_checkstring(L, 1));
5268 hlua_sendlog(NULL, LOG_DEBUG, msg);
5269 return 0;
5270}
5271
5272__LJMP static int hlua_log_info(lua_State *L)
5273{
5274 const char *msg;
5275
5276 MAY_LJMP(check_args(L, 1, "info"));
5277 msg = MAY_LJMP(luaL_checkstring(L, 1));
5278 hlua_sendlog(NULL, LOG_INFO, msg);
5279 return 0;
5280}
5281
5282__LJMP static int hlua_log_warning(lua_State *L)
5283{
5284 const char *msg;
5285
5286 MAY_LJMP(check_args(L, 1, "warning"));
5287 msg = MAY_LJMP(luaL_checkstring(L, 1));
5288 hlua_sendlog(NULL, LOG_WARNING, msg);
5289 return 0;
5290}
5291
5292__LJMP static int hlua_log_alert(lua_State *L)
5293{
5294 const char *msg;
5295
5296 MAY_LJMP(check_args(L, 1, "alert"));
5297 msg = MAY_LJMP(luaL_checkstring(L, 1));
5298 hlua_sendlog(NULL, LOG_ALERT, msg);
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005299 return 0;
5300}
5301
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01005302__LJMP static int hlua_sleep_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005303{
5304 int wakeup_ms = lua_tointeger(L, -1);
5305 if (now_ms < wakeup_ms)
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005306 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_sleep_yield, wakeup_ms, 0));
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005307 return 0;
5308}
5309
5310__LJMP static int hlua_sleep(lua_State *L)
5311{
5312 unsigned int delay;
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005313 unsigned int wakeup_ms;
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005314
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005315 MAY_LJMP(check_args(L, 1, "sleep"));
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005316
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01005317 delay = MAY_LJMP(luaL_checkinteger(L, 1)) * 1000;
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005318 wakeup_ms = tick_add(now_ms, delay);
5319 lua_pushinteger(L, wakeup_ms);
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005320
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005321 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_sleep_yield, wakeup_ms, 0));
5322 return 0;
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005323}
5324
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005325__LJMP static int hlua_msleep(lua_State *L)
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005326{
5327 unsigned int delay;
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005328 unsigned int wakeup_ms;
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005329
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005330 MAY_LJMP(check_args(L, 1, "msleep"));
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005331
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01005332 delay = MAY_LJMP(luaL_checkinteger(L, 1));
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005333 wakeup_ms = tick_add(now_ms, delay);
5334 lua_pushinteger(L, wakeup_ms);
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005335
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005336 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_sleep_yield, wakeup_ms, 0));
5337 return 0;
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005338}
5339
Thierry FOURNIER13416fe2015-02-17 15:01:59 +01005340/* This functionis an LUA binding. it permits to give back
5341 * the hand at the HAProxy scheduler. It is used when the
5342 * LUA processing consumes a lot of time.
5343 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01005344__LJMP static int hlua_yield_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005345{
5346 return 0;
5347}
5348
Thierry FOURNIER13416fe2015-02-17 15:01:59 +01005349__LJMP static int hlua_yield(lua_State *L)
5350{
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005351 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_yield_yield, TICK_ETERNITY, HLUA_CTRLYIELD));
5352 return 0;
Thierry FOURNIER13416fe2015-02-17 15:01:59 +01005353}
5354
Thierry FOURNIER37196f42015-02-16 19:34:56 +01005355/* This function change the nice of the currently executed
5356 * task. It is used set low or high priority at the current
5357 * task.
5358 */
Willy Tarreau59551662015-03-10 14:23:13 +01005359__LJMP static int hlua_set_nice(lua_State *L)
Thierry FOURNIER37196f42015-02-16 19:34:56 +01005360{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005361 struct hlua *hlua;
5362 int nice;
Thierry FOURNIER37196f42015-02-16 19:34:56 +01005363
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005364 MAY_LJMP(check_args(L, 1, "set_nice"));
5365 hlua = hlua_gethlua(L);
5366 nice = MAY_LJMP(luaL_checkinteger(L, 1));
Thierry FOURNIER37196f42015-02-16 19:34:56 +01005367
5368 /* If he task is not set, I'm in a start mode. */
5369 if (!hlua || !hlua->task)
5370 return 0;
5371
5372 if (nice < -1024)
5373 nice = -1024;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005374 else if (nice > 1024)
Thierry FOURNIER37196f42015-02-16 19:34:56 +01005375 nice = 1024;
5376
5377 hlua->task->nice = nice;
5378 return 0;
5379}
5380
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005381/* This function is used as a calback of a task. It is called by the
5382 * HAProxy task subsystem when the task is awaked. The LUA runtime can
5383 * return an E_AGAIN signal, the emmiter of this signal must set a
5384 * signal to wake the task.
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005385 *
5386 * Task wrapper are longjmp safe because the only one Lua code
5387 * executed is the safe hlua_ctx_resume();
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005388 */
5389static struct task *hlua_process_task(struct task *task)
5390{
5391 struct hlua *hlua = task->context;
5392 enum hlua_exec status;
5393
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005394 /* If it is the first call to the task, we must initialize the
5395 * execution timeouts.
5396 */
5397 if (!HLUA_IS_RUNNING(hlua))
Thierry FOURNIER10770fa2015-09-29 01:59:42 +02005398 hlua->max_time = hlua_timeout_task;
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005399
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005400 /* Execute the Lua code. */
5401 status = hlua_ctx_resume(hlua, 1);
5402
5403 switch (status) {
5404 /* finished or yield */
5405 case HLUA_E_OK:
5406 hlua_ctx_destroy(hlua);
5407 task_delete(task);
5408 task_free(task);
5409 break;
5410
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01005411 case HLUA_E_AGAIN: /* co process or timeout wake me later. */
5412 if (hlua->wake_time != TICK_ETERNITY)
Emeric Brun253e53e2017-10-17 18:58:40 +02005413 task->expire = hlua->wake_time;
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005414 break;
5415
5416 /* finished with error. */
5417 case HLUA_E_ERRMSG:
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005418 SEND_ERR(NULL, "Lua task: %s.\n", lua_tostring(hlua->T, -1));
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005419 hlua_ctx_destroy(hlua);
5420 task_delete(task);
5421 task_free(task);
Emeric Brun253e53e2017-10-17 18:58:40 +02005422 task = NULL;
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005423 break;
5424
5425 case HLUA_E_ERR:
5426 default:
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005427 SEND_ERR(NULL, "Lua task: unknown error.\n");
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005428 hlua_ctx_destroy(hlua);
5429 task_delete(task);
5430 task_free(task);
Emeric Brun253e53e2017-10-17 18:58:40 +02005431 task = NULL;
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005432 break;
5433 }
Emeric Brun253e53e2017-10-17 18:58:40 +02005434 return task;
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005435}
5436
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01005437/* This function is an LUA binding that register LUA function to be
5438 * executed after the HAProxy configuration parsing and before the
5439 * HAProxy scheduler starts. This function expect only one LUA
5440 * argument that is a function. This function returns nothing, but
5441 * throws if an error is encountered.
5442 */
5443__LJMP static int hlua_register_init(lua_State *L)
5444{
5445 struct hlua_init_function *init;
5446 int ref;
5447
5448 MAY_LJMP(check_args(L, 1, "register_init"));
5449
5450 ref = MAY_LJMP(hlua_checkfunction(L, 1));
5451
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02005452 init = calloc(1, sizeof(*init));
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01005453 if (!init)
5454 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5455
5456 init->function_ref = ref;
5457 LIST_ADDQ(&hlua_init_functions, &init->l);
5458 return 0;
5459}
5460
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005461/* This functio is an LUA binding. It permits to register a task
5462 * executed in parallel of the main HAroxy activity. The task is
5463 * created and it is set in the HAProxy scheduler. It can be called
5464 * from the "init" section, "post init" or during the runtime.
5465 *
5466 * Lua prototype:
5467 *
5468 * <none> core.register_task(<function>)
5469 */
5470static int hlua_register_task(lua_State *L)
5471{
5472 struct hlua *hlua;
5473 struct task *task;
5474 int ref;
5475
5476 MAY_LJMP(check_args(L, 1, "register_task"));
5477
5478 ref = MAY_LJMP(hlua_checkfunction(L, 1));
5479
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005480 hlua = pool_alloc2(pool2_hlua);
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005481 if (!hlua)
5482 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5483
Emeric Brunc60def82017-09-27 14:59:38 +02005484 task = task_new(MAX_THREADS_MASK);
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005485 task->context = hlua;
5486 task->process = hlua_process_task;
5487
5488 if (!hlua_ctx_init(hlua, task))
5489 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5490
5491 /* Restore the function in the stack. */
5492 lua_rawgeti(hlua->T, LUA_REGISTRYINDEX, ref);
5493 hlua->nargs = 0;
5494
5495 /* Schedule task. */
5496 task_schedule(task, now_ms);
5497
5498 return 0;
5499}
5500
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005501/* Wrapper called by HAProxy to execute an LUA converter. This wrapper
5502 * doesn't allow "yield" functions because the HAProxy engine cannot
5503 * resume converters.
5504 */
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005505static int hlua_sample_conv_wrapper(const struct arg *arg_p, struct sample *smp, void *private)
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005506{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005507 struct hlua_function *fcn = private;
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005508 struct stream *stream = smp->strm;
Thierry Fournierfd107a22016-02-19 19:57:23 +01005509 const char *error;
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005510
Willy Tarreaube508f12016-03-10 11:47:01 +01005511 if (!stream)
5512 return 0;
5513
Willy Tarreau87b09662015-04-03 00:22:06 +02005514 /* In the execution wrappers linked with a stream, the
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01005515 * Lua context can be not initialized. This behavior
5516 * permits to save performances because a systematic
5517 * Lua initialization cause 5% performances loss.
5518 */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005519 if (!stream->hlua) {
5520 stream->hlua = pool_alloc2(pool2_hlua);
5521 if (!stream->hlua) {
5522 SEND_ERR(stream->be, "Lua converter '%s': can't initialize Lua context.\n", fcn->name);
5523 return 0;
5524 }
5525 if (!hlua_ctx_init(stream->hlua, stream->task)) {
5526 SEND_ERR(stream->be, "Lua converter '%s': can't initialize Lua context.\n", fcn->name);
5527 return 0;
5528 }
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01005529 }
5530
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005531 /* If it is the first run, initialize the data for the call. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005532 if (!HLUA_IS_RUNNING(stream->hlua)) {
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005533
5534 /* The following Lua calls can fail. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005535 if (!SET_SAFE_LJMP(stream->hlua->T)) {
5536 if (lua_type(stream->hlua->T, -1) == LUA_TSTRING)
5537 error = lua_tostring(stream->hlua->T, -1);
Thierry Fournierfd107a22016-02-19 19:57:23 +01005538 else
5539 error = "critical error";
5540 SEND_ERR(stream->be, "Lua converter '%s': %s.\n", fcn->name, error);
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005541 return 0;
5542 }
5543
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005544 /* Check stack available size. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005545 if (!lua_checkstack(stream->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005546 SEND_ERR(stream->be, "Lua converter '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005547 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005548 return 0;
5549 }
5550
5551 /* Restore the function in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005552 lua_rawgeti(stream->hlua->T, LUA_REGISTRYINDEX, fcn->function_ref);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005553
5554 /* convert input sample and pust-it in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005555 if (!lua_checkstack(stream->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005556 SEND_ERR(stream->be, "Lua converter '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005557 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005558 return 0;
5559 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005560 hlua_smp2lua(stream->hlua->T, smp);
5561 stream->hlua->nargs = 1;
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005562
5563 /* push keywords in the stack. */
5564 if (arg_p) {
5565 for (; arg_p->type != ARGT_STOP; arg_p++) {
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005566 if (!lua_checkstack(stream->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005567 SEND_ERR(stream->be, "Lua converter '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005568 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005569 return 0;
5570 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005571 hlua_arg2lua(stream->hlua->T, arg_p);
5572 stream->hlua->nargs++;
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005573 }
5574 }
5575
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005576 /* We must initialize the execution timeouts. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005577 stream->hlua->max_time = hlua_timeout_session;
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005578
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005579 /* At this point the execution is safe. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005580 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005581 }
5582
5583 /* Execute the function. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005584 switch (hlua_ctx_resume(stream->hlua, 0)) {
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005585 /* finished. */
5586 case HLUA_E_OK:
Thierry FOURNIERfd80df12017-05-12 16:32:20 +02005587 /* If the stack is empty, the function fails. */
5588 if (lua_gettop(stream->hlua->T) <= 0)
5589 return 0;
5590
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005591 /* Convert the returned value in sample. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005592 hlua_lua2smp(stream->hlua->T, -1, smp);
5593 lua_pop(stream->hlua->T, 1);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005594 return 1;
5595
5596 /* yield. */
5597 case HLUA_E_AGAIN:
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005598 SEND_ERR(stream->be, "Lua converter '%s': cannot use yielded functions.\n", fcn->name);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005599 return 0;
5600
5601 /* finished with error. */
5602 case HLUA_E_ERRMSG:
5603 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005604 SEND_ERR(stream->be, "Lua converter '%s': %s.\n",
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005605 fcn->name, lua_tostring(stream->hlua->T, -1));
5606 lua_pop(stream->hlua->T, 1);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005607 return 0;
5608
5609 case HLUA_E_ERR:
5610 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005611 SEND_ERR(stream->be, "Lua converter '%s' returns an unknown error.\n", fcn->name);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005612
5613 default:
5614 return 0;
5615 }
5616}
5617
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005618/* Wrapper called by HAProxy to execute a sample-fetch. this wrapper
5619 * doesn't allow "yield" functions because the HAProxy engine cannot
Willy Tarreaube508f12016-03-10 11:47:01 +01005620 * resume sample-fetches. This function will be called by the sample
5621 * fetch engine to call lua-based fetch operations.
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005622 */
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005623static int hlua_sample_fetch_wrapper(const struct arg *arg_p, struct sample *smp,
5624 const char *kw, void *private)
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005625{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005626 struct hlua_function *fcn = private;
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005627 struct stream *stream = smp->strm;
Thierry Fournierfd107a22016-02-19 19:57:23 +01005628 const char *error;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005629 const struct chunk msg = { .len = 0 };
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005630
Willy Tarreaube508f12016-03-10 11:47:01 +01005631 if (!stream)
5632 return 0;
5633
Willy Tarreau87b09662015-04-03 00:22:06 +02005634 /* In the execution wrappers linked with a stream, the
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01005635 * Lua context can be not initialized. This behavior
5636 * permits to save performances because a systematic
5637 * Lua initialization cause 5% performances loss.
5638 */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005639 if (!stream->hlua) {
5640 stream->hlua = pool_alloc2(pool2_hlua);
5641 if (!stream->hlua) {
5642 SEND_ERR(stream->be, "Lua sample-fetch '%s': can't initialize Lua context.\n", fcn->name);
5643 return 0;
5644 }
5645 if (!hlua_ctx_init(stream->hlua, stream->task)) {
5646 SEND_ERR(stream->be, "Lua sample-fetch '%s': can't initialize Lua context.\n", fcn->name);
5647 return 0;
5648 }
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01005649 }
5650
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005651 consistency_set(stream, smp->opt, &stream->hlua->cons);
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005652
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005653 /* If it is the first run, initialize the data for the call. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005654 if (!HLUA_IS_RUNNING(stream->hlua)) {
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005655
5656 /* The following Lua calls can fail. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005657 if (!SET_SAFE_LJMP(stream->hlua->T)) {
5658 if (lua_type(stream->hlua->T, -1) == LUA_TSTRING)
5659 error = lua_tostring(stream->hlua->T, -1);
Thierry Fournierfd107a22016-02-19 19:57:23 +01005660 else
5661 error = "critical error";
5662 SEND_ERR(smp->px, "Lua sample-fetch '%s': %s.\n", fcn->name, error);
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005663 return 0;
5664 }
5665
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005666 /* Check stack available size. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005667 if (!lua_checkstack(stream->hlua->T, 2)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005668 SEND_ERR(smp->px, "Lua sample-fetch '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005669 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005670 return 0;
5671 }
5672
5673 /* Restore the function in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005674 lua_rawgeti(stream->hlua->T, LUA_REGISTRYINDEX, fcn->function_ref);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005675
5676 /* push arguments in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005677 if (!hlua_txn_new(stream->hlua->T, stream, smp->px, smp->opt & SMP_OPT_DIR,
Thierry FOURNIERab00df62016-07-14 11:42:37 +02005678 HLUA_TXN_NOTERM)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005679 SEND_ERR(smp->px, "Lua sample-fetch '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005680 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005681 return 0;
5682 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005683 stream->hlua->nargs = 1;
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005684
5685 /* push keywords in the stack. */
5686 for (; arg_p && arg_p->type != ARGT_STOP; arg_p++) {
5687 /* Check stack available size. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005688 if (!lua_checkstack(stream->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005689 SEND_ERR(smp->px, "Lua sample-fetch '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005690 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005691 return 0;
5692 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005693 hlua_arg2lua(stream->hlua->T, arg_p);
5694 stream->hlua->nargs++;
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005695 }
5696
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005697 /* We must initialize the execution timeouts. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005698 stream->hlua->max_time = hlua_timeout_session;
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005699
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005700 /* At this point the execution is safe. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005701 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005702 }
5703
5704 /* Execute the function. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005705 switch (hlua_ctx_resume(stream->hlua, 0)) {
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005706 /* finished. */
5707 case HLUA_E_OK:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005708 if (!consistency_check(stream, smp->opt, &stream->hlua->cons)) {
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005709 stream_int_retnclose(&stream->si[0], &msg);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02005710 return 0;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005711 }
Thierry FOURNIERfd80df12017-05-12 16:32:20 +02005712 /* If the stack is empty, the function fails. */
5713 if (lua_gettop(stream->hlua->T) <= 0)
5714 return 0;
5715
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005716 /* Convert the returned value in sample. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005717 hlua_lua2smp(stream->hlua->T, -1, smp);
5718 lua_pop(stream->hlua->T, 1);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005719
5720 /* Set the end of execution flag. */
5721 smp->flags &= ~SMP_F_MAY_CHANGE;
5722 return 1;
5723
5724 /* yield. */
5725 case HLUA_E_AGAIN:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005726 if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005727 stream_int_retnclose(&stream->si[0], &msg);
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005728 SEND_ERR(smp->px, "Lua sample-fetch '%s': cannot use yielded functions.\n", fcn->name);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005729 return 0;
5730
5731 /* finished with error. */
5732 case HLUA_E_ERRMSG:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005733 if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005734 stream_int_retnclose(&stream->si[0], &msg);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005735 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005736 SEND_ERR(smp->px, "Lua sample-fetch '%s': %s.\n",
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005737 fcn->name, lua_tostring(stream->hlua->T, -1));
5738 lua_pop(stream->hlua->T, 1);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005739 return 0;
5740
5741 case HLUA_E_ERR:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005742 if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005743 stream_int_retnclose(&stream->si[0], &msg);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005744 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005745 SEND_ERR(smp->px, "Lua sample-fetch '%s' returns an unknown error.\n", fcn->name);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005746
5747 default:
5748 return 0;
5749 }
5750}
5751
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005752/* This function is an LUA binding used for registering
5753 * "sample-conv" functions. It expects a converter name used
5754 * in the haproxy configuration file, and an LUA function.
5755 */
5756__LJMP static int hlua_register_converters(lua_State *L)
5757{
5758 struct sample_conv_kw_list *sck;
5759 const char *name;
5760 int ref;
5761 int len;
5762 struct hlua_function *fcn;
5763
5764 MAY_LJMP(check_args(L, 2, "register_converters"));
5765
5766 /* First argument : converter name. */
5767 name = MAY_LJMP(luaL_checkstring(L, 1));
5768
5769 /* Second argument : lua function. */
5770 ref = MAY_LJMP(hlua_checkfunction(L, 2));
5771
5772 /* Allocate and fill the sample fetch keyword struct. */
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02005773 sck = calloc(1, sizeof(*sck) + sizeof(struct sample_conv) * 2);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005774 if (!sck)
5775 WILL_LJMP(luaL_error(L, "lua out of memory error."));
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02005776 fcn = calloc(1, sizeof(*fcn));
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005777 if (!fcn)
5778 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5779
5780 /* Fill fcn. */
5781 fcn->name = strdup(name);
5782 if (!fcn->name)
5783 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5784 fcn->function_ref = ref;
5785
5786 /* List head */
5787 sck->list.n = sck->list.p = NULL;
5788
5789 /* converter keyword. */
5790 len = strlen("lua.") + strlen(name) + 1;
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02005791 sck->kw[0].kw = calloc(1, len);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005792 if (!sck->kw[0].kw)
5793 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5794
5795 snprintf((char *)sck->kw[0].kw, len, "lua.%s", name);
5796 sck->kw[0].process = hlua_sample_conv_wrapper;
David Carlier0c437f42016-04-27 16:21:56 +01005797 sck->kw[0].arg_mask = ARG12(0,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005798 sck->kw[0].val_args = NULL;
5799 sck->kw[0].in_type = SMP_T_STR;
5800 sck->kw[0].out_type = SMP_T_STR;
5801 sck->kw[0].private = fcn;
5802
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005803 /* Register this new converter */
5804 sample_register_convs(sck);
5805
5806 return 0;
5807}
5808
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005809/* This fucntion is an LUA binding used for registering
5810 * "sample-fetch" functions. It expects a converter name used
5811 * in the haproxy configuration file, and an LUA function.
5812 */
5813__LJMP static int hlua_register_fetches(lua_State *L)
5814{
5815 const char *name;
5816 int ref;
5817 int len;
5818 struct sample_fetch_kw_list *sfk;
5819 struct hlua_function *fcn;
5820
5821 MAY_LJMP(check_args(L, 2, "register_fetches"));
5822
5823 /* First argument : sample-fetch name. */
5824 name = MAY_LJMP(luaL_checkstring(L, 1));
5825
5826 /* Second argument : lua function. */
5827 ref = MAY_LJMP(hlua_checkfunction(L, 2));
5828
5829 /* Allocate and fill the sample fetch keyword struct. */
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02005830 sfk = calloc(1, sizeof(*sfk) + sizeof(struct sample_fetch) * 2);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005831 if (!sfk)
5832 WILL_LJMP(luaL_error(L, "lua out of memory error."));
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02005833 fcn = calloc(1, sizeof(*fcn));
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005834 if (!fcn)
5835 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5836
5837 /* Fill fcn. */
5838 fcn->name = strdup(name);
5839 if (!fcn->name)
5840 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5841 fcn->function_ref = ref;
5842
5843 /* List head */
5844 sfk->list.n = sfk->list.p = NULL;
5845
5846 /* sample-fetch keyword. */
5847 len = strlen("lua.") + strlen(name) + 1;
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02005848 sfk->kw[0].kw = calloc(1, len);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005849 if (!sfk->kw[0].kw)
5850 return luaL_error(L, "lua out of memory error.");
5851
5852 snprintf((char *)sfk->kw[0].kw, len, "lua.%s", name);
5853 sfk->kw[0].process = hlua_sample_fetch_wrapper;
David Carlier0c437f42016-04-27 16:21:56 +01005854 sfk->kw[0].arg_mask = ARG12(0,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005855 sfk->kw[0].val_args = NULL;
5856 sfk->kw[0].out_type = SMP_T_STR;
5857 sfk->kw[0].use = SMP_USE_HTTP_ANY;
5858 sfk->kw[0].val = 0;
5859 sfk->kw[0].private = fcn;
5860
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005861 /* Register this new fetch. */
5862 sample_register_fetches(sfk);
5863
5864 return 0;
5865}
5866
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005867/* This function is a wrapper to execute each LUA function declared
5868 * as an action wrapper during the initialisation period. This function
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005869 * return ACT_RET_CONT if the processing is finished (with or without
5870 * error) and return ACT_RET_YIELD if the function must be called again
5871 * because the LUA returns a yield.
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005872 */
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005873static enum act_return hlua_action(struct act_rule *rule, struct proxy *px,
Willy Tarreau658b85b2015-09-27 10:00:49 +02005874 struct session *sess, struct stream *s, int flags)
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005875{
5876 char **arg;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005877 unsigned int analyzer;
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02005878 int dir;
Thierry Fournierfd107a22016-02-19 19:57:23 +01005879 const char *error;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005880 const struct chunk msg = { .len = 0 };
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005881
5882 switch (rule->from) {
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01005883 case ACT_F_TCP_REQ_CNT: analyzer = AN_REQ_INSPECT_FE ; dir = SMP_OPT_DIR_REQ; break;
5884 case ACT_F_TCP_RES_CNT: analyzer = AN_RES_INSPECT ; dir = SMP_OPT_DIR_RES; break;
5885 case ACT_F_HTTP_REQ: analyzer = AN_REQ_HTTP_PROCESS_FE; dir = SMP_OPT_DIR_REQ; break;
5886 case ACT_F_HTTP_RES: analyzer = AN_RES_HTTP_PROCESS_BE; dir = SMP_OPT_DIR_RES; break;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005887 default:
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005888 SEND_ERR(px, "Lua: internal error while execute action.\n");
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005889 return ACT_RET_CONT;
5890 }
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005891
Willy Tarreau87b09662015-04-03 00:22:06 +02005892 /* In the execution wrappers linked with a stream, the
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01005893 * Lua context can be not initialized. This behavior
5894 * permits to save performances because a systematic
5895 * Lua initialization cause 5% performances loss.
5896 */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005897 if (!s->hlua) {
5898 s->hlua = pool_alloc2(pool2_hlua);
5899 if (!s->hlua) {
5900 SEND_ERR(px, "Lua action '%s': can't initialize Lua context.\n",
5901 rule->arg.hlua_rule->fcn.name);
5902 return ACT_RET_CONT;
5903 }
5904 if (!hlua_ctx_init(s->hlua, s->task)) {
5905 SEND_ERR(px, "Lua action '%s': can't initialize Lua context.\n",
5906 rule->arg.hlua_rule->fcn.name);
5907 return ACT_RET_CONT;
5908 }
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01005909 }
5910
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005911 consistency_set(s, dir, &s->hlua->cons);
5912
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005913 /* If it is the first run, initialize the data for the call. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005914 if (!HLUA_IS_RUNNING(s->hlua)) {
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005915
5916 /* The following Lua calls can fail. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005917 if (!SET_SAFE_LJMP(s->hlua->T)) {
5918 if (lua_type(s->hlua->T, -1) == LUA_TSTRING)
5919 error = lua_tostring(s->hlua->T, -1);
Thierry Fournierfd107a22016-02-19 19:57:23 +01005920 else
5921 error = "critical error";
5922 SEND_ERR(px, "Lua function '%s': %s.\n",
5923 rule->arg.hlua_rule->fcn.name, error);
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005924 return ACT_RET_CONT;
5925 }
5926
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005927 /* Check stack available size. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005928 if (!lua_checkstack(s->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005929 SEND_ERR(px, "Lua function '%s': full stack.\n",
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005930 rule->arg.hlua_rule->fcn.name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005931 RESET_SAFE_LJMP(s->hlua->T);
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02005932 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005933 }
5934
5935 /* Restore the function in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005936 lua_rawgeti(s->hlua->T, LUA_REGISTRYINDEX, rule->arg.hlua_rule->fcn.function_ref);
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005937
Willy Tarreau87b09662015-04-03 00:22:06 +02005938 /* Create and and push object stream in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005939 if (!hlua_txn_new(s->hlua->T, s, px, dir, 0)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005940 SEND_ERR(px, "Lua function '%s': full stack.\n",
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005941 rule->arg.hlua_rule->fcn.name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005942 RESET_SAFE_LJMP(s->hlua->T);
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02005943 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005944 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005945 s->hlua->nargs = 1;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005946
5947 /* push keywords in the stack. */
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005948 for (arg = rule->arg.hlua_rule->args; arg && *arg; arg++) {
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005949 if (!lua_checkstack(s->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005950 SEND_ERR(px, "Lua function '%s': full stack.\n",
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005951 rule->arg.hlua_rule->fcn.name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005952 RESET_SAFE_LJMP(s->hlua->T);
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02005953 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005954 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005955 lua_pushstring(s->hlua->T, *arg);
5956 s->hlua->nargs++;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005957 }
5958
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005959 /* Now the execution is safe. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005960 RESET_SAFE_LJMP(s->hlua->T);
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005961
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005962 /* We must initialize the execution timeouts. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005963 s->hlua->max_time = hlua_timeout_session;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005964 }
5965
5966 /* Execute the function. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005967 switch (hlua_ctx_resume(s->hlua, !(flags & ACT_FLAG_FINAL))) {
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005968 /* finished. */
5969 case HLUA_E_OK:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005970 if (!consistency_check(s, dir, &s->hlua->cons)) {
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005971 stream_int_retnclose(&s->si[0], &msg);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02005972 return ACT_RET_ERR;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005973 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005974 if (s->hlua->flags & HLUA_STOP)
Thierry FOURNIER9bd52d42016-07-14 11:45:33 +02005975 return ACT_RET_STOP;
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02005976 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005977
5978 /* yield. */
5979 case HLUA_E_AGAIN:
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01005980 /* Set timeout in the required channel. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005981 if (s->hlua->wake_time != TICK_ETERNITY) {
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01005982 if (analyzer & (AN_REQ_INSPECT_FE|AN_REQ_HTTP_PROCESS_FE))
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005983 s->req.analyse_exp = s->hlua->wake_time;
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01005984 else if (analyzer & (AN_RES_INSPECT|AN_RES_HTTP_PROCESS_BE))
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005985 s->res.analyse_exp = s->hlua->wake_time;
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01005986 }
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005987 /* Some actions can be wake up when a "write" event
5988 * is detected on a response channel. This is useful
5989 * only for actions targetted on the requests.
5990 */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005991 if (HLUA_IS_WAKERESWR(s->hlua)) {
Willy Tarreau22ec1ea2014-11-27 20:45:39 +01005992 s->res.flags |= CF_WAKE_WRITE;
Willy Tarreau76bd97f2015-03-10 17:16:10 +01005993 if ((analyzer & (AN_REQ_INSPECT_FE|AN_REQ_HTTP_PROCESS_FE)))
Willy Tarreau22ec1ea2014-11-27 20:45:39 +01005994 s->res.analysers |= analyzer;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005995 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005996 if (HLUA_IS_WAKEREQWR(s->hlua))
Willy Tarreau22ec1ea2014-11-27 20:45:39 +01005997 s->req.flags |= CF_WAKE_WRITE;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005998 /* We can quit the fcuntion without consistency check
5999 * because HAProxy is not able to manipulate data, it
6000 * is only allowed to call me again. */
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02006001 return ACT_RET_YIELD;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006002
6003 /* finished with error. */
6004 case HLUA_E_ERRMSG:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006005 if (!consistency_check(s, dir, &s->hlua->cons)) {
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01006006 stream_int_retnclose(&s->si[0], &msg);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02006007 return ACT_RET_ERR;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01006008 }
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006009 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02006010 SEND_ERR(px, "Lua function '%s': %s.\n",
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006011 rule->arg.hlua_rule->fcn.name, lua_tostring(s->hlua->T, -1));
6012 lua_pop(s->hlua->T, 1);
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02006013 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006014
6015 case HLUA_E_ERR:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006016 if (!consistency_check(s, dir, &s->hlua->cons)) {
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01006017 stream_int_retnclose(&s->si[0], &msg);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02006018 return ACT_RET_ERR;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01006019 }
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006020 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02006021 SEND_ERR(px, "Lua function '%s' return an unknown error.\n",
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006022 rule->arg.hlua_rule->fcn.name);
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006023
6024 default:
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02006025 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006026 }
6027}
6028
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006029struct task *hlua_applet_wakeup(struct task *t)
6030{
6031 struct appctx *ctx = t->context;
6032 struct stream_interface *si = ctx->owner;
6033
6034 /* If the applet is wake up without any expected work, the sheduler
6035 * remove it from the run queue. This flag indicate that the applet
6036 * is waiting for write. If the buffer is full, the main processing
6037 * will send some data and after call the applet, otherwise it call
6038 * the applet ASAP.
6039 */
6040 si_applet_cant_put(si);
6041 appctx_wakeup(ctx);
Willy Tarreaud9587412017-08-23 16:07:33 +02006042 t->expire = TICK_ETERNITY;
Willy Tarreaud1aa41f2017-07-21 16:41:56 +02006043 return t;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006044}
6045
6046static int hlua_applet_tcp_init(struct appctx *ctx, struct proxy *px, struct stream *strm)
6047{
6048 struct stream_interface *si = ctx->owner;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006049 struct hlua *hlua;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006050 struct task *task;
6051 char **arg;
Thierry Fournierfd107a22016-02-19 19:57:23 +01006052 const char *error;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006053
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006054 hlua = pool_alloc2(pool2_hlua);
6055 if (!hlua) {
6056 SEND_ERR(px, "Lua applet tcp '%s': out of memory.\n",
6057 ctx->rule->arg.hlua_rule->fcn.name);
6058 return 0;
6059 }
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006060 HLUA_INIT(hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006061 ctx->ctx.hlua_apptcp.hlua = hlua;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006062 ctx->ctx.hlua_apptcp.flags = 0;
6063
6064 /* Create task used by signal to wakeup applets. */
Thierry FOURNIER4325ab72017-07-12 11:53:38 +02006065 task = task_new(1UL << tid);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006066 if (!task) {
6067 SEND_ERR(px, "Lua applet tcp '%s': out of memory.\n",
6068 ctx->rule->arg.hlua_rule->fcn.name);
6069 return 0;
6070 }
6071 task->nice = 0;
6072 task->context = ctx;
6073 task->process = hlua_applet_wakeup;
6074 ctx->ctx.hlua_apptcp.task = task;
6075
6076 /* In the execution wrappers linked with a stream, the
6077 * Lua context can be not initialized. This behavior
6078 * permits to save performances because a systematic
6079 * Lua initialization cause 5% performances loss.
6080 */
6081 if (!hlua_ctx_init(hlua, task)) {
6082 SEND_ERR(px, "Lua applet tcp '%s': can't initialize Lua context.\n",
6083 ctx->rule->arg.hlua_rule->fcn.name);
6084 return 0;
6085 }
6086
6087 /* Set timeout according with the applet configuration. */
Thierry FOURNIER10770fa2015-09-29 01:59:42 +02006088 hlua->max_time = ctx->applet->timeout;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006089
6090 /* The following Lua calls can fail. */
6091 if (!SET_SAFE_LJMP(hlua->T)) {
Thierry Fournierfd107a22016-02-19 19:57:23 +01006092 if (lua_type(hlua->T, -1) == LUA_TSTRING)
6093 error = lua_tostring(hlua->T, -1);
6094 else
6095 error = "critical error";
6096 SEND_ERR(px, "Lua applet tcp '%s': %s.\n",
6097 ctx->rule->arg.hlua_rule->fcn.name, error);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006098 RESET_SAFE_LJMP(hlua->T);
6099 return 0;
6100 }
6101
6102 /* Check stack available size. */
6103 if (!lua_checkstack(hlua->T, 1)) {
6104 SEND_ERR(px, "Lua applet tcp '%s': full stack.\n",
6105 ctx->rule->arg.hlua_rule->fcn.name);
6106 RESET_SAFE_LJMP(hlua->T);
6107 return 0;
6108 }
6109
6110 /* Restore the function in the stack. */
6111 lua_rawgeti(hlua->T, LUA_REGISTRYINDEX, ctx->rule->arg.hlua_rule->fcn.function_ref);
6112
6113 /* Create and and push object stream in the stack. */
6114 if (!hlua_applet_tcp_new(hlua->T, ctx)) {
6115 SEND_ERR(px, "Lua applet tcp '%s': full stack.\n",
6116 ctx->rule->arg.hlua_rule->fcn.name);
6117 RESET_SAFE_LJMP(hlua->T);
6118 return 0;
6119 }
6120 hlua->nargs = 1;
6121
6122 /* push keywords in the stack. */
6123 for (arg = ctx->rule->arg.hlua_rule->args; arg && *arg; arg++) {
6124 if (!lua_checkstack(hlua->T, 1)) {
6125 SEND_ERR(px, "Lua applet tcp '%s': full stack.\n",
6126 ctx->rule->arg.hlua_rule->fcn.name);
6127 RESET_SAFE_LJMP(hlua->T);
6128 return 0;
6129 }
6130 lua_pushstring(hlua->T, *arg);
6131 hlua->nargs++;
6132 }
6133
6134 RESET_SAFE_LJMP(hlua->T);
6135
6136 /* Wakeup the applet ASAP. */
6137 si_applet_cant_get(si);
6138 si_applet_cant_put(si);
6139
6140 return 1;
6141}
6142
6143static void hlua_applet_tcp_fct(struct appctx *ctx)
6144{
6145 struct stream_interface *si = ctx->owner;
6146 struct stream *strm = si_strm(si);
6147 struct channel *res = si_ic(si);
6148 struct act_rule *rule = ctx->rule;
6149 struct proxy *px = strm->be;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006150 struct hlua *hlua = ctx->ctx.hlua_apptcp.hlua;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006151
6152 /* The applet execution is already done. */
6153 if (ctx->ctx.hlua_apptcp.flags & APPLET_DONE)
6154 return;
6155
6156 /* If the stream is disconnect or closed, ldo nothing. */
6157 if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO))
6158 return;
6159
6160 /* Execute the function. */
6161 switch (hlua_ctx_resume(hlua, 1)) {
6162 /* finished. */
6163 case HLUA_E_OK:
6164 ctx->ctx.hlua_apptcp.flags |= APPLET_DONE;
6165
6166 /* log time */
6167 strm->logs.tv_request = now;
6168
6169 /* eat the whole request */
Willy Tarreau06d80a92017-10-19 14:32:15 +02006170 co_skip(si_oc(si), si_ob(si)->o);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006171 res->flags |= CF_READ_NULL;
6172 si_shutr(si);
6173 return;
6174
6175 /* yield. */
6176 case HLUA_E_AGAIN:
Thierry Fournier0164f202016-02-20 17:47:43 +01006177 if (hlua->wake_time != TICK_ETERNITY)
6178 task_schedule(ctx->ctx.hlua_apptcp.task, hlua->wake_time);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006179 return;
6180
6181 /* finished with error. */
6182 case HLUA_E_ERRMSG:
6183 /* Display log. */
6184 SEND_ERR(px, "Lua applet tcp '%s': %s.\n",
6185 rule->arg.hlua_rule->fcn.name, lua_tostring(hlua->T, -1));
6186 lua_pop(hlua->T, 1);
6187 goto error;
6188
6189 case HLUA_E_ERR:
6190 /* Display log. */
6191 SEND_ERR(px, "Lua applet tcp '%s' return an unknown error.\n",
6192 rule->arg.hlua_rule->fcn.name);
6193 goto error;
6194
6195 default:
6196 goto error;
6197 }
6198
6199error:
6200
6201 /* For all other cases, just close the stream. */
6202 si_shutw(si);
6203 si_shutr(si);
6204 ctx->ctx.hlua_apptcp.flags |= APPLET_DONE;
6205}
6206
6207static void hlua_applet_tcp_release(struct appctx *ctx)
6208{
Willy Tarreaubd7fc952017-07-24 17:35:27 +02006209 task_delete(ctx->ctx.hlua_apptcp.task);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006210 task_free(ctx->ctx.hlua_apptcp.task);
6211 ctx->ctx.hlua_apptcp.task = NULL;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006212 hlua_ctx_destroy(ctx->ctx.hlua_apptcp.hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006213 ctx->ctx.hlua_apptcp.hlua = NULL;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006214}
6215
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006216/* The function returns 1 if the initialisation is complete, 0 if
6217 * an errors occurs and -1 if more data are required for initializing
6218 * the applet.
6219 */
6220static int hlua_applet_http_init(struct appctx *ctx, struct proxy *px, struct stream *strm)
6221{
6222 struct stream_interface *si = ctx->owner;
6223 struct channel *req = si_oc(si);
6224 struct http_msg *msg;
6225 struct http_txn *txn;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006226 struct hlua *hlua;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006227 char **arg;
6228 struct hdr_ctx hdr;
6229 struct task *task;
6230 struct sample smp; /* just used for a valid call to smp_prefetch_http. */
Thierry Fournierfd107a22016-02-19 19:57:23 +01006231 const char *error;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006232
6233 /* Wait for a full HTTP request. */
6234 if (!smp_prefetch_http(px, strm, 0, NULL, &smp, 0)) {
6235 if (smp.flags & SMP_F_MAY_CHANGE)
6236 return -1;
6237 return 0;
6238 }
6239 txn = strm->txn;
6240 msg = &txn->req;
6241
Willy Tarreau0078bfc2015-10-07 20:20:28 +02006242 /* We want two things in HTTP mode :
6243 * - enforce server-close mode if we were in keep-alive, so that the
6244 * applet is released after each response ;
6245 * - enable request body transfer to the applet in order to resync
6246 * with the response body.
6247 */
6248 if ((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL)
6249 txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | TX_CON_WANT_SCL;
Willy Tarreau0078bfc2015-10-07 20:20:28 +02006250
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006251 hlua = pool_alloc2(pool2_hlua);
6252 if (!hlua) {
6253 SEND_ERR(px, "Lua applet http '%s': out of memory.\n",
6254 ctx->rule->arg.hlua_rule->fcn.name);
6255 return 0;
6256 }
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006257 HLUA_INIT(hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006258 ctx->ctx.hlua_apphttp.hlua = hlua;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006259 ctx->ctx.hlua_apphttp.left_bytes = -1;
6260 ctx->ctx.hlua_apphttp.flags = 0;
6261
Thierry FOURNIERd93ea2b2015-12-20 19:14:52 +01006262 if (txn->req.flags & HTTP_MSGF_VER_11)
6263 ctx->ctx.hlua_apphttp.flags |= APPLET_HTTP11;
6264
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006265 /* Create task used by signal to wakeup applets. */
Thierry FOURNIER4325ab72017-07-12 11:53:38 +02006266 task = task_new(1UL << tid);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006267 if (!task) {
6268 SEND_ERR(px, "Lua applet http '%s': out of memory.\n",
6269 ctx->rule->arg.hlua_rule->fcn.name);
6270 return 0;
6271 }
6272 task->nice = 0;
6273 task->context = ctx;
6274 task->process = hlua_applet_wakeup;
6275 ctx->ctx.hlua_apphttp.task = task;
6276
6277 /* In the execution wrappers linked with a stream, the
6278 * Lua context can be not initialized. This behavior
6279 * permits to save performances because a systematic
6280 * Lua initialization cause 5% performances loss.
6281 */
6282 if (!hlua_ctx_init(hlua, task)) {
6283 SEND_ERR(px, "Lua applet http '%s': can't initialize Lua context.\n",
6284 ctx->rule->arg.hlua_rule->fcn.name);
6285 return 0;
6286 }
6287
6288 /* Set timeout according with the applet configuration. */
Thierry FOURNIER10770fa2015-09-29 01:59:42 +02006289 hlua->max_time = ctx->applet->timeout;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006290
6291 /* The following Lua calls can fail. */
6292 if (!SET_SAFE_LJMP(hlua->T)) {
Thierry Fournierfd107a22016-02-19 19:57:23 +01006293 if (lua_type(hlua->T, -1) == LUA_TSTRING)
6294 error = lua_tostring(hlua->T, -1);
6295 else
6296 error = "critical error";
6297 SEND_ERR(px, "Lua applet http '%s': %s.\n",
6298 ctx->rule->arg.hlua_rule->fcn.name, error);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006299 return 0;
6300 }
6301
6302 /* Check stack available size. */
6303 if (!lua_checkstack(hlua->T, 1)) {
6304 SEND_ERR(px, "Lua applet http '%s': full stack.\n",
6305 ctx->rule->arg.hlua_rule->fcn.name);
6306 RESET_SAFE_LJMP(hlua->T);
6307 return 0;
6308 }
6309
6310 /* Restore the function in the stack. */
6311 lua_rawgeti(hlua->T, LUA_REGISTRYINDEX, ctx->rule->arg.hlua_rule->fcn.function_ref);
6312
6313 /* Create and and push object stream in the stack. */
6314 if (!hlua_applet_http_new(hlua->T, ctx)) {
6315 SEND_ERR(px, "Lua applet http '%s': full stack.\n",
6316 ctx->rule->arg.hlua_rule->fcn.name);
6317 RESET_SAFE_LJMP(hlua->T);
6318 return 0;
6319 }
6320 hlua->nargs = 1;
6321
6322 /* Look for a 100-continue expected. */
6323 if (msg->flags & HTTP_MSGF_VER_11) {
6324 hdr.idx = 0;
6325 if (http_find_header2("Expect", 6, req->buf->p, &txn->hdr_idx, &hdr) &&
6326 unlikely(hdr.vlen == 12 && strncasecmp(hdr.line+hdr.val, "100-continue", 12) == 0))
6327 ctx->ctx.hlua_apphttp.flags |= APPLET_100C;
6328 }
6329
6330 /* push keywords in the stack. */
6331 for (arg = ctx->rule->arg.hlua_rule->args; arg && *arg; arg++) {
6332 if (!lua_checkstack(hlua->T, 1)) {
6333 SEND_ERR(px, "Lua applet http '%s': full stack.\n",
6334 ctx->rule->arg.hlua_rule->fcn.name);
6335 RESET_SAFE_LJMP(hlua->T);
6336 return 0;
6337 }
6338 lua_pushstring(hlua->T, *arg);
6339 hlua->nargs++;
6340 }
6341
6342 RESET_SAFE_LJMP(hlua->T);
6343
6344 /* Wakeup the applet when data is ready for read. */
6345 si_applet_cant_get(si);
6346
6347 return 1;
6348}
6349
6350static void hlua_applet_http_fct(struct appctx *ctx)
6351{
6352 struct stream_interface *si = ctx->owner;
6353 struct stream *strm = si_strm(si);
6354 struct channel *res = si_ic(si);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006355 struct act_rule *rule = ctx->rule;
6356 struct proxy *px = strm->be;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006357 struct hlua *hlua = ctx->ctx.hlua_apphttp.hlua;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006358 char *blk1;
6359 int len1;
6360 char *blk2;
6361 int len2;
6362 int ret;
6363
6364 /* If the stream is disconnect or closed, ldo nothing. */
6365 if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO))
6366 return;
6367
6368 /* Set the currently running flag. */
6369 if (!HLUA_IS_RUNNING(hlua) &&
6370 !(ctx->ctx.hlua_apphttp.flags & APPLET_DONE)) {
6371
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006372 /* Wait for full HTTP analysys. */
6373 if (unlikely(strm->txn->req.msg_state < HTTP_MSG_BODY)) {
6374 si_applet_cant_get(si);
6375 return;
6376 }
6377
6378 /* Store the max amount of bytes that we can read. */
6379 ctx->ctx.hlua_apphttp.left_bytes = strm->txn->req.body_len;
6380
6381 /* We need to flush the request header. This left the body
6382 * for the Lua.
6383 */
6384
6385 /* Read the maximum amount of data avalaible. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02006386 ret = co_getblk_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006387 if (ret == -1)
6388 return;
6389
6390 /* No data available, ask for more data. */
6391 if (ret == 1)
6392 len2 = 0;
6393 if (ret == 0)
6394 len1 = 0;
6395 if (len1 + len2 < strm->txn->req.eoh + 2) {
6396 si_applet_cant_get(si);
6397 return;
6398 }
6399
6400 /* skip the requests bytes. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02006401 co_skip(si_oc(si), strm->txn->req.eoh + 2);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006402 }
6403
6404 /* Executes The applet if it is not done. */
6405 if (!(ctx->ctx.hlua_apphttp.flags & APPLET_DONE)) {
6406
6407 /* Execute the function. */
6408 switch (hlua_ctx_resume(hlua, 1)) {
6409 /* finished. */
6410 case HLUA_E_OK:
6411 ctx->ctx.hlua_apphttp.flags |= APPLET_DONE;
6412 break;
6413
6414 /* yield. */
6415 case HLUA_E_AGAIN:
Thierry Fournier0164f202016-02-20 17:47:43 +01006416 if (hlua->wake_time != TICK_ETERNITY)
6417 task_schedule(ctx->ctx.hlua_apphttp.task, hlua->wake_time);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006418 return;
6419
6420 /* finished with error. */
6421 case HLUA_E_ERRMSG:
6422 /* Display log. */
6423 SEND_ERR(px, "Lua applet http '%s': %s.\n",
6424 rule->arg.hlua_rule->fcn.name, lua_tostring(hlua->T, -1));
6425 lua_pop(hlua->T, 1);
6426 goto error;
6427
6428 case HLUA_E_ERR:
6429 /* Display log. */
6430 SEND_ERR(px, "Lua applet http '%s' return an unknown error.\n",
6431 rule->arg.hlua_rule->fcn.name);
6432 goto error;
6433
6434 default:
6435 goto error;
6436 }
6437 }
6438
6439 if (ctx->ctx.hlua_apphttp.flags & APPLET_DONE) {
6440
6441 /* We must send the final chunk. */
6442 if (ctx->ctx.hlua_apphttp.flags & APPLET_CHUNKED &&
6443 !(ctx->ctx.hlua_apphttp.flags & APPLET_LAST_CHK)) {
6444
6445 /* sent last chunk at once. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02006446 ret = ci_putblk(res, "0\r\n\r\n", 5);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006447
6448 /* critical error. */
6449 if (ret == -2 || ret == -3) {
6450 SEND_ERR(px, "Lua applet http '%s'cannont send last chunk.\n",
6451 rule->arg.hlua_rule->fcn.name);
6452 goto error;
6453 }
6454
6455 /* no enough space error. */
6456 if (ret == -1) {
6457 si_applet_cant_put(si);
6458 return;
6459 }
6460
6461 /* set the last chunk sent. */
6462 ctx->ctx.hlua_apphttp.flags |= APPLET_LAST_CHK;
6463 }
6464
6465 /* close the connection. */
6466
6467 /* status / log */
6468 strm->txn->status = ctx->ctx.hlua_apphttp.status;
6469 strm->logs.tv_request = now;
6470
6471 /* eat the whole request */
Willy Tarreau06d80a92017-10-19 14:32:15 +02006472 co_skip(si_oc(si), si_ob(si)->o);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006473 res->flags |= CF_READ_NULL;
6474 si_shutr(si);
6475
6476 return;
6477 }
6478
6479error:
6480
6481 /* If we are in HTTP mode, and we are not send any
6482 * data, return a 500 server error in best effort:
6483 * if there are no room avalaible in the buffer,
6484 * just close the connection.
6485 */
Willy Tarreau06d80a92017-10-19 14:32:15 +02006486 ci_putblk(res, error_500, strlen(error_500));
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006487 if (!(strm->flags & SF_ERR_MASK))
6488 strm->flags |= SF_ERR_RESOURCE;
6489 si_shutw(si);
6490 si_shutr(si);
6491 ctx->ctx.hlua_apphttp.flags |= APPLET_DONE;
6492}
6493
6494static void hlua_applet_http_release(struct appctx *ctx)
6495{
Willy Tarreaubd7fc952017-07-24 17:35:27 +02006496 task_delete(ctx->ctx.hlua_apphttp.task);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006497 task_free(ctx->ctx.hlua_apphttp.task);
6498 ctx->ctx.hlua_apphttp.task = NULL;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006499 hlua_ctx_destroy(ctx->ctx.hlua_apphttp.hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006500 ctx->ctx.hlua_apphttp.hlua = NULL;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006501}
6502
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006503/* global {tcp|http}-request parser. Return ACT_RET_PRS_OK in
6504 * succes case, else return ACT_RET_PRS_ERR.
Thierry FOURNIERbabae282015-09-17 11:36:37 +02006505 *
6506 * This function can fail with an abort() due to an Lua critical error.
6507 * We are in the configuration parsing process of HAProxy, this abort() is
6508 * tolerated.
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006509 */
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006510static enum act_parse_ret action_register_lua(const char **args, int *cur_arg, struct proxy *px,
6511 struct act_rule *rule, char **err)
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006512{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02006513 struct hlua_function *fcn = rule->kw->private;
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006514 int i;
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006515
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006516 /* Memory for the rule. */
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02006517 rule->arg.hlua_rule = calloc(1, sizeof(*rule->arg.hlua_rule));
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006518 if (!rule->arg.hlua_rule) {
6519 memprintf(err, "out of memory error");
Thierry FOURNIERafa80492015-08-19 09:04:15 +02006520 return ACT_RET_PRS_ERR;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006521 }
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006522
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006523 /* Memory for arguments. */
6524 rule->arg.hlua_rule->args = calloc(fcn->nargs + 1, sizeof(char *));
6525 if (!rule->arg.hlua_rule->args) {
6526 memprintf(err, "out of memory error");
6527 return ACT_RET_PRS_ERR;
6528 }
6529
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006530 /* Reference the Lua function and store the reference. */
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006531 rule->arg.hlua_rule->fcn = *fcn;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006532
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006533 /* Expect some arguments */
6534 for (i = 0; i < fcn->nargs; i++) {
6535 if (*args[i+1] == '\0') {
6536 memprintf(err, "expect %d arguments", fcn->nargs);
6537 return ACT_RET_PRS_ERR;
6538 }
6539 rule->arg.hlua_rule->args[i] = strdup(args[i + 1]);
6540 if (!rule->arg.hlua_rule->args[i]) {
6541 memprintf(err, "out of memory error");
6542 return ACT_RET_PRS_ERR;
6543 }
6544 (*cur_arg)++;
6545 }
6546 rule->arg.hlua_rule->args[i] = NULL;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006547
Thierry FOURNIER42148732015-09-02 17:17:33 +02006548 rule->action = ACT_CUSTOM;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006549 rule->action_ptr = hlua_action;
Thierry FOURNIERafa80492015-08-19 09:04:15 +02006550 return ACT_RET_PRS_OK;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006551}
6552
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006553static enum act_parse_ret action_register_service_http(const char **args, int *cur_arg, struct proxy *px,
6554 struct act_rule *rule, char **err)
6555{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02006556 struct hlua_function *fcn = rule->kw->private;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006557
Thierry FOURNIER718e2a72015-12-20 20:13:14 +01006558 /* HTTP applets are forbidden in tcp-request rules.
6559 * HTTP applet request requires everything initilized by
6560 * "http_process_request" (analyzer flag AN_REQ_HTTP_INNER).
6561 * The applet will be immediately initilized, but its before
6562 * the call of this analyzer.
6563 */
6564 if (rule->from != ACT_F_HTTP_REQ) {
6565 memprintf(err, "HTTP applets are forbidden from 'tcp-request' rulesets");
6566 return ACT_RET_PRS_ERR;
6567 }
6568
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006569 /* Memory for the rule. */
6570 rule->arg.hlua_rule = calloc(1, sizeof(*rule->arg.hlua_rule));
6571 if (!rule->arg.hlua_rule) {
6572 memprintf(err, "out of memory error");
6573 return ACT_RET_PRS_ERR;
6574 }
6575
6576 /* Reference the Lua function and store the reference. */
6577 rule->arg.hlua_rule->fcn = *fcn;
6578
6579 /* TODO: later accept arguments. */
6580 rule->arg.hlua_rule->args = NULL;
6581
6582 /* Add applet pointer in the rule. */
6583 rule->applet.obj_type = OBJ_TYPE_APPLET;
6584 rule->applet.name = fcn->name;
6585 rule->applet.init = hlua_applet_http_init;
6586 rule->applet.fct = hlua_applet_http_fct;
6587 rule->applet.release = hlua_applet_http_release;
6588 rule->applet.timeout = hlua_timeout_applet;
6589
6590 return ACT_RET_PRS_OK;
6591}
6592
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006593/* This function is an LUA binding used for registering
6594 * "sample-conv" functions. It expects a converter name used
6595 * in the haproxy configuration file, and an LUA function.
6596 */
6597__LJMP static int hlua_register_action(lua_State *L)
6598{
6599 struct action_kw_list *akl;
6600 const char *name;
6601 int ref;
6602 int len;
6603 struct hlua_function *fcn;
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006604 int nargs;
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006605
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006606 /* Initialise the number of expected arguments at 0. */
6607 nargs = 0;
6608
6609 if (lua_gettop(L) < 3 || lua_gettop(L) > 4)
6610 WILL_LJMP(luaL_error(L, "'register_action' needs between 3 and 4 arguments"));
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006611
6612 /* First argument : converter name. */
6613 name = MAY_LJMP(luaL_checkstring(L, 1));
6614
6615 /* Second argument : environment. */
6616 if (lua_type(L, 2) != LUA_TTABLE)
6617 WILL_LJMP(luaL_error(L, "register_action: second argument must be a table of strings"));
6618
6619 /* Third argument : lua function. */
6620 ref = MAY_LJMP(hlua_checkfunction(L, 3));
6621
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006622 /* Fouth argument : number of mandatories arguments expected on the configuration line. */
6623 if (lua_gettop(L) >= 4)
6624 nargs = MAY_LJMP(luaL_checkinteger(L, 4));
6625
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006626 /* browse the second argulent as an array. */
6627 lua_pushnil(L);
6628 while (lua_next(L, 2) != 0) {
6629 if (lua_type(L, -1) != LUA_TSTRING)
6630 WILL_LJMP(luaL_error(L, "register_action: second argument must be a table of strings"));
6631
6632 /* Check required environment. Only accepted "http" or "tcp". */
6633 /* Allocate and fill the sample fetch keyword struct. */
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02006634 akl = calloc(1, sizeof(*akl) + sizeof(struct action_kw) * 2);
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006635 if (!akl)
6636 WILL_LJMP(luaL_error(L, "lua out of memory error."));
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02006637 fcn = calloc(1, sizeof(*fcn));
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006638 if (!fcn)
6639 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6640
6641 /* Fill fcn. */
6642 fcn->name = strdup(name);
6643 if (!fcn->name)
6644 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6645 fcn->function_ref = ref;
6646
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006647 /* Set the expected number od arguments. */
6648 fcn->nargs = nargs;
6649
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006650 /* List head */
6651 akl->list.n = akl->list.p = NULL;
6652
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006653 /* action keyword. */
6654 len = strlen("lua.") + strlen(name) + 1;
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02006655 akl->kw[0].kw = calloc(1, len);
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006656 if (!akl->kw[0].kw)
6657 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6658
6659 snprintf((char *)akl->kw[0].kw, len, "lua.%s", name);
6660
6661 akl->kw[0].match_pfx = 0;
6662 akl->kw[0].private = fcn;
6663 akl->kw[0].parse = action_register_lua;
6664
6665 /* select the action registering point. */
6666 if (strcmp(lua_tostring(L, -1), "tcp-req") == 0)
6667 tcp_req_cont_keywords_register(akl);
6668 else if (strcmp(lua_tostring(L, -1), "tcp-res") == 0)
6669 tcp_res_cont_keywords_register(akl);
6670 else if (strcmp(lua_tostring(L, -1), "http-req") == 0)
6671 http_req_keywords_register(akl);
6672 else if (strcmp(lua_tostring(L, -1), "http-res") == 0)
6673 http_res_keywords_register(akl);
6674 else
6675 WILL_LJMP(luaL_error(L, "lua action environment '%s' is unknown. "
6676 "'tcp-req', 'tcp-res', 'http-req' or 'http-res' "
6677 "are expected.", lua_tostring(L, -1)));
6678
6679 /* pop the environment string. */
6680 lua_pop(L, 1);
6681 }
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006682 return ACT_RET_PRS_OK;
6683}
6684
6685static enum act_parse_ret action_register_service_tcp(const char **args, int *cur_arg, struct proxy *px,
6686 struct act_rule *rule, char **err)
6687{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02006688 struct hlua_function *fcn = rule->kw->private;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006689
6690 /* Memory for the rule. */
6691 rule->arg.hlua_rule = calloc(1, sizeof(*rule->arg.hlua_rule));
6692 if (!rule->arg.hlua_rule) {
6693 memprintf(err, "out of memory error");
6694 return ACT_RET_PRS_ERR;
6695 }
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006696
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006697 /* Reference the Lua function and store the reference. */
6698 rule->arg.hlua_rule->fcn = *fcn;
6699
6700 /* TODO: later accept arguments. */
6701 rule->arg.hlua_rule->args = NULL;
6702
6703 /* Add applet pointer in the rule. */
6704 rule->applet.obj_type = OBJ_TYPE_APPLET;
6705 rule->applet.name = fcn->name;
6706 rule->applet.init = hlua_applet_tcp_init;
6707 rule->applet.fct = hlua_applet_tcp_fct;
6708 rule->applet.release = hlua_applet_tcp_release;
6709 rule->applet.timeout = hlua_timeout_applet;
6710
6711 return 0;
6712}
6713
6714/* This function is an LUA binding used for registering
6715 * "sample-conv" functions. It expects a converter name used
6716 * in the haproxy configuration file, and an LUA function.
6717 */
6718__LJMP static int hlua_register_service(lua_State *L)
6719{
6720 struct action_kw_list *akl;
6721 const char *name;
6722 const char *env;
6723 int ref;
6724 int len;
6725 struct hlua_function *fcn;
6726
6727 MAY_LJMP(check_args(L, 3, "register_service"));
6728
6729 /* First argument : converter name. */
6730 name = MAY_LJMP(luaL_checkstring(L, 1));
6731
6732 /* Second argument : environment. */
6733 env = MAY_LJMP(luaL_checkstring(L, 2));
6734
6735 /* Third argument : lua function. */
6736 ref = MAY_LJMP(hlua_checkfunction(L, 3));
6737
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006738 /* Allocate and fill the sample fetch keyword struct. */
6739 akl = calloc(1, sizeof(*akl) + sizeof(struct action_kw) * 2);
6740 if (!akl)
6741 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6742 fcn = calloc(1, sizeof(*fcn));
6743 if (!fcn)
6744 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6745
6746 /* Fill fcn. */
6747 len = strlen("<lua.>") + strlen(name) + 1;
6748 fcn->name = calloc(1, len);
6749 if (!fcn->name)
6750 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6751 snprintf((char *)fcn->name, len, "<lua.%s>", name);
6752 fcn->function_ref = ref;
6753
6754 /* List head */
6755 akl->list.n = akl->list.p = NULL;
6756
6757 /* converter keyword. */
6758 len = strlen("lua.") + strlen(name) + 1;
6759 akl->kw[0].kw = calloc(1, len);
6760 if (!akl->kw[0].kw)
6761 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6762
6763 snprintf((char *)akl->kw[0].kw, len, "lua.%s", name);
6764
Thierry FOURNIER / OZON.IO02564fd2016-11-12 11:07:05 +01006765 /* Check required environment. Only accepted "http" or "tcp". */
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006766 if (strcmp(env, "tcp") == 0)
6767 akl->kw[0].parse = action_register_service_tcp;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006768 else if (strcmp(env, "http") == 0)
6769 akl->kw[0].parse = action_register_service_http;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006770 else
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006771 WILL_LJMP(luaL_error(L, "lua service environment '%s' is unknown. "
6772 "'tcp' or 'http' are expected."));
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006773
6774 akl->kw[0].match_pfx = 0;
6775 akl->kw[0].private = fcn;
6776
6777 /* End of array. */
6778 memset(&akl->kw[1], 0, sizeof(*akl->kw));
6779
6780 /* Register this new converter */
6781 service_keywords_register(akl);
6782
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006783 return 0;
6784}
6785
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006786/* This function initialises Lua cli handler. It copies the
6787 * arguments in the Lua stack and create channel IO objects.
6788 */
6789static int hlua_cli_parse_fct(char **args, struct appctx *appctx, void *private)
6790{
6791 struct hlua *hlua;
6792 struct hlua_function *fcn;
6793 int i;
6794 const char *error;
6795
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006796 fcn = private;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006797 appctx->ctx.hlua_cli.fcn = private;
6798
6799 hlua = pool_alloc2(pool2_hlua);
6800 if (!hlua) {
6801 SEND_ERR(NULL, "Lua cli '%s': out of memory.\n", fcn->name);
Thierry FOURNIER1be34152016-12-17 12:09:51 +01006802 return 1;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006803 }
6804 HLUA_INIT(hlua);
6805 appctx->ctx.hlua_cli.hlua = hlua;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006806
6807 /* Create task used by signal to wakeup applets.
6808 * We use the same wakeup fonction than the Lua applet_tcp and
6809 * applet_http. It is absolutely compatible.
6810 */
Thierry FOURNIER4325ab72017-07-12 11:53:38 +02006811 appctx->ctx.hlua_cli.task = task_new(1UL << tid);
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006812 if (!appctx->ctx.hlua_cli.task) {
Thierry FOURNIERffbf5692016-12-16 11:14:06 +01006813 SEND_ERR(NULL, "Lua cli '%s': out of memory.\n", fcn->name);
Thierry FOURNIER1be34152016-12-17 12:09:51 +01006814 goto error;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006815 }
6816 appctx->ctx.hlua_cli.task->nice = 0;
6817 appctx->ctx.hlua_cli.task->context = appctx;
6818 appctx->ctx.hlua_cli.task->process = hlua_applet_wakeup;
6819
6820 /* Initialises the Lua context */
6821 if (!hlua_ctx_init(hlua, appctx->ctx.hlua_cli.task)) {
6822 SEND_ERR(NULL, "Lua cli '%s': can't initialize Lua context.\n", fcn->name);
Thierry FOURNIER1be34152016-12-17 12:09:51 +01006823 goto error;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006824 }
6825
6826 /* The following Lua calls can fail. */
6827 if (!SET_SAFE_LJMP(hlua->T)) {
6828 if (lua_type(hlua->T, -1) == LUA_TSTRING)
6829 error = lua_tostring(hlua->T, -1);
6830 else
6831 error = "critical error";
6832 SEND_ERR(NULL, "Lua cli '%s': %s.\n", fcn->name, error);
6833 goto error;
6834 }
6835
6836 /* Check stack available size. */
6837 if (!lua_checkstack(hlua->T, 2)) {
6838 SEND_ERR(NULL, "Lua cli '%s': full stack.\n", fcn->name);
6839 goto error;
6840 }
6841
6842 /* Restore the function in the stack. */
6843 lua_rawgeti(hlua->T, LUA_REGISTRYINDEX, fcn->function_ref);
6844
6845 /* Once the arguments parsed, the CLI is like an AppletTCP,
6846 * so push AppletTCP in the stack.
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006847 */
6848 if (!hlua_applet_tcp_new(hlua->T, appctx)) {
6849 SEND_ERR(NULL, "Lua cli '%s': full stack.\n", fcn->name);
6850 goto error;
6851 }
6852 hlua->nargs = 1;
6853
6854 /* push keywords in the stack. */
6855 for (i = 0; *args[i]; i++) {
6856 /* Check stack available size. */
6857 if (!lua_checkstack(hlua->T, 1)) {
6858 SEND_ERR(NULL, "Lua cli '%s': full stack.\n", fcn->name);
6859 goto error;
6860 }
6861 lua_pushstring(hlua->T, args[i]);
6862 hlua->nargs++;
6863 }
6864
6865 /* We must initialize the execution timeouts. */
6866 hlua->max_time = hlua_timeout_session;
6867
6868 /* At this point the execution is safe. */
6869 RESET_SAFE_LJMP(hlua->T);
6870
6871 /* It's ok */
6872 return 0;
6873
6874 /* It's not ok. */
6875error:
6876 RESET_SAFE_LJMP(hlua->T);
6877 hlua_ctx_destroy(hlua);
Thierry FOURNIER1be34152016-12-17 12:09:51 +01006878 appctx->ctx.hlua_cli.hlua = NULL;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006879 return 1;
6880}
6881
6882static int hlua_cli_io_handler_fct(struct appctx *appctx)
6883{
6884 struct hlua *hlua;
6885 struct stream_interface *si;
6886 struct hlua_function *fcn;
6887
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006888 hlua = appctx->ctx.hlua_cli.hlua;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006889 si = appctx->owner;
Willy Tarreau8ae4f752016-12-14 15:41:45 +01006890 fcn = appctx->ctx.hlua_cli.fcn;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006891
6892 /* If the stream is disconnect or closed, ldo nothing. */
6893 if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO))
6894 return 1;
6895
6896 /* Execute the function. */
6897 switch (hlua_ctx_resume(hlua, 1)) {
6898
6899 /* finished. */
6900 case HLUA_E_OK:
6901 return 1;
6902
6903 /* yield. */
6904 case HLUA_E_AGAIN:
6905 /* We want write. */
6906 if (HLUA_IS_WAKERESWR(hlua))
6907 si_applet_cant_put(si);
6908 /* Set the timeout. */
6909 if (hlua->wake_time != TICK_ETERNITY)
6910 task_schedule(hlua->task, hlua->wake_time);
6911 return 0;
6912
6913 /* finished with error. */
6914 case HLUA_E_ERRMSG:
6915 /* Display log. */
6916 SEND_ERR(NULL, "Lua cli '%s': %s.\n",
6917 fcn->name, lua_tostring(hlua->T, -1));
6918 lua_pop(hlua->T, 1);
6919 return 1;
6920
6921 case HLUA_E_ERR:
6922 /* Display log. */
6923 SEND_ERR(NULL, "Lua cli '%s' return an unknown error.\n",
6924 fcn->name);
6925 return 1;
6926
6927 default:
6928 return 1;
6929 }
6930
6931 return 1;
6932}
6933
6934static void hlua_cli_io_release_fct(struct appctx *appctx)
6935{
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006936 hlua_ctx_destroy(appctx->ctx.hlua_cli.hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006937 appctx->ctx.hlua_cli.hlua = NULL;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006938}
6939
6940/* This function is an LUA binding used for registering
6941 * new keywords in the cli. It expects a list of keywords
6942 * which are the "path". It is limited to 5 keywords. A
6943 * description of the command, a function to be executed
6944 * for the parsing and a function for io handlers.
6945 */
6946__LJMP static int hlua_register_cli(lua_State *L)
6947{
6948 struct cli_kw_list *cli_kws;
6949 const char *message;
6950 int ref_io;
6951 int len;
6952 struct hlua_function *fcn;
6953 int index;
6954 int i;
6955
6956 MAY_LJMP(check_args(L, 3, "register_cli"));
6957
6958 /* First argument : an array of maximum 5 keywords. */
6959 if (!lua_istable(L, 1))
6960 WILL_LJMP(luaL_argerror(L, 1, "1st argument must be a table"));
6961
6962 /* Second argument : string with contextual message. */
6963 message = MAY_LJMP(luaL_checkstring(L, 2));
6964
6965 /* Third and fourth argument : lua function. */
6966 ref_io = MAY_LJMP(hlua_checkfunction(L, 3));
6967
6968 /* Allocate and fill the sample fetch keyword struct. */
6969 cli_kws = calloc(1, sizeof(*cli_kws) + sizeof(struct cli_kw) * 2);
6970 if (!cli_kws)
6971 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6972 fcn = calloc(1, sizeof(*fcn));
6973 if (!fcn)
6974 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6975
6976 /* Fill path. */
6977 index = 0;
6978 lua_pushnil(L);
6979 while(lua_next(L, 1) != 0) {
6980 if (index >= 5)
6981 WILL_LJMP(luaL_argerror(L, 1, "1st argument must be a table with a maximum of 5 entries"));
6982 if (lua_type(L, -1) != LUA_TSTRING)
6983 WILL_LJMP(luaL_argerror(L, 1, "1st argument must be a table filled with strings"));
6984 cli_kws->kw[0].str_kw[index] = strdup(lua_tostring(L, -1));
6985 if (!cli_kws->kw[0].str_kw[index])
6986 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6987 index++;
6988 lua_pop(L, 1);
6989 }
6990
6991 /* Copy help message. */
6992 cli_kws->kw[0].usage = strdup(message);
6993 if (!cli_kws->kw[0].usage)
6994 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6995
6996 /* Fill fcn io handler. */
6997 len = strlen("<lua.cli>") + 1;
6998 for (i = 0; i < index; i++)
6999 len += strlen(cli_kws->kw[0].str_kw[i]) + 1;
7000 fcn->name = calloc(1, len);
7001 if (!fcn->name)
7002 WILL_LJMP(luaL_error(L, "lua out of memory error."));
7003 strncat((char *)fcn->name, "<lua.cli", len);
7004 for (i = 0; i < index; i++) {
7005 strncat((char *)fcn->name, ".", len);
7006 strncat((char *)fcn->name, cli_kws->kw[0].str_kw[i], len);
7007 }
7008 strncat((char *)fcn->name, ">", len);
7009 fcn->function_ref = ref_io;
7010
7011 /* Fill last entries. */
7012 cli_kws->kw[0].private = fcn;
7013 cli_kws->kw[0].parse = hlua_cli_parse_fct;
7014 cli_kws->kw[0].io_handler = hlua_cli_io_handler_fct;
7015 cli_kws->kw[0].io_release = hlua_cli_io_release_fct;
7016
7017 /* Register this new converter */
7018 cli_register_kw(cli_kws);
7019
7020 return 0;
7021}
7022
Thierry FOURNIERbd413492015-03-03 16:52:26 +01007023static int hlua_read_timeout(char **args, int section_type, struct proxy *curpx,
7024 struct proxy *defpx, const char *file, int line,
7025 char **err, unsigned int *timeout)
7026{
7027 const char *error;
7028
7029 error = parse_time_err(args[1], timeout, TIME_UNIT_MS);
7030 if (error && *error != '\0') {
7031 memprintf(err, "%s: invalid timeout", args[0]);
7032 return -1;
7033 }
7034 return 0;
7035}
7036
7037static int hlua_session_timeout(char **args, int section_type, struct proxy *curpx,
7038 struct proxy *defpx, const char *file, int line,
7039 char **err)
7040{
7041 return hlua_read_timeout(args, section_type, curpx, defpx,
7042 file, line, err, &hlua_timeout_session);
7043}
7044
7045static int hlua_task_timeout(char **args, int section_type, struct proxy *curpx,
7046 struct proxy *defpx, const char *file, int line,
7047 char **err)
7048{
7049 return hlua_read_timeout(args, section_type, curpx, defpx,
7050 file, line, err, &hlua_timeout_task);
7051}
7052
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007053static int hlua_applet_timeout(char **args, int section_type, struct proxy *curpx,
7054 struct proxy *defpx, const char *file, int line,
7055 char **err)
7056{
7057 return hlua_read_timeout(args, section_type, curpx, defpx,
7058 file, line, err, &hlua_timeout_applet);
7059}
7060
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01007061static int hlua_forced_yield(char **args, int section_type, struct proxy *curpx,
7062 struct proxy *defpx, const char *file, int line,
7063 char **err)
7064{
7065 char *error;
7066
7067 hlua_nb_instruction = strtoll(args[1], &error, 10);
7068 if (*error != '\0') {
7069 memprintf(err, "%s: invalid number", args[0]);
7070 return -1;
7071 }
7072 return 0;
7073}
7074
Willy Tarreau32f61e22015-03-18 17:54:59 +01007075static int hlua_parse_maxmem(char **args, int section_type, struct proxy *curpx,
7076 struct proxy *defpx, const char *file, int line,
7077 char **err)
7078{
7079 char *error;
7080
7081 if (*(args[1]) == 0) {
7082 memprintf(err, "'%s' expects an integer argument (Lua memory size in MB).\n", args[0]);
7083 return -1;
7084 }
7085 hlua_global_allocator.limit = strtoll(args[1], &error, 10) * 1024L * 1024L;
7086 if (*error != '\0') {
7087 memprintf(err, "%s: invalid number %s (error at '%c')", args[0], args[1], *error);
7088 return -1;
7089 }
7090 return 0;
7091}
7092
7093
Thierry FOURNIER6c9b52c2015-01-23 15:57:06 +01007094/* This function is called by the main configuration key "lua-load". It loads and
7095 * execute an lua file during the parsing of the HAProxy configuration file. It is
7096 * the main lua entry point.
7097 *
7098 * This funtion runs with the HAProxy keywords API. It returns -1 if an error is
7099 * occured, otherwise it returns 0.
7100 *
7101 * In some error case, LUA set an error message in top of the stack. This function
7102 * returns this error message in the HAProxy logs and pop it from the stack.
Thierry FOURNIERbabae282015-09-17 11:36:37 +02007103 *
7104 * This function can fail with an abort() due to an Lua critical error.
7105 * We are in the configuration parsing process of HAProxy, this abort() is
7106 * tolerated.
Thierry FOURNIER6c9b52c2015-01-23 15:57:06 +01007107 */
7108static int hlua_load(char **args, int section_type, struct proxy *curpx,
7109 struct proxy *defpx, const char *file, int line,
7110 char **err)
7111{
7112 int error;
7113
7114 /* Just load and compile the file. */
7115 error = luaL_loadfile(gL.T, args[1]);
7116 if (error) {
7117 memprintf(err, "error in lua file '%s': %s", args[1], lua_tostring(gL.T, -1));
7118 lua_pop(gL.T, 1);
7119 return -1;
7120 }
7121
7122 /* If no syntax error where detected, execute the code. */
7123 error = lua_pcall(gL.T, 0, LUA_MULTRET, 0);
7124 switch (error) {
7125 case LUA_OK:
7126 break;
7127 case LUA_ERRRUN:
7128 memprintf(err, "lua runtime error: %s\n", lua_tostring(gL.T, -1));
7129 lua_pop(gL.T, 1);
7130 return -1;
7131 case LUA_ERRMEM:
7132 memprintf(err, "lua out of memory error\n");
7133 return -1;
7134 case LUA_ERRERR:
7135 memprintf(err, "lua message handler error: %s\n", lua_tostring(gL.T, -1));
7136 lua_pop(gL.T, 1);
7137 return -1;
7138 case LUA_ERRGCMM:
7139 memprintf(err, "lua garbage collector error: %s\n", lua_tostring(gL.T, -1));
7140 lua_pop(gL.T, 1);
7141 return -1;
7142 default:
7143 memprintf(err, "lua unknonwn error: %s\n", lua_tostring(gL.T, -1));
7144 lua_pop(gL.T, 1);
7145 return -1;
7146 }
7147
7148 return 0;
7149}
7150
7151/* configuration keywords declaration */
7152static struct cfg_kw_list cfg_kws = {{ },{
Thierry FOURNIERbd413492015-03-03 16:52:26 +01007153 { CFG_GLOBAL, "lua-load", hlua_load },
7154 { CFG_GLOBAL, "tune.lua.session-timeout", hlua_session_timeout },
7155 { CFG_GLOBAL, "tune.lua.task-timeout", hlua_task_timeout },
Thierry FOURNIER56da1012015-10-01 08:42:31 +02007156 { CFG_GLOBAL, "tune.lua.service-timeout", hlua_applet_timeout },
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01007157 { CFG_GLOBAL, "tune.lua.forced-yield", hlua_forced_yield },
Willy Tarreau32f61e22015-03-18 17:54:59 +01007158 { CFG_GLOBAL, "tune.lua.maxmem", hlua_parse_maxmem },
Thierry FOURNIER6c9b52c2015-01-23 15:57:06 +01007159 { 0, NULL, NULL },
7160}};
7161
Thierry FOURNIERbabae282015-09-17 11:36:37 +02007162/* This function can fail with an abort() due to an Lua critical error.
7163 * We are in the initialisation process of HAProxy, this abort() is
7164 * tolerated.
7165 */
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007166int hlua_post_init()
7167{
7168 struct hlua_init_function *init;
7169 const char *msg;
7170 enum hlua_exec ret;
Thierry Fournierfd107a22016-02-19 19:57:23 +01007171 const char *error;
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007172
Thierry Fournier3d4a6752016-02-19 20:53:30 +01007173 /* Call post initialisation function in safe environement. */
7174 if (!SET_SAFE_LJMP(gL.T)) {
7175 if (lua_type(gL.T, -1) == LUA_TSTRING)
7176 error = lua_tostring(gL.T, -1);
7177 else
7178 error = "critical error";
7179 fprintf(stderr, "Lua post-init: %s.\n", error);
7180 exit(1);
7181 }
7182 hlua_fcn_post_init(gL.T);
7183 RESET_SAFE_LJMP(gL.T);
7184
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007185 list_for_each_entry(init, &hlua_init_functions, l) {
7186 lua_rawgeti(gL.T, LUA_REGISTRYINDEX, init->function_ref);
7187 ret = hlua_ctx_resume(&gL, 0);
7188 switch (ret) {
7189 case HLUA_E_OK:
7190 lua_pop(gL.T, -1);
7191 return 1;
7192 case HLUA_E_AGAIN:
7193 Alert("lua init: yield not allowed.\n");
7194 return 0;
7195 case HLUA_E_ERRMSG:
7196 msg = lua_tostring(gL.T, -1);
7197 Alert("lua init: %s.\n", msg);
7198 return 0;
7199 case HLUA_E_ERR:
7200 default:
7201 Alert("lua init: unknown runtime error.\n");
7202 return 0;
7203 }
7204 }
7205 return 1;
7206}
7207
Willy Tarreau32f61e22015-03-18 17:54:59 +01007208/* The memory allocator used by the Lua stack. <ud> is a pointer to the
7209 * allocator's context. <ptr> is the pointer to alloc/free/realloc. <osize>
7210 * is the previously allocated size or the kind of object in case of a new
7211 * allocation. <nsize> is the requested new size.
7212 */
7213static void *hlua_alloc(void *ud, void *ptr, size_t osize, size_t nsize)
7214{
7215 struct hlua_mem_allocator *zone = ud;
7216
7217 if (nsize == 0) {
7218 /* it's a free */
7219 if (ptr)
7220 zone->allocated -= osize;
7221 free(ptr);
7222 return NULL;
7223 }
7224
7225 if (!ptr) {
7226 /* it's a new allocation */
7227 if (zone->limit && zone->allocated + nsize > zone->limit)
7228 return NULL;
7229
7230 ptr = malloc(nsize);
7231 if (ptr)
7232 zone->allocated += nsize;
7233 return ptr;
7234 }
7235
7236 /* it's a realloc */
7237 if (zone->limit && zone->allocated + nsize - osize > zone->limit)
7238 return NULL;
7239
7240 ptr = realloc(ptr, nsize);
7241 if (ptr)
7242 zone->allocated += nsize - osize;
7243 return ptr;
7244}
7245
Thierry FOURNIERbabae282015-09-17 11:36:37 +02007246/* Ithis function can fail with an abort() due to an Lua critical error.
7247 * We are in the initialisation process of HAProxy, this abort() is
7248 * tolerated.
7249 */
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01007250void hlua_init(void)
7251{
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007252 int i;
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +01007253 int idx;
7254 struct sample_fetch *sf;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01007255 struct sample_conv *sc;
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +01007256 char *p;
Thierry Fournierfd107a22016-02-19 19:57:23 +01007257 const char *error_msg;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01007258#ifdef USE_OPENSSL
Willy Tarreau80f5fae2015-02-27 16:38:20 +01007259 struct srv_kw *kw;
7260 int tmp_error;
7261 char *error;
Thierry FOURNIER36d13742015-03-17 16:48:53 +01007262 char *args[] = { /* SSL client configuration. */
7263 "ssl",
7264 "verify",
7265 "none",
Thierry FOURNIER36d13742015-03-17 16:48:53 +01007266 NULL
7267 };
Willy Tarreau80f5fae2015-02-27 16:38:20 +01007268#endif
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007269
Thierry FOURNIER61ba0e22017-07-12 11:41:21 +02007270 SPIN_INIT(&hlua_global_lock);
7271
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01007272 /* Initialise struct hlua and com signals pool */
7273 pool2_hlua = create_pool("hlua", sizeof(struct hlua), MEM_F_SHARED);
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +01007274
Thierry FOURNIER6c9b52c2015-01-23 15:57:06 +01007275 /* Register configuration keywords. */
7276 cfg_register_keywords(&cfg_kws);
7277
Thierry FOURNIER380d0932015-01-23 14:27:52 +01007278 /* Init main lua stack. */
7279 gL.Mref = LUA_REFNIL;
Thierry FOURNIERa097fdf2015-03-03 15:17:35 +01007280 gL.flags = 0;
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +01007281 LIST_INIT(&gL.com);
Willy Tarreau42ef75f2017-04-12 21:40:29 +02007282 gL.T = lua_newstate(hlua_alloc, &hlua_global_allocator);
Thierry FOURNIER380d0932015-01-23 14:27:52 +01007283 hlua_sethlua(&gL);
7284 gL.Tref = LUA_REFNIL;
7285 gL.task = NULL;
7286
Thierry FOURNIERbabae282015-09-17 11:36:37 +02007287 /* From this point, until the end of the initialisation fucntion,
7288 * the Lua function can fail with an abort. We are in the initialisation
7289 * process of HAProxy, this abort() is tolerated.
7290 */
7291
Thierry FOURNIER380d0932015-01-23 14:27:52 +01007292 /* Initialise lua. */
7293 luaL_openlibs(gL.T);
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007294
Thierry Fournier75933d42016-01-21 09:30:18 +01007295 /* Set safe environment for the initialisation. */
7296 if (!SET_SAFE_LJMP(gL.T)) {
Thierry Fournierfd107a22016-02-19 19:57:23 +01007297 if (lua_type(gL.T, -1) == LUA_TSTRING)
7298 error_msg = lua_tostring(gL.T, -1);
7299 else
7300 error_msg = "critical error";
7301 fprintf(stderr, "Lua init: %s.\n", error_msg);
Thierry Fournier75933d42016-01-21 09:30:18 +01007302 exit(1);
7303 }
7304
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007305 /*
7306 *
7307 * Create "core" object.
7308 *
7309 */
7310
Thierry FOURNIERa2d8c652015-03-11 17:29:39 +01007311 /* This table entry is the object "core" base. */
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007312 lua_newtable(gL.T);
7313
7314 /* Push the loglevel constants. */
Willy Tarreau80f5fae2015-02-27 16:38:20 +01007315 for (i = 0; i < NB_LOG_LEVELS; i++)
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007316 hlua_class_const_int(gL.T, log_levels[i], i);
7317
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007318 /* Register special functions. */
7319 hlua_class_function(gL.T, "register_init", hlua_register_init);
Thierry FOURNIER24f33532015-01-23 12:13:00 +01007320 hlua_class_function(gL.T, "register_task", hlua_register_task);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01007321 hlua_class_function(gL.T, "register_fetches", hlua_register_fetches);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01007322 hlua_class_function(gL.T, "register_converters", hlua_register_converters);
Thierry FOURNIER8255a752015-09-23 21:03:35 +02007323 hlua_class_function(gL.T, "register_action", hlua_register_action);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007324 hlua_class_function(gL.T, "register_service", hlua_register_service);
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007325 hlua_class_function(gL.T, "register_cli", hlua_register_cli);
Thierry FOURNIER13416fe2015-02-17 15:01:59 +01007326 hlua_class_function(gL.T, "yield", hlua_yield);
Willy Tarreau59551662015-03-10 14:23:13 +01007327 hlua_class_function(gL.T, "set_nice", hlua_set_nice);
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01007328 hlua_class_function(gL.T, "sleep", hlua_sleep);
7329 hlua_class_function(gL.T, "msleep", hlua_msleep);
Thierry FOURNIER83758bb2015-02-04 13:21:04 +01007330 hlua_class_function(gL.T, "add_acl", hlua_add_acl);
7331 hlua_class_function(gL.T, "del_acl", hlua_del_acl);
7332 hlua_class_function(gL.T, "set_map", hlua_set_map);
7333 hlua_class_function(gL.T, "del_map", hlua_del_map);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007334 hlua_class_function(gL.T, "tcp", hlua_socket_new);
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +01007335 hlua_class_function(gL.T, "log", hlua_log);
7336 hlua_class_function(gL.T, "Debug", hlua_log_debug);
7337 hlua_class_function(gL.T, "Info", hlua_log_info);
7338 hlua_class_function(gL.T, "Warning", hlua_log_warning);
7339 hlua_class_function(gL.T, "Alert", hlua_log_alert);
Thierry FOURNIER0a99b892015-08-26 00:14:17 +02007340 hlua_class_function(gL.T, "done", hlua_done);
Thierry Fournierfb0b5462016-01-21 09:28:58 +01007341 hlua_fcn_reg_core_fcn(gL.T);
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007342
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007343 lua_setglobal(gL.T, "core");
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01007344
7345 /*
7346 *
Thierry FOURNIER3def3932015-04-07 11:27:54 +02007347 * Register class Map
7348 *
7349 */
7350
7351 /* This table entry is the object "Map" base. */
7352 lua_newtable(gL.T);
7353
7354 /* register pattern types. */
7355 for (i=0; i<PAT_MATCH_NUM; i++)
7356 hlua_class_const_int(gL.T, pat_match_names[i], i);
Thierry FOURNIER4dc71972017-01-28 08:33:08 +01007357 for (i=0; i<PAT_MATCH_NUM; i++) {
7358 snprintf(trash.str, trash.size, "_%s", pat_match_names[i]);
7359 hlua_class_const_int(gL.T, trash.str, i);
7360 }
Thierry FOURNIER3def3932015-04-07 11:27:54 +02007361
7362 /* register constructor. */
7363 hlua_class_function(gL.T, "new", hlua_map_new);
7364
7365 /* Create and fill the metatable. */
7366 lua_newtable(gL.T);
7367
7368 /* Create and fille the __index entry. */
7369 lua_pushstring(gL.T, "__index");
7370 lua_newtable(gL.T);
7371
7372 /* Register . */
7373 hlua_class_function(gL.T, "lookup", hlua_map_lookup);
7374 hlua_class_function(gL.T, "slookup", hlua_map_slookup);
7375
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007376 lua_rawset(gL.T, -3);
Thierry FOURNIER3def3932015-04-07 11:27:54 +02007377
Thierry Fournier45e78d72016-02-19 18:34:46 +01007378 /* Register previous table in the registry with reference and named entry.
7379 * The function hlua_register_metatable() pops the stack, so we
7380 * previously create a copy of the table.
7381 */
Thierry FOURNIER3def3932015-04-07 11:27:54 +02007382 lua_pushvalue(gL.T, -1); /* Copy the -1 entry and push it on the stack. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007383 class_map_ref = hlua_register_metatable(gL.T, CLASS_MAP);
Thierry FOURNIER3def3932015-04-07 11:27:54 +02007384
7385 /* Assign the metatable to the mai Map object. */
7386 lua_setmetatable(gL.T, -2);
7387
7388 /* Set a name to the table. */
7389 lua_setglobal(gL.T, "Map");
7390
7391 /*
7392 *
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01007393 * Register class Channel
7394 *
7395 */
7396
7397 /* Create and fill the metatable. */
7398 lua_newtable(gL.T);
7399
7400 /* Create and fille the __index entry. */
7401 lua_pushstring(gL.T, "__index");
7402 lua_newtable(gL.T);
7403
7404 /* Register . */
7405 hlua_class_function(gL.T, "get", hlua_channel_get);
7406 hlua_class_function(gL.T, "dup", hlua_channel_dup);
7407 hlua_class_function(gL.T, "getline", hlua_channel_getline);
7408 hlua_class_function(gL.T, "set", hlua_channel_set);
7409 hlua_class_function(gL.T, "append", hlua_channel_append);
7410 hlua_class_function(gL.T, "send", hlua_channel_send);
7411 hlua_class_function(gL.T, "forward", hlua_channel_forward);
7412 hlua_class_function(gL.T, "get_in_len", hlua_channel_get_in_len);
7413 hlua_class_function(gL.T, "get_out_len", hlua_channel_get_out_len);
Thierry FOURNIER / OZON.IO65192f32016-11-07 15:28:40 +01007414 hlua_class_function(gL.T, "is_full", hlua_channel_is_full);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01007415
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007416 lua_rawset(gL.T, -3);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01007417
7418 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007419 class_channel_ref = hlua_register_metatable(gL.T, CLASS_CHANNEL);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01007420
7421 /*
7422 *
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01007423 * Register class Fetches
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01007424 *
7425 */
7426
7427 /* Create and fill the metatable. */
7428 lua_newtable(gL.T);
7429
7430 /* Create and fille the __index entry. */
7431 lua_pushstring(gL.T, "__index");
7432 lua_newtable(gL.T);
7433
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +01007434 /* Browse existing fetches and create the associated
7435 * object method.
7436 */
7437 sf = NULL;
7438 while ((sf = sample_fetch_getnext(sf, &idx)) != NULL) {
7439
7440 /* Dont register the keywork if the arguments check function are
7441 * not safe during the runtime.
7442 */
7443 if ((sf->val_args != NULL) &&
7444 (sf->val_args != val_payload_lv) &&
7445 (sf->val_args != val_hdr))
7446 continue;
7447
7448 /* gL.Tua doesn't support '.' and '-' in the function names, replace it
7449 * by an underscore.
7450 */
7451 strncpy(trash.str, sf->kw, trash.size);
7452 trash.str[trash.size - 1] = '\0';
7453 for (p = trash.str; *p; p++)
7454 if (*p == '.' || *p == '-' || *p == '+')
7455 *p = '_';
7456
7457 /* Register the function. */
7458 lua_pushstring(gL.T, trash.str);
Willy Tarreau2ec22742015-03-10 14:27:20 +01007459 lua_pushlightuserdata(gL.T, sf);
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +01007460 lua_pushcclosure(gL.T, hlua_run_sample_fetch, 1);
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007461 lua_rawset(gL.T, -3);
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +01007462 }
7463
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007464 lua_rawset(gL.T, -3);
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01007465
7466 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007467 class_fetches_ref = hlua_register_metatable(gL.T, CLASS_FETCHES);
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01007468
7469 /*
7470 *
Thierry FOURNIER594afe72015-03-10 23:58:30 +01007471 * Register class Converters
7472 *
7473 */
7474
7475 /* Create and fill the metatable. */
7476 lua_newtable(gL.T);
7477
7478 /* Create and fill the __index entry. */
7479 lua_pushstring(gL.T, "__index");
7480 lua_newtable(gL.T);
7481
7482 /* Browse existing converters and create the associated
7483 * object method.
7484 */
7485 sc = NULL;
7486 while ((sc = sample_conv_getnext(sc, &idx)) != NULL) {
7487 /* Dont register the keywork if the arguments check function are
7488 * not safe during the runtime.
7489 */
7490 if (sc->val_args != NULL)
7491 continue;
7492
7493 /* gL.Tua doesn't support '.' and '-' in the function names, replace it
7494 * by an underscore.
7495 */
7496 strncpy(trash.str, sc->kw, trash.size);
7497 trash.str[trash.size - 1] = '\0';
7498 for (p = trash.str; *p; p++)
7499 if (*p == '.' || *p == '-' || *p == '+')
7500 *p = '_';
7501
7502 /* Register the function. */
7503 lua_pushstring(gL.T, trash.str);
7504 lua_pushlightuserdata(gL.T, sc);
7505 lua_pushcclosure(gL.T, hlua_run_sample_conv, 1);
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007506 lua_rawset(gL.T, -3);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01007507 }
7508
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007509 lua_rawset(gL.T, -3);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01007510
7511 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007512 class_converters_ref = hlua_register_metatable(gL.T, CLASS_CONVERTERS);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01007513
7514 /*
7515 *
Thierry FOURNIER08504f42015-03-16 14:17:08 +01007516 * Register class HTTP
7517 *
7518 */
7519
7520 /* Create and fill the metatable. */
7521 lua_newtable(gL.T);
7522
7523 /* Create and fille the __index entry. */
7524 lua_pushstring(gL.T, "__index");
7525 lua_newtable(gL.T);
7526
7527 /* Register Lua functions. */
7528 hlua_class_function(gL.T, "req_get_headers",hlua_http_req_get_headers);
7529 hlua_class_function(gL.T, "req_del_header", hlua_http_req_del_hdr);
7530 hlua_class_function(gL.T, "req_rep_header", hlua_http_req_rep_hdr);
7531 hlua_class_function(gL.T, "req_rep_value", hlua_http_req_rep_val);
7532 hlua_class_function(gL.T, "req_add_header", hlua_http_req_add_hdr);
7533 hlua_class_function(gL.T, "req_set_header", hlua_http_req_set_hdr);
7534 hlua_class_function(gL.T, "req_set_method", hlua_http_req_set_meth);
7535 hlua_class_function(gL.T, "req_set_path", hlua_http_req_set_path);
7536 hlua_class_function(gL.T, "req_set_query", hlua_http_req_set_query);
7537 hlua_class_function(gL.T, "req_set_uri", hlua_http_req_set_uri);
7538
7539 hlua_class_function(gL.T, "res_get_headers",hlua_http_res_get_headers);
7540 hlua_class_function(gL.T, "res_del_header", hlua_http_res_del_hdr);
7541 hlua_class_function(gL.T, "res_rep_header", hlua_http_res_rep_hdr);
7542 hlua_class_function(gL.T, "res_rep_value", hlua_http_res_rep_val);
7543 hlua_class_function(gL.T, "res_add_header", hlua_http_res_add_hdr);
7544 hlua_class_function(gL.T, "res_set_header", hlua_http_res_set_hdr);
Thierry FOURNIER35d70ef2015-08-26 16:21:56 +02007545 hlua_class_function(gL.T, "res_set_status", hlua_http_res_set_status);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01007546
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007547 lua_rawset(gL.T, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01007548
7549 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007550 class_http_ref = hlua_register_metatable(gL.T, CLASS_HTTP);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01007551
7552 /*
7553 *
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007554 * Register class AppletTCP
7555 *
7556 */
7557
7558 /* Create and fill the metatable. */
7559 lua_newtable(gL.T);
7560
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007561 /* Create and fille the __index entry. */
7562 lua_pushstring(gL.T, "__index");
7563 lua_newtable(gL.T);
7564
7565 /* Register Lua functions. */
Thierry FOURNIER / OZON.IO3e1d7912016-12-12 12:29:34 +01007566 hlua_class_function(gL.T, "getline", hlua_applet_tcp_getline);
7567 hlua_class_function(gL.T, "receive", hlua_applet_tcp_recv);
7568 hlua_class_function(gL.T, "send", hlua_applet_tcp_send);
7569 hlua_class_function(gL.T, "set_priv", hlua_applet_tcp_set_priv);
7570 hlua_class_function(gL.T, "get_priv", hlua_applet_tcp_get_priv);
Thierry FOURNIER / OZON.IO4394a2c2016-12-12 12:31:54 +01007571 hlua_class_function(gL.T, "set_var", hlua_applet_tcp_set_var);
7572 hlua_class_function(gL.T, "unset_var", hlua_applet_tcp_unset_var);
7573 hlua_class_function(gL.T, "get_var", hlua_applet_tcp_get_var);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007574
7575 lua_settable(gL.T, -3);
7576
7577 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007578 class_applet_tcp_ref = hlua_register_metatable(gL.T, CLASS_APPLET_TCP);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007579
7580 /*
7581 *
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02007582 * Register class AppletHTTP
7583 *
7584 */
7585
7586 /* Create and fill the metatable. */
7587 lua_newtable(gL.T);
7588
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02007589 /* Create and fille the __index entry. */
7590 lua_pushstring(gL.T, "__index");
7591 lua_newtable(gL.T);
7592
7593 /* Register Lua functions. */
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01007594 hlua_class_function(gL.T, "set_priv", hlua_applet_http_set_priv);
7595 hlua_class_function(gL.T, "get_priv", hlua_applet_http_get_priv);
Thierry FOURNIER / OZON.IO4394a2c2016-12-12 12:31:54 +01007596 hlua_class_function(gL.T, "set_var", hlua_applet_http_set_var);
7597 hlua_class_function(gL.T, "unset_var", hlua_applet_http_unset_var);
7598 hlua_class_function(gL.T, "get_var", hlua_applet_http_get_var);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02007599 hlua_class_function(gL.T, "getline", hlua_applet_http_getline);
7600 hlua_class_function(gL.T, "receive", hlua_applet_http_recv);
7601 hlua_class_function(gL.T, "send", hlua_applet_http_send);
7602 hlua_class_function(gL.T, "add_header", hlua_applet_http_addheader);
7603 hlua_class_function(gL.T, "set_status", hlua_applet_http_status);
7604 hlua_class_function(gL.T, "start_response", hlua_applet_http_start_response);
7605
7606 lua_settable(gL.T, -3);
7607
7608 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007609 class_applet_http_ref = hlua_register_metatable(gL.T, CLASS_APPLET_HTTP);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02007610
7611 /*
7612 *
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01007613 * Register class TXN
7614 *
7615 */
7616
7617 /* Create and fill the metatable. */
7618 lua_newtable(gL.T);
7619
7620 /* Create and fille the __index entry. */
7621 lua_pushstring(gL.T, "__index");
7622 lua_newtable(gL.T);
7623
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01007624 /* Register Lua functions. */
Willy Tarreau59551662015-03-10 14:23:13 +01007625 hlua_class_function(gL.T, "set_priv", hlua_set_priv);
7626 hlua_class_function(gL.T, "get_priv", hlua_get_priv);
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +02007627 hlua_class_function(gL.T, "set_var", hlua_set_var);
Christopher Faulet85d79c92016-11-09 16:54:56 +01007628 hlua_class_function(gL.T, "unset_var", hlua_unset_var);
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +02007629 hlua_class_function(gL.T, "get_var", hlua_get_var);
Thierry FOURNIER4bb375c2015-08-26 08:42:21 +02007630 hlua_class_function(gL.T, "done", hlua_txn_done);
Thierry FOURNIER2cce3532015-03-16 12:04:16 +01007631 hlua_class_function(gL.T, "set_loglevel",hlua_txn_set_loglevel);
7632 hlua_class_function(gL.T, "set_tos", hlua_txn_set_tos);
7633 hlua_class_function(gL.T, "set_mark", hlua_txn_set_mark);
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +01007634 hlua_class_function(gL.T, "deflog", hlua_txn_deflog);
7635 hlua_class_function(gL.T, "log", hlua_txn_log);
7636 hlua_class_function(gL.T, "Debug", hlua_txn_log_debug);
7637 hlua_class_function(gL.T, "Info", hlua_txn_log_info);
7638 hlua_class_function(gL.T, "Warning", hlua_txn_log_warning);
7639 hlua_class_function(gL.T, "Alert", hlua_txn_log_alert);
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01007640
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007641 lua_rawset(gL.T, -3);
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01007642
7643 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007644 class_txn_ref = hlua_register_metatable(gL.T, CLASS_TXN);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007645
7646 /*
7647 *
7648 * Register class Socket
7649 *
7650 */
7651
7652 /* Create and fill the metatable. */
7653 lua_newtable(gL.T);
7654
7655 /* Create and fille the __index entry. */
7656 lua_pushstring(gL.T, "__index");
7657 lua_newtable(gL.T);
7658
Baptiste Assmann84bb4932015-03-02 21:40:06 +01007659#ifdef USE_OPENSSL
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007660 hlua_class_function(gL.T, "connect_ssl", hlua_socket_connect_ssl);
Baptiste Assmann84bb4932015-03-02 21:40:06 +01007661#endif
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007662 hlua_class_function(gL.T, "connect", hlua_socket_connect);
7663 hlua_class_function(gL.T, "send", hlua_socket_send);
7664 hlua_class_function(gL.T, "receive", hlua_socket_receive);
7665 hlua_class_function(gL.T, "close", hlua_socket_close);
7666 hlua_class_function(gL.T, "getpeername", hlua_socket_getpeername);
7667 hlua_class_function(gL.T, "getsockname", hlua_socket_getsockname);
7668 hlua_class_function(gL.T, "setoption", hlua_socket_setoption);
7669 hlua_class_function(gL.T, "settimeout", hlua_socket_settimeout);
7670
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007671 lua_rawset(gL.T, -3); /* Push the last 2 entries in the table at index -3 */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007672
7673 /* Register the garbage collector entry. */
7674 lua_pushstring(gL.T, "__gc");
7675 lua_pushcclosure(gL.T, hlua_socket_gc, 0);
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007676 lua_rawset(gL.T, -3); /* Push the last 2 entries in the table at index -3 */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007677
7678 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007679 class_socket_ref = hlua_register_metatable(gL.T, CLASS_SOCKET);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007680
7681 /* Proxy and server configuration initialisation. */
7682 memset(&socket_proxy, 0, sizeof(socket_proxy));
7683 init_new_proxy(&socket_proxy);
7684 socket_proxy.parent = NULL;
7685 socket_proxy.last_change = now.tv_sec;
7686 socket_proxy.id = "LUA-SOCKET";
7687 socket_proxy.cap = PR_CAP_FE | PR_CAP_BE;
7688 socket_proxy.maxconn = 0;
7689 socket_proxy.accept = NULL;
7690 socket_proxy.options2 |= PR_O2_INDEPSTR;
7691 socket_proxy.srv = NULL;
7692 socket_proxy.conn_retries = 0;
7693 socket_proxy.timeout.connect = 5000; /* By default the timeout connection is 5s. */
7694
7695 /* Init TCP server: unchanged parameters */
7696 memset(&socket_tcp, 0, sizeof(socket_tcp));
7697 socket_tcp.next = NULL;
7698 socket_tcp.proxy = &socket_proxy;
7699 socket_tcp.obj_type = OBJ_TYPE_SERVER;
7700 LIST_INIT(&socket_tcp.actconns);
7701 LIST_INIT(&socket_tcp.pendconns);
Christopher Faulet40a007c2017-07-03 15:41:01 +02007702 socket_tcp.priv_conns = NULL;
7703 socket_tcp.idle_conns = NULL;
7704 socket_tcp.safe_conns = NULL;
Emeric Brun52a91d32017-08-31 14:41:55 +02007705 socket_tcp.next_state = SRV_ST_RUNNING; /* early server setup */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007706 socket_tcp.last_change = 0;
7707 socket_tcp.id = "LUA-TCP-CONN";
7708 socket_tcp.check.state &= ~CHK_ST_ENABLED; /* Disable health checks. */
7709 socket_tcp.agent.state &= ~CHK_ST_ENABLED; /* Disable health checks. */
7710 socket_tcp.pp_opts = 0; /* Remove proxy protocol. */
7711
7712 /* XXX: Copy default parameter from default server,
7713 * but the default server is not initialized.
7714 */
7715 socket_tcp.maxqueue = socket_proxy.defsrv.maxqueue;
7716 socket_tcp.minconn = socket_proxy.defsrv.minconn;
7717 socket_tcp.maxconn = socket_proxy.defsrv.maxconn;
7718 socket_tcp.slowstart = socket_proxy.defsrv.slowstart;
7719 socket_tcp.onerror = socket_proxy.defsrv.onerror;
7720 socket_tcp.onmarkeddown = socket_proxy.defsrv.onmarkeddown;
7721 socket_tcp.onmarkedup = socket_proxy.defsrv.onmarkedup;
7722 socket_tcp.consecutive_errors_limit = socket_proxy.defsrv.consecutive_errors_limit;
7723 socket_tcp.uweight = socket_proxy.defsrv.iweight;
7724 socket_tcp.iweight = socket_proxy.defsrv.iweight;
7725
7726 socket_tcp.check.status = HCHK_STATUS_INI;
7727 socket_tcp.check.rise = socket_proxy.defsrv.check.rise;
7728 socket_tcp.check.fall = socket_proxy.defsrv.check.fall;
7729 socket_tcp.check.health = socket_tcp.check.rise; /* socket, but will fall down at first failure */
7730 socket_tcp.check.server = &socket_tcp;
7731
7732 socket_tcp.agent.status = HCHK_STATUS_INI;
7733 socket_tcp.agent.rise = socket_proxy.defsrv.agent.rise;
7734 socket_tcp.agent.fall = socket_proxy.defsrv.agent.fall;
7735 socket_tcp.agent.health = socket_tcp.agent.rise; /* socket, but will fall down at first failure */
7736 socket_tcp.agent.server = &socket_tcp;
7737
Willy Tarreaua261e9b2016-12-22 20:44:00 +01007738 socket_tcp.xprt = xprt_get(XPRT_RAW);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007739
7740#ifdef USE_OPENSSL
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007741 /* Init TCP server: unchanged parameters */
7742 memset(&socket_ssl, 0, sizeof(socket_ssl));
7743 socket_ssl.next = NULL;
7744 socket_ssl.proxy = &socket_proxy;
7745 socket_ssl.obj_type = OBJ_TYPE_SERVER;
7746 LIST_INIT(&socket_ssl.actconns);
7747 LIST_INIT(&socket_ssl.pendconns);
Christopher Faulet40a007c2017-07-03 15:41:01 +02007748 socket_tcp.priv_conns = NULL;
7749 socket_tcp.idle_conns = NULL;
7750 socket_tcp.safe_conns = NULL;
Emeric Brun52a91d32017-08-31 14:41:55 +02007751 socket_ssl.next_state = SRV_ST_RUNNING; /* early server setup */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007752 socket_ssl.last_change = 0;
7753 socket_ssl.id = "LUA-SSL-CONN";
7754 socket_ssl.check.state &= ~CHK_ST_ENABLED; /* Disable health checks. */
7755 socket_ssl.agent.state &= ~CHK_ST_ENABLED; /* Disable health checks. */
7756 socket_ssl.pp_opts = 0; /* Remove proxy protocol. */
7757
7758 /* XXX: Copy default parameter from default server,
7759 * but the default server is not initialized.
7760 */
7761 socket_ssl.maxqueue = socket_proxy.defsrv.maxqueue;
7762 socket_ssl.minconn = socket_proxy.defsrv.minconn;
7763 socket_ssl.maxconn = socket_proxy.defsrv.maxconn;
7764 socket_ssl.slowstart = socket_proxy.defsrv.slowstart;
7765 socket_ssl.onerror = socket_proxy.defsrv.onerror;
7766 socket_ssl.onmarkeddown = socket_proxy.defsrv.onmarkeddown;
7767 socket_ssl.onmarkedup = socket_proxy.defsrv.onmarkedup;
7768 socket_ssl.consecutive_errors_limit = socket_proxy.defsrv.consecutive_errors_limit;
7769 socket_ssl.uweight = socket_proxy.defsrv.iweight;
7770 socket_ssl.iweight = socket_proxy.defsrv.iweight;
7771
7772 socket_ssl.check.status = HCHK_STATUS_INI;
7773 socket_ssl.check.rise = socket_proxy.defsrv.check.rise;
7774 socket_ssl.check.fall = socket_proxy.defsrv.check.fall;
7775 socket_ssl.check.health = socket_ssl.check.rise; /* socket, but will fall down at first failure */
7776 socket_ssl.check.server = &socket_ssl;
7777
7778 socket_ssl.agent.status = HCHK_STATUS_INI;
7779 socket_ssl.agent.rise = socket_proxy.defsrv.agent.rise;
7780 socket_ssl.agent.fall = socket_proxy.defsrv.agent.fall;
7781 socket_ssl.agent.health = socket_ssl.agent.rise; /* socket, but will fall down at first failure */
7782 socket_ssl.agent.server = &socket_ssl;
7783
Thierry FOURNIER36d13742015-03-17 16:48:53 +01007784 socket_ssl.use_ssl = 1;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01007785 socket_ssl.xprt = xprt_get(XPRT_SSL);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007786
Thierry FOURNIER36d13742015-03-17 16:48:53 +01007787 for (idx = 0; args[idx] != NULL; idx++) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007788 if ((kw = srv_find_kw(args[idx])) != NULL) { /* Maybe it's registered server keyword */
7789 /*
7790 *
7791 * If the keyword is not known, we can search in the registered
7792 * server keywords. This is usefull to configure special SSL
7793 * features like client certificates and ssl_verify.
7794 *
7795 */
7796 tmp_error = kw->parse(args, &idx, &socket_proxy, &socket_ssl, &error);
7797 if (tmp_error != 0) {
7798 fprintf(stderr, "INTERNAL ERROR: %s\n", error);
7799 abort(); /* This must be never arrives because the command line
7800 not editable by the user. */
7801 }
7802 idx += kw->skip;
7803 }
7804 }
7805
7806 /* Initialize SSL server. */
Willy Tarreau17d45382016-12-22 21:16:08 +01007807 if (socket_ssl.xprt->prepare_srv)
7808 socket_ssl.xprt->prepare_srv(&socket_ssl);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007809#endif
Thierry Fournier75933d42016-01-21 09:30:18 +01007810
7811 RESET_SAFE_LJMP(gL.T);
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01007812}
Willy Tarreaubb57d942016-12-21 19:04:56 +01007813
7814__attribute__((constructor))
7815static void __hlua_init(void)
7816{
7817 char *ptr = NULL;
7818 memprintf(&ptr, "Built with Lua version : %s", LUA_RELEASE);
7819 hap_register_build_opts(ptr, 1);
7820}