blob: 761fa7f3e593dd474cf8a9d5cbc3acecf6a98ee9 [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;
Olivier Houchard9aaf7782017-09-13 18:30:23 +02001524 struct connection *c = cs_conn(objt_cs(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 FOURNIER952939d2017-09-01 14:17:32 +02001582 struct xref *peer;
1583
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001584 /* Remove my link in the original object. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001585 peer = xref_get_peer_and_lock(&appctx->ctx.hlua_cosocket.xref);
1586 if (peer)
1587 xref_disconnect(&appctx->ctx.hlua_cosocket.xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001588
1589 /* Wake all the task waiting for me. */
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001590 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_read);
1591 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_write);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001592}
1593
1594/* If the garbage collectio of the object is launch, nobody
Willy Tarreau87b09662015-04-03 00:22:06 +02001595 * uses this object. If the stream does not exists, just quit.
1596 * Send the shutdown signal to the stream. In some cases,
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001597 * pending signal can rest in the read and write lists. destroy
1598 * it.
1599 */
1600__LJMP static int hlua_socket_gc(lua_State *L)
1601{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001602 struct hlua_socket *socket;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001603 struct appctx *appctx;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001604 struct xref *peer;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001605
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001606 MAY_LJMP(check_args(L, 1, "__gc"));
1607
1608 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001609 peer = xref_get_peer_and_lock(&socket->xref);
1610 if (!peer)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001611 return 0;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001612 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001613
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001614 /* Set the flag which destroy the session. */
Thierry FOURNIERb13b20a2017-07-16 20:48:54 +02001615 appctx->ctx.hlua_cosocket.die = 1;
1616 appctx_wakeup(appctx);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001617
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001618 /* Remove all reference between the Lua stack and the coroutine stream. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001619 xref_disconnect(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001620 return 0;
1621}
1622
1623/* The close function send shutdown signal and break the
Willy Tarreau87b09662015-04-03 00:22:06 +02001624 * links between the stream and the object.
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001625 */
1626__LJMP static int hlua_socket_close(lua_State *L)
1627{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001628 struct hlua_socket *socket;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001629 struct appctx *appctx;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001630 struct xref *peer;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001631
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001632 MAY_LJMP(check_args(L, 1, "close"));
1633
1634 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02001635
1636 /* Check if we run on the same thread than the xreator thread.
1637 * We cannot access to the socket if the thread is different.
1638 */
1639 if (socket->tid != tid)
1640 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
1641
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001642 peer = xref_get_peer_and_lock(&socket->xref);
1643 if (!peer)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001644 return 0;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001645 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001646
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001647 /* Set the flag which destroy the session. */
Thierry FOURNIERb13b20a2017-07-16 20:48:54 +02001648 appctx->ctx.hlua_cosocket.die = 1;
1649 appctx_wakeup(appctx);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001650
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001651 /* Remove all reference between the Lua stack and the coroutine stream. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001652 xref_disconnect(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001653 return 0;
1654}
1655
1656/* This Lua function assumes that the stack contain three parameters.
1657 * 1 - USERDATA containing a struct socket
1658 * 2 - INTEGER with values of the macro defined below
1659 * If the integer is -1, we must read at most one line.
1660 * If the integer is -2, we ust read all the data until the
1661 * end of the stream.
1662 * If the integer is positive value, we must read a number of
1663 * bytes corresponding to this value.
1664 */
1665#define HLSR_READ_LINE (-1)
1666#define HLSR_READ_ALL (-2)
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01001667__LJMP static int hlua_socket_receive_yield(struct lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001668{
1669 struct hlua_socket *socket = MAY_LJMP(hlua_checksocket(L, 1));
1670 int wanted = lua_tointeger(L, 2);
1671 struct hlua *hlua = hlua_gethlua(L);
1672 struct appctx *appctx;
1673 int len;
1674 int nblk;
1675 char *blk1;
1676 int len1;
1677 char *blk2;
1678 int len2;
Thierry FOURNIER00543922015-03-09 18:35:06 +01001679 int skip_at_end = 0;
Willy Tarreau81389672015-03-10 12:03:52 +01001680 struct channel *oc;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001681 struct stream_interface *si;
1682 struct stream *s;
1683 struct xref *peer;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001684
1685 /* Check if this lua stack is schedulable. */
1686 if (!hlua || !hlua->task)
1687 WILL_LJMP(luaL_error(L, "The 'receive' function is only allowed in "
1688 "'frontend', 'backend' or 'task'"));
1689
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02001690 /* Check if we run on the same thread than the xreator thread.
1691 * We cannot access to the socket if the thread is different.
1692 */
1693 if (socket->tid != tid)
1694 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
1695
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001696 /* check for connection break. If some data where read, return it. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001697 peer = xref_get_peer_and_lock(&socket->xref);
1698 if (!peer)
1699 goto no_peer;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001700 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
1701 si = appctx->owner;
1702 s = si_strm(si);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001703
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001704 oc = &s->res;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001705 if (wanted == HLSR_READ_LINE) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001706 /* Read line. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02001707 nblk = co_getline_nc(oc, &blk1, &len1, &blk2, &len2);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001708 if (nblk < 0) /* Connection close. */
1709 goto connection_closed;
1710 if (nblk == 0) /* No data avalaible. */
1711 goto connection_empty;
Thierry FOURNIER00543922015-03-09 18:35:06 +01001712
1713 /* remove final \r\n. */
1714 if (nblk == 1) {
1715 if (blk1[len1-1] == '\n') {
1716 len1--;
1717 skip_at_end++;
1718 if (blk1[len1-1] == '\r') {
1719 len1--;
1720 skip_at_end++;
1721 }
1722 }
1723 }
1724 else {
1725 if (blk2[len2-1] == '\n') {
1726 len2--;
1727 skip_at_end++;
1728 if (blk2[len2-1] == '\r') {
1729 len2--;
1730 skip_at_end++;
1731 }
1732 }
1733 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001734 }
1735
1736 else if (wanted == HLSR_READ_ALL) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001737 /* Read all the available data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02001738 nblk = co_getblk_nc(oc, &blk1, &len1, &blk2, &len2);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001739 if (nblk < 0) /* Connection close. */
1740 goto connection_closed;
1741 if (nblk == 0) /* No data avalaible. */
1742 goto connection_empty;
1743 }
1744
1745 else {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001746 /* Read a block of data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02001747 nblk = co_getblk_nc(oc, &blk1, &len1, &blk2, &len2);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001748 if (nblk < 0) /* Connection close. */
1749 goto connection_closed;
1750 if (nblk == 0) /* No data avalaible. */
1751 goto connection_empty;
1752
1753 if (len1 > wanted) {
1754 nblk = 1;
1755 len1 = wanted;
1756 } if (nblk == 2 && len1 + len2 > wanted)
1757 len2 = wanted - len1;
1758 }
1759
1760 len = len1;
1761
1762 luaL_addlstring(&socket->b, blk1, len1);
1763 if (nblk == 2) {
1764 len += len2;
1765 luaL_addlstring(&socket->b, blk2, len2);
1766 }
1767
1768 /* Consume data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02001769 co_skip(oc, len + skip_at_end);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001770
1771 /* Don't wait anything. */
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001772 stream_int_notify(&s->si[0]);
1773 stream_int_update_applet(&s->si[0]);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001774
1775 /* If the pattern reclaim to read all the data
1776 * in the connection, got out.
1777 */
1778 if (wanted == HLSR_READ_ALL)
1779 goto connection_empty;
1780 else if (wanted >= 0 && len < wanted)
1781 goto connection_empty;
1782
1783 /* Return result. */
1784 luaL_pushresult(&socket->b);
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001785 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001786 return 1;
1787
1788connection_closed:
1789
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001790 xref_unlock(&socket->xref, peer);
1791
1792no_peer:
1793
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001794 /* If the buffer containds data. */
1795 if (socket->b.n > 0) {
1796 luaL_pushresult(&socket->b);
1797 return 1;
1798 }
1799 lua_pushnil(L);
1800 lua_pushstring(L, "connection closed.");
1801 return 2;
1802
1803connection_empty:
1804
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001805 appctx = objt_appctx(s->si[0].end);
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001806 if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_read, hlua->task)) {
1807 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001808 WILL_LJMP(luaL_error(L, "out of memory"));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001809 }
1810 xref_unlock(&socket->xref, peer);
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +01001811 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_receive_yield, TICK_ETERNITY, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001812 return 0;
1813}
1814
1815/* This Lus function gets two parameters. The first one can be string
1816 * or a number. If the string is "*l", the user require one line. If
1817 * the string is "*a", the user require all the content of the stream.
1818 * If the value is a number, the user require a number of bytes equal
1819 * to the value. The default value is "*l" (a line).
1820 *
1821 * This paraeter with a variable type is converted in integer. This
1822 * integer takes this values:
1823 * -1 : read a line
1824 * -2 : read all the stream
1825 * >0 : amount if bytes.
1826 *
1827 * The second parameter is optinal. It contains a string that must be
1828 * concatenated with the read data.
1829 */
1830__LJMP static int hlua_socket_receive(struct lua_State *L)
1831{
1832 int wanted = HLSR_READ_LINE;
1833 const char *pattern;
1834 int type;
1835 char *error;
1836 size_t len;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001837 struct hlua_socket *socket;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001838
1839 if (lua_gettop(L) < 1 || lua_gettop(L) > 3)
1840 WILL_LJMP(luaL_error(L, "The 'receive' function requires between 1 and 3 arguments."));
1841
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001842 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001843
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02001844 /* Check if we run on the same thread than the xreator thread.
1845 * We cannot access to the socket if the thread is different.
1846 */
1847 if (socket->tid != tid)
1848 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
1849
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001850 /* check for pattern. */
1851 if (lua_gettop(L) >= 2) {
1852 type = lua_type(L, 2);
1853 if (type == LUA_TSTRING) {
1854 pattern = lua_tostring(L, 2);
1855 if (strcmp(pattern, "*a") == 0)
1856 wanted = HLSR_READ_ALL;
1857 else if (strcmp(pattern, "*l") == 0)
1858 wanted = HLSR_READ_LINE;
1859 else {
1860 wanted = strtoll(pattern, &error, 10);
1861 if (*error != '\0')
1862 WILL_LJMP(luaL_error(L, "Unsupported pattern."));
1863 }
1864 }
1865 else if (type == LUA_TNUMBER) {
1866 wanted = lua_tointeger(L, 2);
1867 if (wanted < 0)
1868 WILL_LJMP(luaL_error(L, "Unsupported size."));
1869 }
1870 }
1871
1872 /* Set pattern. */
1873 lua_pushinteger(L, wanted);
1874 lua_replace(L, 2);
1875
1876 /* init bufffer, and fiil it wih prefix. */
1877 luaL_buffinit(L, &socket->b);
1878
1879 /* Check prefix. */
1880 if (lua_gettop(L) >= 3) {
1881 if (lua_type(L, 3) != LUA_TSTRING)
1882 WILL_LJMP(luaL_error(L, "Expect a 'string' for the prefix"));
1883 pattern = lua_tolstring(L, 3, &len);
1884 luaL_addlstring(&socket->b, pattern, len);
1885 }
1886
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01001887 return __LJMP(hlua_socket_receive_yield(L, 0, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001888}
1889
1890/* Write the Lua input string in the output buffer.
1891 * This fucntion returns a yield if no space are available.
1892 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01001893static int hlua_socket_write_yield(struct lua_State *L,int status, lua_KContext ctx)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001894{
1895 struct hlua_socket *socket;
1896 struct hlua *hlua = hlua_gethlua(L);
1897 struct appctx *appctx;
1898 size_t buf_len;
1899 const char *buf;
1900 int len;
1901 int send_len;
1902 int sent;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001903 struct xref *peer;
1904 struct stream_interface *si;
1905 struct stream *s;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001906
1907 /* Check if this lua stack is schedulable. */
1908 if (!hlua || !hlua->task)
1909 WILL_LJMP(luaL_error(L, "The 'write' function is only allowed in "
1910 "'frontend', 'backend' or 'task'"));
1911
1912 /* Get object */
1913 socket = MAY_LJMP(hlua_checksocket(L, 1));
1914 buf = MAY_LJMP(luaL_checklstring(L, 2, &buf_len));
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01001915 sent = MAY_LJMP(luaL_checkinteger(L, 3));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001916
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02001917 /* Check if we run on the same thread than the xreator thread.
1918 * We cannot access to the socket if the thread is different.
1919 */
1920 if (socket->tid != tid)
1921 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
1922
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001923 /* check for connection break. If some data where read, return it. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001924 peer = xref_get_peer_and_lock(&socket->xref);
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001925 if (!peer) {
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001926 lua_pushinteger(L, -1);
1927 return 1;
1928 }
1929 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
1930 si = appctx->owner;
1931 s = si_strm(si);
1932
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001933 /* Check for connection close. */
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001934 if (channel_output_closed(&s->req)) {
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001935 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001936 lua_pushinteger(L, -1);
1937 return 1;
1938 }
1939
1940 /* Update the input buffer data. */
1941 buf += sent;
1942 send_len = buf_len - sent;
1943
1944 /* All the data are sent. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001945 if (sent >= buf_len) {
1946 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001947 return 1; /* Implicitly return the length sent. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001948 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001949
Thierry FOURNIER486d52a2015-03-09 17:51:43 +01001950 /* Check if the buffer is avalaible because HAProxy doesn't allocate
1951 * the request buffer if its not required.
1952 */
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001953 if (s->req.buf->size == 0) {
Christopher Faulet33834b12016-12-19 09:29:06 +01001954 appctx = hlua->task->context;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001955 if (!channel_alloc_buffer(&s->req, &appctx->buffer_wait))
Christopher Faulet33834b12016-12-19 09:29:06 +01001956 goto hlua_socket_write_yield_return;
Thierry FOURNIER486d52a2015-03-09 17:51:43 +01001957 }
1958
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001959 /* Check for avalaible space. */
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001960 len = buffer_total_space(s->req.buf);
Christopher Faulet33834b12016-12-19 09:29:06 +01001961 if (len <= 0) {
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001962 appctx = objt_appctx(s->si[0].end);
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001963 if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task)) {
1964 xref_unlock(&socket->xref, peer);
Christopher Faulet33834b12016-12-19 09:29:06 +01001965 WILL_LJMP(luaL_error(L, "out of memory"));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001966 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001967 goto hlua_socket_write_yield_return;
Christopher Faulet33834b12016-12-19 09:29:06 +01001968 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001969
1970 /* send data */
1971 if (len < send_len)
1972 send_len = len;
Willy Tarreau06d80a92017-10-19 14:32:15 +02001973 len = ci_putblk(&s->req, buf+sent, send_len);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001974
1975 /* "Not enough space" (-1), "Buffer too little to contain
1976 * the data" (-2) are not expected because the available length
1977 * is tested.
1978 * Other unknown error are also not expected.
1979 */
1980 if (len <= 0) {
Willy Tarreaubc18da12015-03-13 14:00:47 +01001981 if (len == -1)
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001982 s->req.flags |= CF_WAKE_WRITE;
Willy Tarreaubc18da12015-03-13 14:00:47 +01001983
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001984 MAY_LJMP(hlua_socket_close(L));
1985 lua_pop(L, 1);
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01001986 lua_pushinteger(L, -1);
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001987 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001988 return 1;
1989 }
1990
1991 /* update buffers. */
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001992 stream_int_notify(&s->si[0]);
1993 stream_int_update_applet(&s->si[0]);
Willy Tarreaude70fa12015-09-26 11:25:05 +02001994
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001995 s->req.rex = TICK_ETERNITY;
1996 s->res.wex = TICK_ETERNITY;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001997
1998 /* Update length sent. */
1999 lua_pop(L, 1);
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002000 lua_pushinteger(L, sent + len);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002001
2002 /* All the data buffer is sent ? */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002003 if (sent + len >= buf_len) {
2004 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002005 return 1;
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002006 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002007
2008hlua_socket_write_yield_return:
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002009 xref_unlock(&socket->xref, peer);
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +01002010 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_write_yield, TICK_ETERNITY, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002011 return 0;
2012}
2013
2014/* This function initiate the send of data. It just check the input
2015 * parameters and push an integer in the Lua stack that contain the
2016 * amount of data writed in the buffer. This is used by the function
2017 * "hlua_socket_write_yield" that can yield.
2018 *
2019 * The Lua function gets between 3 and 4 parameters. The first one is
2020 * the associated object. The second is a string buffer. The third is
2021 * a facultative integer that represents where is the buffer position
2022 * of the start of the data that can send. The first byte is the
2023 * position "1". The default value is "1". The fourth argument is a
2024 * facultative integer that represents where is the buffer position
2025 * of the end of the data that can send. The default is the last byte.
2026 */
2027static int hlua_socket_send(struct lua_State *L)
2028{
2029 int i;
2030 int j;
2031 const char *buf;
2032 size_t buf_len;
2033
2034 /* Check number of arguments. */
2035 if (lua_gettop(L) < 2 || lua_gettop(L) > 4)
2036 WILL_LJMP(luaL_error(L, "'send' needs between 2 and 4 arguments"));
2037
2038 /* Get the string. */
2039 buf = MAY_LJMP(luaL_checklstring(L, 2, &buf_len));
2040
2041 /* Get and check j. */
2042 if (lua_gettop(L) == 4) {
2043 j = MAY_LJMP(luaL_checkinteger(L, 4));
2044 if (j < 0)
2045 j = buf_len + j + 1;
2046 if (j > buf_len)
2047 j = buf_len + 1;
2048 lua_pop(L, 1);
2049 }
2050 else
2051 j = buf_len;
2052
2053 /* Get and check i. */
2054 if (lua_gettop(L) == 3) {
2055 i = MAY_LJMP(luaL_checkinteger(L, 3));
2056 if (i < 0)
2057 i = buf_len + i + 1;
2058 if (i > buf_len)
2059 i = buf_len + 1;
2060 lua_pop(L, 1);
2061 } else
2062 i = 1;
2063
2064 /* Check bth i and j. */
2065 if (i > j) {
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002066 lua_pushinteger(L, 0);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002067 return 1;
2068 }
2069 if (i == 0 && j == 0) {
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002070 lua_pushinteger(L, 0);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002071 return 1;
2072 }
2073 if (i == 0)
2074 i = 1;
2075 if (j == 0)
2076 j = 1;
2077
2078 /* Pop the string. */
2079 lua_pop(L, 1);
2080
2081 /* Update the buffer length. */
2082 buf += i - 1;
2083 buf_len = j - i + 1;
2084 lua_pushlstring(L, buf, buf_len);
2085
2086 /* This unsigned is used to remember the amount of sent data. */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002087 lua_pushinteger(L, 0);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002088
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002089 return MAY_LJMP(hlua_socket_write_yield(L, 0, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002090}
2091
Willy Tarreau22b0a682015-06-17 19:43:49 +02002092#define SOCKET_INFO_MAX_LEN sizeof("[0000:0000:0000:0000:0000:0000:0000:0000]:12345")
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002093__LJMP static inline int hlua_socket_info(struct lua_State *L, struct sockaddr_storage *addr)
2094{
2095 static char buffer[SOCKET_INFO_MAX_LEN];
2096 int ret;
2097 int len;
2098 char *p;
2099
2100 ret = addr_to_str(addr, buffer+1, SOCKET_INFO_MAX_LEN-1);
2101 if (ret <= 0) {
2102 lua_pushnil(L);
2103 return 1;
2104 }
2105
2106 if (ret == AF_UNIX) {
2107 lua_pushstring(L, buffer+1);
2108 return 1;
2109 }
2110 else if (ret == AF_INET6) {
2111 buffer[0] = '[';
2112 len = strlen(buffer);
2113 buffer[len] = ']';
2114 len++;
2115 buffer[len] = ':';
2116 len++;
2117 p = buffer;
2118 }
2119 else if (ret == AF_INET) {
2120 p = buffer + 1;
2121 len = strlen(p);
2122 p[len] = ':';
2123 len++;
2124 }
2125 else {
2126 lua_pushnil(L);
2127 return 1;
2128 }
2129
2130 if (port_to_str(addr, p + len, SOCKET_INFO_MAX_LEN-1 - len) <= 0) {
2131 lua_pushnil(L);
2132 return 1;
2133 }
2134
2135 lua_pushstring(L, p);
2136 return 1;
2137}
2138
2139/* Returns information about the peer of the connection. */
2140__LJMP static int hlua_socket_getpeername(struct lua_State *L)
2141{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002142 struct hlua_socket *socket;
2143 struct connection *conn;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002144 struct xref *peer;
2145 struct appctx *appctx;
2146 struct stream_interface *si;
2147 struct stream *s;
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002148 int ret;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002149
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002150 MAY_LJMP(check_args(L, 1, "getpeername"));
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 FOURNIER94a6bfc2017-07-12 12:10:44 +02002154 /* Check if we run on the same thread than the xreator thread.
2155 * We cannot access to the socket if the thread is different.
2156 */
2157 if (socket->tid != tid)
2158 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
2159
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002160 /* check for connection break. If some data where read, return it. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002161 peer = xref_get_peer_and_lock(&socket->xref);
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002162 if (!peer) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002163 lua_pushnil(L);
2164 return 1;
2165 }
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002166 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2167 si = appctx->owner;
2168 s = si_strm(si);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002169
Olivier Houchard9aaf7782017-09-13 18:30:23 +02002170 conn = cs_conn(objt_cs(s->si[1].end));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002171 if (!conn) {
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002172 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002173 lua_pushnil(L);
2174 return 1;
2175 }
2176
Willy Tarreaua71f6422016-11-16 17:00:14 +01002177 conn_get_to_addr(conn);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002178 if (!(conn->flags & CO_FL_ADDR_TO_SET)) {
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002179 xref_unlock(&socket->xref, peer);
Willy Tarreaua71f6422016-11-16 17:00:14 +01002180 lua_pushnil(L);
2181 return 1;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002182 }
2183
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002184 ret = MAY_LJMP(hlua_socket_info(L, &conn->addr.to));
2185 xref_unlock(&socket->xref, peer);
2186 return ret;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002187}
2188
2189/* Returns information about my connection side. */
2190static int hlua_socket_getsockname(struct lua_State *L)
2191{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002192 struct hlua_socket *socket;
2193 struct connection *conn;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002194 struct appctx *appctx;
2195 struct xref *peer;
2196 struct stream_interface *si;
2197 struct stream *s;
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002198 int ret;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002199
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002200 MAY_LJMP(check_args(L, 1, "getsockname"));
2201
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002202 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002203
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02002204 /* Check if we run on the same thread than the xreator thread.
2205 * We cannot access to the socket if the thread is different.
2206 */
2207 if (socket->tid != tid)
2208 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
2209
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002210 /* check for connection break. If some data where read, return it. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002211 peer = xref_get_peer_and_lock(&socket->xref);
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002212 if (!peer) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002213 lua_pushnil(L);
2214 return 1;
2215 }
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002216 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2217 si = appctx->owner;
2218 s = si_strm(si);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002219
Olivier Houchard9aaf7782017-09-13 18:30:23 +02002220 conn = cs_conn(objt_cs(s->si[1].end));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002221 if (!conn) {
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002222 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002223 lua_pushnil(L);
2224 return 1;
2225 }
2226
Willy Tarreaua71f6422016-11-16 17:00:14 +01002227 conn_get_from_addr(conn);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002228 if (!(conn->flags & CO_FL_ADDR_FROM_SET)) {
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002229 xref_unlock(&socket->xref, peer);
Willy Tarreaua71f6422016-11-16 17:00:14 +01002230 lua_pushnil(L);
2231 return 1;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002232 }
2233
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002234 ret = hlua_socket_info(L, &conn->addr.from);
2235 xref_unlock(&socket->xref, peer);
2236 return ret;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002237}
2238
2239/* This struct define the applet. */
Willy Tarreau30576452015-04-13 13:50:30 +02002240static struct applet update_applet = {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002241 .obj_type = OBJ_TYPE_APPLET,
2242 .name = "<LUA_TCP>",
2243 .fct = hlua_socket_handler,
2244 .release = hlua_socket_release,
2245};
2246
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002247__LJMP static int hlua_socket_connect_yield(struct lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002248{
2249 struct hlua_socket *socket = MAY_LJMP(hlua_checksocket(L, 1));
2250 struct hlua *hlua = hlua_gethlua(L);
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002251 struct xref *peer;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002252 struct appctx *appctx;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002253 struct stream_interface *si;
2254 struct stream *s;
2255
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02002256 /* Check if we run on the same thread than the xreator thread.
2257 * We cannot access to the socket if the thread is different.
2258 */
2259 if (socket->tid != tid)
2260 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
2261
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002262 /* check for connection break. If some data where read, return it. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002263 peer = xref_get_peer_and_lock(&socket->xref);
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002264 if (!peer) {
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002265 lua_pushnil(L);
2266 lua_pushstring(L, "Can't connect");
2267 return 2;
2268 }
2269 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2270 si = appctx->owner;
2271 s = si_strm(si);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002272
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02002273 /* Check if we run on the same thread than the xreator thread.
2274 * We cannot access to the socket if the thread is different.
2275 */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002276 if (socket->tid != tid) {
2277 xref_unlock(&socket->xref, peer);
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02002278 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002279 }
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02002280
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002281 /* Check for connection close. */
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002282 if (!hlua || channel_output_closed(&s->req)) {
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002283 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002284 lua_pushnil(L);
2285 lua_pushstring(L, "Can't connect");
2286 return 2;
2287 }
2288
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002289 appctx = objt_appctx(s->si[0].end);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002290
2291 /* Check for connection established. */
Thierry FOURNIER18d09902016-12-16 09:25:38 +01002292 if (appctx->ctx.hlua_cosocket.connected) {
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002293 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002294 lua_pushinteger(L, 1);
2295 return 1;
2296 }
2297
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002298 if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task)) {
2299 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002300 WILL_LJMP(luaL_error(L, "out of memory error"));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002301 }
2302 xref_unlock(&socket->xref, peer);
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +01002303 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_connect_yield, TICK_ETERNITY, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002304 return 0;
2305}
2306
2307/* This function fail or initite the connection. */
2308__LJMP static int hlua_socket_connect(struct lua_State *L)
2309{
2310 struct hlua_socket *socket;
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002311 int port = -1;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002312 const char *ip;
2313 struct connection *conn;
Thierry FOURNIER95ad96a2015-03-09 18:12:40 +01002314 struct hlua *hlua;
2315 struct appctx *appctx;
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002316 int low, high;
2317 struct sockaddr_storage *addr;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002318 struct xref *peer;
2319 struct stream_interface *si;
2320 struct stream *s;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002321
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002322 if (lua_gettop(L) < 2)
2323 WILL_LJMP(luaL_error(L, "connect: need at least 2 arguments"));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002324
2325 /* Get args. */
2326 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02002327
2328 /* Check if we run on the same thread than the xreator thread.
2329 * We cannot access to the socket if the thread is different.
2330 */
2331 if (socket->tid != tid)
2332 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
2333
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002334 ip = MAY_LJMP(luaL_checkstring(L, 2));
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002335 if (lua_gettop(L) >= 3)
2336 port = MAY_LJMP(luaL_checkinteger(L, 3));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002337
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002338 /* check for connection break. If some data where read, return it. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002339 peer = xref_get_peer_and_lock(&socket->xref);
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002340 if (!peer) {
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002341 lua_pushnil(L);
2342 return 1;
2343 }
2344 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2345 si = appctx->owner;
2346 s = si_strm(si);
2347
2348 /* Initialise connection. */
Olivier Houchard9aaf7782017-09-13 18:30:23 +02002349 conn = cs_conn(si_alloc_cs(&s->si[1], NULL));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002350 if (!conn) {
2351 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002352 WILL_LJMP(luaL_error(L, "connect: internal error"));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002353 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002354
Willy Tarreau3adac082015-09-26 17:51:09 +02002355 /* needed for the connection not to be closed */
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002356 conn->target = s->target;
Willy Tarreau3adac082015-09-26 17:51:09 +02002357
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002358 /* Parse ip address. */
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002359 addr = str2sa_range(ip, NULL, &low, &high, NULL, NULL, NULL, 0);
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002360 if (!addr) {
2361 xref_unlock(&socket->xref, peer);
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002362 WILL_LJMP(luaL_error(L, "connect: cannot parse destination address '%s'", ip));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002363 }
2364 if (low != high) {
2365 xref_unlock(&socket->xref, peer);
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002366 WILL_LJMP(luaL_error(L, "connect: port ranges not supported : address '%s'", ip));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002367 }
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002368 memcpy(&conn->addr.to, addr, sizeof(struct sockaddr_storage));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002369
2370 /* Set port. */
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002371 if (low == 0) {
2372 if (conn->addr.to.ss_family == AF_INET) {
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002373 if (port == -1) {
2374 xref_unlock(&socket->xref, peer);
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002375 WILL_LJMP(luaL_error(L, "connect: port missing"));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002376 }
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002377 ((struct sockaddr_in *)&conn->addr.to)->sin_port = htons(port);
2378 } else if (conn->addr.to.ss_family == AF_INET6) {
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002379 if (port == -1) {
2380 xref_unlock(&socket->xref, peer);
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002381 WILL_LJMP(luaL_error(L, "connect: port missing"));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002382 }
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002383 ((struct sockaddr_in6 *)&conn->addr.to)->sin6_port = htons(port);
2384 }
2385 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002386
Thierry FOURNIER95ad96a2015-03-09 18:12:40 +01002387 hlua = hlua_gethlua(L);
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002388 appctx = objt_appctx(s->si[0].end);
Willy Tarreaubdc97a82015-08-24 15:42:28 +02002389
2390 /* inform the stream that we want to be notified whenever the
2391 * connection completes.
2392 */
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002393 si_applet_cant_get(&s->si[0]);
2394 si_applet_cant_put(&s->si[0]);
Thierry FOURNIER8c8fbbe2015-09-26 17:02:35 +02002395 appctx_wakeup(appctx);
Willy Tarreaubdc97a82015-08-24 15:42:28 +02002396
Thierry FOURNIER7c39ab42015-09-27 22:53:33 +02002397 hlua->flags |= HLUA_MUST_GC;
2398
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002399 if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task)) {
2400 xref_unlock(&socket->xref, peer);
Thierry FOURNIER95ad96a2015-03-09 18:12:40 +01002401 WILL_LJMP(luaL_error(L, "out of memory"));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002402 }
2403 xref_unlock(&socket->xref, peer);
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +01002404 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_connect_yield, TICK_ETERNITY, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002405
2406 return 0;
2407}
2408
Baptiste Assmann84bb4932015-03-02 21:40:06 +01002409#ifdef USE_OPENSSL
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002410__LJMP static int hlua_socket_connect_ssl(struct lua_State *L)
2411{
2412 struct hlua_socket *socket;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002413 struct xref *peer;
2414 struct appctx *appctx;
2415 struct stream_interface *si;
2416 struct stream *s;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002417
2418 MAY_LJMP(check_args(L, 3, "connect_ssl"));
2419 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002420
2421 /* check for connection break. If some data where read, return it. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002422 peer = xref_get_peer_and_lock(&socket->xref);
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002423 if (!peer) {
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002424 lua_pushnil(L);
2425 return 1;
2426 }
2427 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2428 si = appctx->owner;
2429 s = si_strm(si);
2430
2431 s->target = &socket_ssl.obj_type;
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002432 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002433 return MAY_LJMP(hlua_socket_connect(L));
2434}
Baptiste Assmann84bb4932015-03-02 21:40:06 +01002435#endif
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002436
2437__LJMP static int hlua_socket_setoption(struct lua_State *L)
2438{
2439 return 0;
2440}
2441
2442__LJMP static int hlua_socket_settimeout(struct lua_State *L)
2443{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002444 struct hlua_socket *socket;
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002445 int tmout;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002446 struct xref *peer;
2447 struct appctx *appctx;
2448 struct stream_interface *si;
2449 struct stream *s;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002450
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002451 MAY_LJMP(check_args(L, 2, "settimeout"));
2452
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002453 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002454 tmout = MAY_LJMP(luaL_checkinteger(L, 2)) * 1000;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002455
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02002456 /* Check if we run on the same thread than the xreator thread.
2457 * We cannot access to the socket if the thread is different.
2458 */
2459 if (socket->tid != tid)
2460 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
2461
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002462 /* check for connection break. If some data where read, return it. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002463 peer = xref_get_peer_and_lock(&socket->xref);
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002464 if (!peer) {
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002465 hlua_pusherror(L, "socket: not yet initialised, you can't set timeouts.");
2466 WILL_LJMP(lua_error(L));
2467 return 0;
2468 }
2469 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2470 si = appctx->owner;
2471 s = si_strm(si);
2472
2473 s->req.rto = tmout;
2474 s->req.wto = tmout;
2475 s->res.rto = tmout;
2476 s->res.wto = tmout;
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002477 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002478
2479 return 0;
2480}
2481
2482__LJMP static int hlua_socket_new(lua_State *L)
2483{
2484 struct hlua_socket *socket;
2485 struct appctx *appctx;
Willy Tarreau15b5e142015-04-04 14:38:25 +02002486 struct session *sess;
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002487 struct stream *strm;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002488
2489 /* Check stack size. */
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002490 if (!lua_checkstack(L, 3)) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002491 hlua_pusherror(L, "socket: full stack");
2492 goto out_fail_conf;
2493 }
2494
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002495 /* Create the object: obj[0] = userdata. */
2496 lua_newtable(L);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002497 socket = MAY_LJMP(lua_newuserdata(L, sizeof(*socket)));
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002498 lua_rawseti(L, -2, 0);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002499 memset(socket, 0, sizeof(*socket));
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02002500 socket->tid = tid;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002501
Thierry FOURNIER4a6170c2015-03-09 17:07:10 +01002502 /* Check if the various memory pools are intialized. */
Willy Tarreau87b09662015-04-03 00:22:06 +02002503 if (!pool2_stream || !pool2_buffer) {
Thierry FOURNIER4a6170c2015-03-09 17:07:10 +01002504 hlua_pusherror(L, "socket: uninitialized pools.");
2505 goto out_fail_conf;
2506 }
2507
Willy Tarreau87b09662015-04-03 00:22:06 +02002508 /* Pop a class stream metatable and affect it to the userdata. */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002509 lua_rawgeti(L, LUA_REGISTRYINDEX, class_socket_ref);
2510 lua_setmetatable(L, -2);
2511
Willy Tarreaud420a972015-04-06 00:39:18 +02002512 /* Create the applet context */
Willy Tarreau5f4a47b2017-10-31 15:59:32 +01002513 appctx = appctx_new(&update_applet, tid_bit);
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002514 if (!appctx) {
2515 hlua_pusherror(L, "socket: out of memory");
Willy Tarreaufeb76402015-04-03 14:10:06 +02002516 goto out_fail_conf;
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002517 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002518
Thierry FOURNIER18d09902016-12-16 09:25:38 +01002519 appctx->ctx.hlua_cosocket.connected = 0;
Thierry FOURNIERb13b20a2017-07-16 20:48:54 +02002520 appctx->ctx.hlua_cosocket.die = 0;
Thierry FOURNIER18d09902016-12-16 09:25:38 +01002521 LIST_INIT(&appctx->ctx.hlua_cosocket.wake_on_write);
2522 LIST_INIT(&appctx->ctx.hlua_cosocket.wake_on_read);
Willy Tarreaub2bf8332015-04-04 15:58:58 +02002523
Willy Tarreaud420a972015-04-06 00:39:18 +02002524 /* Now create a session, task and stream for this applet */
2525 sess = session_new(&socket_proxy, NULL, &appctx->obj_type);
2526 if (!sess) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002527 hlua_pusherror(L, "socket: out of memory");
Willy Tarreaud420a972015-04-06 00:39:18 +02002528 goto out_fail_sess;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002529 }
2530
Willy Tarreau87787ac2017-08-28 16:22:54 +02002531 strm = stream_new(sess, &appctx->obj_type);
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002532 if (!strm) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002533 hlua_pusherror(L, "socket: out of memory");
Willy Tarreaud420a972015-04-06 00:39:18 +02002534 goto out_fail_stream;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002535 }
2536
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002537 /* Initialise cross reference between stream and Lua socket object. */
2538 xref_create(&socket->xref, &appctx->ctx.hlua_cosocket.xref);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002539
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002540 /* Configure "right" stream interface. this "si" is used to connect
2541 * and retrieve data from the server. The connection is initialized
2542 * with the "struct server".
2543 */
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002544 si_set_state(&strm->si[1], SI_ST_ASS);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002545
2546 /* Force destination server. */
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002547 strm->flags |= SF_DIRECT | SF_ASSIGNED | SF_ADDR_SET | SF_BE_ASSIGNED;
2548 strm->target = &socket_tcp.obj_type;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002549
Willy Tarreau87787ac2017-08-28 16:22:54 +02002550 task_wakeup(strm->task, TASK_WOKEN_INIT);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002551 /* Return yield waiting for connection. */
2552 return 1;
2553
Willy Tarreaud420a972015-04-06 00:39:18 +02002554 out_fail_stream:
Willy Tarreau11c36242015-04-04 15:54:03 +02002555 session_free(sess);
Willy Tarreaud420a972015-04-06 00:39:18 +02002556 out_fail_sess:
2557 appctx_free(appctx);
2558 out_fail_conf:
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002559 WILL_LJMP(lua_error(L));
2560 return 0;
2561}
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01002562
2563/*
2564 *
2565 *
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002566 * Class Channel
2567 *
2568 *
2569 */
2570
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002571/* The state between the channel data and the HTTP parser state can be
2572 * unconsistent, so reset the parser and call it again. Warning, this
2573 * action not revalidate the request and not send a 400 if the modified
2574 * resuest is not valid.
2575 *
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01002576 * This function never fails. The direction is set using dir, which equals
2577 * either SMP_OPT_DIR_REQ or SMP_OPT_DIR_RES.
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002578 */
2579static void hlua_resynchonize_proto(struct stream *stream, int dir)
2580{
2581 /* Protocol HTTP. */
2582 if (stream->be->mode == PR_MODE_HTTP) {
2583
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01002584 if (dir == SMP_OPT_DIR_REQ)
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002585 http_txn_reset_req(stream->txn);
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01002586 else if (dir == SMP_OPT_DIR_RES)
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002587 http_txn_reset_res(stream->txn);
2588
2589 if (stream->txn->hdr_idx.v)
2590 hdr_idx_init(&stream->txn->hdr_idx);
2591
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01002592 if (dir == SMP_OPT_DIR_REQ)
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002593 http_msg_analyzer(&stream->txn->req, &stream->txn->hdr_idx);
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01002594 else if (dir == SMP_OPT_DIR_RES)
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002595 http_msg_analyzer(&stream->txn->rsp, &stream->txn->hdr_idx);
2596 }
2597}
2598
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01002599/* This function is called before the Lua execution. It stores
2600 * the differents parsers state before executing some Lua code.
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002601 */
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01002602static inline void consistency_set(struct stream *stream, int opt, struct hlua_consistency *c)
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002603{
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01002604 c->mode = stream->be->mode;
2605 switch (c->mode) {
2606 case PR_MODE_HTTP:
2607 c->data.http.dir = opt & SMP_OPT_DIR;
2608 if (c->data.http.dir == SMP_OPT_DIR_REQ)
2609 c->data.http.state = stream->txn->req.msg_state;
2610 else
2611 c->data.http.state = stream->txn->rsp.msg_state;
2612 break;
2613 default:
2614 break;
2615 }
2616}
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002617
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01002618/* This function is called after the Lua execution. it
2619 * returns true if the parser state is consistent, otherwise,
2620 * it return false.
2621 *
2622 * In HTTP mode, the parser state must be in the same state
2623 * or greater when we exit the function. Even if we do a
2624 * control yield. This prevent to break the HTTP message
2625 * from the Lua code.
2626 */
2627static inline int consistency_check(struct stream *stream, int opt, struct hlua_consistency *c)
2628{
2629 if (c->mode != stream->be->mode)
2630 return 0;
2631
2632 switch (c->mode) {
2633 case PR_MODE_HTTP:
2634 if (c->data.http.dir != (opt & SMP_OPT_DIR))
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002635 return 0;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01002636 if (c->data.http.dir == SMP_OPT_DIR_REQ)
2637 return stream->txn->req.msg_state >= c->data.http.state;
2638 else
2639 return stream->txn->rsp.msg_state >= c->data.http.state;
2640 default:
2641 return 1;
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002642 }
2643 return 1;
2644}
2645
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002646/* Returns the struct hlua_channel join to the class channel in the
2647 * stack entry "ud" or throws an argument error.
2648 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002649__LJMP static struct channel *hlua_checkchannel(lua_State *L, int ud)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002650{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002651 return MAY_LJMP(hlua_checkudata(L, ud, class_channel_ref));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002652}
2653
Willy Tarreau47860ed2015-03-10 14:07:50 +01002654/* Pushes the channel onto the top of the stack. If the stask does not have a
2655 * free slots, the function fails and returns 0;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002656 */
Willy Tarreau2a71af42015-03-10 13:51:50 +01002657static int hlua_channel_new(lua_State *L, struct channel *channel)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002658{
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002659 /* Check stack size. */
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002660 if (!lua_checkstack(L, 3))
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002661 return 0;
2662
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002663 lua_newtable(L);
Willy Tarreau47860ed2015-03-10 14:07:50 +01002664 lua_pushlightuserdata(L, channel);
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002665 lua_rawseti(L, -2, 0);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002666
2667 /* Pop a class sesison metatable and affect it to the userdata. */
2668 lua_rawgeti(L, LUA_REGISTRYINDEX, class_channel_ref);
2669 lua_setmetatable(L, -2);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002670 return 1;
2671}
2672
2673/* Duplicate all the data present in the input channel and put it
2674 * in a string LUA variables. Returns -1 and push a nil value in
2675 * the stack if the channel is closed and all the data are consumed,
2676 * returns 0 if no data are available, otherwise it returns the length
2677 * of the builded string.
2678 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002679static inline int _hlua_channel_dup(struct channel *chn, lua_State *L)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002680{
2681 char *blk1;
2682 char *blk2;
2683 int len1;
2684 int len2;
2685 int ret;
2686 luaL_Buffer b;
2687
Willy Tarreau06d80a92017-10-19 14:32:15 +02002688 ret = ci_getblk_nc(chn, &blk1, &len1, &blk2, &len2);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002689 if (unlikely(ret == 0))
2690 return 0;
2691
2692 if (unlikely(ret < 0)) {
2693 lua_pushnil(L);
2694 return -1;
2695 }
2696
2697 luaL_buffinit(L, &b);
2698 luaL_addlstring(&b, blk1, len1);
2699 if (unlikely(ret == 2))
2700 luaL_addlstring(&b, blk2, len2);
2701 luaL_pushresult(&b);
2702
2703 if (unlikely(ret == 2))
2704 return len1 + len2;
2705 return len1;
2706}
2707
2708/* "_hlua_channel_dup" wrapper. If no data are available, it returns
2709 * a yield. This function keep the data in the buffer.
2710 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002711__LJMP static int hlua_channel_dup_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002712{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002713 struct channel *chn;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002714
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002715 chn = MAY_LJMP(hlua_checkchannel(L, 1));
2716
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002717 if (_hlua_channel_dup(chn, L) == 0)
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002718 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_dup_yield, TICK_ETERNITY, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002719 return 1;
2720}
2721
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002722/* Check arguments for the function "hlua_channel_dup_yield". */
2723__LJMP static int hlua_channel_dup(lua_State *L)
2724{
2725 MAY_LJMP(check_args(L, 1, "dup"));
2726 MAY_LJMP(hlua_checkchannel(L, 1));
2727 return MAY_LJMP(hlua_channel_dup_yield(L, 0, 0));
2728}
2729
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002730/* "_hlua_channel_dup" wrapper. If no data are available, it returns
2731 * a yield. This function consumes the data in the buffer. It returns
2732 * a string containing the data or a nil pointer if no data are available
2733 * and the channel is closed.
2734 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002735__LJMP static int hlua_channel_get_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002736{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002737 struct channel *chn;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002738 int ret;
2739
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002740 chn = MAY_LJMP(hlua_checkchannel(L, 1));
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002741
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002742 ret = _hlua_channel_dup(chn, L);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002743 if (unlikely(ret == 0))
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002744 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_get_yield, TICK_ETERNITY, 0));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002745
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002746 if (unlikely(ret == -1))
2747 return 1;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002748
Willy Tarreau47860ed2015-03-10 14:07:50 +01002749 chn->buf->i -= ret;
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002750 hlua_resynchonize_proto(chn_strm(chn), !!(chn->flags & CF_ISRESP));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002751 return 1;
2752}
2753
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002754/* Check arguments for the fucntion "hlua_channel_get_yield". */
2755__LJMP static int hlua_channel_get(lua_State *L)
2756{
2757 MAY_LJMP(check_args(L, 1, "get"));
2758 MAY_LJMP(hlua_checkchannel(L, 1));
2759 return MAY_LJMP(hlua_channel_get_yield(L, 0, 0));
2760}
2761
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002762/* This functions consumes and returns one line. If the channel is closed,
2763 * and the last data does not contains a final '\n', the data are returned
2764 * without the final '\n'. When no more data are avalaible, it returns nil
2765 * value.
2766 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002767__LJMP static int hlua_channel_getline_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002768{
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002769 char *blk1;
2770 char *blk2;
2771 int len1;
2772 int len2;
2773 int len;
Willy Tarreau47860ed2015-03-10 14:07:50 +01002774 struct channel *chn;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002775 int ret;
2776 luaL_Buffer b;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002777
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002778 chn = MAY_LJMP(hlua_checkchannel(L, 1));
2779
Willy Tarreau06d80a92017-10-19 14:32:15 +02002780 ret = ci_getline_nc(chn, &blk1, &len1, &blk2, &len2);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002781 if (ret == 0)
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002782 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_getline_yield, TICK_ETERNITY, 0));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002783
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002784 if (ret == -1) {
2785 lua_pushnil(L);
2786 return 1;
2787 }
2788
2789 luaL_buffinit(L, &b);
2790 luaL_addlstring(&b, blk1, len1);
2791 len = len1;
2792 if (unlikely(ret == 2)) {
2793 luaL_addlstring(&b, blk2, len2);
2794 len += len2;
2795 }
2796 luaL_pushresult(&b);
Willy Tarreau47860ed2015-03-10 14:07:50 +01002797 buffer_replace2(chn->buf, chn->buf->p, chn->buf->p + len, NULL, 0);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002798 hlua_resynchonize_proto(chn_strm(chn), !!(chn->flags & CF_ISRESP));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002799 return 1;
2800}
2801
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002802/* Check arguments for the fucntion "hlua_channel_getline_yield". */
2803__LJMP static int hlua_channel_getline(lua_State *L)
2804{
2805 MAY_LJMP(check_args(L, 1, "getline"));
2806 MAY_LJMP(hlua_checkchannel(L, 1));
2807 return MAY_LJMP(hlua_channel_getline_yield(L, 0, 0));
2808}
2809
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002810/* This function takes a string as input, and append it at the
2811 * input side of channel. If the data is too big, but a space
2812 * is probably available after sending some data, the function
2813 * yield. If the data is bigger than the buffer, or if the
2814 * channel is closed, it returns -1. otherwise, it returns the
2815 * amount of data writed.
2816 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002817__LJMP static int hlua_channel_append_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002818{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002819 struct channel *chn = MAY_LJMP(hlua_checkchannel(L, 1));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002820 size_t len;
2821 const char *str = MAY_LJMP(luaL_checklstring(L, 2, &len));
2822 int l = MAY_LJMP(luaL_checkinteger(L, 3));
2823 int ret;
2824 int max;
2825
Christopher Fauleta73e59b2016-12-09 17:30:18 +01002826 /* Check if the buffer is avalaible because HAProxy doesn't allocate
2827 * the request buffer if its not required.
2828 */
2829 if (chn->buf->size == 0) {
2830 si_applet_cant_put(chn_prod(chn));
2831 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_append_yield, TICK_ETERNITY, 0));
2832 }
2833
Willy Tarreau47860ed2015-03-10 14:07:50 +01002834 max = channel_recv_limit(chn) - buffer_len(chn->buf);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002835 if (max > len - l)
2836 max = len - l;
2837
Willy Tarreau06d80a92017-10-19 14:32:15 +02002838 ret = ci_putblk(chn, str + l, max);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002839 if (ret == -2 || ret == -3) {
2840 lua_pushinteger(L, -1);
2841 return 1;
2842 }
Willy Tarreaubc18da12015-03-13 14:00:47 +01002843 if (ret == -1) {
2844 chn->flags |= CF_WAKE_WRITE;
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002845 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_append_yield, TICK_ETERNITY, 0));
Willy Tarreaubc18da12015-03-13 14:00:47 +01002846 }
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002847 l += ret;
2848 lua_pop(L, 1);
2849 lua_pushinteger(L, l);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002850 hlua_resynchonize_proto(chn_strm(chn), !!(chn->flags & CF_ISRESP));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002851
Willy Tarreau47860ed2015-03-10 14:07:50 +01002852 max = channel_recv_limit(chn) - buffer_len(chn->buf);
2853 if (max == 0 && chn->buf->o == 0) {
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002854 /* There are no space avalaible, and the output buffer is empty.
2855 * in this case, we cannot add more data, so we cannot yield,
2856 * we return the amount of copyied data.
2857 */
2858 return 1;
2859 }
2860 if (l < len)
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002861 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_append_yield, TICK_ETERNITY, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002862 return 1;
2863}
2864
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002865/* just a wrapper of "hlua_channel_append_yield". It returns the length
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002866 * of the writed string, or -1 if the channel is closed or if the
2867 * buffer size is too little for the data.
2868 */
2869__LJMP static int hlua_channel_append(lua_State *L)
2870{
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002871 size_t len;
2872
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002873 MAY_LJMP(check_args(L, 2, "append"));
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002874 MAY_LJMP(hlua_checkchannel(L, 1));
2875 MAY_LJMP(luaL_checklstring(L, 2, &len));
2876 MAY_LJMP(luaL_checkinteger(L, 3));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002877 lua_pushinteger(L, 0);
2878
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002879 return MAY_LJMP(hlua_channel_append_yield(L, 0, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002880}
2881
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002882/* just a wrapper of "hlua_channel_append_yield". This wrapper starts
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002883 * his process by cleaning the buffer. The result is a replacement
2884 * of the current data. It returns the length of the writed string,
2885 * or -1 if the channel is closed or if the buffer size is too
2886 * little for the data.
2887 */
2888__LJMP static int hlua_channel_set(lua_State *L)
2889{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002890 struct channel *chn;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002891
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002892 MAY_LJMP(check_args(L, 2, "set"));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002893 chn = MAY_LJMP(hlua_checkchannel(L, 1));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002894 lua_pushinteger(L, 0);
2895
Willy Tarreau47860ed2015-03-10 14:07:50 +01002896 chn->buf->i = 0;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002897
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002898 return MAY_LJMP(hlua_channel_append_yield(L, 0, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002899}
2900
2901/* Append data in the output side of the buffer. This data is immediatly
2902 * sent. The fcuntion returns the ammount of data writed. If the buffer
2903 * cannot contains the data, the function yield. The function returns -1
2904 * if the channel is closed.
2905 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002906__LJMP static int hlua_channel_send_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002907{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002908 struct channel *chn = MAY_LJMP(hlua_checkchannel(L, 1));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002909 size_t len;
2910 const char *str = MAY_LJMP(luaL_checklstring(L, 2, &len));
2911 int l = MAY_LJMP(luaL_checkinteger(L, 3));
2912 int max;
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01002913 struct hlua *hlua = hlua_gethlua(L);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002914
Willy Tarreau47860ed2015-03-10 14:07:50 +01002915 if (unlikely(channel_output_closed(chn))) {
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002916 lua_pushinteger(L, -1);
2917 return 1;
2918 }
2919
Thierry FOURNIER3e3a6082015-03-05 17:06:12 +01002920 /* Check if the buffer is avalaible because HAProxy doesn't allocate
2921 * the request buffer if its not required.
2922 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002923 if (chn->buf->size == 0) {
Christopher Fauleta73e59b2016-12-09 17:30:18 +01002924 si_applet_cant_put(chn_prod(chn));
2925 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_send_yield, TICK_ETERNITY, 0));
Thierry FOURNIER3e3a6082015-03-05 17:06:12 +01002926 }
2927
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002928 /* the writed data will be immediatly sent, so we can check
2929 * the avalaible space without taking in account the reserve.
2930 * The reserve is guaranted for the processing of incoming
2931 * data, because the buffer will be flushed.
2932 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002933 max = chn->buf->size - buffer_len(chn->buf);
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002934
2935 /* If there are no space avalaible, and the output buffer is empty.
2936 * in this case, we cannot add more data, so we cannot yield,
2937 * we return the amount of copyied data.
2938 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002939 if (max == 0 && chn->buf->o == 0)
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002940 return 1;
2941
2942 /* Adjust the real required length. */
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002943 if (max > len - l)
2944 max = len - l;
2945
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002946 /* The buffer avalaible size may be not contiguous. This test
2947 * detects a non contiguous buffer and realign it.
2948 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002949 if (bi_space_for_replace(chn->buf) < max)
2950 buffer_slow_realign(chn->buf);
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002951
2952 /* Copy input data in the buffer. */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002953 max = buffer_replace2(chn->buf, chn->buf->p, chn->buf->p, str + l, max);
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002954
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002955 /* buffer replace considers that the input part is filled.
2956 * so, I must forward these new data in the output part.
2957 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002958 b_adv(chn->buf, max);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002959
2960 l += max;
2961 lua_pop(L, 1);
2962 lua_pushinteger(L, l);
2963
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002964 /* If there are no space avalaible, and the output buffer is empty.
2965 * in this case, we cannot add more data, so we cannot yield,
2966 * we return the amount of copyied data.
2967 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002968 max = chn->buf->size - buffer_len(chn->buf);
2969 if (max == 0 && chn->buf->o == 0)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002970 return 1;
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002971
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01002972 if (l < len) {
2973 /* If we are waiting for space in the response buffer, we
2974 * must set the flag WAKERESWR. This flag required the task
2975 * wake up if any activity is detected on the response buffer.
2976 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002977 if (chn->flags & CF_ISRESP)
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01002978 HLUA_SET_WAKERESWR(hlua);
Thierry FOURNIER53e08ec2015-03-06 00:35:53 +01002979 else
2980 HLUA_SET_WAKEREQWR(hlua);
2981 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_send_yield, TICK_ETERNITY, 0));
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01002982 }
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002983
2984 return 1;
2985}
2986
2987/* Just a wraper of "_hlua_channel_send". This wrapper permits
2988 * yield the LUA process, and resume it without checking the
2989 * input arguments.
2990 */
2991__LJMP static int hlua_channel_send(lua_State *L)
2992{
2993 MAY_LJMP(check_args(L, 2, "send"));
2994 lua_pushinteger(L, 0);
2995
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002996 return MAY_LJMP(hlua_channel_send_yield(L, 0, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002997}
2998
2999/* This function forward and amount of butes. The data pass from
3000 * the input side of the buffer to the output side, and can be
3001 * forwarded. This function never fails.
3002 *
3003 * The Lua function takes an amount of bytes to be forwarded in
3004 * imput. It returns the number of bytes forwarded.
3005 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01003006__LJMP static int hlua_channel_forward_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003007{
Willy Tarreau47860ed2015-03-10 14:07:50 +01003008 struct channel *chn;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003009 int len;
3010 int l;
3011 int max;
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01003012 struct hlua *hlua = hlua_gethlua(L);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003013
3014 chn = MAY_LJMP(hlua_checkchannel(L, 1));
3015 len = MAY_LJMP(luaL_checkinteger(L, 2));
3016 l = MAY_LJMP(luaL_checkinteger(L, -1));
3017
3018 max = len - l;
Willy Tarreau47860ed2015-03-10 14:07:50 +01003019 if (max > chn->buf->i)
3020 max = chn->buf->i;
3021 channel_forward(chn, max);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003022 l += max;
3023
3024 lua_pop(L, 1);
3025 lua_pushinteger(L, l);
3026
3027 /* Check if it miss bytes to forward. */
3028 if (l < len) {
3029 /* The the input channel or the output channel are closed, we
3030 * must return the amount of data forwarded.
3031 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01003032 if (channel_input_closed(chn) || channel_output_closed(chn))
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003033 return 1;
3034
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01003035 /* If we are waiting for space data in the response buffer, we
3036 * must set the flag WAKERESWR. This flag required the task
3037 * wake up if any activity is detected on the response buffer.
3038 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01003039 if (chn->flags & CF_ISRESP)
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01003040 HLUA_SET_WAKERESWR(hlua);
Thierry FOURNIER53e08ec2015-03-06 00:35:53 +01003041 else
3042 HLUA_SET_WAKEREQWR(hlua);
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01003043
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003044 /* Otherwise, we can yield waiting for new data in the inpout side. */
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +01003045 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_forward_yield, TICK_ETERNITY, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003046 }
3047
3048 return 1;
3049}
3050
3051/* Just check the input and prepare the stack for the previous
3052 * function "hlua_channel_forward_yield"
3053 */
3054__LJMP static int hlua_channel_forward(lua_State *L)
3055{
3056 MAY_LJMP(check_args(L, 2, "forward"));
3057 MAY_LJMP(hlua_checkchannel(L, 1));
3058 MAY_LJMP(luaL_checkinteger(L, 2));
3059
3060 lua_pushinteger(L, 0);
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01003061 return MAY_LJMP(hlua_channel_forward_yield(L, 0, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003062}
3063
3064/* Just returns the number of bytes available in the input
3065 * side of the buffer. This function never fails.
3066 */
3067__LJMP static int hlua_channel_get_in_len(lua_State *L)
3068{
Willy Tarreau47860ed2015-03-10 14:07:50 +01003069 struct channel *chn;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01003070
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003071 MAY_LJMP(check_args(L, 1, "get_in_len"));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01003072 chn = MAY_LJMP(hlua_checkchannel(L, 1));
Willy Tarreau47860ed2015-03-10 14:07:50 +01003073 lua_pushinteger(L, chn->buf->i);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003074 return 1;
3075}
3076
Thierry FOURNIER / OZON.IO65192f32016-11-07 15:28:40 +01003077/* Returns true if the channel is full. */
3078__LJMP static int hlua_channel_is_full(lua_State *L)
3079{
3080 struct channel *chn;
3081 int rem;
3082
3083 MAY_LJMP(check_args(L, 1, "is_full"));
3084 chn = MAY_LJMP(hlua_checkchannel(L, 1));
3085
3086 rem = chn->buf->size;
3087 rem -= chn->buf->o; /* Output size */
3088 rem -= chn->buf->i; /* Input size */
3089 rem -= global.tune.maxrewrite; /* Rewrite reserved size */
3090
3091 lua_pushboolean(L, rem <= 0);
3092 return 1;
3093}
3094
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003095/* Just returns the number of bytes available in the output
3096 * side of the buffer. This function never fails.
3097 */
3098__LJMP static int hlua_channel_get_out_len(lua_State *L)
3099{
Willy Tarreau47860ed2015-03-10 14:07:50 +01003100 struct channel *chn;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01003101
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003102 MAY_LJMP(check_args(L, 1, "get_out_len"));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01003103 chn = MAY_LJMP(hlua_checkchannel(L, 1));
Willy Tarreau47860ed2015-03-10 14:07:50 +01003104 lua_pushinteger(L, chn->buf->o);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003105 return 1;
3106}
3107
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003108/*
3109 *
3110 *
3111 * Class Fetches
3112 *
3113 *
3114 */
3115
3116/* Returns a struct hlua_session if the stack entry "ud" is
Willy Tarreau87b09662015-04-03 00:22:06 +02003117 * a class stream, otherwise it throws an error.
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003118 */
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003119__LJMP static struct hlua_smp *hlua_checkfetches(lua_State *L, int ud)
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003120{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003121 return MAY_LJMP(hlua_checkudata(L, ud, class_fetches_ref));
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003122}
3123
3124/* This function creates and push in the stack a fetch object according
3125 * with a current TXN.
3126 */
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003127static int hlua_fetches_new(lua_State *L, struct hlua_txn *txn, unsigned int flags)
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003128{
Willy Tarreau7073c472015-04-06 11:15:40 +02003129 struct hlua_smp *hsmp;
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003130
3131 /* Check stack size. */
3132 if (!lua_checkstack(L, 3))
3133 return 0;
3134
3135 /* Create the object: obj[0] = userdata.
3136 * Note that the base of the Fetches object is the
3137 * transaction object.
3138 */
3139 lua_newtable(L);
Willy Tarreau7073c472015-04-06 11:15:40 +02003140 hsmp = lua_newuserdata(L, sizeof(*hsmp));
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003141 lua_rawseti(L, -2, 0);
3142
Willy Tarreau7073c472015-04-06 11:15:40 +02003143 hsmp->s = txn->s;
3144 hsmp->p = txn->p;
Thierry FOURNIERc4eebc82015-11-02 10:01:59 +01003145 hsmp->dir = txn->dir;
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003146 hsmp->flags = flags;
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003147
3148 /* Pop a class sesison metatable and affect it to the userdata. */
3149 lua_rawgeti(L, LUA_REGISTRYINDEX, class_fetches_ref);
3150 lua_setmetatable(L, -2);
3151
3152 return 1;
3153}
3154
3155/* This function is an LUA binding. It is called with each sample-fetch.
3156 * It uses closure argument to store the associated sample-fetch. It
3157 * returns only one argument or throws an error. An error is thrown
3158 * only if an error is encountered during the argument parsing. If
3159 * the "sample-fetch" function fails, nil is returned.
3160 */
3161__LJMP static int hlua_run_sample_fetch(lua_State *L)
3162{
Willy Tarreaub2ccb562015-04-06 11:11:15 +02003163 struct hlua_smp *hsmp;
Willy Tarreau2ec22742015-03-10 14:27:20 +01003164 struct sample_fetch *f;
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003165 struct arg args[ARGM_NBARGS + 1];
3166 int i;
3167 struct sample smp;
3168
3169 /* Get closure arguments. */
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003170 f = lua_touserdata(L, lua_upvalueindex(1));
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003171
3172 /* Get traditionnal arguments. */
Willy Tarreaub2ccb562015-04-06 11:11:15 +02003173 hsmp = MAY_LJMP(hlua_checkfetches(L, 1));
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003174
Thierry FOURNIERca988662015-12-20 18:43:03 +01003175 /* Check execution authorization. */
3176 if (f->use & SMP_USE_HTTP_ANY &&
3177 !(hsmp->flags & HLUA_F_MAY_USE_HTTP)) {
3178 lua_pushfstring(L, "the sample-fetch '%s' needs an HTTP parser which "
3179 "is not available in Lua services", f->kw);
3180 WILL_LJMP(lua_error(L));
3181 }
3182
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003183 /* Get extra arguments. */
3184 for (i = 0; i < lua_gettop(L) - 1; i++) {
3185 if (i >= ARGM_NBARGS)
3186 break;
3187 hlua_lua2arg(L, i + 2, &args[i]);
3188 }
3189 args[i].type = ARGT_STOP;
David Carlierabdb00f2016-04-27 16:14:50 +01003190 args[i].data.str.str = NULL;
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003191
3192 /* Check arguments. */
Willy Tarreaub2ccb562015-04-06 11:11:15 +02003193 MAY_LJMP(hlua_lua2arg_check(L, 2, args, f->arg_mask, hsmp->p));
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003194
3195 /* Run the special args checker. */
Willy Tarreau2ec22742015-03-10 14:27:20 +01003196 if (f->val_args && !f->val_args(args, NULL)) {
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003197 lua_pushfstring(L, "error in arguments");
3198 WILL_LJMP(lua_error(L));
3199 }
3200
3201 /* Initialise the sample. */
3202 memset(&smp, 0, sizeof(smp));
3203
3204 /* Run the sample fetch process. */
Willy Tarreau1777ea62016-03-10 16:15:46 +01003205 smp_set_owner(&smp, hsmp->p, hsmp->s->sess, hsmp->s, hsmp->dir & SMP_OPT_DIR);
Thierry FOURNIER0786d052015-05-11 15:42:45 +02003206 if (!f->process(args, &smp, f->kw, f->private)) {
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003207 if (hsmp->flags & HLUA_F_AS_STRING)
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003208 lua_pushstring(L, "");
3209 else
3210 lua_pushnil(L);
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003211 return 1;
3212 }
3213
3214 /* Convert the returned sample in lua value. */
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003215 if (hsmp->flags & HLUA_F_AS_STRING)
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003216 hlua_smp2lua_str(L, &smp);
3217 else
3218 hlua_smp2lua(L, &smp);
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003219 return 1;
3220}
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003221
3222/*
3223 *
3224 *
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003225 * Class Converters
3226 *
3227 *
3228 */
3229
3230/* Returns a struct hlua_session if the stack entry "ud" is
Willy Tarreau87b09662015-04-03 00:22:06 +02003231 * a class stream, otherwise it throws an error.
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003232 */
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003233__LJMP static struct hlua_smp *hlua_checkconverters(lua_State *L, int ud)
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003234{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003235 return MAY_LJMP(hlua_checkudata(L, ud, class_converters_ref));
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003236}
3237
3238/* This function creates and push in the stack a Converters object
3239 * according with a current TXN.
3240 */
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003241static int hlua_converters_new(lua_State *L, struct hlua_txn *txn, unsigned int flags)
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003242{
Willy Tarreau7073c472015-04-06 11:15:40 +02003243 struct hlua_smp *hsmp;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003244
3245 /* Check stack size. */
3246 if (!lua_checkstack(L, 3))
3247 return 0;
3248
3249 /* Create the object: obj[0] = userdata.
3250 * Note that the base of the Converters object is the
3251 * same than the TXN object.
3252 */
3253 lua_newtable(L);
Willy Tarreau7073c472015-04-06 11:15:40 +02003254 hsmp = lua_newuserdata(L, sizeof(*hsmp));
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003255 lua_rawseti(L, -2, 0);
3256
Willy Tarreau7073c472015-04-06 11:15:40 +02003257 hsmp->s = txn->s;
3258 hsmp->p = txn->p;
Thierry FOURNIERc4eebc82015-11-02 10:01:59 +01003259 hsmp->dir = txn->dir;
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003260 hsmp->flags = flags;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003261
Willy Tarreau87b09662015-04-03 00:22:06 +02003262 /* Pop a class stream metatable and affect it to the table. */
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003263 lua_rawgeti(L, LUA_REGISTRYINDEX, class_converters_ref);
3264 lua_setmetatable(L, -2);
3265
3266 return 1;
3267}
3268
3269/* This function is an LUA binding. It is called with each converter.
3270 * It uses closure argument to store the associated converter. It
3271 * returns only one argument or throws an error. An error is thrown
3272 * only if an error is encountered during the argument parsing. If
3273 * the converter function function fails, nil is returned.
3274 */
3275__LJMP static int hlua_run_sample_conv(lua_State *L)
3276{
Willy Tarreauda5f1082015-04-06 11:17:13 +02003277 struct hlua_smp *hsmp;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003278 struct sample_conv *conv;
3279 struct arg args[ARGM_NBARGS + 1];
3280 int i;
3281 struct sample smp;
3282
3283 /* Get closure arguments. */
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003284 conv = lua_touserdata(L, lua_upvalueindex(1));
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003285
3286 /* Get traditionnal arguments. */
Willy Tarreauda5f1082015-04-06 11:17:13 +02003287 hsmp = MAY_LJMP(hlua_checkconverters(L, 1));
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003288
3289 /* Get extra arguments. */
3290 for (i = 0; i < lua_gettop(L) - 2; i++) {
3291 if (i >= ARGM_NBARGS)
3292 break;
3293 hlua_lua2arg(L, i + 3, &args[i]);
3294 }
3295 args[i].type = ARGT_STOP;
David Carlierabdb00f2016-04-27 16:14:50 +01003296 args[i].data.str.str = NULL;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003297
3298 /* Check arguments. */
Willy Tarreauda5f1082015-04-06 11:17:13 +02003299 MAY_LJMP(hlua_lua2arg_check(L, 3, args, conv->arg_mask, hsmp->p));
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003300
3301 /* Run the special args checker. */
3302 if (conv->val_args && !conv->val_args(args, conv, "", 0, NULL)) {
3303 hlua_pusherror(L, "error in arguments");
3304 WILL_LJMP(lua_error(L));
3305 }
3306
3307 /* Initialise the sample. */
3308 if (!hlua_lua2smp(L, 2, &smp)) {
3309 hlua_pusherror(L, "error in the input argument");
3310 WILL_LJMP(lua_error(L));
3311 }
3312
Willy Tarreau1777ea62016-03-10 16:15:46 +01003313 smp_set_owner(&smp, hsmp->p, hsmp->s->sess, hsmp->s, hsmp->dir & SMP_OPT_DIR);
3314
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003315 /* Apply expected cast. */
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02003316 if (!sample_casts[smp.data.type][conv->in_type]) {
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003317 hlua_pusherror(L, "invalid input argument: cannot cast '%s' to '%s'",
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02003318 smp_to_type[smp.data.type], smp_to_type[conv->in_type]);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003319 WILL_LJMP(lua_error(L));
3320 }
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02003321 if (sample_casts[smp.data.type][conv->in_type] != c_none &&
3322 !sample_casts[smp.data.type][conv->in_type](&smp)) {
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003323 hlua_pusherror(L, "error during the input argument casting");
3324 WILL_LJMP(lua_error(L));
3325 }
3326
3327 /* Run the sample conversion process. */
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02003328 if (!conv->process(args, &smp, conv->private)) {
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003329 if (hsmp->flags & HLUA_F_AS_STRING)
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003330 lua_pushstring(L, "");
3331 else
Willy Tarreaua678b432015-08-28 10:14:59 +02003332 lua_pushnil(L);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003333 return 1;
3334 }
3335
3336 /* Convert the returned sample in lua value. */
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003337 if (hsmp->flags & HLUA_F_AS_STRING)
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003338 hlua_smp2lua_str(L, &smp);
3339 else
3340 hlua_smp2lua(L, &smp);
Willy Tarreaua678b432015-08-28 10:14:59 +02003341 return 1;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003342}
3343
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003344/*
3345 *
3346 *
3347 * Class AppletTCP
3348 *
3349 *
3350 */
3351
3352/* Returns a struct hlua_txn if the stack entry "ud" is
3353 * a class stream, otherwise it throws an error.
3354 */
3355__LJMP static struct hlua_appctx *hlua_checkapplet_tcp(lua_State *L, int ud)
3356{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003357 return MAY_LJMP(hlua_checkudata(L, ud, class_applet_tcp_ref));
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003358}
3359
3360/* This function creates and push in the stack an Applet object
3361 * according with a current TXN.
3362 */
3363static int hlua_applet_tcp_new(lua_State *L, struct appctx *ctx)
3364{
3365 struct hlua_appctx *appctx;
3366 struct stream_interface *si = ctx->owner;
3367 struct stream *s = si_strm(si);
3368 struct proxy *p = s->be;
3369
3370 /* Check stack size. */
3371 if (!lua_checkstack(L, 3))
3372 return 0;
3373
3374 /* Create the object: obj[0] = userdata.
3375 * Note that the base of the Converters object is the
3376 * same than the TXN object.
3377 */
3378 lua_newtable(L);
3379 appctx = lua_newuserdata(L, sizeof(*appctx));
3380 lua_rawseti(L, -2, 0);
3381 appctx->appctx = ctx;
3382 appctx->htxn.s = s;
3383 appctx->htxn.p = p;
3384
3385 /* Create the "f" field that contains a list of fetches. */
3386 lua_pushstring(L, "f");
3387 if (!hlua_fetches_new(L, &appctx->htxn, 0))
3388 return 0;
3389 lua_settable(L, -3);
3390
3391 /* Create the "sf" field that contains a list of stringsafe fetches. */
3392 lua_pushstring(L, "sf");
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003393 if (!hlua_fetches_new(L, &appctx->htxn, HLUA_F_AS_STRING))
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003394 return 0;
3395 lua_settable(L, -3);
3396
3397 /* Create the "c" field that contains a list of converters. */
3398 lua_pushstring(L, "c");
3399 if (!hlua_converters_new(L, &appctx->htxn, 0))
3400 return 0;
3401 lua_settable(L, -3);
3402
3403 /* Create the "sc" field that contains a list of stringsafe converters. */
3404 lua_pushstring(L, "sc");
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003405 if (!hlua_converters_new(L, &appctx->htxn, HLUA_F_AS_STRING))
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003406 return 0;
3407 lua_settable(L, -3);
3408
3409 /* Pop a class stream metatable and affect it to the table. */
3410 lua_rawgeti(L, LUA_REGISTRYINDEX, class_applet_tcp_ref);
3411 lua_setmetatable(L, -2);
3412
3413 return 1;
3414}
3415
Thierry FOURNIER / OZON.IO4394a2c2016-12-12 12:31:54 +01003416__LJMP static int hlua_applet_tcp_set_var(lua_State *L)
3417{
3418 struct hlua_appctx *appctx;
3419 struct stream *s;
3420 const char *name;
3421 size_t len;
3422 struct sample smp;
3423
3424 MAY_LJMP(check_args(L, 3, "set_var"));
3425
3426 /* It is useles to retrieve the stream, but this function
3427 * runs only in a stream context.
3428 */
3429 appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3430 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3431 s = appctx->htxn.s;
3432
3433 /* Converts the third argument in a sample. */
3434 hlua_lua2smp(L, 3, &smp);
3435
3436 /* Store the sample in a variable. */
3437 smp_set_owner(&smp, s->be, s->sess, s, 0);
3438 vars_set_by_name(name, len, &smp);
3439 return 0;
3440}
3441
3442__LJMP static int hlua_applet_tcp_unset_var(lua_State *L)
3443{
3444 struct hlua_appctx *appctx;
3445 struct stream *s;
3446 const char *name;
3447 size_t len;
3448 struct sample smp;
3449
3450 MAY_LJMP(check_args(L, 2, "unset_var"));
3451
3452 /* It is useles to retrieve the stream, but this function
3453 * runs only in a stream context.
3454 */
3455 appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3456 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3457 s = appctx->htxn.s;
3458
3459 /* Unset the variable. */
3460 smp_set_owner(&smp, s->be, s->sess, s, 0);
3461 vars_unset_by_name(name, len, &smp);
3462 return 0;
3463}
3464
3465__LJMP static int hlua_applet_tcp_get_var(lua_State *L)
3466{
3467 struct hlua_appctx *appctx;
3468 struct stream *s;
3469 const char *name;
3470 size_t len;
3471 struct sample smp;
3472
3473 MAY_LJMP(check_args(L, 2, "get_var"));
3474
3475 /* It is useles to retrieve the stream, but this function
3476 * runs only in a stream context.
3477 */
3478 appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3479 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3480 s = appctx->htxn.s;
3481
3482 smp_set_owner(&smp, s->be, s->sess, s, 0);
3483 if (!vars_get_by_name(name, len, &smp)) {
3484 lua_pushnil(L);
3485 return 1;
3486 }
3487
3488 return hlua_smp2lua(L, &smp);
3489}
3490
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003491__LJMP static int hlua_applet_tcp_set_priv(lua_State *L)
3492{
3493 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3494 struct stream *s = appctx->htxn.s;
Thierry FOURNIER3b0a6d42016-12-16 08:48:32 +01003495 struct hlua *hlua;
3496
3497 /* Note that this hlua struct is from the session and not from the applet. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01003498 if (!s->hlua)
3499 return 0;
3500 hlua = s->hlua;
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003501
3502 MAY_LJMP(check_args(L, 2, "set_priv"));
3503
3504 /* Remove previous value. */
Thierry FOURNIERe068b602017-04-26 13:27:05 +02003505 luaL_unref(L, LUA_REGISTRYINDEX, hlua->Mref);
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003506
3507 /* Get and store new value. */
3508 lua_pushvalue(L, 2); /* Copy the element 2 at the top of the stack. */
3509 hlua->Mref = luaL_ref(L, LUA_REGISTRYINDEX); /* pop the previously pushed value. */
3510
3511 return 0;
3512}
3513
3514__LJMP static int hlua_applet_tcp_get_priv(lua_State *L)
3515{
3516 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3517 struct stream *s = appctx->htxn.s;
Thierry FOURNIER3b0a6d42016-12-16 08:48:32 +01003518 struct hlua *hlua;
3519
3520 /* Note that this hlua struct is from the session and not from the applet. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01003521 if (!s->hlua) {
3522 lua_pushnil(L);
3523 return 1;
3524 }
3525 hlua = s->hlua;
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003526
3527 /* Push configuration index in the stack. */
3528 lua_rawgeti(L, LUA_REGISTRYINDEX, hlua->Mref);
3529
3530 return 1;
3531}
3532
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003533/* If expected data not yet available, it returns a yield. This function
3534 * consumes the data in the buffer. It returns a string containing the
3535 * data. This string can be empty.
3536 */
3537__LJMP static int hlua_applet_tcp_getline_yield(lua_State *L, int status, lua_KContext ctx)
3538{
3539 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3540 struct stream_interface *si = appctx->appctx->owner;
3541 int ret;
3542 char *blk1;
3543 int len1;
3544 char *blk2;
3545 int len2;
3546
3547 /* Read the maximum amount of data avalaible. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02003548 ret = co_getline_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003549
3550 /* Data not yet avalaible. return yield. */
3551 if (ret == 0) {
3552 si_applet_cant_get(si);
3553 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_getline_yield, TICK_ETERNITY, 0));
3554 }
3555
3556 /* End of data: commit the total strings and return. */
3557 if (ret < 0) {
3558 luaL_pushresult(&appctx->b);
3559 return 1;
3560 }
3561
3562 /* Ensure that the block 2 length is usable. */
3563 if (ret == 1)
3564 len2 = 0;
3565
3566 /* dont check the max length read and dont check. */
3567 luaL_addlstring(&appctx->b, blk1, len1);
3568 luaL_addlstring(&appctx->b, blk2, len2);
3569
3570 /* Consume input channel output buffer data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02003571 co_skip(si_oc(si), len1 + len2);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003572 luaL_pushresult(&appctx->b);
3573 return 1;
3574}
3575
3576/* Check arguments for the fucntion "hlua_channel_get_yield". */
3577__LJMP static int hlua_applet_tcp_getline(lua_State *L)
3578{
3579 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3580
3581 /* Initialise the string catenation. */
3582 luaL_buffinit(L, &appctx->b);
3583
3584 return MAY_LJMP(hlua_applet_tcp_getline_yield(L, 0, 0));
3585}
3586
3587/* If expected data not yet available, it returns a yield. This function
3588 * consumes the data in the buffer. It returns a string containing the
3589 * data. This string can be empty.
3590 */
3591__LJMP static int hlua_applet_tcp_recv_yield(lua_State *L, int status, lua_KContext ctx)
3592{
3593 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3594 struct stream_interface *si = appctx->appctx->owner;
3595 int len = MAY_LJMP(luaL_checkinteger(L, 2));
3596 int ret;
3597 char *blk1;
3598 int len1;
3599 char *blk2;
3600 int len2;
3601
3602 /* Read the maximum amount of data avalaible. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02003603 ret = co_getblk_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003604
3605 /* Data not yet avalaible. return yield. */
3606 if (ret == 0) {
3607 si_applet_cant_get(si);
3608 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_recv_yield, TICK_ETERNITY, 0));
3609 }
3610
3611 /* End of data: commit the total strings and return. */
3612 if (ret < 0) {
3613 luaL_pushresult(&appctx->b);
3614 return 1;
3615 }
3616
3617 /* Ensure that the block 2 length is usable. */
3618 if (ret == 1)
3619 len2 = 0;
3620
3621 if (len == -1) {
3622
3623 /* If len == -1, catenate all the data avalaile and
3624 * yield because we want to get all the data until
3625 * the end of data stream.
3626 */
3627 luaL_addlstring(&appctx->b, blk1, len1);
3628 luaL_addlstring(&appctx->b, blk2, len2);
Willy Tarreau06d80a92017-10-19 14:32:15 +02003629 co_skip(si_oc(si), len1 + len2);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003630 si_applet_cant_get(si);
3631 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_recv_yield, TICK_ETERNITY, 0));
3632
3633 } else {
3634
3635 /* Copy the fisrt block caping to the length required. */
3636 if (len1 > len)
3637 len1 = len;
3638 luaL_addlstring(&appctx->b, blk1, len1);
3639 len -= len1;
3640
3641 /* Copy the second block. */
3642 if (len2 > len)
3643 len2 = len;
3644 luaL_addlstring(&appctx->b, blk2, len2);
3645 len -= len2;
3646
3647 /* Consume input channel output buffer data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02003648 co_skip(si_oc(si), len1 + len2);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003649
3650 /* If we are no other data avalaible, yield waiting for new data. */
3651 if (len > 0) {
3652 lua_pushinteger(L, len);
3653 lua_replace(L, 2);
3654 si_applet_cant_get(si);
3655 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_recv_yield, TICK_ETERNITY, 0));
3656 }
3657
3658 /* return the result. */
3659 luaL_pushresult(&appctx->b);
3660 return 1;
3661 }
3662
3663 /* we never executes this */
3664 hlua_pusherror(L, "Lua: internal error");
3665 WILL_LJMP(lua_error(L));
3666 return 0;
3667}
3668
3669/* Check arguments for the fucntion "hlua_channel_get_yield". */
3670__LJMP static int hlua_applet_tcp_recv(lua_State *L)
3671{
3672 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3673 int len = -1;
3674
3675 if (lua_gettop(L) > 2)
3676 WILL_LJMP(luaL_error(L, "The 'recv' function requires between 1 and 2 arguments."));
3677 if (lua_gettop(L) >= 2) {
3678 len = MAY_LJMP(luaL_checkinteger(L, 2));
3679 lua_pop(L, 1);
3680 }
3681
3682 /* Confirm or set the required length */
3683 lua_pushinteger(L, len);
3684
3685 /* Initialise the string catenation. */
3686 luaL_buffinit(L, &appctx->b);
3687
3688 return MAY_LJMP(hlua_applet_tcp_recv_yield(L, 0, 0));
3689}
3690
3691/* Append data in the output side of the buffer. This data is immediatly
3692 * sent. The fcuntion returns the ammount of data writed. If the buffer
3693 * cannot contains the data, the function yield. The function returns -1
3694 * if the channel is closed.
3695 */
3696__LJMP static int hlua_applet_tcp_send_yield(lua_State *L, int status, lua_KContext ctx)
3697{
3698 size_t len;
3699 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3700 const char *str = MAY_LJMP(luaL_checklstring(L, 2, &len));
3701 int l = MAY_LJMP(luaL_checkinteger(L, 3));
3702 struct stream_interface *si = appctx->appctx->owner;
3703 struct channel *chn = si_ic(si);
3704 int max;
3705
3706 /* Get the max amount of data which can write as input in the channel. */
3707 max = channel_recv_max(chn);
3708 if (max > (len - l))
3709 max = len - l;
3710
3711 /* Copy data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02003712 ci_putblk(chn, str + l, max);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003713
3714 /* update counters. */
3715 l += max;
3716 lua_pop(L, 1);
3717 lua_pushinteger(L, l);
3718
3719 /* If some data is not send, declares the situation to the
3720 * applet, and returns a yield.
3721 */
3722 if (l < len) {
3723 si_applet_cant_put(si);
3724 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_send_yield, TICK_ETERNITY, 0));
3725 }
3726
3727 return 1;
3728}
3729
3730/* Just a wraper of "hlua_applet_tcp_send_yield". This wrapper permits
3731 * yield the LUA process, and resume it without checking the
3732 * input arguments.
3733 */
3734__LJMP static int hlua_applet_tcp_send(lua_State *L)
3735{
3736 MAY_LJMP(check_args(L, 2, "send"));
3737 lua_pushinteger(L, 0);
3738
3739 return MAY_LJMP(hlua_applet_tcp_send_yield(L, 0, 0));
3740}
3741
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003742/*
3743 *
3744 *
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003745 * Class AppletHTTP
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003746 *
3747 *
3748 */
3749
3750/* Returns a struct hlua_txn if the stack entry "ud" is
Willy Tarreau87b09662015-04-03 00:22:06 +02003751 * a class stream, otherwise it throws an error.
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003752 */
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003753__LJMP static struct hlua_appctx *hlua_checkapplet_http(lua_State *L, int ud)
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003754{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003755 return MAY_LJMP(hlua_checkudata(L, ud, class_applet_http_ref));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003756}
3757
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003758/* This function creates and push in the stack an Applet object
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003759 * according with a current TXN.
3760 */
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003761static int hlua_applet_http_new(lua_State *L, struct appctx *ctx)
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003762{
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003763 struct hlua_appctx *appctx;
Thierry FOURNIER841475e2015-12-11 17:10:09 +01003764 struct hlua_txn htxn;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003765 struct stream_interface *si = ctx->owner;
3766 struct stream *s = si_strm(si);
3767 struct proxy *px = s->be;
3768 struct http_txn *txn = s->txn;
3769 const char *path;
3770 const char *end;
3771 const char *p;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003772
3773 /* Check stack size. */
3774 if (!lua_checkstack(L, 3))
3775 return 0;
3776
3777 /* Create the object: obj[0] = userdata.
3778 * Note that the base of the Converters object is the
3779 * same than the TXN object.
3780 */
3781 lua_newtable(L);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003782 appctx = lua_newuserdata(L, sizeof(*appctx));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003783 lua_rawseti(L, -2, 0);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003784 appctx->appctx = ctx;
3785 appctx->appctx->ctx.hlua_apphttp.status = 200; /* Default status code returned. */
Robin H. Johnson52f5db22017-01-01 13:10:52 -08003786 appctx->appctx->ctx.hlua_apphttp.reason = NULL; /* Use default reason based on status */
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003787 appctx->htxn.s = s;
3788 appctx->htxn.p = px;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003789
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003790 /* Create the "f" field that contains a list of fetches. */
3791 lua_pushstring(L, "f");
3792 if (!hlua_fetches_new(L, &appctx->htxn, 0))
3793 return 0;
3794 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003795
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003796 /* Create the "sf" field that contains a list of stringsafe fetches. */
3797 lua_pushstring(L, "sf");
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003798 if (!hlua_fetches_new(L, &appctx->htxn, HLUA_F_AS_STRING))
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003799 return 0;
3800 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003801
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003802 /* Create the "c" field that contains a list of converters. */
3803 lua_pushstring(L, "c");
3804 if (!hlua_converters_new(L, &appctx->htxn, 0))
3805 return 0;
3806 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003807
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003808 /* Create the "sc" field that contains a list of stringsafe converters. */
3809 lua_pushstring(L, "sc");
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003810 if (!hlua_converters_new(L, &appctx->htxn, HLUA_F_AS_STRING))
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003811 return 0;
3812 lua_settable(L, -3);
Willy Tarreaueee5b512015-04-03 23:46:31 +02003813
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003814 /* Stores the request method. */
3815 lua_pushstring(L, "method");
3816 lua_pushlstring(L, txn->req.chn->buf->p, txn->req.sl.rq.m_l);
3817 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003818
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003819 /* Stores the http version. */
3820 lua_pushstring(L, "version");
3821 lua_pushlstring(L, txn->req.chn->buf->p + txn->req.sl.rq.v, txn->req.sl.rq.v_l);
3822 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003823
Thierry FOURNIER841475e2015-12-11 17:10:09 +01003824 /* creates an array of headers. hlua_http_get_headers() crates and push
3825 * the array on the top of the stack.
3826 */
3827 lua_pushstring(L, "headers");
3828 htxn.s = s;
3829 htxn.p = px;
3830 htxn.dir = SMP_OPT_DIR_REQ;
3831 if (!hlua_http_get_headers(L, &htxn, &htxn.s->txn->req))
3832 return 0;
3833 lua_settable(L, -3);
3834
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003835 /* Get path and qs */
3836 path = http_get_path(txn);
Thierry FOURNIER7d388632017-02-22 02:06:16 +01003837 if (path) {
3838 end = txn->req.chn->buf->p + txn->req.sl.rq.u + txn->req.sl.rq.u_l;
3839 p = path;
3840 while (p < end && *p != '?')
3841 p++;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003842
Thierry FOURNIER7d388632017-02-22 02:06:16 +01003843 /* Stores the request path. */
3844 lua_pushstring(L, "path");
3845 lua_pushlstring(L, path, p - path);
3846 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003847
Thierry FOURNIER7d388632017-02-22 02:06:16 +01003848 /* Stores the query string. */
3849 lua_pushstring(L, "qs");
3850 if (*p == '?')
3851 p++;
3852 lua_pushlstring(L, p, end - p);
3853 lua_settable(L, -3);
3854 }
Thierry FOURNIER04c57b32015-03-18 13:43:10 +01003855
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003856 /* Stores the request path. */
3857 lua_pushstring(L, "length");
3858 lua_pushinteger(L, txn->req.body_len);
3859 lua_settable(L, -3);
Thierry FOURNIER04c57b32015-03-18 13:43:10 +01003860
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003861 /* Create an array of HTTP request headers. */
3862 lua_pushstring(L, "headers");
3863 MAY_LJMP(hlua_http_get_headers(L, &appctx->htxn, &appctx->htxn.s->txn->req));
3864 lua_settable(L, -3);
Thierry FOURNIER04c57b32015-03-18 13:43:10 +01003865
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003866 /* Create an empty array of HTTP request headers. */
3867 lua_pushstring(L, "response");
3868 lua_newtable(L);
3869 lua_settable(L, -3);
Thierry FOURNIER04c57b32015-03-18 13:43:10 +01003870
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003871 /* Pop a class stream metatable and affect it to the table. */
3872 lua_rawgeti(L, LUA_REGISTRYINDEX, class_applet_http_ref);
3873 lua_setmetatable(L, -2);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003874
3875 return 1;
3876}
3877
Thierry FOURNIER / OZON.IO4394a2c2016-12-12 12:31:54 +01003878__LJMP static int hlua_applet_http_set_var(lua_State *L)
3879{
3880 struct hlua_appctx *appctx;
3881 struct stream *s;
3882 const char *name;
3883 size_t len;
3884 struct sample smp;
3885
3886 MAY_LJMP(check_args(L, 3, "set_var"));
3887
3888 /* It is useles to retrieve the stream, but this function
3889 * runs only in a stream context.
3890 */
3891 appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
3892 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3893 s = appctx->htxn.s;
3894
3895 /* Converts the third argument in a sample. */
3896 hlua_lua2smp(L, 3, &smp);
3897
3898 /* Store the sample in a variable. */
3899 smp_set_owner(&smp, s->be, s->sess, s, 0);
3900 vars_set_by_name(name, len, &smp);
3901 return 0;
3902}
3903
3904__LJMP static int hlua_applet_http_unset_var(lua_State *L)
3905{
3906 struct hlua_appctx *appctx;
3907 struct stream *s;
3908 const char *name;
3909 size_t len;
3910 struct sample smp;
3911
3912 MAY_LJMP(check_args(L, 2, "unset_var"));
3913
3914 /* It is useles to retrieve the stream, but this function
3915 * runs only in a stream context.
3916 */
3917 appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
3918 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3919 s = appctx->htxn.s;
3920
3921 /* Unset the variable. */
3922 smp_set_owner(&smp, s->be, s->sess, s, 0);
3923 vars_unset_by_name(name, len, &smp);
3924 return 0;
3925}
3926
3927__LJMP static int hlua_applet_http_get_var(lua_State *L)
3928{
3929 struct hlua_appctx *appctx;
3930 struct stream *s;
3931 const char *name;
3932 size_t len;
3933 struct sample smp;
3934
3935 MAY_LJMP(check_args(L, 2, "get_var"));
3936
3937 /* It is useles to retrieve the stream, but this function
3938 * runs only in a stream context.
3939 */
3940 appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
3941 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3942 s = appctx->htxn.s;
3943
3944 smp_set_owner(&smp, s->be, s->sess, s, 0);
3945 if (!vars_get_by_name(name, len, &smp)) {
3946 lua_pushnil(L);
3947 return 1;
3948 }
3949
3950 return hlua_smp2lua(L, &smp);
3951}
3952
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003953__LJMP static int hlua_applet_http_set_priv(lua_State *L)
3954{
3955 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
3956 struct stream *s = appctx->htxn.s;
Thierry FOURNIER3b0a6d42016-12-16 08:48:32 +01003957 struct hlua *hlua;
3958
3959 /* Note that this hlua struct is from the session and not from the applet. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01003960 if (!s->hlua)
3961 return 0;
3962 hlua = s->hlua;
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003963
3964 MAY_LJMP(check_args(L, 2, "set_priv"));
3965
3966 /* Remove previous value. */
Thierry FOURNIERe068b602017-04-26 13:27:05 +02003967 luaL_unref(L, LUA_REGISTRYINDEX, hlua->Mref);
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003968
3969 /* Get and store new value. */
3970 lua_pushvalue(L, 2); /* Copy the element 2 at the top of the stack. */
3971 hlua->Mref = luaL_ref(L, LUA_REGISTRYINDEX); /* pop the previously pushed value. */
3972
3973 return 0;
3974}
3975
3976__LJMP static int hlua_applet_http_get_priv(lua_State *L)
3977{
3978 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
3979 struct stream *s = appctx->htxn.s;
Thierry FOURNIER3b0a6d42016-12-16 08:48:32 +01003980 struct hlua *hlua;
3981
3982 /* Note that this hlua struct is from the session and not from the applet. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01003983 if (!s->hlua) {
3984 lua_pushnil(L);
3985 return 1;
3986 }
3987 hlua = s->hlua;
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003988
3989 /* Push configuration index in the stack. */
3990 lua_rawgeti(L, LUA_REGISTRYINDEX, hlua->Mref);
3991
3992 return 1;
3993}
3994
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003995/* If expected data not yet available, it returns a yield. This function
3996 * consumes the data in the buffer. It returns a string containing the
3997 * data. This string can be empty.
3998 */
3999__LJMP static int hlua_applet_http_getline_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004000{
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004001 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4002 struct stream_interface *si = appctx->appctx->owner;
4003 struct channel *chn = si_ic(si);
4004 int ret;
4005 char *blk1;
4006 int len1;
4007 char *blk2;
4008 int len2;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004009
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004010 /* Maybe we cant send a 100-continue ? */
4011 if (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_100C) {
Willy Tarreau06d80a92017-10-19 14:32:15 +02004012 ret = ci_putblk(chn, HTTP_100C, strlen(HTTP_100C));
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004013 /* if ret == -2 or -3 the channel closed or the message si too
4014 * big for the buffers. We cant send anything. So, we ignoring
4015 * the error, considers that the 100-continue is sent, and try
4016 * to receive.
4017 * If ret is -1, we dont have room in the buffer, so we yield.
4018 */
4019 if (ret == -1) {
4020 si_applet_cant_put(si);
4021 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_getline_yield, TICK_ETERNITY, 0));
4022 }
4023 appctx->appctx->ctx.hlua_apphttp.flags &= ~APPLET_100C;
4024 }
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004025
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004026 /* Check for the end of the data. */
4027 if (appctx->appctx->ctx.hlua_apphttp.left_bytes <= 0) {
4028 luaL_pushresult(&appctx->b);
4029 return 1;
4030 }
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004031
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004032 /* Read the maximum amount of data avalaible. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02004033 ret = co_getline_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004034
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004035 /* Data not yet avalaible. return yield. */
4036 if (ret == 0) {
4037 si_applet_cant_get(si);
4038 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_getline_yield, TICK_ETERNITY, 0));
4039 }
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004040
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004041 /* End of data: commit the total strings and return. */
4042 if (ret < 0) {
4043 luaL_pushresult(&appctx->b);
4044 return 1;
4045 }
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004046
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004047 /* Ensure that the block 2 length is usable. */
4048 if (ret == 1)
4049 len2 = 0;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004050
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004051 /* Copy the fisrt block caping to the length required. */
4052 if (len1 > appctx->appctx->ctx.hlua_apphttp.left_bytes)
4053 len1 = appctx->appctx->ctx.hlua_apphttp.left_bytes;
4054 luaL_addlstring(&appctx->b, blk1, len1);
4055 appctx->appctx->ctx.hlua_apphttp.left_bytes -= len1;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004056
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004057 /* Copy the second block. */
4058 if (len2 > appctx->appctx->ctx.hlua_apphttp.left_bytes)
4059 len2 = appctx->appctx->ctx.hlua_apphttp.left_bytes;
4060 luaL_addlstring(&appctx->b, blk2, len2);
4061 appctx->appctx->ctx.hlua_apphttp.left_bytes -= len2;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004062
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004063 /* Consume input channel output buffer data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02004064 co_skip(si_oc(si), len1 + len2);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004065 luaL_pushresult(&appctx->b);
4066 return 1;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004067}
4068
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004069/* Check arguments for the fucntion "hlua_channel_get_yield". */
4070__LJMP static int hlua_applet_http_getline(lua_State *L)
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004071{
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004072 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004073
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004074 /* Initialise the string catenation. */
4075 luaL_buffinit(L, &appctx->b);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004076
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004077 return MAY_LJMP(hlua_applet_http_getline_yield(L, 0, 0));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004078}
4079
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004080/* If expected data not yet available, it returns a yield. This function
4081 * consumes the data in the buffer. It returns a string containing the
4082 * data. This string can be empty.
4083 */
4084__LJMP static int hlua_applet_http_recv_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004085{
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004086 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4087 struct stream_interface *si = appctx->appctx->owner;
4088 int len = MAY_LJMP(luaL_checkinteger(L, 2));
4089 struct channel *chn = si_ic(si);
4090 int ret;
4091 char *blk1;
4092 int len1;
4093 char *blk2;
4094 int len2;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004095
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004096 /* Maybe we cant send a 100-continue ? */
4097 if (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_100C) {
Willy Tarreau06d80a92017-10-19 14:32:15 +02004098 ret = ci_putblk(chn, HTTP_100C, strlen(HTTP_100C));
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004099 /* if ret == -2 or -3 the channel closed or the message si too
4100 * big for the buffers. We cant send anything. So, we ignoring
4101 * the error, considers that the 100-continue is sent, and try
4102 * to receive.
4103 * If ret is -1, we dont have room in the buffer, so we yield.
4104 */
4105 if (ret == -1) {
4106 si_applet_cant_put(si);
4107 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_recv_yield, TICK_ETERNITY, 0));
4108 }
4109 appctx->appctx->ctx.hlua_apphttp.flags &= ~APPLET_100C;
4110 }
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004111
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004112 /* Read the maximum amount of data avalaible. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02004113 ret = co_getblk_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004114
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004115 /* Data not yet avalaible. return yield. */
4116 if (ret == 0) {
4117 si_applet_cant_get(si);
4118 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_recv_yield, TICK_ETERNITY, 0));
4119 }
4120
4121 /* End of data: commit the total strings and return. */
4122 if (ret < 0) {
4123 luaL_pushresult(&appctx->b);
4124 return 1;
4125 }
4126
4127 /* Ensure that the block 2 length is usable. */
4128 if (ret == 1)
4129 len2 = 0;
4130
4131 /* Copy the fisrt block caping to the length required. */
4132 if (len1 > len)
4133 len1 = len;
4134 luaL_addlstring(&appctx->b, blk1, len1);
4135 len -= len1;
4136
4137 /* Copy the second block. */
4138 if (len2 > len)
4139 len2 = len;
4140 luaL_addlstring(&appctx->b, blk2, len2);
4141 len -= len2;
4142
4143 /* Consume input channel output buffer data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02004144 co_skip(si_oc(si), len1 + len2);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004145 if (appctx->appctx->ctx.hlua_apphttp.left_bytes != -1)
4146 appctx->appctx->ctx.hlua_apphttp.left_bytes -= len;
4147
4148 /* If we are no other data avalaible, yield waiting for new data. */
4149 if (len > 0) {
4150 lua_pushinteger(L, len);
4151 lua_replace(L, 2);
4152 si_applet_cant_get(si);
4153 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_recv_yield, TICK_ETERNITY, 0));
4154 }
4155
4156 /* return the result. */
4157 luaL_pushresult(&appctx->b);
4158 return 1;
4159}
4160
4161/* Check arguments for the fucntion "hlua_channel_get_yield". */
4162__LJMP static int hlua_applet_http_recv(lua_State *L)
4163{
4164 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4165 int len = -1;
4166
4167 /* Check arguments. */
4168 if (lua_gettop(L) > 2)
4169 WILL_LJMP(luaL_error(L, "The 'recv' function requires between 1 and 2 arguments."));
4170 if (lua_gettop(L) >= 2) {
4171 len = MAY_LJMP(luaL_checkinteger(L, 2));
4172 lua_pop(L, 1);
4173 }
4174
4175 /* Check the required length */
4176 if (len == -1 || len > appctx->appctx->ctx.hlua_apphttp.left_bytes)
4177 len = appctx->appctx->ctx.hlua_apphttp.left_bytes;
4178 lua_pushinteger(L, len);
4179
4180 /* Initialise the string catenation. */
4181 luaL_buffinit(L, &appctx->b);
4182
4183 return MAY_LJMP(hlua_applet_http_recv_yield(L, 0, 0));
4184}
4185
4186/* Append data in the output side of the buffer. This data is immediatly
4187 * sent. The fcuntion returns the ammount of data writed. If the buffer
4188 * cannot contains the data, the function yield. The function returns -1
4189 * if the channel is closed.
4190 */
4191__LJMP static int hlua_applet_http_send_yield(lua_State *L, int status, lua_KContext ctx)
4192{
4193 size_t len;
4194 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4195 const char *str = MAY_LJMP(luaL_checklstring(L, 2, &len));
4196 int l = MAY_LJMP(luaL_checkinteger(L, 3));
4197 struct stream_interface *si = appctx->appctx->owner;
4198 struct channel *chn = si_ic(si);
4199 int max;
4200
4201 /* Get the max amount of data which can write as input in the channel. */
4202 max = channel_recv_max(chn);
4203 if (max > (len - l))
4204 max = len - l;
4205
4206 /* Copy data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02004207 ci_putblk(chn, str + l, max);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004208
4209 /* update counters. */
4210 l += max;
4211 lua_pop(L, 1);
4212 lua_pushinteger(L, l);
4213
4214 /* If some data is not send, declares the situation to the
4215 * applet, and returns a yield.
4216 */
4217 if (l < len) {
4218 si_applet_cant_put(si);
4219 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_send_yield, TICK_ETERNITY, 0));
4220 }
4221
4222 return 1;
4223}
4224
4225/* Just a wraper of "hlua_applet_send_yield". This wrapper permits
4226 * yield the LUA process, and resume it without checking the
4227 * input arguments.
4228 */
4229__LJMP static int hlua_applet_http_send(lua_State *L)
4230{
4231 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4232 size_t len;
4233 char hex[10];
4234
4235 MAY_LJMP(luaL_checklstring(L, 2, &len));
4236
4237 /* If transfer encoding chunked is selected, we surround the data
4238 * by chunk data.
4239 */
4240 if (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_CHUNKED) {
4241 snprintf(hex, 9, "%x", (unsigned int)len);
4242 lua_pushfstring(L, "%s\r\n", hex);
4243 lua_insert(L, 2); /* swap the last 2 entries. */
4244 lua_pushstring(L, "\r\n");
4245 lua_concat(L, 3);
4246 }
4247
4248 /* This interger is used for followinf the amount of data sent. */
4249 lua_pushinteger(L, 0);
4250
4251 /* We want to send some data. Headers must be sent. */
4252 if (!(appctx->appctx->ctx.hlua_apphttp.flags & APPLET_HDR_SENT)) {
4253 hlua_pusherror(L, "Lua: 'send' you must call start_response() before sending data.");
4254 WILL_LJMP(lua_error(L));
4255 }
4256
4257 return MAY_LJMP(hlua_applet_http_send_yield(L, 0, 0));
4258}
4259
4260__LJMP static int hlua_applet_http_addheader(lua_State *L)
4261{
4262 const char *name;
4263 int ret;
4264
4265 MAY_LJMP(hlua_checkapplet_http(L, 1));
4266 name = MAY_LJMP(luaL_checkstring(L, 2));
4267 MAY_LJMP(luaL_checkstring(L, 3));
4268
4269 /* Push in the stack the "response" entry. */
4270 ret = lua_getfield(L, 1, "response");
4271 if (ret != LUA_TTABLE) {
4272 hlua_pusherror(L, "Lua: 'add_header' internal error: AppletHTTP['response'] "
4273 "is expected as an array. %s found", lua_typename(L, ret));
4274 WILL_LJMP(lua_error(L));
4275 }
4276
4277 /* check if the header is already registered if it is not
4278 * the case, register it.
4279 */
4280 ret = lua_getfield(L, -1, name);
4281 if (ret == LUA_TNIL) {
4282
4283 /* Entry not found. */
4284 lua_pop(L, 1); /* remove the nil. The "response" table is the top of the stack. */
4285
4286 /* Insert the new header name in the array in the top of the stack.
4287 * It left the new array in the top of the stack.
4288 */
4289 lua_newtable(L);
4290 lua_pushvalue(L, 2);
4291 lua_pushvalue(L, -2);
4292 lua_settable(L, -4);
4293
4294 } else if (ret != LUA_TTABLE) {
4295
4296 /* corruption error. */
4297 hlua_pusherror(L, "Lua: 'add_header' internal error: AppletHTTP['response']['%s'] "
4298 "is expected as an array. %s found", name, lua_typename(L, ret));
4299 WILL_LJMP(lua_error(L));
4300 }
4301
4302 /* Now the top od thestack is an array of values. We push
4303 * the header value as new entry.
4304 */
4305 lua_pushvalue(L, 3);
4306 ret = lua_rawlen(L, -2);
4307 lua_rawseti(L, -2, ret + 1);
4308 lua_pushboolean(L, 1);
4309 return 1;
4310}
4311
4312__LJMP static int hlua_applet_http_status(lua_State *L)
4313{
4314 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4315 int status = MAY_LJMP(luaL_checkinteger(L, 2));
Robin H. Johnson52f5db22017-01-01 13:10:52 -08004316 const char *reason = MAY_LJMP(luaL_optlstring(L, 3, NULL, NULL));
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004317
4318 if (status < 100 || status > 599) {
4319 lua_pushboolean(L, 0);
4320 return 1;
4321 }
4322
4323 appctx->appctx->ctx.hlua_apphttp.status = status;
Robin H. Johnson52f5db22017-01-01 13:10:52 -08004324 appctx->appctx->ctx.hlua_apphttp.reason = reason;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004325 lua_pushboolean(L, 1);
4326 return 1;
4327}
4328
4329/* We will build the status line and the headers of the HTTP response.
4330 * We will try send at once if its not possible, we give back the hand
4331 * waiting for more room.
4332 */
4333__LJMP static int hlua_applet_http_start_response_yield(lua_State *L, int status, lua_KContext ctx)
4334{
4335 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4336 struct stream_interface *si = appctx->appctx->owner;
4337 struct channel *chn = si_ic(si);
4338 int ret;
4339 size_t len;
4340 const char *msg;
4341
4342 /* Get the message as the first argument on the stack. */
4343 msg = MAY_LJMP(luaL_checklstring(L, 2, &len));
4344
4345 /* Send the message at once. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02004346 ret = ci_putblk(chn, msg, len);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004347
4348 /* if ret == -2 or -3 the channel closed or the message si too
4349 * big for the buffers.
4350 */
4351 if (ret == -2 || ret == -3) {
4352 hlua_pusherror(L, "Lua: 'start_response': response header block too big");
4353 WILL_LJMP(lua_error(L));
4354 }
4355
4356 /* If ret is -1, we dont have room in the buffer, so we yield. */
4357 if (ret == -1) {
4358 si_applet_cant_put(si);
4359 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_start_response_yield, TICK_ETERNITY, 0));
4360 }
4361
4362 /* Headers sent, set the flag. */
4363 appctx->appctx->ctx.hlua_apphttp.flags |= APPLET_HDR_SENT;
4364 return 0;
4365}
4366
4367__LJMP static int hlua_applet_http_start_response(lua_State *L)
4368{
4369 struct chunk *tmp = get_trash_chunk();
4370 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004371 const char *name;
Willy Tarreaua3294632017-08-23 11:24:47 +02004372 size_t name_len;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004373 const char *value;
Willy Tarreaua3294632017-08-23 11:24:47 +02004374 size_t value_len;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004375 int id;
Willy Tarreauc9f4ea02017-08-23 09:32:06 +02004376 long long hdr_contentlength = -1;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004377 int hdr_chunked = 0;
Robin H. Johnson52f5db22017-01-01 13:10:52 -08004378 const char *reason = appctx->appctx->ctx.hlua_apphttp.reason;
4379
4380 if (reason == NULL)
4381 reason = get_reason(appctx->appctx->ctx.hlua_apphttp.status);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004382
4383 /* Use the same http version than the request. */
4384 chunk_appendf(tmp, "HTTP/1.%c %d %s\r\n",
Thierry FOURNIERd93ea2b2015-12-20 19:14:52 +01004385 appctx->appctx->ctx.hlua_apphttp.flags & APPLET_HTTP11 ? '1' : '0',
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004386 appctx->appctx->ctx.hlua_apphttp.status,
Robin H. Johnson52f5db22017-01-01 13:10:52 -08004387 reason);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004388
4389 /* Get the array associated to the field "response" in the object AppletHTTP. */
4390 lua_pushvalue(L, 0);
4391 if (lua_getfield(L, 1, "response") != LUA_TTABLE) {
4392 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response'] missing.\n",
4393 appctx->appctx->rule->arg.hlua_rule->fcn.name);
4394 WILL_LJMP(lua_error(L));
4395 }
4396
4397 /* Browse the list of headers. */
4398 lua_pushnil(L);
4399 while(lua_next(L, -2) != 0) {
4400
4401 /* We expect a string as -2. */
4402 if (lua_type(L, -2) != LUA_TSTRING) {
4403 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response'][] element must be a string. got %s.\n",
4404 appctx->appctx->rule->arg.hlua_rule->fcn.name,
4405 lua_typename(L, lua_type(L, -2)));
4406 WILL_LJMP(lua_error(L));
4407 }
Willy Tarreaua3294632017-08-23 11:24:47 +02004408 name = lua_tolstring(L, -2, &name_len);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004409
4410 /* We expect an array as -1. */
4411 if (lua_type(L, -1) != LUA_TTABLE) {
4412 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response']['%s'] element must be an table. got %s.\n",
4413 appctx->appctx->rule->arg.hlua_rule->fcn.name,
4414 name,
4415 lua_typename(L, lua_type(L, -1)));
4416 WILL_LJMP(lua_error(L));
4417 }
4418
4419 /* Browse the table who is on the top of the stack. */
4420 lua_pushnil(L);
4421 while(lua_next(L, -2) != 0) {
4422
4423 /* We expect a number as -2. */
4424 if (lua_type(L, -2) != LUA_TNUMBER) {
4425 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response']['%s'][] element must be a number. got %s.\n",
4426 appctx->appctx->rule->arg.hlua_rule->fcn.name,
4427 name,
4428 lua_typename(L, lua_type(L, -2)));
4429 WILL_LJMP(lua_error(L));
4430 }
4431 id = lua_tointeger(L, -2);
4432
4433 /* We expect a string as -2. */
4434 if (lua_type(L, -1) != LUA_TSTRING) {
4435 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response']['%s'][%d] element must be a string. got %s.\n",
4436 appctx->appctx->rule->arg.hlua_rule->fcn.name,
4437 name, id,
4438 lua_typename(L, lua_type(L, -1)));
4439 WILL_LJMP(lua_error(L));
4440 }
Willy Tarreaua3294632017-08-23 11:24:47 +02004441 value = lua_tolstring(L, -1, &value_len);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004442
4443 /* Catenate a new header. */
Willy Tarreaua3294632017-08-23 11:24:47 +02004444 if (tmp->len + name_len + 2 + value_len + 2 < tmp->size) {
4445 memcpy(tmp->str + tmp->len, name, name_len);
4446 tmp->len += name_len;
4447 tmp->str[tmp->len++] = ':';
4448 tmp->str[tmp->len++] = ' ';
4449
4450 memcpy(tmp->str + tmp->len, value, value_len);
4451 tmp->len += value_len;
4452 tmp->str[tmp->len++] = '\r';
4453 tmp->str[tmp->len++] = '\n';
4454 }
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004455
4456 /* Protocol checks. */
4457
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004458 /* Copy the header content length. The length conversion
Willy Tarreauc9f4ea02017-08-23 09:32:06 +02004459 * is done without control. If it contains a bad value,
4460 * the content-length remains negative so that we can
4461 * switch to either chunked encoding or close.
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004462 */
Willy Tarreaua3294632017-08-23 11:24:47 +02004463 if (name_len == 14 && strcasecmp("content-length", name) == 0)
Willy Tarreauc9f4ea02017-08-23 09:32:06 +02004464 strl2llrc(value, strlen(value), &hdr_contentlength);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004465
4466 /* Check if the client annouces a transfer-encoding chunked it self. */
Willy Tarreaua3294632017-08-23 11:24:47 +02004467 if (name_len == 17 && value_len == 7 &&
4468 strcasecmp("transfer-encoding", name) == 0 &&
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004469 strcasecmp("chunked", value) == 0)
4470 hdr_chunked = 1;
4471
4472 /* Remove the array from the stack, and get next element with a remaining string. */
4473 lua_pop(L, 1);
4474 }
4475
4476 /* Remove the array from the stack, and get next element with a remaining string. */
4477 lua_pop(L, 1);
4478 }
4479
Willy Tarreau06c75fe2017-08-23 09:10:38 +02004480 /* If we dont have a content-length set, and the HTTP version is 1.1
4481 * and the status code implies the presence of a message body, we must
4482 * announce a transfer encoding chunked. This is required by haproxy
4483 * for the keepalive compliance. If the applet annouces a transfer-encoding
4484 * chunked itslef, don't do anything.
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004485 */
Willy Tarreauc9f4ea02017-08-23 09:32:06 +02004486 if (hdr_contentlength < 0 && hdr_chunked == 0 &&
Willy Tarreau06c75fe2017-08-23 09:10:38 +02004487 (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_HTTP11) &&
4488 appctx->appctx->ctx.hlua_apphttp.status >= 200 &&
4489 appctx->appctx->ctx.hlua_apphttp.status != 204 &&
4490 appctx->appctx->ctx.hlua_apphttp.status != 304) {
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004491 chunk_appendf(tmp, "Transfer-encoding: chunked\r\n");
4492 appctx->appctx->ctx.hlua_apphttp.flags |= APPLET_CHUNKED;
4493 }
4494
4495 /* Finalize headers. */
4496 chunk_appendf(tmp, "\r\n");
4497
4498 /* Remove the last entry and the array of headers */
4499 lua_pop(L, 2);
4500
4501 /* Push the headers block. */
4502 lua_pushlstring(L, tmp->str, tmp->len);
4503
4504 return MAY_LJMP(hlua_applet_http_start_response_yield(L, 0, 0));
4505}
4506
4507/*
4508 *
4509 *
4510 * Class HTTP
4511 *
4512 *
4513 */
4514
4515/* Returns a struct hlua_txn if the stack entry "ud" is
4516 * a class stream, otherwise it throws an error.
4517 */
4518__LJMP static struct hlua_txn *hlua_checkhttp(lua_State *L, int ud)
4519{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004520 return MAY_LJMP(hlua_checkudata(L, ud, class_http_ref));
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004521}
4522
4523/* This function creates and push in the stack a HTTP object
4524 * according with a current TXN.
4525 */
4526static int hlua_http_new(lua_State *L, struct hlua_txn *txn)
4527{
4528 struct hlua_txn *htxn;
4529
4530 /* Check stack size. */
4531 if (!lua_checkstack(L, 3))
4532 return 0;
4533
4534 /* Create the object: obj[0] = userdata.
4535 * Note that the base of the Converters object is the
4536 * same than the TXN object.
4537 */
4538 lua_newtable(L);
4539 htxn = lua_newuserdata(L, sizeof(*htxn));
4540 lua_rawseti(L, -2, 0);
4541
4542 htxn->s = txn->s;
4543 htxn->p = txn->p;
4544
4545 /* Pop a class stream metatable and affect it to the table. */
4546 lua_rawgeti(L, LUA_REGISTRYINDEX, class_http_ref);
4547 lua_setmetatable(L, -2);
4548
4549 return 1;
4550}
4551
4552/* This function creates ans returns an array of HTTP headers.
4553 * This function does not fails. It is used as wrapper with the
4554 * 2 following functions.
4555 */
4556__LJMP static int hlua_http_get_headers(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg)
4557{
4558 const char *cur_ptr, *cur_next, *p;
4559 int old_idx, cur_idx;
4560 struct hdr_idx_elem *cur_hdr;
4561 const char *hn, *hv;
4562 int hnl, hvl;
4563 int type;
4564 const char *in;
4565 char *out;
4566 int len;
4567
4568 /* Create the table. */
4569 lua_newtable(L);
4570
4571 if (!htxn->s->txn)
4572 return 1;
4573
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004574 /* Check if a valid response is parsed */
4575 if (unlikely(msg->msg_state < HTTP_MSG_BODY))
4576 return 1;
4577
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004578 /* Build array of headers. */
4579 old_idx = 0;
4580 cur_next = msg->chn->buf->p + hdr_idx_first_pos(&htxn->s->txn->hdr_idx);
4581
4582 while (1) {
4583 cur_idx = htxn->s->txn->hdr_idx.v[old_idx].next;
4584 if (!cur_idx)
4585 break;
4586 old_idx = cur_idx;
4587
4588 cur_hdr = &htxn->s->txn->hdr_idx.v[cur_idx];
4589 cur_ptr = cur_next;
4590 cur_next = cur_ptr + cur_hdr->len + cur_hdr->cr + 1;
4591
4592 /* Now we have one full header at cur_ptr of len cur_hdr->len,
4593 * and the next header starts at cur_next. We'll check
4594 * this header in the list as well as against the default
4595 * rule.
4596 */
4597
4598 /* look for ': *'. */
4599 hn = cur_ptr;
4600 for (p = cur_ptr; p < cur_ptr + cur_hdr->len && *p != ':'; p++);
4601 if (p >= cur_ptr+cur_hdr->len)
4602 continue;
4603 hnl = p - hn;
4604 p++;
4605 while (p < cur_ptr+cur_hdr->len && ( *p == ' ' || *p == '\t' ))
4606 p++;
4607 if (p >= cur_ptr+cur_hdr->len)
4608 continue;
4609 hv = p;
4610 hvl = cur_ptr+cur_hdr->len-p;
4611
4612 /* Lowercase the key. Don't check the size of trash, it have
4613 * the size of one buffer and the input data contains in one
4614 * buffer.
4615 */
4616 out = trash.str;
4617 for (in=hn; in<hn+hnl; in++, out++)
4618 *out = tolower(*in);
4619 *out = '\0';
4620
4621 /* Check for existing entry:
4622 * assume that the table is on the top of the stack, and
4623 * push the key in the stack, the function lua_gettable()
4624 * perform the lookup.
4625 */
4626 lua_pushlstring(L, trash.str, hnl);
4627 lua_gettable(L, -2);
4628 type = lua_type(L, -1);
4629
4630 switch (type) {
4631 case LUA_TNIL:
4632 /* Table not found, create it. */
4633 lua_pop(L, 1); /* remove the nil value. */
4634 lua_pushlstring(L, trash.str, hnl); /* push the header name as key. */
4635 lua_newtable(L); /* create and push empty table. */
4636 lua_pushlstring(L, hv, hvl); /* push header value. */
4637 lua_rawseti(L, -2, 0); /* index header value (pop it). */
4638 lua_rawset(L, -3); /* index new table with header name (pop the values). */
4639 break;
4640
4641 case LUA_TTABLE:
4642 /* Entry found: push the value in the table. */
4643 len = lua_rawlen(L, -1);
4644 lua_pushlstring(L, hv, hvl); /* push header value. */
4645 lua_rawseti(L, -2, len+1); /* index header value (pop it). */
4646 lua_pop(L, 1); /* remove the table (it is stored in the main table). */
4647 break;
4648
4649 default:
4650 /* Other cases are errors. */
4651 hlua_pusherror(L, "internal error during the parsing of headers.");
4652 WILL_LJMP(lua_error(L));
4653 }
4654 }
4655
4656 return 1;
4657}
4658
4659__LJMP static int hlua_http_req_get_headers(lua_State *L)
4660{
4661 struct hlua_txn *htxn;
4662
4663 MAY_LJMP(check_args(L, 1, "req_get_headers"));
4664 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4665
4666 return hlua_http_get_headers(L, htxn, &htxn->s->txn->req);
4667}
4668
4669__LJMP static int hlua_http_res_get_headers(lua_State *L)
4670{
4671 struct hlua_txn *htxn;
4672
4673 MAY_LJMP(check_args(L, 1, "res_get_headers"));
4674 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4675
4676 return hlua_http_get_headers(L, htxn, &htxn->s->txn->rsp);
4677}
4678
4679/* This function replace full header, or just a value in
4680 * the request or in the response. It is a wrapper fir the
4681 * 4 following functions.
4682 */
4683__LJMP static inline int hlua_http_rep_hdr(lua_State *L, struct hlua_txn *htxn,
4684 struct http_msg *msg, int action)
4685{
4686 size_t name_len;
4687 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
4688 const char *reg = MAY_LJMP(luaL_checkstring(L, 3));
4689 const char *value = MAY_LJMP(luaL_checkstring(L, 4));
4690 struct my_regex re;
4691
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004692 /* Check if a valid response is parsed */
4693 if (unlikely(msg->msg_state < HTTP_MSG_BODY))
4694 return 0;
4695
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004696 if (!regex_comp(reg, &re, 1, 1, NULL))
4697 WILL_LJMP(luaL_argerror(L, 3, "invalid regex"));
4698
4699 http_transform_header_str(htxn->s, msg, name, name_len, value, &re, action);
4700 regex_free(&re);
4701 return 0;
4702}
4703
4704__LJMP static int hlua_http_req_rep_hdr(lua_State *L)
4705{
4706 struct hlua_txn *htxn;
4707
4708 MAY_LJMP(check_args(L, 4, "req_rep_hdr"));
4709 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4710
4711 return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->req, ACT_HTTP_REPLACE_HDR));
4712}
4713
4714__LJMP static int hlua_http_res_rep_hdr(lua_State *L)
4715{
4716 struct hlua_txn *htxn;
4717
4718 MAY_LJMP(check_args(L, 4, "res_rep_hdr"));
4719 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4720
4721 return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->rsp, ACT_HTTP_REPLACE_HDR));
4722}
4723
4724__LJMP static int hlua_http_req_rep_val(lua_State *L)
4725{
4726 struct hlua_txn *htxn;
4727
4728 MAY_LJMP(check_args(L, 4, "req_rep_hdr"));
4729 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4730
4731 return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->req, ACT_HTTP_REPLACE_VAL));
4732}
4733
4734__LJMP static int hlua_http_res_rep_val(lua_State *L)
4735{
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004736 struct hlua_txn *htxn;
4737
4738 MAY_LJMP(check_args(L, 4, "res_rep_val"));
4739 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4740
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02004741 return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->rsp, ACT_HTTP_REPLACE_VAL));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004742}
4743
4744/* This function deletes all the occurences of an header.
4745 * It is a wrapper for the 2 following functions.
4746 */
4747__LJMP static inline int hlua_http_del_hdr(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg)
4748{
4749 size_t len;
4750 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &len));
4751 struct hdr_ctx ctx;
Willy Tarreaueee5b512015-04-03 23:46:31 +02004752 struct http_txn *txn = htxn->s->txn;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004753
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004754 /* Check if a valid response is parsed */
4755 if (unlikely(msg->msg_state < HTTP_MSG_BODY))
4756 return 0;
4757
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004758 ctx.idx = 0;
4759 while (http_find_header2(name, len, msg->chn->buf->p, &txn->hdr_idx, &ctx))
4760 http_remove_header2(msg, &txn->hdr_idx, &ctx);
4761 return 0;
4762}
4763
4764__LJMP static int hlua_http_req_del_hdr(lua_State *L)
4765{
4766 struct hlua_txn *htxn;
4767
4768 MAY_LJMP(check_args(L, 2, "req_del_hdr"));
4769 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4770
Willy Tarreaueee5b512015-04-03 23:46:31 +02004771 return hlua_http_del_hdr(L, htxn, &htxn->s->txn->req);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004772}
4773
4774__LJMP static int hlua_http_res_del_hdr(lua_State *L)
4775{
4776 struct hlua_txn *htxn;
4777
4778 MAY_LJMP(check_args(L, 2, "req_del_hdr"));
4779 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4780
Willy Tarreaueee5b512015-04-03 23:46:31 +02004781 return hlua_http_del_hdr(L, htxn, &htxn->s->txn->rsp);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004782}
4783
4784/* This function adds an header. It is a wrapper used by
4785 * the 2 following functions.
4786 */
4787__LJMP static inline int hlua_http_add_hdr(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg)
4788{
4789 size_t name_len;
4790 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
4791 size_t value_len;
4792 const char *value = MAY_LJMP(luaL_checklstring(L, 3, &value_len));
4793 char *p;
4794
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004795 /* Check if a valid message is parsed */
4796 if (unlikely(msg->msg_state < HTTP_MSG_BODY))
4797 return 0;
4798
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004799 /* Check length. */
4800 trash.len = value_len + name_len + 2;
4801 if (trash.len > trash.size)
4802 return 0;
4803
4804 /* Creates the header string. */
4805 p = trash.str;
4806 memcpy(p, name, name_len);
4807 p += name_len;
4808 *p = ':';
4809 p++;
4810 *p = ' ';
4811 p++;
4812 memcpy(p, value, value_len);
4813
Willy Tarreaueee5b512015-04-03 23:46:31 +02004814 lua_pushboolean(L, http_header_add_tail2(msg, &htxn->s->txn->hdr_idx,
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004815 trash.str, trash.len) != 0);
4816
4817 return 0;
4818}
4819
4820__LJMP static int hlua_http_req_add_hdr(lua_State *L)
4821{
4822 struct hlua_txn *htxn;
4823
4824 MAY_LJMP(check_args(L, 3, "req_add_hdr"));
4825 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4826
Willy Tarreaueee5b512015-04-03 23:46:31 +02004827 return hlua_http_add_hdr(L, htxn, &htxn->s->txn->req);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004828}
4829
4830__LJMP static int hlua_http_res_add_hdr(lua_State *L)
4831{
4832 struct hlua_txn *htxn;
4833
4834 MAY_LJMP(check_args(L, 3, "res_add_hdr"));
4835 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4836
Willy Tarreaueee5b512015-04-03 23:46:31 +02004837 return hlua_http_add_hdr(L, htxn, &htxn->s->txn->rsp);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004838}
4839
4840static int hlua_http_req_set_hdr(lua_State *L)
4841{
4842 struct hlua_txn *htxn;
4843
4844 MAY_LJMP(check_args(L, 3, "req_set_hdr"));
4845 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4846
Willy Tarreaueee5b512015-04-03 23:46:31 +02004847 hlua_http_del_hdr(L, htxn, &htxn->s->txn->req);
4848 return hlua_http_add_hdr(L, htxn, &htxn->s->txn->req);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004849}
4850
4851static int hlua_http_res_set_hdr(lua_State *L)
4852{
4853 struct hlua_txn *htxn;
4854
4855 MAY_LJMP(check_args(L, 3, "res_set_hdr"));
4856 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4857
Willy Tarreaueee5b512015-04-03 23:46:31 +02004858 hlua_http_del_hdr(L, htxn, &htxn->s->txn->rsp);
4859 return hlua_http_add_hdr(L, htxn, &htxn->s->txn->rsp);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004860}
4861
4862/* This function set the method. */
4863static int hlua_http_req_set_meth(lua_State *L)
4864{
Willy Tarreaubcb39cc2015-04-06 11:21:44 +02004865 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004866 size_t name_len;
4867 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004868
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004869 /* Check if a valid request is parsed */
4870 if (unlikely(htxn->s->txn->req.msg_state < HTTP_MSG_BODY)) {
4871 lua_pushboolean(L, 0);
4872 return 1;
4873 }
4874
Willy Tarreau987e3fb2015-04-04 01:09:08 +02004875 lua_pushboolean(L, http_replace_req_line(0, name, name_len, htxn->p, htxn->s) != -1);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004876 return 1;
4877}
4878
4879/* This function set the method. */
4880static int hlua_http_req_set_path(lua_State *L)
4881{
Willy Tarreaubcb39cc2015-04-06 11:21:44 +02004882 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004883 size_t name_len;
4884 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004885
4886 /* Check if a valid request is parsed */
4887 if (unlikely(htxn->s->txn->req.msg_state < HTTP_MSG_BODY)) {
4888 lua_pushboolean(L, 0);
4889 return 1;
4890 }
4891
Willy Tarreau987e3fb2015-04-04 01:09:08 +02004892 lua_pushboolean(L, http_replace_req_line(1, name, name_len, htxn->p, htxn->s) != -1);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004893 return 1;
4894}
4895
4896/* This function set the query-string. */
4897static int hlua_http_req_set_query(lua_State *L)
4898{
Willy Tarreaubcb39cc2015-04-06 11:21:44 +02004899 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004900 size_t name_len;
4901 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004902
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004903 /* Check if a valid request is parsed */
4904 if (unlikely(htxn->s->txn->req.msg_state < HTTP_MSG_BODY)) {
4905 lua_pushboolean(L, 0);
4906 return 1;
4907 }
4908
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004909 /* Check length. */
4910 if (name_len > trash.size - 1) {
4911 lua_pushboolean(L, 0);
4912 return 1;
4913 }
4914
4915 /* Add the mark question as prefix. */
4916 chunk_reset(&trash);
4917 trash.str[trash.len++] = '?';
4918 memcpy(trash.str + trash.len, name, name_len);
4919 trash.len += name_len;
4920
Willy Tarreau987e3fb2015-04-04 01:09:08 +02004921 lua_pushboolean(L, http_replace_req_line(2, trash.str, trash.len, htxn->p, htxn->s) != -1);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004922 return 1;
4923}
4924
4925/* This function set the uri. */
4926static int hlua_http_req_set_uri(lua_State *L)
4927{
Willy Tarreaubcb39cc2015-04-06 11:21:44 +02004928 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004929 size_t name_len;
4930 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004931
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004932 /* Check if a valid request is parsed */
4933 if (unlikely(htxn->s->txn->req.msg_state < HTTP_MSG_BODY)) {
4934 lua_pushboolean(L, 0);
4935 return 1;
4936 }
4937
Willy Tarreau987e3fb2015-04-04 01:09:08 +02004938 lua_pushboolean(L, http_replace_req_line(3, name, name_len, htxn->p, htxn->s) != -1);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004939 return 1;
4940}
4941
Robin H. Johnson52f5db22017-01-01 13:10:52 -08004942/* This function set the response code & optionally reason. */
Thierry FOURNIER35d70ef2015-08-26 16:21:56 +02004943static int hlua_http_res_set_status(lua_State *L)
4944{
4945 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4946 unsigned int code = MAY_LJMP(luaL_checkinteger(L, 2));
Robin H. Johnson52f5db22017-01-01 13:10:52 -08004947 const char *reason = MAY_LJMP(luaL_optlstring(L, 3, NULL, NULL));
Thierry FOURNIER35d70ef2015-08-26 16:21:56 +02004948
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004949 /* Check if a valid response is parsed */
4950 if (unlikely(htxn->s->txn->rsp.msg_state < HTTP_MSG_BODY))
4951 return 0;
4952
Robin H. Johnson52f5db22017-01-01 13:10:52 -08004953 http_set_status(code, reason, htxn->s);
Thierry FOURNIER35d70ef2015-08-26 16:21:56 +02004954 return 0;
4955}
4956
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004957/*
4958 *
4959 *
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01004960 * Class TXN
4961 *
4962 *
4963 */
4964
4965/* Returns a struct hlua_session if the stack entry "ud" is
Willy Tarreau87b09662015-04-03 00:22:06 +02004966 * a class stream, otherwise it throws an error.
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01004967 */
4968__LJMP static struct hlua_txn *hlua_checktxn(lua_State *L, int ud)
4969{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004970 return MAY_LJMP(hlua_checkudata(L, ud, class_txn_ref));
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01004971}
4972
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +02004973__LJMP static int hlua_set_var(lua_State *L)
4974{
4975 struct hlua_txn *htxn;
4976 const char *name;
4977 size_t len;
4978 struct sample smp;
4979
4980 MAY_LJMP(check_args(L, 3, "set_var"));
4981
4982 /* It is useles to retrieve the stream, but this function
4983 * runs only in a stream context.
4984 */
4985 htxn = MAY_LJMP(hlua_checktxn(L, 1));
4986 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
4987
4988 /* Converts the third argument in a sample. */
4989 hlua_lua2smp(L, 3, &smp);
4990
4991 /* Store the sample in a variable. */
Willy Tarreau7560dd42016-03-10 16:28:58 +01004992 smp_set_owner(&smp, htxn->p, htxn->s->sess, htxn->s, htxn->dir & SMP_OPT_DIR);
Willy Tarreau6204cd92016-03-10 16:33:04 +01004993 vars_set_by_name(name, len, &smp);
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +02004994 return 0;
4995}
4996
Christopher Faulet85d79c92016-11-09 16:54:56 +01004997__LJMP static int hlua_unset_var(lua_State *L)
4998{
4999 struct hlua_txn *htxn;
5000 const char *name;
5001 size_t len;
5002 struct sample smp;
5003
5004 MAY_LJMP(check_args(L, 2, "unset_var"));
5005
5006 /* It is useles to retrieve the stream, but this function
5007 * runs only in a stream context.
5008 */
5009 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5010 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
5011
5012 /* Unset the variable. */
5013 smp_set_owner(&smp, htxn->p, htxn->s->sess, htxn->s, htxn->dir & SMP_OPT_DIR);
5014 vars_unset_by_name(name, len, &smp);
5015 return 0;
5016}
5017
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +02005018__LJMP static int hlua_get_var(lua_State *L)
5019{
5020 struct hlua_txn *htxn;
5021 const char *name;
5022 size_t len;
5023 struct sample smp;
5024
5025 MAY_LJMP(check_args(L, 2, "get_var"));
5026
5027 /* It is useles to retrieve the stream, but this function
5028 * runs only in a stream context.
5029 */
5030 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5031 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
5032
Willy Tarreau7560dd42016-03-10 16:28:58 +01005033 smp_set_owner(&smp, htxn->p, htxn->s->sess, htxn->s, htxn->dir & SMP_OPT_DIR);
Willy Tarreau6204cd92016-03-10 16:33:04 +01005034 if (!vars_get_by_name(name, len, &smp)) {
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +02005035 lua_pushnil(L);
5036 return 1;
5037 }
5038
5039 return hlua_smp2lua(L, &smp);
5040}
5041
Willy Tarreau59551662015-03-10 14:23:13 +01005042__LJMP static int hlua_set_priv(lua_State *L)
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01005043{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005044 struct hlua *hlua;
5045
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01005046 MAY_LJMP(check_args(L, 2, "set_priv"));
5047
Willy Tarreau87b09662015-04-03 00:22:06 +02005048 /* It is useles to retrieve the stream, but this function
5049 * runs only in a stream context.
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01005050 */
5051 MAY_LJMP(hlua_checktxn(L, 1));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005052 hlua = hlua_gethlua(L);
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01005053
5054 /* Remove previous value. */
Thierry FOURNIERe068b602017-04-26 13:27:05 +02005055 luaL_unref(L, LUA_REGISTRYINDEX, hlua->Mref);
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01005056
5057 /* Get and store new value. */
5058 lua_pushvalue(L, 2); /* Copy the element 2 at the top of the stack. */
5059 hlua->Mref = luaL_ref(L, LUA_REGISTRYINDEX); /* pop the previously pushed value. */
5060
5061 return 0;
5062}
5063
Willy Tarreau59551662015-03-10 14:23:13 +01005064__LJMP static int hlua_get_priv(lua_State *L)
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01005065{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005066 struct hlua *hlua;
5067
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01005068 MAY_LJMP(check_args(L, 1, "get_priv"));
5069
Willy Tarreau87b09662015-04-03 00:22:06 +02005070 /* It is useles to retrieve the stream, but this function
5071 * runs only in a stream context.
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01005072 */
5073 MAY_LJMP(hlua_checktxn(L, 1));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005074 hlua = hlua_gethlua(L);
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01005075
5076 /* Push configuration index in the stack. */
5077 lua_rawgeti(L, LUA_REGISTRYINDEX, hlua->Mref);
5078
5079 return 1;
5080}
5081
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01005082/* Create stack entry containing a class TXN. This function
5083 * return 0 if the stack does not contains free slots,
5084 * otherwise it returns 1.
5085 */
Thierry FOURNIERab00df62016-07-14 11:42:37 +02005086static int hlua_txn_new(lua_State *L, struct stream *s, struct proxy *p, int dir, int flags)
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01005087{
Willy Tarreaude491382015-04-06 11:04:28 +02005088 struct hlua_txn *htxn;
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01005089
5090 /* Check stack size. */
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01005091 if (!lua_checkstack(L, 3))
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01005092 return 0;
5093
5094 /* NOTE: The allocation never fails. The failure
5095 * throw an error, and the function never returns.
5096 * if the throw is not avalaible, the process is aborted.
5097 */
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01005098 /* Create the object: obj[0] = userdata. */
5099 lua_newtable(L);
Willy Tarreaude491382015-04-06 11:04:28 +02005100 htxn = lua_newuserdata(L, sizeof(*htxn));
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01005101 lua_rawseti(L, -2, 0);
5102
Willy Tarreaude491382015-04-06 11:04:28 +02005103 htxn->s = s;
5104 htxn->p = p;
Thierry FOURNIERc4eebc82015-11-02 10:01:59 +01005105 htxn->dir = dir;
Thierry FOURNIERab00df62016-07-14 11:42:37 +02005106 htxn->flags = flags;
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01005107
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01005108 /* Create the "f" field that contains a list of fetches. */
5109 lua_pushstring(L, "f");
Thierry FOURNIERca988662015-12-20 18:43:03 +01005110 if (!hlua_fetches_new(L, htxn, HLUA_F_MAY_USE_HTTP))
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01005111 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02005112 lua_rawset(L, -3);
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01005113
5114 /* Create the "sf" field that contains a list of stringsafe fetches. */
5115 lua_pushstring(L, "sf");
Thierry FOURNIERca988662015-12-20 18:43:03 +01005116 if (!hlua_fetches_new(L, htxn, HLUA_F_MAY_USE_HTTP | HLUA_F_AS_STRING))
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01005117 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02005118 lua_rawset(L, -3);
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01005119
Thierry FOURNIER594afe72015-03-10 23:58:30 +01005120 /* Create the "c" field that contains a list of converters. */
5121 lua_pushstring(L, "c");
Willy Tarreaude491382015-04-06 11:04:28 +02005122 if (!hlua_converters_new(L, htxn, 0))
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01005123 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02005124 lua_rawset(L, -3);
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01005125
5126 /* Create the "sc" field that contains a list of stringsafe converters. */
5127 lua_pushstring(L, "sc");
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01005128 if (!hlua_converters_new(L, htxn, HLUA_F_AS_STRING))
Thierry FOURNIER594afe72015-03-10 23:58:30 +01005129 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02005130 lua_rawset(L, -3);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01005131
Thierry FOURNIER397826a2015-03-11 19:39:09 +01005132 /* Create the "req" field that contains the request channel object. */
5133 lua_pushstring(L, "req");
Willy Tarreau2a71af42015-03-10 13:51:50 +01005134 if (!hlua_channel_new(L, &s->req))
Thierry FOURNIER397826a2015-03-11 19:39:09 +01005135 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02005136 lua_rawset(L, -3);
Thierry FOURNIER397826a2015-03-11 19:39:09 +01005137
5138 /* Create the "res" field that contains the response channel object. */
5139 lua_pushstring(L, "res");
Willy Tarreau2a71af42015-03-10 13:51:50 +01005140 if (!hlua_channel_new(L, &s->res))
Thierry FOURNIER397826a2015-03-11 19:39:09 +01005141 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02005142 lua_rawset(L, -3);
Thierry FOURNIER397826a2015-03-11 19:39:09 +01005143
Thierry FOURNIER08504f42015-03-16 14:17:08 +01005144 /* Creates the HTTP object is the current proxy allows http. */
5145 lua_pushstring(L, "http");
5146 if (p->mode == PR_MODE_HTTP) {
Willy Tarreaude491382015-04-06 11:04:28 +02005147 if (!hlua_http_new(L, htxn))
Thierry FOURNIER08504f42015-03-16 14:17:08 +01005148 return 0;
5149 }
5150 else
5151 lua_pushnil(L);
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02005152 lua_rawset(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01005153
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01005154 /* Pop a class sesison metatable and affect it to the userdata. */
5155 lua_rawgeti(L, LUA_REGISTRYINDEX, class_txn_ref);
5156 lua_setmetatable(L, -2);
5157
5158 return 1;
5159}
5160
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +01005161__LJMP static int hlua_txn_deflog(lua_State *L)
5162{
5163 const char *msg;
5164 struct hlua_txn *htxn;
5165
5166 MAY_LJMP(check_args(L, 2, "deflog"));
5167 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5168 msg = MAY_LJMP(luaL_checkstring(L, 2));
5169
5170 hlua_sendlog(htxn->s->be, htxn->s->logs.level, msg);
5171 return 0;
5172}
5173
5174__LJMP static int hlua_txn_log(lua_State *L)
5175{
5176 int level;
5177 const char *msg;
5178 struct hlua_txn *htxn;
5179
5180 MAY_LJMP(check_args(L, 3, "log"));
5181 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5182 level = MAY_LJMP(luaL_checkinteger(L, 2));
5183 msg = MAY_LJMP(luaL_checkstring(L, 3));
5184
5185 if (level < 0 || level >= NB_LOG_LEVELS)
5186 WILL_LJMP(luaL_argerror(L, 1, "Invalid loglevel."));
5187
5188 hlua_sendlog(htxn->s->be, level, msg);
5189 return 0;
5190}
5191
5192__LJMP static int hlua_txn_log_debug(lua_State *L)
5193{
5194 const char *msg;
5195 struct hlua_txn *htxn;
5196
5197 MAY_LJMP(check_args(L, 2, "Debug"));
5198 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5199 msg = MAY_LJMP(luaL_checkstring(L, 2));
5200 hlua_sendlog(htxn->s->be, LOG_DEBUG, msg);
5201 return 0;
5202}
5203
5204__LJMP static int hlua_txn_log_info(lua_State *L)
5205{
5206 const char *msg;
5207 struct hlua_txn *htxn;
5208
5209 MAY_LJMP(check_args(L, 2, "Info"));
5210 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5211 msg = MAY_LJMP(luaL_checkstring(L, 2));
5212 hlua_sendlog(htxn->s->be, LOG_INFO, msg);
5213 return 0;
5214}
5215
5216__LJMP static int hlua_txn_log_warning(lua_State *L)
5217{
5218 const char *msg;
5219 struct hlua_txn *htxn;
5220
5221 MAY_LJMP(check_args(L, 2, "Warning"));
5222 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5223 msg = MAY_LJMP(luaL_checkstring(L, 2));
5224 hlua_sendlog(htxn->s->be, LOG_WARNING, msg);
5225 return 0;
5226}
5227
5228__LJMP static int hlua_txn_log_alert(lua_State *L)
5229{
5230 const char *msg;
5231 struct hlua_txn *htxn;
5232
5233 MAY_LJMP(check_args(L, 2, "Alert"));
5234 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5235 msg = MAY_LJMP(luaL_checkstring(L, 2));
5236 hlua_sendlog(htxn->s->be, LOG_ALERT, msg);
5237 return 0;
5238}
5239
Thierry FOURNIER2cce3532015-03-16 12:04:16 +01005240__LJMP static int hlua_txn_set_loglevel(lua_State *L)
5241{
5242 struct hlua_txn *htxn;
5243 int ll;
5244
5245 MAY_LJMP(check_args(L, 2, "set_loglevel"));
5246 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5247 ll = MAY_LJMP(luaL_checkinteger(L, 2));
5248
5249 if (ll < 0 || ll > 7)
5250 WILL_LJMP(luaL_argerror(L, 2, "Bad log level. It must be between 0 and 7"));
5251
5252 htxn->s->logs.level = ll;
5253 return 0;
5254}
5255
5256__LJMP static int hlua_txn_set_tos(lua_State *L)
5257{
5258 struct hlua_txn *htxn;
5259 struct connection *cli_conn;
5260 int tos;
5261
5262 MAY_LJMP(check_args(L, 2, "set_tos"));
5263 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5264 tos = MAY_LJMP(luaL_checkinteger(L, 2));
5265
Willy Tarreau9ad7bd42015-04-03 19:19:59 +02005266 if ((cli_conn = objt_conn(htxn->s->sess->origin)) && conn_ctrl_ready(cli_conn))
Willy Tarreau585744b2017-08-24 14:31:19 +02005267 inet_set_tos(cli_conn->handle.fd, &cli_conn->addr.from, tos);
Thierry FOURNIER2cce3532015-03-16 12:04:16 +01005268
5269 return 0;
5270}
5271
5272__LJMP static int hlua_txn_set_mark(lua_State *L)
5273{
5274#ifdef SO_MARK
5275 struct hlua_txn *htxn;
5276 struct connection *cli_conn;
5277 int mark;
5278
5279 MAY_LJMP(check_args(L, 2, "set_mark"));
5280 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5281 mark = MAY_LJMP(luaL_checkinteger(L, 2));
5282
Willy Tarreau9ad7bd42015-04-03 19:19:59 +02005283 if ((cli_conn = objt_conn(htxn->s->sess->origin)) && conn_ctrl_ready(cli_conn))
Willy Tarreau585744b2017-08-24 14:31:19 +02005284 setsockopt(cli_conn->handle.fd, SOL_SOCKET, SO_MARK, &mark, sizeof(mark));
Thierry FOURNIER2cce3532015-03-16 12:04:16 +01005285#endif
5286 return 0;
5287}
5288
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005289/* This function is an Lua binding that send pending data
5290 * to the client, and close the stream interface.
5291 */
Thierry FOURNIER4bb375c2015-08-26 08:42:21 +02005292__LJMP static int hlua_txn_done(lua_State *L)
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005293{
Willy Tarreaub2ccb562015-04-06 11:11:15 +02005294 struct hlua_txn *htxn;
Thierry FOURNIER9bd52d42016-07-14 11:45:33 +02005295 struct hlua *hlua;
Willy Tarreau81389672015-03-10 12:03:52 +01005296 struct channel *ic, *oc;
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005297
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005298 MAY_LJMP(check_args(L, 1, "close"));
Willy Tarreaub2ccb562015-04-06 11:11:15 +02005299 htxn = MAY_LJMP(hlua_checktxn(L, 1));
Thierry FOURNIER9bd52d42016-07-14 11:45:33 +02005300 hlua = hlua_gethlua(L);
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005301
Thierry FOURNIERab00df62016-07-14 11:42:37 +02005302 /* If the flags NOTERM is set, we cannot terminate the http
5303 * session, so we just end the execution of the current
5304 * lua code.
5305 */
5306 if (htxn->flags & HLUA_TXN_NOTERM) {
5307 WILL_LJMP(hlua_done(L));
5308 return 0;
5309 }
5310
Willy Tarreaub2ccb562015-04-06 11:11:15 +02005311 ic = &htxn->s->req;
5312 oc = &htxn->s->res;
Willy Tarreau81389672015-03-10 12:03:52 +01005313
Willy Tarreau630ef452015-08-28 10:06:15 +02005314 if (htxn->s->txn) {
5315 /* HTTP mode, let's stay in sync with the stream */
5316 bi_fast_delete(ic->buf, htxn->s->txn->req.sov);
5317 htxn->s->txn->req.next -= htxn->s->txn->req.sov;
5318 htxn->s->txn->req.sov = 0;
5319 ic->analysers &= AN_REQ_HTTP_XFER_BODY;
5320 oc->analysers = AN_RES_HTTP_XFER_BODY;
5321 htxn->s->txn->req.msg_state = HTTP_MSG_CLOSED;
5322 htxn->s->txn->rsp.msg_state = HTTP_MSG_DONE;
5323
Willy Tarreau630ef452015-08-28 10:06:15 +02005324 /* Note that if we want to support keep-alive, we need
5325 * to bypass the close/shutr_now calls below, but that
5326 * may only be done if the HTTP request was already
5327 * processed and the connection header is known (ie
5328 * not during TCP rules).
5329 */
5330 }
5331
Thierry FOURNIER10ec2142015-08-24 17:23:45 +02005332 channel_auto_read(ic);
Willy Tarreau81389672015-03-10 12:03:52 +01005333 channel_abort(ic);
5334 channel_auto_close(ic);
5335 channel_erase(ic);
Thierry FOURNIER10ec2142015-08-24 17:23:45 +02005336
5337 oc->wex = tick_add_ifset(now_ms, oc->wto);
Willy Tarreau81389672015-03-10 12:03:52 +01005338 channel_auto_read(oc);
5339 channel_auto_close(oc);
5340 channel_shutr_now(oc);
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005341
Willy Tarreau0458b082015-08-28 09:40:04 +02005342 ic->analysers = 0;
Thierry FOURNIER4bb375c2015-08-26 08:42:21 +02005343
Thierry FOURNIER9bd52d42016-07-14 11:45:33 +02005344 hlua->flags |= HLUA_STOP;
Thierry FOURNIER4bb375c2015-08-26 08:42:21 +02005345 WILL_LJMP(hlua_done(L));
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +01005346 return 0;
5347}
5348
5349__LJMP static int hlua_log(lua_State *L)
5350{
5351 int level;
5352 const char *msg;
5353
5354 MAY_LJMP(check_args(L, 2, "log"));
5355 level = MAY_LJMP(luaL_checkinteger(L, 1));
5356 msg = MAY_LJMP(luaL_checkstring(L, 2));
5357
5358 if (level < 0 || level >= NB_LOG_LEVELS)
5359 WILL_LJMP(luaL_argerror(L, 1, "Invalid loglevel."));
5360
5361 hlua_sendlog(NULL, level, msg);
5362 return 0;
5363}
5364
5365__LJMP static int hlua_log_debug(lua_State *L)
5366{
5367 const char *msg;
5368
5369 MAY_LJMP(check_args(L, 1, "debug"));
5370 msg = MAY_LJMP(luaL_checkstring(L, 1));
5371 hlua_sendlog(NULL, LOG_DEBUG, msg);
5372 return 0;
5373}
5374
5375__LJMP static int hlua_log_info(lua_State *L)
5376{
5377 const char *msg;
5378
5379 MAY_LJMP(check_args(L, 1, "info"));
5380 msg = MAY_LJMP(luaL_checkstring(L, 1));
5381 hlua_sendlog(NULL, LOG_INFO, msg);
5382 return 0;
5383}
5384
5385__LJMP static int hlua_log_warning(lua_State *L)
5386{
5387 const char *msg;
5388
5389 MAY_LJMP(check_args(L, 1, "warning"));
5390 msg = MAY_LJMP(luaL_checkstring(L, 1));
5391 hlua_sendlog(NULL, LOG_WARNING, msg);
5392 return 0;
5393}
5394
5395__LJMP static int hlua_log_alert(lua_State *L)
5396{
5397 const char *msg;
5398
5399 MAY_LJMP(check_args(L, 1, "alert"));
5400 msg = MAY_LJMP(luaL_checkstring(L, 1));
5401 hlua_sendlog(NULL, LOG_ALERT, msg);
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005402 return 0;
5403}
5404
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01005405__LJMP static int hlua_sleep_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005406{
5407 int wakeup_ms = lua_tointeger(L, -1);
5408 if (now_ms < wakeup_ms)
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005409 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_sleep_yield, wakeup_ms, 0));
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005410 return 0;
5411}
5412
5413__LJMP static int hlua_sleep(lua_State *L)
5414{
5415 unsigned int delay;
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005416 unsigned int wakeup_ms;
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005417
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005418 MAY_LJMP(check_args(L, 1, "sleep"));
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005419
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01005420 delay = MAY_LJMP(luaL_checkinteger(L, 1)) * 1000;
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005421 wakeup_ms = tick_add(now_ms, delay);
5422 lua_pushinteger(L, wakeup_ms);
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005423
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005424 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_sleep_yield, wakeup_ms, 0));
5425 return 0;
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005426}
5427
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005428__LJMP static int hlua_msleep(lua_State *L)
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005429{
5430 unsigned int delay;
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005431 unsigned int wakeup_ms;
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005432
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005433 MAY_LJMP(check_args(L, 1, "msleep"));
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005434
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01005435 delay = MAY_LJMP(luaL_checkinteger(L, 1));
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005436 wakeup_ms = tick_add(now_ms, delay);
5437 lua_pushinteger(L, wakeup_ms);
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005438
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005439 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_sleep_yield, wakeup_ms, 0));
5440 return 0;
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005441}
5442
Thierry FOURNIER13416fe2015-02-17 15:01:59 +01005443/* This functionis an LUA binding. it permits to give back
5444 * the hand at the HAProxy scheduler. It is used when the
5445 * LUA processing consumes a lot of time.
5446 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01005447__LJMP static int hlua_yield_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005448{
5449 return 0;
5450}
5451
Thierry FOURNIER13416fe2015-02-17 15:01:59 +01005452__LJMP static int hlua_yield(lua_State *L)
5453{
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005454 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_yield_yield, TICK_ETERNITY, HLUA_CTRLYIELD));
5455 return 0;
Thierry FOURNIER13416fe2015-02-17 15:01:59 +01005456}
5457
Thierry FOURNIER37196f42015-02-16 19:34:56 +01005458/* This function change the nice of the currently executed
5459 * task. It is used set low or high priority at the current
5460 * task.
5461 */
Willy Tarreau59551662015-03-10 14:23:13 +01005462__LJMP static int hlua_set_nice(lua_State *L)
Thierry FOURNIER37196f42015-02-16 19:34:56 +01005463{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005464 struct hlua *hlua;
5465 int nice;
Thierry FOURNIER37196f42015-02-16 19:34:56 +01005466
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005467 MAY_LJMP(check_args(L, 1, "set_nice"));
5468 hlua = hlua_gethlua(L);
5469 nice = MAY_LJMP(luaL_checkinteger(L, 1));
Thierry FOURNIER37196f42015-02-16 19:34:56 +01005470
5471 /* If he task is not set, I'm in a start mode. */
5472 if (!hlua || !hlua->task)
5473 return 0;
5474
5475 if (nice < -1024)
5476 nice = -1024;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005477 else if (nice > 1024)
Thierry FOURNIER37196f42015-02-16 19:34:56 +01005478 nice = 1024;
5479
5480 hlua->task->nice = nice;
5481 return 0;
5482}
5483
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005484/* This function is used as a calback of a task. It is called by the
5485 * HAProxy task subsystem when the task is awaked. The LUA runtime can
5486 * return an E_AGAIN signal, the emmiter of this signal must set a
5487 * signal to wake the task.
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005488 *
5489 * Task wrapper are longjmp safe because the only one Lua code
5490 * executed is the safe hlua_ctx_resume();
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005491 */
5492static struct task *hlua_process_task(struct task *task)
5493{
5494 struct hlua *hlua = task->context;
5495 enum hlua_exec status;
5496
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005497 /* If it is the first call to the task, we must initialize the
5498 * execution timeouts.
5499 */
5500 if (!HLUA_IS_RUNNING(hlua))
Thierry FOURNIER10770fa2015-09-29 01:59:42 +02005501 hlua->max_time = hlua_timeout_task;
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005502
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005503 /* Execute the Lua code. */
5504 status = hlua_ctx_resume(hlua, 1);
5505
5506 switch (status) {
5507 /* finished or yield */
5508 case HLUA_E_OK:
5509 hlua_ctx_destroy(hlua);
5510 task_delete(task);
5511 task_free(task);
5512 break;
5513
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01005514 case HLUA_E_AGAIN: /* co process or timeout wake me later. */
5515 if (hlua->wake_time != TICK_ETERNITY)
Emeric Brun253e53e2017-10-17 18:58:40 +02005516 task->expire = hlua->wake_time;
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005517 break;
5518
5519 /* finished with error. */
5520 case HLUA_E_ERRMSG:
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005521 SEND_ERR(NULL, "Lua task: %s.\n", lua_tostring(hlua->T, -1));
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005522 hlua_ctx_destroy(hlua);
5523 task_delete(task);
5524 task_free(task);
Emeric Brun253e53e2017-10-17 18:58:40 +02005525 task = NULL;
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005526 break;
5527
5528 case HLUA_E_ERR:
5529 default:
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005530 SEND_ERR(NULL, "Lua task: unknown error.\n");
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005531 hlua_ctx_destroy(hlua);
5532 task_delete(task);
5533 task_free(task);
Emeric Brun253e53e2017-10-17 18:58:40 +02005534 task = NULL;
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005535 break;
5536 }
Emeric Brun253e53e2017-10-17 18:58:40 +02005537 return task;
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005538}
5539
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01005540/* This function is an LUA binding that register LUA function to be
5541 * executed after the HAProxy configuration parsing and before the
5542 * HAProxy scheduler starts. This function expect only one LUA
5543 * argument that is a function. This function returns nothing, but
5544 * throws if an error is encountered.
5545 */
5546__LJMP static int hlua_register_init(lua_State *L)
5547{
5548 struct hlua_init_function *init;
5549 int ref;
5550
5551 MAY_LJMP(check_args(L, 1, "register_init"));
5552
5553 ref = MAY_LJMP(hlua_checkfunction(L, 1));
5554
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02005555 init = calloc(1, sizeof(*init));
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01005556 if (!init)
5557 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5558
5559 init->function_ref = ref;
5560 LIST_ADDQ(&hlua_init_functions, &init->l);
5561 return 0;
5562}
5563
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005564/* This functio is an LUA binding. It permits to register a task
5565 * executed in parallel of the main HAroxy activity. The task is
5566 * created and it is set in the HAProxy scheduler. It can be called
5567 * from the "init" section, "post init" or during the runtime.
5568 *
5569 * Lua prototype:
5570 *
5571 * <none> core.register_task(<function>)
5572 */
5573static int hlua_register_task(lua_State *L)
5574{
5575 struct hlua *hlua;
5576 struct task *task;
5577 int ref;
5578
5579 MAY_LJMP(check_args(L, 1, "register_task"));
5580
5581 ref = MAY_LJMP(hlua_checkfunction(L, 1));
5582
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005583 hlua = pool_alloc2(pool2_hlua);
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005584 if (!hlua)
5585 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5586
Emeric Brunc60def82017-09-27 14:59:38 +02005587 task = task_new(MAX_THREADS_MASK);
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005588 task->context = hlua;
5589 task->process = hlua_process_task;
5590
5591 if (!hlua_ctx_init(hlua, task))
5592 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5593
5594 /* Restore the function in the stack. */
5595 lua_rawgeti(hlua->T, LUA_REGISTRYINDEX, ref);
5596 hlua->nargs = 0;
5597
5598 /* Schedule task. */
5599 task_schedule(task, now_ms);
5600
5601 return 0;
5602}
5603
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005604/* Wrapper called by HAProxy to execute an LUA converter. This wrapper
5605 * doesn't allow "yield" functions because the HAProxy engine cannot
5606 * resume converters.
5607 */
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005608static int hlua_sample_conv_wrapper(const struct arg *arg_p, struct sample *smp, void *private)
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005609{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005610 struct hlua_function *fcn = private;
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005611 struct stream *stream = smp->strm;
Thierry Fournierfd107a22016-02-19 19:57:23 +01005612 const char *error;
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005613
Willy Tarreaube508f12016-03-10 11:47:01 +01005614 if (!stream)
5615 return 0;
5616
Willy Tarreau87b09662015-04-03 00:22:06 +02005617 /* In the execution wrappers linked with a stream, the
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01005618 * Lua context can be not initialized. This behavior
5619 * permits to save performances because a systematic
5620 * Lua initialization cause 5% performances loss.
5621 */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005622 if (!stream->hlua) {
5623 stream->hlua = pool_alloc2(pool2_hlua);
5624 if (!stream->hlua) {
5625 SEND_ERR(stream->be, "Lua converter '%s': can't initialize Lua context.\n", fcn->name);
5626 return 0;
5627 }
5628 if (!hlua_ctx_init(stream->hlua, stream->task)) {
5629 SEND_ERR(stream->be, "Lua converter '%s': can't initialize Lua context.\n", fcn->name);
5630 return 0;
5631 }
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01005632 }
5633
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005634 /* If it is the first run, initialize the data for the call. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005635 if (!HLUA_IS_RUNNING(stream->hlua)) {
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005636
5637 /* The following Lua calls can fail. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005638 if (!SET_SAFE_LJMP(stream->hlua->T)) {
5639 if (lua_type(stream->hlua->T, -1) == LUA_TSTRING)
5640 error = lua_tostring(stream->hlua->T, -1);
Thierry Fournierfd107a22016-02-19 19:57:23 +01005641 else
5642 error = "critical error";
5643 SEND_ERR(stream->be, "Lua converter '%s': %s.\n", fcn->name, error);
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005644 return 0;
5645 }
5646
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005647 /* Check stack available size. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005648 if (!lua_checkstack(stream->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005649 SEND_ERR(stream->be, "Lua converter '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005650 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005651 return 0;
5652 }
5653
5654 /* Restore the function in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005655 lua_rawgeti(stream->hlua->T, LUA_REGISTRYINDEX, fcn->function_ref);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005656
5657 /* convert input sample and pust-it in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005658 if (!lua_checkstack(stream->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005659 SEND_ERR(stream->be, "Lua converter '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005660 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005661 return 0;
5662 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005663 hlua_smp2lua(stream->hlua->T, smp);
5664 stream->hlua->nargs = 1;
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005665
5666 /* push keywords in the stack. */
5667 if (arg_p) {
5668 for (; arg_p->type != ARGT_STOP; arg_p++) {
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005669 if (!lua_checkstack(stream->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005670 SEND_ERR(stream->be, "Lua converter '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005671 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005672 return 0;
5673 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005674 hlua_arg2lua(stream->hlua->T, arg_p);
5675 stream->hlua->nargs++;
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005676 }
5677 }
5678
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005679 /* We must initialize the execution timeouts. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005680 stream->hlua->max_time = hlua_timeout_session;
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005681
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005682 /* At this point the execution is safe. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005683 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005684 }
5685
5686 /* Execute the function. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005687 switch (hlua_ctx_resume(stream->hlua, 0)) {
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005688 /* finished. */
5689 case HLUA_E_OK:
Thierry FOURNIERfd80df12017-05-12 16:32:20 +02005690 /* If the stack is empty, the function fails. */
5691 if (lua_gettop(stream->hlua->T) <= 0)
5692 return 0;
5693
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005694 /* Convert the returned value in sample. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005695 hlua_lua2smp(stream->hlua->T, -1, smp);
5696 lua_pop(stream->hlua->T, 1);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005697 return 1;
5698
5699 /* yield. */
5700 case HLUA_E_AGAIN:
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005701 SEND_ERR(stream->be, "Lua converter '%s': cannot use yielded functions.\n", fcn->name);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005702 return 0;
5703
5704 /* finished with error. */
5705 case HLUA_E_ERRMSG:
5706 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005707 SEND_ERR(stream->be, "Lua converter '%s': %s.\n",
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005708 fcn->name, lua_tostring(stream->hlua->T, -1));
5709 lua_pop(stream->hlua->T, 1);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005710 return 0;
5711
5712 case HLUA_E_ERR:
5713 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005714 SEND_ERR(stream->be, "Lua converter '%s' returns an unknown error.\n", fcn->name);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005715
5716 default:
5717 return 0;
5718 }
5719}
5720
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005721/* Wrapper called by HAProxy to execute a sample-fetch. this wrapper
5722 * doesn't allow "yield" functions because the HAProxy engine cannot
Willy Tarreaube508f12016-03-10 11:47:01 +01005723 * resume sample-fetches. This function will be called by the sample
5724 * fetch engine to call lua-based fetch operations.
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005725 */
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005726static int hlua_sample_fetch_wrapper(const struct arg *arg_p, struct sample *smp,
5727 const char *kw, void *private)
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005728{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005729 struct hlua_function *fcn = private;
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005730 struct stream *stream = smp->strm;
Thierry Fournierfd107a22016-02-19 19:57:23 +01005731 const char *error;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005732 const struct chunk msg = { .len = 0 };
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005733
Willy Tarreaube508f12016-03-10 11:47:01 +01005734 if (!stream)
5735 return 0;
5736
Willy Tarreau87b09662015-04-03 00:22:06 +02005737 /* In the execution wrappers linked with a stream, the
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01005738 * Lua context can be not initialized. This behavior
5739 * permits to save performances because a systematic
5740 * Lua initialization cause 5% performances loss.
5741 */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005742 if (!stream->hlua) {
5743 stream->hlua = pool_alloc2(pool2_hlua);
5744 if (!stream->hlua) {
5745 SEND_ERR(stream->be, "Lua sample-fetch '%s': can't initialize Lua context.\n", fcn->name);
5746 return 0;
5747 }
5748 if (!hlua_ctx_init(stream->hlua, stream->task)) {
5749 SEND_ERR(stream->be, "Lua sample-fetch '%s': can't initialize Lua context.\n", fcn->name);
5750 return 0;
5751 }
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01005752 }
5753
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005754 consistency_set(stream, smp->opt, &stream->hlua->cons);
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005755
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005756 /* If it is the first run, initialize the data for the call. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005757 if (!HLUA_IS_RUNNING(stream->hlua)) {
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005758
5759 /* The following Lua calls can fail. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005760 if (!SET_SAFE_LJMP(stream->hlua->T)) {
5761 if (lua_type(stream->hlua->T, -1) == LUA_TSTRING)
5762 error = lua_tostring(stream->hlua->T, -1);
Thierry Fournierfd107a22016-02-19 19:57:23 +01005763 else
5764 error = "critical error";
5765 SEND_ERR(smp->px, "Lua sample-fetch '%s': %s.\n", fcn->name, error);
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005766 return 0;
5767 }
5768
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005769 /* Check stack available size. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005770 if (!lua_checkstack(stream->hlua->T, 2)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005771 SEND_ERR(smp->px, "Lua sample-fetch '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005772 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005773 return 0;
5774 }
5775
5776 /* Restore the function in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005777 lua_rawgeti(stream->hlua->T, LUA_REGISTRYINDEX, fcn->function_ref);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005778
5779 /* push arguments in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005780 if (!hlua_txn_new(stream->hlua->T, stream, smp->px, smp->opt & SMP_OPT_DIR,
Thierry FOURNIERab00df62016-07-14 11:42:37 +02005781 HLUA_TXN_NOTERM)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005782 SEND_ERR(smp->px, "Lua sample-fetch '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005783 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005784 return 0;
5785 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005786 stream->hlua->nargs = 1;
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005787
5788 /* push keywords in the stack. */
5789 for (; arg_p && arg_p->type != ARGT_STOP; arg_p++) {
5790 /* Check stack available size. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005791 if (!lua_checkstack(stream->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005792 SEND_ERR(smp->px, "Lua sample-fetch '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005793 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005794 return 0;
5795 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005796 hlua_arg2lua(stream->hlua->T, arg_p);
5797 stream->hlua->nargs++;
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005798 }
5799
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005800 /* We must initialize the execution timeouts. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005801 stream->hlua->max_time = hlua_timeout_session;
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005802
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005803 /* At this point the execution is safe. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005804 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005805 }
5806
5807 /* Execute the function. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005808 switch (hlua_ctx_resume(stream->hlua, 0)) {
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005809 /* finished. */
5810 case HLUA_E_OK:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005811 if (!consistency_check(stream, smp->opt, &stream->hlua->cons)) {
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005812 stream_int_retnclose(&stream->si[0], &msg);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02005813 return 0;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005814 }
Thierry FOURNIERfd80df12017-05-12 16:32:20 +02005815 /* If the stack is empty, the function fails. */
5816 if (lua_gettop(stream->hlua->T) <= 0)
5817 return 0;
5818
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005819 /* Convert the returned value in sample. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005820 hlua_lua2smp(stream->hlua->T, -1, smp);
5821 lua_pop(stream->hlua->T, 1);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005822
5823 /* Set the end of execution flag. */
5824 smp->flags &= ~SMP_F_MAY_CHANGE;
5825 return 1;
5826
5827 /* yield. */
5828 case HLUA_E_AGAIN:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005829 if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005830 stream_int_retnclose(&stream->si[0], &msg);
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005831 SEND_ERR(smp->px, "Lua sample-fetch '%s': cannot use yielded functions.\n", fcn->name);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005832 return 0;
5833
5834 /* finished with error. */
5835 case HLUA_E_ERRMSG:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005836 if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005837 stream_int_retnclose(&stream->si[0], &msg);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005838 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005839 SEND_ERR(smp->px, "Lua sample-fetch '%s': %s.\n",
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005840 fcn->name, lua_tostring(stream->hlua->T, -1));
5841 lua_pop(stream->hlua->T, 1);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005842 return 0;
5843
5844 case HLUA_E_ERR:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005845 if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005846 stream_int_retnclose(&stream->si[0], &msg);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005847 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005848 SEND_ERR(smp->px, "Lua sample-fetch '%s' returns an unknown error.\n", fcn->name);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005849
5850 default:
5851 return 0;
5852 }
5853}
5854
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005855/* This function is an LUA binding used for registering
5856 * "sample-conv" functions. It expects a converter name used
5857 * in the haproxy configuration file, and an LUA function.
5858 */
5859__LJMP static int hlua_register_converters(lua_State *L)
5860{
5861 struct sample_conv_kw_list *sck;
5862 const char *name;
5863 int ref;
5864 int len;
5865 struct hlua_function *fcn;
5866
5867 MAY_LJMP(check_args(L, 2, "register_converters"));
5868
5869 /* First argument : converter name. */
5870 name = MAY_LJMP(luaL_checkstring(L, 1));
5871
5872 /* Second argument : lua function. */
5873 ref = MAY_LJMP(hlua_checkfunction(L, 2));
5874
5875 /* Allocate and fill the sample fetch keyword struct. */
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02005876 sck = calloc(1, sizeof(*sck) + sizeof(struct sample_conv) * 2);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005877 if (!sck)
5878 WILL_LJMP(luaL_error(L, "lua out of memory error."));
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02005879 fcn = calloc(1, sizeof(*fcn));
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005880 if (!fcn)
5881 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5882
5883 /* Fill fcn. */
5884 fcn->name = strdup(name);
5885 if (!fcn->name)
5886 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5887 fcn->function_ref = ref;
5888
5889 /* List head */
5890 sck->list.n = sck->list.p = NULL;
5891
5892 /* converter keyword. */
5893 len = strlen("lua.") + strlen(name) + 1;
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02005894 sck->kw[0].kw = calloc(1, len);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005895 if (!sck->kw[0].kw)
5896 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5897
5898 snprintf((char *)sck->kw[0].kw, len, "lua.%s", name);
5899 sck->kw[0].process = hlua_sample_conv_wrapper;
David Carlier0c437f42016-04-27 16:21:56 +01005900 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 +01005901 sck->kw[0].val_args = NULL;
5902 sck->kw[0].in_type = SMP_T_STR;
5903 sck->kw[0].out_type = SMP_T_STR;
5904 sck->kw[0].private = fcn;
5905
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005906 /* Register this new converter */
5907 sample_register_convs(sck);
5908
5909 return 0;
5910}
5911
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005912/* This fucntion is an LUA binding used for registering
5913 * "sample-fetch" functions. It expects a converter name used
5914 * in the haproxy configuration file, and an LUA function.
5915 */
5916__LJMP static int hlua_register_fetches(lua_State *L)
5917{
5918 const char *name;
5919 int ref;
5920 int len;
5921 struct sample_fetch_kw_list *sfk;
5922 struct hlua_function *fcn;
5923
5924 MAY_LJMP(check_args(L, 2, "register_fetches"));
5925
5926 /* First argument : sample-fetch name. */
5927 name = MAY_LJMP(luaL_checkstring(L, 1));
5928
5929 /* Second argument : lua function. */
5930 ref = MAY_LJMP(hlua_checkfunction(L, 2));
5931
5932 /* Allocate and fill the sample fetch keyword struct. */
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02005933 sfk = calloc(1, sizeof(*sfk) + sizeof(struct sample_fetch) * 2);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005934 if (!sfk)
5935 WILL_LJMP(luaL_error(L, "lua out of memory error."));
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02005936 fcn = calloc(1, sizeof(*fcn));
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005937 if (!fcn)
5938 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5939
5940 /* Fill fcn. */
5941 fcn->name = strdup(name);
5942 if (!fcn->name)
5943 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5944 fcn->function_ref = ref;
5945
5946 /* List head */
5947 sfk->list.n = sfk->list.p = NULL;
5948
5949 /* sample-fetch keyword. */
5950 len = strlen("lua.") + strlen(name) + 1;
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02005951 sfk->kw[0].kw = calloc(1, len);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005952 if (!sfk->kw[0].kw)
5953 return luaL_error(L, "lua out of memory error.");
5954
5955 snprintf((char *)sfk->kw[0].kw, len, "lua.%s", name);
5956 sfk->kw[0].process = hlua_sample_fetch_wrapper;
David Carlier0c437f42016-04-27 16:21:56 +01005957 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 +01005958 sfk->kw[0].val_args = NULL;
5959 sfk->kw[0].out_type = SMP_T_STR;
5960 sfk->kw[0].use = SMP_USE_HTTP_ANY;
5961 sfk->kw[0].val = 0;
5962 sfk->kw[0].private = fcn;
5963
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005964 /* Register this new fetch. */
5965 sample_register_fetches(sfk);
5966
5967 return 0;
5968}
5969
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005970/* This function is a wrapper to execute each LUA function declared
5971 * as an action wrapper during the initialisation period. This function
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005972 * return ACT_RET_CONT if the processing is finished (with or without
5973 * error) and return ACT_RET_YIELD if the function must be called again
5974 * because the LUA returns a yield.
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005975 */
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005976static enum act_return hlua_action(struct act_rule *rule, struct proxy *px,
Willy Tarreau658b85b2015-09-27 10:00:49 +02005977 struct session *sess, struct stream *s, int flags)
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005978{
5979 char **arg;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005980 unsigned int analyzer;
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02005981 int dir;
Thierry Fournierfd107a22016-02-19 19:57:23 +01005982 const char *error;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005983 const struct chunk msg = { .len = 0 };
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005984
5985 switch (rule->from) {
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01005986 case ACT_F_TCP_REQ_CNT: analyzer = AN_REQ_INSPECT_FE ; dir = SMP_OPT_DIR_REQ; break;
5987 case ACT_F_TCP_RES_CNT: analyzer = AN_RES_INSPECT ; dir = SMP_OPT_DIR_RES; break;
5988 case ACT_F_HTTP_REQ: analyzer = AN_REQ_HTTP_PROCESS_FE; dir = SMP_OPT_DIR_REQ; break;
5989 case ACT_F_HTTP_RES: analyzer = AN_RES_HTTP_PROCESS_BE; dir = SMP_OPT_DIR_RES; break;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005990 default:
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005991 SEND_ERR(px, "Lua: internal error while execute action.\n");
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005992 return ACT_RET_CONT;
5993 }
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005994
Willy Tarreau87b09662015-04-03 00:22:06 +02005995 /* In the execution wrappers linked with a stream, the
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01005996 * Lua context can be not initialized. This behavior
5997 * permits to save performances because a systematic
5998 * Lua initialization cause 5% performances loss.
5999 */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006000 if (!s->hlua) {
6001 s->hlua = pool_alloc2(pool2_hlua);
6002 if (!s->hlua) {
6003 SEND_ERR(px, "Lua action '%s': can't initialize Lua context.\n",
6004 rule->arg.hlua_rule->fcn.name);
6005 return ACT_RET_CONT;
6006 }
6007 if (!hlua_ctx_init(s->hlua, s->task)) {
6008 SEND_ERR(px, "Lua action '%s': can't initialize Lua context.\n",
6009 rule->arg.hlua_rule->fcn.name);
6010 return ACT_RET_CONT;
6011 }
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01006012 }
6013
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006014 consistency_set(s, dir, &s->hlua->cons);
6015
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006016 /* If it is the first run, initialize the data for the call. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006017 if (!HLUA_IS_RUNNING(s->hlua)) {
Thierry FOURNIERbabae282015-09-17 11:36:37 +02006018
6019 /* The following Lua calls can fail. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006020 if (!SET_SAFE_LJMP(s->hlua->T)) {
6021 if (lua_type(s->hlua->T, -1) == LUA_TSTRING)
6022 error = lua_tostring(s->hlua->T, -1);
Thierry Fournierfd107a22016-02-19 19:57:23 +01006023 else
6024 error = "critical error";
6025 SEND_ERR(px, "Lua function '%s': %s.\n",
6026 rule->arg.hlua_rule->fcn.name, error);
Thierry FOURNIERbabae282015-09-17 11:36:37 +02006027 return ACT_RET_CONT;
6028 }
6029
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006030 /* Check stack available size. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006031 if (!lua_checkstack(s->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02006032 SEND_ERR(px, "Lua function '%s': full stack.\n",
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006033 rule->arg.hlua_rule->fcn.name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006034 RESET_SAFE_LJMP(s->hlua->T);
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02006035 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006036 }
6037
6038 /* Restore the function in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006039 lua_rawgeti(s->hlua->T, LUA_REGISTRYINDEX, rule->arg.hlua_rule->fcn.function_ref);
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006040
Willy Tarreau87b09662015-04-03 00:22:06 +02006041 /* Create and and push object stream in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006042 if (!hlua_txn_new(s->hlua->T, s, px, dir, 0)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02006043 SEND_ERR(px, "Lua function '%s': full stack.\n",
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006044 rule->arg.hlua_rule->fcn.name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006045 RESET_SAFE_LJMP(s->hlua->T);
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02006046 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006047 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006048 s->hlua->nargs = 1;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006049
6050 /* push keywords in the stack. */
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006051 for (arg = rule->arg.hlua_rule->args; arg && *arg; arg++) {
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006052 if (!lua_checkstack(s->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02006053 SEND_ERR(px, "Lua function '%s': full stack.\n",
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006054 rule->arg.hlua_rule->fcn.name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006055 RESET_SAFE_LJMP(s->hlua->T);
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02006056 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006057 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006058 lua_pushstring(s->hlua->T, *arg);
6059 s->hlua->nargs++;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006060 }
6061
Thierry FOURNIERbabae282015-09-17 11:36:37 +02006062 /* Now the execution is safe. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006063 RESET_SAFE_LJMP(s->hlua->T);
Thierry FOURNIERbabae282015-09-17 11:36:37 +02006064
Thierry FOURNIERbd413492015-03-03 16:52:26 +01006065 /* We must initialize the execution timeouts. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006066 s->hlua->max_time = hlua_timeout_session;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006067 }
6068
6069 /* Execute the function. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006070 switch (hlua_ctx_resume(s->hlua, !(flags & ACT_FLAG_FINAL))) {
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006071 /* finished. */
6072 case HLUA_E_OK:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006073 if (!consistency_check(s, dir, &s->hlua->cons)) {
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01006074 stream_int_retnclose(&s->si[0], &msg);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02006075 return ACT_RET_ERR;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01006076 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006077 if (s->hlua->flags & HLUA_STOP)
Thierry FOURNIER9bd52d42016-07-14 11:45:33 +02006078 return ACT_RET_STOP;
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02006079 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006080
6081 /* yield. */
6082 case HLUA_E_AGAIN:
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01006083 /* Set timeout in the required channel. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006084 if (s->hlua->wake_time != TICK_ETERNITY) {
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01006085 if (analyzer & (AN_REQ_INSPECT_FE|AN_REQ_HTTP_PROCESS_FE))
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006086 s->req.analyse_exp = s->hlua->wake_time;
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01006087 else if (analyzer & (AN_RES_INSPECT|AN_RES_HTTP_PROCESS_BE))
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006088 s->res.analyse_exp = s->hlua->wake_time;
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01006089 }
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006090 /* Some actions can be wake up when a "write" event
6091 * is detected on a response channel. This is useful
6092 * only for actions targetted on the requests.
6093 */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006094 if (HLUA_IS_WAKERESWR(s->hlua)) {
Willy Tarreau22ec1ea2014-11-27 20:45:39 +01006095 s->res.flags |= CF_WAKE_WRITE;
Willy Tarreau76bd97f2015-03-10 17:16:10 +01006096 if ((analyzer & (AN_REQ_INSPECT_FE|AN_REQ_HTTP_PROCESS_FE)))
Willy Tarreau22ec1ea2014-11-27 20:45:39 +01006097 s->res.analysers |= analyzer;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006098 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006099 if (HLUA_IS_WAKEREQWR(s->hlua))
Willy Tarreau22ec1ea2014-11-27 20:45:39 +01006100 s->req.flags |= CF_WAKE_WRITE;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01006101 /* We can quit the fcuntion without consistency check
6102 * because HAProxy is not able to manipulate data, it
6103 * is only allowed to call me again. */
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02006104 return ACT_RET_YIELD;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006105
6106 /* finished with error. */
6107 case HLUA_E_ERRMSG:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006108 if (!consistency_check(s, dir, &s->hlua->cons)) {
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01006109 stream_int_retnclose(&s->si[0], &msg);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02006110 return ACT_RET_ERR;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01006111 }
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006112 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02006113 SEND_ERR(px, "Lua function '%s': %s.\n",
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006114 rule->arg.hlua_rule->fcn.name, lua_tostring(s->hlua->T, -1));
6115 lua_pop(s->hlua->T, 1);
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02006116 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006117
6118 case HLUA_E_ERR:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006119 if (!consistency_check(s, dir, &s->hlua->cons)) {
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01006120 stream_int_retnclose(&s->si[0], &msg);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02006121 return ACT_RET_ERR;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01006122 }
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006123 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02006124 SEND_ERR(px, "Lua function '%s' return an unknown error.\n",
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006125 rule->arg.hlua_rule->fcn.name);
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006126
6127 default:
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02006128 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006129 }
6130}
6131
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006132struct task *hlua_applet_wakeup(struct task *t)
6133{
6134 struct appctx *ctx = t->context;
6135 struct stream_interface *si = ctx->owner;
6136
6137 /* If the applet is wake up without any expected work, the sheduler
6138 * remove it from the run queue. This flag indicate that the applet
6139 * is waiting for write. If the buffer is full, the main processing
6140 * will send some data and after call the applet, otherwise it call
6141 * the applet ASAP.
6142 */
6143 si_applet_cant_put(si);
6144 appctx_wakeup(ctx);
Willy Tarreaud9587412017-08-23 16:07:33 +02006145 t->expire = TICK_ETERNITY;
Willy Tarreaud1aa41f2017-07-21 16:41:56 +02006146 return t;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006147}
6148
6149static int hlua_applet_tcp_init(struct appctx *ctx, struct proxy *px, struct stream *strm)
6150{
6151 struct stream_interface *si = ctx->owner;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006152 struct hlua *hlua;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006153 struct task *task;
6154 char **arg;
Thierry Fournierfd107a22016-02-19 19:57:23 +01006155 const char *error;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006156
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006157 hlua = pool_alloc2(pool2_hlua);
6158 if (!hlua) {
6159 SEND_ERR(px, "Lua applet tcp '%s': out of memory.\n",
6160 ctx->rule->arg.hlua_rule->fcn.name);
6161 return 0;
6162 }
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006163 HLUA_INIT(hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006164 ctx->ctx.hlua_apptcp.hlua = hlua;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006165 ctx->ctx.hlua_apptcp.flags = 0;
6166
6167 /* Create task used by signal to wakeup applets. */
Willy Tarreau5f4a47b2017-10-31 15:59:32 +01006168 task = task_new(tid_bit);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006169 if (!task) {
6170 SEND_ERR(px, "Lua applet tcp '%s': out of memory.\n",
6171 ctx->rule->arg.hlua_rule->fcn.name);
6172 return 0;
6173 }
6174 task->nice = 0;
6175 task->context = ctx;
6176 task->process = hlua_applet_wakeup;
6177 ctx->ctx.hlua_apptcp.task = task;
6178
6179 /* In the execution wrappers linked with a stream, the
6180 * Lua context can be not initialized. This behavior
6181 * permits to save performances because a systematic
6182 * Lua initialization cause 5% performances loss.
6183 */
6184 if (!hlua_ctx_init(hlua, task)) {
6185 SEND_ERR(px, "Lua applet tcp '%s': can't initialize Lua context.\n",
6186 ctx->rule->arg.hlua_rule->fcn.name);
6187 return 0;
6188 }
6189
6190 /* Set timeout according with the applet configuration. */
Thierry FOURNIER10770fa2015-09-29 01:59:42 +02006191 hlua->max_time = ctx->applet->timeout;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006192
6193 /* The following Lua calls can fail. */
6194 if (!SET_SAFE_LJMP(hlua->T)) {
Thierry Fournierfd107a22016-02-19 19:57:23 +01006195 if (lua_type(hlua->T, -1) == LUA_TSTRING)
6196 error = lua_tostring(hlua->T, -1);
6197 else
6198 error = "critical error";
6199 SEND_ERR(px, "Lua applet tcp '%s': %s.\n",
6200 ctx->rule->arg.hlua_rule->fcn.name, error);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006201 RESET_SAFE_LJMP(hlua->T);
6202 return 0;
6203 }
6204
6205 /* Check stack available size. */
6206 if (!lua_checkstack(hlua->T, 1)) {
6207 SEND_ERR(px, "Lua applet tcp '%s': full stack.\n",
6208 ctx->rule->arg.hlua_rule->fcn.name);
6209 RESET_SAFE_LJMP(hlua->T);
6210 return 0;
6211 }
6212
6213 /* Restore the function in the stack. */
6214 lua_rawgeti(hlua->T, LUA_REGISTRYINDEX, ctx->rule->arg.hlua_rule->fcn.function_ref);
6215
6216 /* Create and and push object stream in the stack. */
6217 if (!hlua_applet_tcp_new(hlua->T, ctx)) {
6218 SEND_ERR(px, "Lua applet tcp '%s': full stack.\n",
6219 ctx->rule->arg.hlua_rule->fcn.name);
6220 RESET_SAFE_LJMP(hlua->T);
6221 return 0;
6222 }
6223 hlua->nargs = 1;
6224
6225 /* push keywords in the stack. */
6226 for (arg = ctx->rule->arg.hlua_rule->args; arg && *arg; arg++) {
6227 if (!lua_checkstack(hlua->T, 1)) {
6228 SEND_ERR(px, "Lua applet tcp '%s': full stack.\n",
6229 ctx->rule->arg.hlua_rule->fcn.name);
6230 RESET_SAFE_LJMP(hlua->T);
6231 return 0;
6232 }
6233 lua_pushstring(hlua->T, *arg);
6234 hlua->nargs++;
6235 }
6236
6237 RESET_SAFE_LJMP(hlua->T);
6238
6239 /* Wakeup the applet ASAP. */
6240 si_applet_cant_get(si);
6241 si_applet_cant_put(si);
6242
6243 return 1;
6244}
6245
6246static void hlua_applet_tcp_fct(struct appctx *ctx)
6247{
6248 struct stream_interface *si = ctx->owner;
6249 struct stream *strm = si_strm(si);
6250 struct channel *res = si_ic(si);
6251 struct act_rule *rule = ctx->rule;
6252 struct proxy *px = strm->be;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006253 struct hlua *hlua = ctx->ctx.hlua_apptcp.hlua;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006254
6255 /* The applet execution is already done. */
6256 if (ctx->ctx.hlua_apptcp.flags & APPLET_DONE)
6257 return;
6258
6259 /* If the stream is disconnect or closed, ldo nothing. */
6260 if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO))
6261 return;
6262
6263 /* Execute the function. */
6264 switch (hlua_ctx_resume(hlua, 1)) {
6265 /* finished. */
6266 case HLUA_E_OK:
6267 ctx->ctx.hlua_apptcp.flags |= APPLET_DONE;
6268
6269 /* log time */
6270 strm->logs.tv_request = now;
6271
6272 /* eat the whole request */
Willy Tarreau06d80a92017-10-19 14:32:15 +02006273 co_skip(si_oc(si), si_ob(si)->o);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006274 res->flags |= CF_READ_NULL;
6275 si_shutr(si);
6276 return;
6277
6278 /* yield. */
6279 case HLUA_E_AGAIN:
Thierry Fournier0164f202016-02-20 17:47:43 +01006280 if (hlua->wake_time != TICK_ETERNITY)
6281 task_schedule(ctx->ctx.hlua_apptcp.task, hlua->wake_time);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006282 return;
6283
6284 /* finished with error. */
6285 case HLUA_E_ERRMSG:
6286 /* Display log. */
6287 SEND_ERR(px, "Lua applet tcp '%s': %s.\n",
6288 rule->arg.hlua_rule->fcn.name, lua_tostring(hlua->T, -1));
6289 lua_pop(hlua->T, 1);
6290 goto error;
6291
6292 case HLUA_E_ERR:
6293 /* Display log. */
6294 SEND_ERR(px, "Lua applet tcp '%s' return an unknown error.\n",
6295 rule->arg.hlua_rule->fcn.name);
6296 goto error;
6297
6298 default:
6299 goto error;
6300 }
6301
6302error:
6303
6304 /* For all other cases, just close the stream. */
6305 si_shutw(si);
6306 si_shutr(si);
6307 ctx->ctx.hlua_apptcp.flags |= APPLET_DONE;
6308}
6309
6310static void hlua_applet_tcp_release(struct appctx *ctx)
6311{
Willy Tarreaubd7fc952017-07-24 17:35:27 +02006312 task_delete(ctx->ctx.hlua_apptcp.task);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006313 task_free(ctx->ctx.hlua_apptcp.task);
6314 ctx->ctx.hlua_apptcp.task = NULL;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006315 hlua_ctx_destroy(ctx->ctx.hlua_apptcp.hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006316 ctx->ctx.hlua_apptcp.hlua = NULL;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006317}
6318
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006319/* The function returns 1 if the initialisation is complete, 0 if
6320 * an errors occurs and -1 if more data are required for initializing
6321 * the applet.
6322 */
6323static int hlua_applet_http_init(struct appctx *ctx, struct proxy *px, struct stream *strm)
6324{
6325 struct stream_interface *si = ctx->owner;
6326 struct channel *req = si_oc(si);
6327 struct http_msg *msg;
6328 struct http_txn *txn;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006329 struct hlua *hlua;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006330 char **arg;
6331 struct hdr_ctx hdr;
6332 struct task *task;
6333 struct sample smp; /* just used for a valid call to smp_prefetch_http. */
Thierry Fournierfd107a22016-02-19 19:57:23 +01006334 const char *error;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006335
6336 /* Wait for a full HTTP request. */
6337 if (!smp_prefetch_http(px, strm, 0, NULL, &smp, 0)) {
6338 if (smp.flags & SMP_F_MAY_CHANGE)
6339 return -1;
6340 return 0;
6341 }
6342 txn = strm->txn;
6343 msg = &txn->req;
6344
Willy Tarreau0078bfc2015-10-07 20:20:28 +02006345 /* We want two things in HTTP mode :
6346 * - enforce server-close mode if we were in keep-alive, so that the
6347 * applet is released after each response ;
6348 * - enable request body transfer to the applet in order to resync
6349 * with the response body.
6350 */
6351 if ((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL)
6352 txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | TX_CON_WANT_SCL;
Willy Tarreau0078bfc2015-10-07 20:20:28 +02006353
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006354 hlua = pool_alloc2(pool2_hlua);
6355 if (!hlua) {
6356 SEND_ERR(px, "Lua applet http '%s': out of memory.\n",
6357 ctx->rule->arg.hlua_rule->fcn.name);
6358 return 0;
6359 }
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006360 HLUA_INIT(hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006361 ctx->ctx.hlua_apphttp.hlua = hlua;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006362 ctx->ctx.hlua_apphttp.left_bytes = -1;
6363 ctx->ctx.hlua_apphttp.flags = 0;
6364
Thierry FOURNIERd93ea2b2015-12-20 19:14:52 +01006365 if (txn->req.flags & HTTP_MSGF_VER_11)
6366 ctx->ctx.hlua_apphttp.flags |= APPLET_HTTP11;
6367
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006368 /* Create task used by signal to wakeup applets. */
Willy Tarreau5f4a47b2017-10-31 15:59:32 +01006369 task = task_new(tid_bit);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006370 if (!task) {
6371 SEND_ERR(px, "Lua applet http '%s': out of memory.\n",
6372 ctx->rule->arg.hlua_rule->fcn.name);
6373 return 0;
6374 }
6375 task->nice = 0;
6376 task->context = ctx;
6377 task->process = hlua_applet_wakeup;
6378 ctx->ctx.hlua_apphttp.task = task;
6379
6380 /* In the execution wrappers linked with a stream, the
6381 * Lua context can be not initialized. This behavior
6382 * permits to save performances because a systematic
6383 * Lua initialization cause 5% performances loss.
6384 */
6385 if (!hlua_ctx_init(hlua, task)) {
6386 SEND_ERR(px, "Lua applet http '%s': can't initialize Lua context.\n",
6387 ctx->rule->arg.hlua_rule->fcn.name);
6388 return 0;
6389 }
6390
6391 /* Set timeout according with the applet configuration. */
Thierry FOURNIER10770fa2015-09-29 01:59:42 +02006392 hlua->max_time = ctx->applet->timeout;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006393
6394 /* The following Lua calls can fail. */
6395 if (!SET_SAFE_LJMP(hlua->T)) {
Thierry Fournierfd107a22016-02-19 19:57:23 +01006396 if (lua_type(hlua->T, -1) == LUA_TSTRING)
6397 error = lua_tostring(hlua->T, -1);
6398 else
6399 error = "critical error";
6400 SEND_ERR(px, "Lua applet http '%s': %s.\n",
6401 ctx->rule->arg.hlua_rule->fcn.name, error);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006402 return 0;
6403 }
6404
6405 /* Check stack available size. */
6406 if (!lua_checkstack(hlua->T, 1)) {
6407 SEND_ERR(px, "Lua applet http '%s': full stack.\n",
6408 ctx->rule->arg.hlua_rule->fcn.name);
6409 RESET_SAFE_LJMP(hlua->T);
6410 return 0;
6411 }
6412
6413 /* Restore the function in the stack. */
6414 lua_rawgeti(hlua->T, LUA_REGISTRYINDEX, ctx->rule->arg.hlua_rule->fcn.function_ref);
6415
6416 /* Create and and push object stream in the stack. */
6417 if (!hlua_applet_http_new(hlua->T, ctx)) {
6418 SEND_ERR(px, "Lua applet http '%s': full stack.\n",
6419 ctx->rule->arg.hlua_rule->fcn.name);
6420 RESET_SAFE_LJMP(hlua->T);
6421 return 0;
6422 }
6423 hlua->nargs = 1;
6424
6425 /* Look for a 100-continue expected. */
6426 if (msg->flags & HTTP_MSGF_VER_11) {
6427 hdr.idx = 0;
6428 if (http_find_header2("Expect", 6, req->buf->p, &txn->hdr_idx, &hdr) &&
6429 unlikely(hdr.vlen == 12 && strncasecmp(hdr.line+hdr.val, "100-continue", 12) == 0))
6430 ctx->ctx.hlua_apphttp.flags |= APPLET_100C;
6431 }
6432
6433 /* push keywords in the stack. */
6434 for (arg = ctx->rule->arg.hlua_rule->args; arg && *arg; arg++) {
6435 if (!lua_checkstack(hlua->T, 1)) {
6436 SEND_ERR(px, "Lua applet http '%s': full stack.\n",
6437 ctx->rule->arg.hlua_rule->fcn.name);
6438 RESET_SAFE_LJMP(hlua->T);
6439 return 0;
6440 }
6441 lua_pushstring(hlua->T, *arg);
6442 hlua->nargs++;
6443 }
6444
6445 RESET_SAFE_LJMP(hlua->T);
6446
6447 /* Wakeup the applet when data is ready for read. */
6448 si_applet_cant_get(si);
6449
6450 return 1;
6451}
6452
6453static void hlua_applet_http_fct(struct appctx *ctx)
6454{
6455 struct stream_interface *si = ctx->owner;
6456 struct stream *strm = si_strm(si);
6457 struct channel *res = si_ic(si);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006458 struct act_rule *rule = ctx->rule;
6459 struct proxy *px = strm->be;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006460 struct hlua *hlua = ctx->ctx.hlua_apphttp.hlua;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006461 char *blk1;
6462 int len1;
6463 char *blk2;
6464 int len2;
6465 int ret;
6466
6467 /* If the stream is disconnect or closed, ldo nothing. */
6468 if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO))
6469 return;
6470
6471 /* Set the currently running flag. */
6472 if (!HLUA_IS_RUNNING(hlua) &&
6473 !(ctx->ctx.hlua_apphttp.flags & APPLET_DONE)) {
6474
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006475 /* Wait for full HTTP analysys. */
6476 if (unlikely(strm->txn->req.msg_state < HTTP_MSG_BODY)) {
6477 si_applet_cant_get(si);
6478 return;
6479 }
6480
6481 /* Store the max amount of bytes that we can read. */
6482 ctx->ctx.hlua_apphttp.left_bytes = strm->txn->req.body_len;
6483
6484 /* We need to flush the request header. This left the body
6485 * for the Lua.
6486 */
6487
6488 /* Read the maximum amount of data avalaible. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02006489 ret = co_getblk_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006490 if (ret == -1)
6491 return;
6492
6493 /* No data available, ask for more data. */
6494 if (ret == 1)
6495 len2 = 0;
6496 if (ret == 0)
6497 len1 = 0;
6498 if (len1 + len2 < strm->txn->req.eoh + 2) {
6499 si_applet_cant_get(si);
6500 return;
6501 }
6502
6503 /* skip the requests bytes. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02006504 co_skip(si_oc(si), strm->txn->req.eoh + 2);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006505 }
6506
6507 /* Executes The applet if it is not done. */
6508 if (!(ctx->ctx.hlua_apphttp.flags & APPLET_DONE)) {
6509
6510 /* Execute the function. */
6511 switch (hlua_ctx_resume(hlua, 1)) {
6512 /* finished. */
6513 case HLUA_E_OK:
6514 ctx->ctx.hlua_apphttp.flags |= APPLET_DONE;
6515 break;
6516
6517 /* yield. */
6518 case HLUA_E_AGAIN:
Thierry Fournier0164f202016-02-20 17:47:43 +01006519 if (hlua->wake_time != TICK_ETERNITY)
6520 task_schedule(ctx->ctx.hlua_apphttp.task, hlua->wake_time);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006521 return;
6522
6523 /* finished with error. */
6524 case HLUA_E_ERRMSG:
6525 /* Display log. */
6526 SEND_ERR(px, "Lua applet http '%s': %s.\n",
6527 rule->arg.hlua_rule->fcn.name, lua_tostring(hlua->T, -1));
6528 lua_pop(hlua->T, 1);
6529 goto error;
6530
6531 case HLUA_E_ERR:
6532 /* Display log. */
6533 SEND_ERR(px, "Lua applet http '%s' return an unknown error.\n",
6534 rule->arg.hlua_rule->fcn.name);
6535 goto error;
6536
6537 default:
6538 goto error;
6539 }
6540 }
6541
6542 if (ctx->ctx.hlua_apphttp.flags & APPLET_DONE) {
6543
6544 /* We must send the final chunk. */
6545 if (ctx->ctx.hlua_apphttp.flags & APPLET_CHUNKED &&
6546 !(ctx->ctx.hlua_apphttp.flags & APPLET_LAST_CHK)) {
6547
6548 /* sent last chunk at once. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02006549 ret = ci_putblk(res, "0\r\n\r\n", 5);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006550
6551 /* critical error. */
6552 if (ret == -2 || ret == -3) {
6553 SEND_ERR(px, "Lua applet http '%s'cannont send last chunk.\n",
6554 rule->arg.hlua_rule->fcn.name);
6555 goto error;
6556 }
6557
6558 /* no enough space error. */
6559 if (ret == -1) {
6560 si_applet_cant_put(si);
6561 return;
6562 }
6563
6564 /* set the last chunk sent. */
6565 ctx->ctx.hlua_apphttp.flags |= APPLET_LAST_CHK;
6566 }
6567
6568 /* close the connection. */
6569
6570 /* status / log */
6571 strm->txn->status = ctx->ctx.hlua_apphttp.status;
6572 strm->logs.tv_request = now;
6573
6574 /* eat the whole request */
Willy Tarreau06d80a92017-10-19 14:32:15 +02006575 co_skip(si_oc(si), si_ob(si)->o);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006576 res->flags |= CF_READ_NULL;
6577 si_shutr(si);
6578
6579 return;
6580 }
6581
6582error:
6583
6584 /* If we are in HTTP mode, and we are not send any
6585 * data, return a 500 server error in best effort:
6586 * if there are no room avalaible in the buffer,
6587 * just close the connection.
6588 */
Willy Tarreau06d80a92017-10-19 14:32:15 +02006589 ci_putblk(res, error_500, strlen(error_500));
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006590 if (!(strm->flags & SF_ERR_MASK))
6591 strm->flags |= SF_ERR_RESOURCE;
6592 si_shutw(si);
6593 si_shutr(si);
6594 ctx->ctx.hlua_apphttp.flags |= APPLET_DONE;
6595}
6596
6597static void hlua_applet_http_release(struct appctx *ctx)
6598{
Willy Tarreaubd7fc952017-07-24 17:35:27 +02006599 task_delete(ctx->ctx.hlua_apphttp.task);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006600 task_free(ctx->ctx.hlua_apphttp.task);
6601 ctx->ctx.hlua_apphttp.task = NULL;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006602 hlua_ctx_destroy(ctx->ctx.hlua_apphttp.hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006603 ctx->ctx.hlua_apphttp.hlua = NULL;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006604}
6605
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006606/* global {tcp|http}-request parser. Return ACT_RET_PRS_OK in
6607 * succes case, else return ACT_RET_PRS_ERR.
Thierry FOURNIERbabae282015-09-17 11:36:37 +02006608 *
6609 * This function can fail with an abort() due to an Lua critical error.
6610 * We are in the configuration parsing process of HAProxy, this abort() is
6611 * tolerated.
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006612 */
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006613static enum act_parse_ret action_register_lua(const char **args, int *cur_arg, struct proxy *px,
6614 struct act_rule *rule, char **err)
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006615{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02006616 struct hlua_function *fcn = rule->kw->private;
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006617 int i;
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006618
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006619 /* Memory for the rule. */
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02006620 rule->arg.hlua_rule = calloc(1, sizeof(*rule->arg.hlua_rule));
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006621 if (!rule->arg.hlua_rule) {
6622 memprintf(err, "out of memory error");
Thierry FOURNIERafa80492015-08-19 09:04:15 +02006623 return ACT_RET_PRS_ERR;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006624 }
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006625
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006626 /* Memory for arguments. */
6627 rule->arg.hlua_rule->args = calloc(fcn->nargs + 1, sizeof(char *));
6628 if (!rule->arg.hlua_rule->args) {
6629 memprintf(err, "out of memory error");
6630 return ACT_RET_PRS_ERR;
6631 }
6632
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006633 /* Reference the Lua function and store the reference. */
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006634 rule->arg.hlua_rule->fcn = *fcn;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006635
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006636 /* Expect some arguments */
6637 for (i = 0; i < fcn->nargs; i++) {
6638 if (*args[i+1] == '\0') {
6639 memprintf(err, "expect %d arguments", fcn->nargs);
6640 return ACT_RET_PRS_ERR;
6641 }
6642 rule->arg.hlua_rule->args[i] = strdup(args[i + 1]);
6643 if (!rule->arg.hlua_rule->args[i]) {
6644 memprintf(err, "out of memory error");
6645 return ACT_RET_PRS_ERR;
6646 }
6647 (*cur_arg)++;
6648 }
6649 rule->arg.hlua_rule->args[i] = NULL;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006650
Thierry FOURNIER42148732015-09-02 17:17:33 +02006651 rule->action = ACT_CUSTOM;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006652 rule->action_ptr = hlua_action;
Thierry FOURNIERafa80492015-08-19 09:04:15 +02006653 return ACT_RET_PRS_OK;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006654}
6655
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006656static enum act_parse_ret action_register_service_http(const char **args, int *cur_arg, struct proxy *px,
6657 struct act_rule *rule, char **err)
6658{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02006659 struct hlua_function *fcn = rule->kw->private;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006660
Thierry FOURNIER718e2a72015-12-20 20:13:14 +01006661 /* HTTP applets are forbidden in tcp-request rules.
6662 * HTTP applet request requires everything initilized by
6663 * "http_process_request" (analyzer flag AN_REQ_HTTP_INNER).
6664 * The applet will be immediately initilized, but its before
6665 * the call of this analyzer.
6666 */
6667 if (rule->from != ACT_F_HTTP_REQ) {
6668 memprintf(err, "HTTP applets are forbidden from 'tcp-request' rulesets");
6669 return ACT_RET_PRS_ERR;
6670 }
6671
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006672 /* Memory for the rule. */
6673 rule->arg.hlua_rule = calloc(1, sizeof(*rule->arg.hlua_rule));
6674 if (!rule->arg.hlua_rule) {
6675 memprintf(err, "out of memory error");
6676 return ACT_RET_PRS_ERR;
6677 }
6678
6679 /* Reference the Lua function and store the reference. */
6680 rule->arg.hlua_rule->fcn = *fcn;
6681
6682 /* TODO: later accept arguments. */
6683 rule->arg.hlua_rule->args = NULL;
6684
6685 /* Add applet pointer in the rule. */
6686 rule->applet.obj_type = OBJ_TYPE_APPLET;
6687 rule->applet.name = fcn->name;
6688 rule->applet.init = hlua_applet_http_init;
6689 rule->applet.fct = hlua_applet_http_fct;
6690 rule->applet.release = hlua_applet_http_release;
6691 rule->applet.timeout = hlua_timeout_applet;
6692
6693 return ACT_RET_PRS_OK;
6694}
6695
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006696/* This function is an LUA binding used for registering
6697 * "sample-conv" functions. It expects a converter name used
6698 * in the haproxy configuration file, and an LUA function.
6699 */
6700__LJMP static int hlua_register_action(lua_State *L)
6701{
6702 struct action_kw_list *akl;
6703 const char *name;
6704 int ref;
6705 int len;
6706 struct hlua_function *fcn;
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006707 int nargs;
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006708
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006709 /* Initialise the number of expected arguments at 0. */
6710 nargs = 0;
6711
6712 if (lua_gettop(L) < 3 || lua_gettop(L) > 4)
6713 WILL_LJMP(luaL_error(L, "'register_action' needs between 3 and 4 arguments"));
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006714
6715 /* First argument : converter name. */
6716 name = MAY_LJMP(luaL_checkstring(L, 1));
6717
6718 /* Second argument : environment. */
6719 if (lua_type(L, 2) != LUA_TTABLE)
6720 WILL_LJMP(luaL_error(L, "register_action: second argument must be a table of strings"));
6721
6722 /* Third argument : lua function. */
6723 ref = MAY_LJMP(hlua_checkfunction(L, 3));
6724
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006725 /* Fouth argument : number of mandatories arguments expected on the configuration line. */
6726 if (lua_gettop(L) >= 4)
6727 nargs = MAY_LJMP(luaL_checkinteger(L, 4));
6728
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006729 /* browse the second argulent as an array. */
6730 lua_pushnil(L);
6731 while (lua_next(L, 2) != 0) {
6732 if (lua_type(L, -1) != LUA_TSTRING)
6733 WILL_LJMP(luaL_error(L, "register_action: second argument must be a table of strings"));
6734
6735 /* Check required environment. Only accepted "http" or "tcp". */
6736 /* Allocate and fill the sample fetch keyword struct. */
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02006737 akl = calloc(1, sizeof(*akl) + sizeof(struct action_kw) * 2);
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006738 if (!akl)
6739 WILL_LJMP(luaL_error(L, "lua out of memory error."));
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02006740 fcn = calloc(1, sizeof(*fcn));
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006741 if (!fcn)
6742 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6743
6744 /* Fill fcn. */
6745 fcn->name = strdup(name);
6746 if (!fcn->name)
6747 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6748 fcn->function_ref = ref;
6749
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006750 /* Set the expected number od arguments. */
6751 fcn->nargs = nargs;
6752
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006753 /* List head */
6754 akl->list.n = akl->list.p = NULL;
6755
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006756 /* action keyword. */
6757 len = strlen("lua.") + strlen(name) + 1;
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02006758 akl->kw[0].kw = calloc(1, len);
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006759 if (!akl->kw[0].kw)
6760 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6761
6762 snprintf((char *)akl->kw[0].kw, len, "lua.%s", name);
6763
6764 akl->kw[0].match_pfx = 0;
6765 akl->kw[0].private = fcn;
6766 akl->kw[0].parse = action_register_lua;
6767
6768 /* select the action registering point. */
6769 if (strcmp(lua_tostring(L, -1), "tcp-req") == 0)
6770 tcp_req_cont_keywords_register(akl);
6771 else if (strcmp(lua_tostring(L, -1), "tcp-res") == 0)
6772 tcp_res_cont_keywords_register(akl);
6773 else if (strcmp(lua_tostring(L, -1), "http-req") == 0)
6774 http_req_keywords_register(akl);
6775 else if (strcmp(lua_tostring(L, -1), "http-res") == 0)
6776 http_res_keywords_register(akl);
6777 else
6778 WILL_LJMP(luaL_error(L, "lua action environment '%s' is unknown. "
6779 "'tcp-req', 'tcp-res', 'http-req' or 'http-res' "
6780 "are expected.", lua_tostring(L, -1)));
6781
6782 /* pop the environment string. */
6783 lua_pop(L, 1);
6784 }
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006785 return ACT_RET_PRS_OK;
6786}
6787
6788static enum act_parse_ret action_register_service_tcp(const char **args, int *cur_arg, struct proxy *px,
6789 struct act_rule *rule, char **err)
6790{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02006791 struct hlua_function *fcn = rule->kw->private;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006792
6793 /* Memory for the rule. */
6794 rule->arg.hlua_rule = calloc(1, sizeof(*rule->arg.hlua_rule));
6795 if (!rule->arg.hlua_rule) {
6796 memprintf(err, "out of memory error");
6797 return ACT_RET_PRS_ERR;
6798 }
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006799
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006800 /* Reference the Lua function and store the reference. */
6801 rule->arg.hlua_rule->fcn = *fcn;
6802
6803 /* TODO: later accept arguments. */
6804 rule->arg.hlua_rule->args = NULL;
6805
6806 /* Add applet pointer in the rule. */
6807 rule->applet.obj_type = OBJ_TYPE_APPLET;
6808 rule->applet.name = fcn->name;
6809 rule->applet.init = hlua_applet_tcp_init;
6810 rule->applet.fct = hlua_applet_tcp_fct;
6811 rule->applet.release = hlua_applet_tcp_release;
6812 rule->applet.timeout = hlua_timeout_applet;
6813
6814 return 0;
6815}
6816
6817/* This function is an LUA binding used for registering
6818 * "sample-conv" functions. It expects a converter name used
6819 * in the haproxy configuration file, and an LUA function.
6820 */
6821__LJMP static int hlua_register_service(lua_State *L)
6822{
6823 struct action_kw_list *akl;
6824 const char *name;
6825 const char *env;
6826 int ref;
6827 int len;
6828 struct hlua_function *fcn;
6829
6830 MAY_LJMP(check_args(L, 3, "register_service"));
6831
6832 /* First argument : converter name. */
6833 name = MAY_LJMP(luaL_checkstring(L, 1));
6834
6835 /* Second argument : environment. */
6836 env = MAY_LJMP(luaL_checkstring(L, 2));
6837
6838 /* Third argument : lua function. */
6839 ref = MAY_LJMP(hlua_checkfunction(L, 3));
6840
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006841 /* Allocate and fill the sample fetch keyword struct. */
6842 akl = calloc(1, sizeof(*akl) + sizeof(struct action_kw) * 2);
6843 if (!akl)
6844 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6845 fcn = calloc(1, sizeof(*fcn));
6846 if (!fcn)
6847 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6848
6849 /* Fill fcn. */
6850 len = strlen("<lua.>") + strlen(name) + 1;
6851 fcn->name = calloc(1, len);
6852 if (!fcn->name)
6853 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6854 snprintf((char *)fcn->name, len, "<lua.%s>", name);
6855 fcn->function_ref = ref;
6856
6857 /* List head */
6858 akl->list.n = akl->list.p = NULL;
6859
6860 /* converter keyword. */
6861 len = strlen("lua.") + strlen(name) + 1;
6862 akl->kw[0].kw = calloc(1, len);
6863 if (!akl->kw[0].kw)
6864 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6865
6866 snprintf((char *)akl->kw[0].kw, len, "lua.%s", name);
6867
Thierry FOURNIER / OZON.IO02564fd2016-11-12 11:07:05 +01006868 /* Check required environment. Only accepted "http" or "tcp". */
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006869 if (strcmp(env, "tcp") == 0)
6870 akl->kw[0].parse = action_register_service_tcp;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006871 else if (strcmp(env, "http") == 0)
6872 akl->kw[0].parse = action_register_service_http;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006873 else
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006874 WILL_LJMP(luaL_error(L, "lua service environment '%s' is unknown. "
6875 "'tcp' or 'http' are expected."));
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006876
6877 akl->kw[0].match_pfx = 0;
6878 akl->kw[0].private = fcn;
6879
6880 /* End of array. */
6881 memset(&akl->kw[1], 0, sizeof(*akl->kw));
6882
6883 /* Register this new converter */
6884 service_keywords_register(akl);
6885
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006886 return 0;
6887}
6888
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006889/* This function initialises Lua cli handler. It copies the
6890 * arguments in the Lua stack and create channel IO objects.
6891 */
6892static int hlua_cli_parse_fct(char **args, struct appctx *appctx, void *private)
6893{
6894 struct hlua *hlua;
6895 struct hlua_function *fcn;
6896 int i;
6897 const char *error;
6898
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006899 fcn = private;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006900 appctx->ctx.hlua_cli.fcn = private;
6901
6902 hlua = pool_alloc2(pool2_hlua);
6903 if (!hlua) {
6904 SEND_ERR(NULL, "Lua cli '%s': out of memory.\n", fcn->name);
Thierry FOURNIER1be34152016-12-17 12:09:51 +01006905 return 1;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006906 }
6907 HLUA_INIT(hlua);
6908 appctx->ctx.hlua_cli.hlua = hlua;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006909
6910 /* Create task used by signal to wakeup applets.
6911 * We use the same wakeup fonction than the Lua applet_tcp and
6912 * applet_http. It is absolutely compatible.
6913 */
Willy Tarreau5f4a47b2017-10-31 15:59:32 +01006914 appctx->ctx.hlua_cli.task = task_new(tid_bit);
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006915 if (!appctx->ctx.hlua_cli.task) {
Thierry FOURNIERffbf5692016-12-16 11:14:06 +01006916 SEND_ERR(NULL, "Lua cli '%s': out of memory.\n", fcn->name);
Thierry FOURNIER1be34152016-12-17 12:09:51 +01006917 goto error;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006918 }
6919 appctx->ctx.hlua_cli.task->nice = 0;
6920 appctx->ctx.hlua_cli.task->context = appctx;
6921 appctx->ctx.hlua_cli.task->process = hlua_applet_wakeup;
6922
6923 /* Initialises the Lua context */
6924 if (!hlua_ctx_init(hlua, appctx->ctx.hlua_cli.task)) {
6925 SEND_ERR(NULL, "Lua cli '%s': can't initialize Lua context.\n", fcn->name);
Thierry FOURNIER1be34152016-12-17 12:09:51 +01006926 goto error;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006927 }
6928
6929 /* The following Lua calls can fail. */
6930 if (!SET_SAFE_LJMP(hlua->T)) {
6931 if (lua_type(hlua->T, -1) == LUA_TSTRING)
6932 error = lua_tostring(hlua->T, -1);
6933 else
6934 error = "critical error";
6935 SEND_ERR(NULL, "Lua cli '%s': %s.\n", fcn->name, error);
6936 goto error;
6937 }
6938
6939 /* Check stack available size. */
6940 if (!lua_checkstack(hlua->T, 2)) {
6941 SEND_ERR(NULL, "Lua cli '%s': full stack.\n", fcn->name);
6942 goto error;
6943 }
6944
6945 /* Restore the function in the stack. */
6946 lua_rawgeti(hlua->T, LUA_REGISTRYINDEX, fcn->function_ref);
6947
6948 /* Once the arguments parsed, the CLI is like an AppletTCP,
6949 * so push AppletTCP in the stack.
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006950 */
6951 if (!hlua_applet_tcp_new(hlua->T, appctx)) {
6952 SEND_ERR(NULL, "Lua cli '%s': full stack.\n", fcn->name);
6953 goto error;
6954 }
6955 hlua->nargs = 1;
6956
6957 /* push keywords in the stack. */
6958 for (i = 0; *args[i]; i++) {
6959 /* Check stack available size. */
6960 if (!lua_checkstack(hlua->T, 1)) {
6961 SEND_ERR(NULL, "Lua cli '%s': full stack.\n", fcn->name);
6962 goto error;
6963 }
6964 lua_pushstring(hlua->T, args[i]);
6965 hlua->nargs++;
6966 }
6967
6968 /* We must initialize the execution timeouts. */
6969 hlua->max_time = hlua_timeout_session;
6970
6971 /* At this point the execution is safe. */
6972 RESET_SAFE_LJMP(hlua->T);
6973
6974 /* It's ok */
6975 return 0;
6976
6977 /* It's not ok. */
6978error:
6979 RESET_SAFE_LJMP(hlua->T);
6980 hlua_ctx_destroy(hlua);
Thierry FOURNIER1be34152016-12-17 12:09:51 +01006981 appctx->ctx.hlua_cli.hlua = NULL;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006982 return 1;
6983}
6984
6985static int hlua_cli_io_handler_fct(struct appctx *appctx)
6986{
6987 struct hlua *hlua;
6988 struct stream_interface *si;
6989 struct hlua_function *fcn;
6990
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006991 hlua = appctx->ctx.hlua_cli.hlua;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006992 si = appctx->owner;
Willy Tarreau8ae4f752016-12-14 15:41:45 +01006993 fcn = appctx->ctx.hlua_cli.fcn;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006994
6995 /* If the stream is disconnect or closed, ldo nothing. */
6996 if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO))
6997 return 1;
6998
6999 /* Execute the function. */
7000 switch (hlua_ctx_resume(hlua, 1)) {
7001
7002 /* finished. */
7003 case HLUA_E_OK:
7004 return 1;
7005
7006 /* yield. */
7007 case HLUA_E_AGAIN:
7008 /* We want write. */
7009 if (HLUA_IS_WAKERESWR(hlua))
7010 si_applet_cant_put(si);
7011 /* Set the timeout. */
7012 if (hlua->wake_time != TICK_ETERNITY)
7013 task_schedule(hlua->task, hlua->wake_time);
7014 return 0;
7015
7016 /* finished with error. */
7017 case HLUA_E_ERRMSG:
7018 /* Display log. */
7019 SEND_ERR(NULL, "Lua cli '%s': %s.\n",
7020 fcn->name, lua_tostring(hlua->T, -1));
7021 lua_pop(hlua->T, 1);
7022 return 1;
7023
7024 case HLUA_E_ERR:
7025 /* Display log. */
7026 SEND_ERR(NULL, "Lua cli '%s' return an unknown error.\n",
7027 fcn->name);
7028 return 1;
7029
7030 default:
7031 return 1;
7032 }
7033
7034 return 1;
7035}
7036
7037static void hlua_cli_io_release_fct(struct appctx *appctx)
7038{
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01007039 hlua_ctx_destroy(appctx->ctx.hlua_cli.hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01007040 appctx->ctx.hlua_cli.hlua = NULL;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007041}
7042
7043/* This function is an LUA binding used for registering
7044 * new keywords in the cli. It expects a list of keywords
7045 * which are the "path". It is limited to 5 keywords. A
7046 * description of the command, a function to be executed
7047 * for the parsing and a function for io handlers.
7048 */
7049__LJMP static int hlua_register_cli(lua_State *L)
7050{
7051 struct cli_kw_list *cli_kws;
7052 const char *message;
7053 int ref_io;
7054 int len;
7055 struct hlua_function *fcn;
7056 int index;
7057 int i;
7058
7059 MAY_LJMP(check_args(L, 3, "register_cli"));
7060
7061 /* First argument : an array of maximum 5 keywords. */
7062 if (!lua_istable(L, 1))
7063 WILL_LJMP(luaL_argerror(L, 1, "1st argument must be a table"));
7064
7065 /* Second argument : string with contextual message. */
7066 message = MAY_LJMP(luaL_checkstring(L, 2));
7067
7068 /* Third and fourth argument : lua function. */
7069 ref_io = MAY_LJMP(hlua_checkfunction(L, 3));
7070
7071 /* Allocate and fill the sample fetch keyword struct. */
7072 cli_kws = calloc(1, sizeof(*cli_kws) + sizeof(struct cli_kw) * 2);
7073 if (!cli_kws)
7074 WILL_LJMP(luaL_error(L, "lua out of memory error."));
7075 fcn = calloc(1, sizeof(*fcn));
7076 if (!fcn)
7077 WILL_LJMP(luaL_error(L, "lua out of memory error."));
7078
7079 /* Fill path. */
7080 index = 0;
7081 lua_pushnil(L);
7082 while(lua_next(L, 1) != 0) {
7083 if (index >= 5)
7084 WILL_LJMP(luaL_argerror(L, 1, "1st argument must be a table with a maximum of 5 entries"));
7085 if (lua_type(L, -1) != LUA_TSTRING)
7086 WILL_LJMP(luaL_argerror(L, 1, "1st argument must be a table filled with strings"));
7087 cli_kws->kw[0].str_kw[index] = strdup(lua_tostring(L, -1));
7088 if (!cli_kws->kw[0].str_kw[index])
7089 WILL_LJMP(luaL_error(L, "lua out of memory error."));
7090 index++;
7091 lua_pop(L, 1);
7092 }
7093
7094 /* Copy help message. */
7095 cli_kws->kw[0].usage = strdup(message);
7096 if (!cli_kws->kw[0].usage)
7097 WILL_LJMP(luaL_error(L, "lua out of memory error."));
7098
7099 /* Fill fcn io handler. */
7100 len = strlen("<lua.cli>") + 1;
7101 for (i = 0; i < index; i++)
7102 len += strlen(cli_kws->kw[0].str_kw[i]) + 1;
7103 fcn->name = calloc(1, len);
7104 if (!fcn->name)
7105 WILL_LJMP(luaL_error(L, "lua out of memory error."));
7106 strncat((char *)fcn->name, "<lua.cli", len);
7107 for (i = 0; i < index; i++) {
7108 strncat((char *)fcn->name, ".", len);
7109 strncat((char *)fcn->name, cli_kws->kw[0].str_kw[i], len);
7110 }
7111 strncat((char *)fcn->name, ">", len);
7112 fcn->function_ref = ref_io;
7113
7114 /* Fill last entries. */
7115 cli_kws->kw[0].private = fcn;
7116 cli_kws->kw[0].parse = hlua_cli_parse_fct;
7117 cli_kws->kw[0].io_handler = hlua_cli_io_handler_fct;
7118 cli_kws->kw[0].io_release = hlua_cli_io_release_fct;
7119
7120 /* Register this new converter */
7121 cli_register_kw(cli_kws);
7122
7123 return 0;
7124}
7125
Thierry FOURNIERbd413492015-03-03 16:52:26 +01007126static int hlua_read_timeout(char **args, int section_type, struct proxy *curpx,
7127 struct proxy *defpx, const char *file, int line,
7128 char **err, unsigned int *timeout)
7129{
7130 const char *error;
7131
7132 error = parse_time_err(args[1], timeout, TIME_UNIT_MS);
7133 if (error && *error != '\0') {
7134 memprintf(err, "%s: invalid timeout", args[0]);
7135 return -1;
7136 }
7137 return 0;
7138}
7139
7140static int hlua_session_timeout(char **args, int section_type, struct proxy *curpx,
7141 struct proxy *defpx, const char *file, int line,
7142 char **err)
7143{
7144 return hlua_read_timeout(args, section_type, curpx, defpx,
7145 file, line, err, &hlua_timeout_session);
7146}
7147
7148static int hlua_task_timeout(char **args, int section_type, struct proxy *curpx,
7149 struct proxy *defpx, const char *file, int line,
7150 char **err)
7151{
7152 return hlua_read_timeout(args, section_type, curpx, defpx,
7153 file, line, err, &hlua_timeout_task);
7154}
7155
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007156static int hlua_applet_timeout(char **args, int section_type, struct proxy *curpx,
7157 struct proxy *defpx, const char *file, int line,
7158 char **err)
7159{
7160 return hlua_read_timeout(args, section_type, curpx, defpx,
7161 file, line, err, &hlua_timeout_applet);
7162}
7163
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01007164static int hlua_forced_yield(char **args, int section_type, struct proxy *curpx,
7165 struct proxy *defpx, const char *file, int line,
7166 char **err)
7167{
7168 char *error;
7169
7170 hlua_nb_instruction = strtoll(args[1], &error, 10);
7171 if (*error != '\0') {
7172 memprintf(err, "%s: invalid number", args[0]);
7173 return -1;
7174 }
7175 return 0;
7176}
7177
Willy Tarreau32f61e22015-03-18 17:54:59 +01007178static int hlua_parse_maxmem(char **args, int section_type, struct proxy *curpx,
7179 struct proxy *defpx, const char *file, int line,
7180 char **err)
7181{
7182 char *error;
7183
7184 if (*(args[1]) == 0) {
7185 memprintf(err, "'%s' expects an integer argument (Lua memory size in MB).\n", args[0]);
7186 return -1;
7187 }
7188 hlua_global_allocator.limit = strtoll(args[1], &error, 10) * 1024L * 1024L;
7189 if (*error != '\0') {
7190 memprintf(err, "%s: invalid number %s (error at '%c')", args[0], args[1], *error);
7191 return -1;
7192 }
7193 return 0;
7194}
7195
7196
Thierry FOURNIER6c9b52c2015-01-23 15:57:06 +01007197/* This function is called by the main configuration key "lua-load". It loads and
7198 * execute an lua file during the parsing of the HAProxy configuration file. It is
7199 * the main lua entry point.
7200 *
7201 * This funtion runs with the HAProxy keywords API. It returns -1 if an error is
7202 * occured, otherwise it returns 0.
7203 *
7204 * In some error case, LUA set an error message in top of the stack. This function
7205 * returns this error message in the HAProxy logs and pop it from the stack.
Thierry FOURNIERbabae282015-09-17 11:36:37 +02007206 *
7207 * This function can fail with an abort() due to an Lua critical error.
7208 * We are in the configuration parsing process of HAProxy, this abort() is
7209 * tolerated.
Thierry FOURNIER6c9b52c2015-01-23 15:57:06 +01007210 */
7211static int hlua_load(char **args, int section_type, struct proxy *curpx,
7212 struct proxy *defpx, const char *file, int line,
7213 char **err)
7214{
7215 int error;
7216
7217 /* Just load and compile the file. */
7218 error = luaL_loadfile(gL.T, args[1]);
7219 if (error) {
7220 memprintf(err, "error in lua file '%s': %s", args[1], lua_tostring(gL.T, -1));
7221 lua_pop(gL.T, 1);
7222 return -1;
7223 }
7224
7225 /* If no syntax error where detected, execute the code. */
7226 error = lua_pcall(gL.T, 0, LUA_MULTRET, 0);
7227 switch (error) {
7228 case LUA_OK:
7229 break;
7230 case LUA_ERRRUN:
7231 memprintf(err, "lua runtime error: %s\n", lua_tostring(gL.T, -1));
7232 lua_pop(gL.T, 1);
7233 return -1;
7234 case LUA_ERRMEM:
7235 memprintf(err, "lua out of memory error\n");
7236 return -1;
7237 case LUA_ERRERR:
7238 memprintf(err, "lua message handler error: %s\n", lua_tostring(gL.T, -1));
7239 lua_pop(gL.T, 1);
7240 return -1;
7241 case LUA_ERRGCMM:
7242 memprintf(err, "lua garbage collector error: %s\n", lua_tostring(gL.T, -1));
7243 lua_pop(gL.T, 1);
7244 return -1;
7245 default:
7246 memprintf(err, "lua unknonwn error: %s\n", lua_tostring(gL.T, -1));
7247 lua_pop(gL.T, 1);
7248 return -1;
7249 }
7250
7251 return 0;
7252}
7253
7254/* configuration keywords declaration */
7255static struct cfg_kw_list cfg_kws = {{ },{
Thierry FOURNIERbd413492015-03-03 16:52:26 +01007256 { CFG_GLOBAL, "lua-load", hlua_load },
7257 { CFG_GLOBAL, "tune.lua.session-timeout", hlua_session_timeout },
7258 { CFG_GLOBAL, "tune.lua.task-timeout", hlua_task_timeout },
Thierry FOURNIER56da1012015-10-01 08:42:31 +02007259 { CFG_GLOBAL, "tune.lua.service-timeout", hlua_applet_timeout },
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01007260 { CFG_GLOBAL, "tune.lua.forced-yield", hlua_forced_yield },
Willy Tarreau32f61e22015-03-18 17:54:59 +01007261 { CFG_GLOBAL, "tune.lua.maxmem", hlua_parse_maxmem },
Thierry FOURNIER6c9b52c2015-01-23 15:57:06 +01007262 { 0, NULL, NULL },
7263}};
7264
Thierry FOURNIERbabae282015-09-17 11:36:37 +02007265/* This function can fail with an abort() due to an Lua critical error.
7266 * We are in the initialisation process of HAProxy, this abort() is
7267 * tolerated.
7268 */
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007269int hlua_post_init()
7270{
7271 struct hlua_init_function *init;
7272 const char *msg;
7273 enum hlua_exec ret;
Thierry Fournierfd107a22016-02-19 19:57:23 +01007274 const char *error;
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007275
Thierry Fournier3d4a6752016-02-19 20:53:30 +01007276 /* Call post initialisation function in safe environement. */
7277 if (!SET_SAFE_LJMP(gL.T)) {
7278 if (lua_type(gL.T, -1) == LUA_TSTRING)
7279 error = lua_tostring(gL.T, -1);
7280 else
7281 error = "critical error";
7282 fprintf(stderr, "Lua post-init: %s.\n", error);
7283 exit(1);
7284 }
7285 hlua_fcn_post_init(gL.T);
7286 RESET_SAFE_LJMP(gL.T);
7287
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007288 list_for_each_entry(init, &hlua_init_functions, l) {
7289 lua_rawgeti(gL.T, LUA_REGISTRYINDEX, init->function_ref);
7290 ret = hlua_ctx_resume(&gL, 0);
7291 switch (ret) {
7292 case HLUA_E_OK:
7293 lua_pop(gL.T, -1);
7294 return 1;
7295 case HLUA_E_AGAIN:
7296 Alert("lua init: yield not allowed.\n");
7297 return 0;
7298 case HLUA_E_ERRMSG:
7299 msg = lua_tostring(gL.T, -1);
7300 Alert("lua init: %s.\n", msg);
7301 return 0;
7302 case HLUA_E_ERR:
7303 default:
7304 Alert("lua init: unknown runtime error.\n");
7305 return 0;
7306 }
7307 }
7308 return 1;
7309}
7310
Willy Tarreau32f61e22015-03-18 17:54:59 +01007311/* The memory allocator used by the Lua stack. <ud> is a pointer to the
7312 * allocator's context. <ptr> is the pointer to alloc/free/realloc. <osize>
7313 * is the previously allocated size or the kind of object in case of a new
7314 * allocation. <nsize> is the requested new size.
7315 */
7316static void *hlua_alloc(void *ud, void *ptr, size_t osize, size_t nsize)
7317{
7318 struct hlua_mem_allocator *zone = ud;
7319
7320 if (nsize == 0) {
7321 /* it's a free */
7322 if (ptr)
7323 zone->allocated -= osize;
7324 free(ptr);
7325 return NULL;
7326 }
7327
7328 if (!ptr) {
7329 /* it's a new allocation */
7330 if (zone->limit && zone->allocated + nsize > zone->limit)
7331 return NULL;
7332
7333 ptr = malloc(nsize);
7334 if (ptr)
7335 zone->allocated += nsize;
7336 return ptr;
7337 }
7338
7339 /* it's a realloc */
7340 if (zone->limit && zone->allocated + nsize - osize > zone->limit)
7341 return NULL;
7342
7343 ptr = realloc(ptr, nsize);
7344 if (ptr)
7345 zone->allocated += nsize - osize;
7346 return ptr;
7347}
7348
Thierry FOURNIERbabae282015-09-17 11:36:37 +02007349/* Ithis function can fail with an abort() due to an Lua critical error.
7350 * We are in the initialisation process of HAProxy, this abort() is
7351 * tolerated.
7352 */
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01007353void hlua_init(void)
7354{
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007355 int i;
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +01007356 int idx;
7357 struct sample_fetch *sf;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01007358 struct sample_conv *sc;
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +01007359 char *p;
Thierry Fournierfd107a22016-02-19 19:57:23 +01007360 const char *error_msg;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01007361#ifdef USE_OPENSSL
Willy Tarreau80f5fae2015-02-27 16:38:20 +01007362 struct srv_kw *kw;
7363 int tmp_error;
7364 char *error;
Thierry FOURNIER36d13742015-03-17 16:48:53 +01007365 char *args[] = { /* SSL client configuration. */
7366 "ssl",
7367 "verify",
7368 "none",
Thierry FOURNIER36d13742015-03-17 16:48:53 +01007369 NULL
7370 };
Willy Tarreau80f5fae2015-02-27 16:38:20 +01007371#endif
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007372
Thierry FOURNIER61ba0e22017-07-12 11:41:21 +02007373 SPIN_INIT(&hlua_global_lock);
7374
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01007375 /* Initialise struct hlua and com signals pool */
7376 pool2_hlua = create_pool("hlua", sizeof(struct hlua), MEM_F_SHARED);
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +01007377
Thierry FOURNIER6c9b52c2015-01-23 15:57:06 +01007378 /* Register configuration keywords. */
7379 cfg_register_keywords(&cfg_kws);
7380
Thierry FOURNIER380d0932015-01-23 14:27:52 +01007381 /* Init main lua stack. */
7382 gL.Mref = LUA_REFNIL;
Thierry FOURNIERa097fdf2015-03-03 15:17:35 +01007383 gL.flags = 0;
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +01007384 LIST_INIT(&gL.com);
Willy Tarreau42ef75f2017-04-12 21:40:29 +02007385 gL.T = lua_newstate(hlua_alloc, &hlua_global_allocator);
Thierry FOURNIER380d0932015-01-23 14:27:52 +01007386 hlua_sethlua(&gL);
7387 gL.Tref = LUA_REFNIL;
7388 gL.task = NULL;
7389
Thierry FOURNIERbabae282015-09-17 11:36:37 +02007390 /* From this point, until the end of the initialisation fucntion,
7391 * the Lua function can fail with an abort. We are in the initialisation
7392 * process of HAProxy, this abort() is tolerated.
7393 */
7394
Thierry FOURNIER380d0932015-01-23 14:27:52 +01007395 /* Initialise lua. */
7396 luaL_openlibs(gL.T);
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007397
Thierry Fournier75933d42016-01-21 09:30:18 +01007398 /* Set safe environment for the initialisation. */
7399 if (!SET_SAFE_LJMP(gL.T)) {
Thierry Fournierfd107a22016-02-19 19:57:23 +01007400 if (lua_type(gL.T, -1) == LUA_TSTRING)
7401 error_msg = lua_tostring(gL.T, -1);
7402 else
7403 error_msg = "critical error";
7404 fprintf(stderr, "Lua init: %s.\n", error_msg);
Thierry Fournier75933d42016-01-21 09:30:18 +01007405 exit(1);
7406 }
7407
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007408 /*
7409 *
7410 * Create "core" object.
7411 *
7412 */
7413
Thierry FOURNIERa2d8c652015-03-11 17:29:39 +01007414 /* This table entry is the object "core" base. */
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007415 lua_newtable(gL.T);
7416
7417 /* Push the loglevel constants. */
Willy Tarreau80f5fae2015-02-27 16:38:20 +01007418 for (i = 0; i < NB_LOG_LEVELS; i++)
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007419 hlua_class_const_int(gL.T, log_levels[i], i);
7420
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007421 /* Register special functions. */
7422 hlua_class_function(gL.T, "register_init", hlua_register_init);
Thierry FOURNIER24f33532015-01-23 12:13:00 +01007423 hlua_class_function(gL.T, "register_task", hlua_register_task);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01007424 hlua_class_function(gL.T, "register_fetches", hlua_register_fetches);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01007425 hlua_class_function(gL.T, "register_converters", hlua_register_converters);
Thierry FOURNIER8255a752015-09-23 21:03:35 +02007426 hlua_class_function(gL.T, "register_action", hlua_register_action);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007427 hlua_class_function(gL.T, "register_service", hlua_register_service);
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007428 hlua_class_function(gL.T, "register_cli", hlua_register_cli);
Thierry FOURNIER13416fe2015-02-17 15:01:59 +01007429 hlua_class_function(gL.T, "yield", hlua_yield);
Willy Tarreau59551662015-03-10 14:23:13 +01007430 hlua_class_function(gL.T, "set_nice", hlua_set_nice);
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01007431 hlua_class_function(gL.T, "sleep", hlua_sleep);
7432 hlua_class_function(gL.T, "msleep", hlua_msleep);
Thierry FOURNIER83758bb2015-02-04 13:21:04 +01007433 hlua_class_function(gL.T, "add_acl", hlua_add_acl);
7434 hlua_class_function(gL.T, "del_acl", hlua_del_acl);
7435 hlua_class_function(gL.T, "set_map", hlua_set_map);
7436 hlua_class_function(gL.T, "del_map", hlua_del_map);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007437 hlua_class_function(gL.T, "tcp", hlua_socket_new);
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +01007438 hlua_class_function(gL.T, "log", hlua_log);
7439 hlua_class_function(gL.T, "Debug", hlua_log_debug);
7440 hlua_class_function(gL.T, "Info", hlua_log_info);
7441 hlua_class_function(gL.T, "Warning", hlua_log_warning);
7442 hlua_class_function(gL.T, "Alert", hlua_log_alert);
Thierry FOURNIER0a99b892015-08-26 00:14:17 +02007443 hlua_class_function(gL.T, "done", hlua_done);
Thierry Fournierfb0b5462016-01-21 09:28:58 +01007444 hlua_fcn_reg_core_fcn(gL.T);
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007445
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007446 lua_setglobal(gL.T, "core");
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01007447
7448 /*
7449 *
Thierry FOURNIER3def3932015-04-07 11:27:54 +02007450 * Register class Map
7451 *
7452 */
7453
7454 /* This table entry is the object "Map" base. */
7455 lua_newtable(gL.T);
7456
7457 /* register pattern types. */
7458 for (i=0; i<PAT_MATCH_NUM; i++)
7459 hlua_class_const_int(gL.T, pat_match_names[i], i);
Thierry FOURNIER4dc71972017-01-28 08:33:08 +01007460 for (i=0; i<PAT_MATCH_NUM; i++) {
7461 snprintf(trash.str, trash.size, "_%s", pat_match_names[i]);
7462 hlua_class_const_int(gL.T, trash.str, i);
7463 }
Thierry FOURNIER3def3932015-04-07 11:27:54 +02007464
7465 /* register constructor. */
7466 hlua_class_function(gL.T, "new", hlua_map_new);
7467
7468 /* Create and fill the metatable. */
7469 lua_newtable(gL.T);
7470
7471 /* Create and fille the __index entry. */
7472 lua_pushstring(gL.T, "__index");
7473 lua_newtable(gL.T);
7474
7475 /* Register . */
7476 hlua_class_function(gL.T, "lookup", hlua_map_lookup);
7477 hlua_class_function(gL.T, "slookup", hlua_map_slookup);
7478
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007479 lua_rawset(gL.T, -3);
Thierry FOURNIER3def3932015-04-07 11:27:54 +02007480
Thierry Fournier45e78d72016-02-19 18:34:46 +01007481 /* Register previous table in the registry with reference and named entry.
7482 * The function hlua_register_metatable() pops the stack, so we
7483 * previously create a copy of the table.
7484 */
Thierry FOURNIER3def3932015-04-07 11:27:54 +02007485 lua_pushvalue(gL.T, -1); /* Copy the -1 entry and push it on the stack. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007486 class_map_ref = hlua_register_metatable(gL.T, CLASS_MAP);
Thierry FOURNIER3def3932015-04-07 11:27:54 +02007487
7488 /* Assign the metatable to the mai Map object. */
7489 lua_setmetatable(gL.T, -2);
7490
7491 /* Set a name to the table. */
7492 lua_setglobal(gL.T, "Map");
7493
7494 /*
7495 *
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01007496 * Register class Channel
7497 *
7498 */
7499
7500 /* Create and fill the metatable. */
7501 lua_newtable(gL.T);
7502
7503 /* Create and fille the __index entry. */
7504 lua_pushstring(gL.T, "__index");
7505 lua_newtable(gL.T);
7506
7507 /* Register . */
7508 hlua_class_function(gL.T, "get", hlua_channel_get);
7509 hlua_class_function(gL.T, "dup", hlua_channel_dup);
7510 hlua_class_function(gL.T, "getline", hlua_channel_getline);
7511 hlua_class_function(gL.T, "set", hlua_channel_set);
7512 hlua_class_function(gL.T, "append", hlua_channel_append);
7513 hlua_class_function(gL.T, "send", hlua_channel_send);
7514 hlua_class_function(gL.T, "forward", hlua_channel_forward);
7515 hlua_class_function(gL.T, "get_in_len", hlua_channel_get_in_len);
7516 hlua_class_function(gL.T, "get_out_len", hlua_channel_get_out_len);
Thierry FOURNIER / OZON.IO65192f32016-11-07 15:28:40 +01007517 hlua_class_function(gL.T, "is_full", hlua_channel_is_full);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01007518
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007519 lua_rawset(gL.T, -3);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01007520
7521 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007522 class_channel_ref = hlua_register_metatable(gL.T, CLASS_CHANNEL);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01007523
7524 /*
7525 *
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01007526 * Register class Fetches
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01007527 *
7528 */
7529
7530 /* Create and fill the metatable. */
7531 lua_newtable(gL.T);
7532
7533 /* Create and fille the __index entry. */
7534 lua_pushstring(gL.T, "__index");
7535 lua_newtable(gL.T);
7536
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +01007537 /* Browse existing fetches and create the associated
7538 * object method.
7539 */
7540 sf = NULL;
7541 while ((sf = sample_fetch_getnext(sf, &idx)) != NULL) {
7542
7543 /* Dont register the keywork if the arguments check function are
7544 * not safe during the runtime.
7545 */
7546 if ((sf->val_args != NULL) &&
7547 (sf->val_args != val_payload_lv) &&
7548 (sf->val_args != val_hdr))
7549 continue;
7550
7551 /* gL.Tua doesn't support '.' and '-' in the function names, replace it
7552 * by an underscore.
7553 */
7554 strncpy(trash.str, sf->kw, trash.size);
7555 trash.str[trash.size - 1] = '\0';
7556 for (p = trash.str; *p; p++)
7557 if (*p == '.' || *p == '-' || *p == '+')
7558 *p = '_';
7559
7560 /* Register the function. */
7561 lua_pushstring(gL.T, trash.str);
Willy Tarreau2ec22742015-03-10 14:27:20 +01007562 lua_pushlightuserdata(gL.T, sf);
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +01007563 lua_pushcclosure(gL.T, hlua_run_sample_fetch, 1);
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007564 lua_rawset(gL.T, -3);
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +01007565 }
7566
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007567 lua_rawset(gL.T, -3);
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01007568
7569 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007570 class_fetches_ref = hlua_register_metatable(gL.T, CLASS_FETCHES);
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01007571
7572 /*
7573 *
Thierry FOURNIER594afe72015-03-10 23:58:30 +01007574 * Register class Converters
7575 *
7576 */
7577
7578 /* Create and fill the metatable. */
7579 lua_newtable(gL.T);
7580
7581 /* Create and fill the __index entry. */
7582 lua_pushstring(gL.T, "__index");
7583 lua_newtable(gL.T);
7584
7585 /* Browse existing converters and create the associated
7586 * object method.
7587 */
7588 sc = NULL;
7589 while ((sc = sample_conv_getnext(sc, &idx)) != NULL) {
7590 /* Dont register the keywork if the arguments check function are
7591 * not safe during the runtime.
7592 */
7593 if (sc->val_args != NULL)
7594 continue;
7595
7596 /* gL.Tua doesn't support '.' and '-' in the function names, replace it
7597 * by an underscore.
7598 */
7599 strncpy(trash.str, sc->kw, trash.size);
7600 trash.str[trash.size - 1] = '\0';
7601 for (p = trash.str; *p; p++)
7602 if (*p == '.' || *p == '-' || *p == '+')
7603 *p = '_';
7604
7605 /* Register the function. */
7606 lua_pushstring(gL.T, trash.str);
7607 lua_pushlightuserdata(gL.T, sc);
7608 lua_pushcclosure(gL.T, hlua_run_sample_conv, 1);
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007609 lua_rawset(gL.T, -3);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01007610 }
7611
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007612 lua_rawset(gL.T, -3);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01007613
7614 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007615 class_converters_ref = hlua_register_metatable(gL.T, CLASS_CONVERTERS);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01007616
7617 /*
7618 *
Thierry FOURNIER08504f42015-03-16 14:17:08 +01007619 * Register class HTTP
7620 *
7621 */
7622
7623 /* Create and fill the metatable. */
7624 lua_newtable(gL.T);
7625
7626 /* Create and fille the __index entry. */
7627 lua_pushstring(gL.T, "__index");
7628 lua_newtable(gL.T);
7629
7630 /* Register Lua functions. */
7631 hlua_class_function(gL.T, "req_get_headers",hlua_http_req_get_headers);
7632 hlua_class_function(gL.T, "req_del_header", hlua_http_req_del_hdr);
7633 hlua_class_function(gL.T, "req_rep_header", hlua_http_req_rep_hdr);
7634 hlua_class_function(gL.T, "req_rep_value", hlua_http_req_rep_val);
7635 hlua_class_function(gL.T, "req_add_header", hlua_http_req_add_hdr);
7636 hlua_class_function(gL.T, "req_set_header", hlua_http_req_set_hdr);
7637 hlua_class_function(gL.T, "req_set_method", hlua_http_req_set_meth);
7638 hlua_class_function(gL.T, "req_set_path", hlua_http_req_set_path);
7639 hlua_class_function(gL.T, "req_set_query", hlua_http_req_set_query);
7640 hlua_class_function(gL.T, "req_set_uri", hlua_http_req_set_uri);
7641
7642 hlua_class_function(gL.T, "res_get_headers",hlua_http_res_get_headers);
7643 hlua_class_function(gL.T, "res_del_header", hlua_http_res_del_hdr);
7644 hlua_class_function(gL.T, "res_rep_header", hlua_http_res_rep_hdr);
7645 hlua_class_function(gL.T, "res_rep_value", hlua_http_res_rep_val);
7646 hlua_class_function(gL.T, "res_add_header", hlua_http_res_add_hdr);
7647 hlua_class_function(gL.T, "res_set_header", hlua_http_res_set_hdr);
Thierry FOURNIER35d70ef2015-08-26 16:21:56 +02007648 hlua_class_function(gL.T, "res_set_status", hlua_http_res_set_status);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01007649
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007650 lua_rawset(gL.T, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01007651
7652 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007653 class_http_ref = hlua_register_metatable(gL.T, CLASS_HTTP);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01007654
7655 /*
7656 *
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007657 * Register class AppletTCP
7658 *
7659 */
7660
7661 /* Create and fill the metatable. */
7662 lua_newtable(gL.T);
7663
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007664 /* Create and fille the __index entry. */
7665 lua_pushstring(gL.T, "__index");
7666 lua_newtable(gL.T);
7667
7668 /* Register Lua functions. */
Thierry FOURNIER / OZON.IO3e1d7912016-12-12 12:29:34 +01007669 hlua_class_function(gL.T, "getline", hlua_applet_tcp_getline);
7670 hlua_class_function(gL.T, "receive", hlua_applet_tcp_recv);
7671 hlua_class_function(gL.T, "send", hlua_applet_tcp_send);
7672 hlua_class_function(gL.T, "set_priv", hlua_applet_tcp_set_priv);
7673 hlua_class_function(gL.T, "get_priv", hlua_applet_tcp_get_priv);
Thierry FOURNIER / OZON.IO4394a2c2016-12-12 12:31:54 +01007674 hlua_class_function(gL.T, "set_var", hlua_applet_tcp_set_var);
7675 hlua_class_function(gL.T, "unset_var", hlua_applet_tcp_unset_var);
7676 hlua_class_function(gL.T, "get_var", hlua_applet_tcp_get_var);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007677
7678 lua_settable(gL.T, -3);
7679
7680 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007681 class_applet_tcp_ref = hlua_register_metatable(gL.T, CLASS_APPLET_TCP);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007682
7683 /*
7684 *
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02007685 * Register class AppletHTTP
7686 *
7687 */
7688
7689 /* Create and fill the metatable. */
7690 lua_newtable(gL.T);
7691
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02007692 /* Create and fille the __index entry. */
7693 lua_pushstring(gL.T, "__index");
7694 lua_newtable(gL.T);
7695
7696 /* Register Lua functions. */
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01007697 hlua_class_function(gL.T, "set_priv", hlua_applet_http_set_priv);
7698 hlua_class_function(gL.T, "get_priv", hlua_applet_http_get_priv);
Thierry FOURNIER / OZON.IO4394a2c2016-12-12 12:31:54 +01007699 hlua_class_function(gL.T, "set_var", hlua_applet_http_set_var);
7700 hlua_class_function(gL.T, "unset_var", hlua_applet_http_unset_var);
7701 hlua_class_function(gL.T, "get_var", hlua_applet_http_get_var);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02007702 hlua_class_function(gL.T, "getline", hlua_applet_http_getline);
7703 hlua_class_function(gL.T, "receive", hlua_applet_http_recv);
7704 hlua_class_function(gL.T, "send", hlua_applet_http_send);
7705 hlua_class_function(gL.T, "add_header", hlua_applet_http_addheader);
7706 hlua_class_function(gL.T, "set_status", hlua_applet_http_status);
7707 hlua_class_function(gL.T, "start_response", hlua_applet_http_start_response);
7708
7709 lua_settable(gL.T, -3);
7710
7711 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007712 class_applet_http_ref = hlua_register_metatable(gL.T, CLASS_APPLET_HTTP);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02007713
7714 /*
7715 *
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01007716 * Register class TXN
7717 *
7718 */
7719
7720 /* Create and fill the metatable. */
7721 lua_newtable(gL.T);
7722
7723 /* Create and fille the __index entry. */
7724 lua_pushstring(gL.T, "__index");
7725 lua_newtable(gL.T);
7726
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01007727 /* Register Lua functions. */
Willy Tarreau59551662015-03-10 14:23:13 +01007728 hlua_class_function(gL.T, "set_priv", hlua_set_priv);
7729 hlua_class_function(gL.T, "get_priv", hlua_get_priv);
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +02007730 hlua_class_function(gL.T, "set_var", hlua_set_var);
Christopher Faulet85d79c92016-11-09 16:54:56 +01007731 hlua_class_function(gL.T, "unset_var", hlua_unset_var);
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +02007732 hlua_class_function(gL.T, "get_var", hlua_get_var);
Thierry FOURNIER4bb375c2015-08-26 08:42:21 +02007733 hlua_class_function(gL.T, "done", hlua_txn_done);
Thierry FOURNIER2cce3532015-03-16 12:04:16 +01007734 hlua_class_function(gL.T, "set_loglevel",hlua_txn_set_loglevel);
7735 hlua_class_function(gL.T, "set_tos", hlua_txn_set_tos);
7736 hlua_class_function(gL.T, "set_mark", hlua_txn_set_mark);
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +01007737 hlua_class_function(gL.T, "deflog", hlua_txn_deflog);
7738 hlua_class_function(gL.T, "log", hlua_txn_log);
7739 hlua_class_function(gL.T, "Debug", hlua_txn_log_debug);
7740 hlua_class_function(gL.T, "Info", hlua_txn_log_info);
7741 hlua_class_function(gL.T, "Warning", hlua_txn_log_warning);
7742 hlua_class_function(gL.T, "Alert", hlua_txn_log_alert);
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01007743
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007744 lua_rawset(gL.T, -3);
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01007745
7746 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007747 class_txn_ref = hlua_register_metatable(gL.T, CLASS_TXN);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007748
7749 /*
7750 *
7751 * Register class Socket
7752 *
7753 */
7754
7755 /* Create and fill the metatable. */
7756 lua_newtable(gL.T);
7757
7758 /* Create and fille the __index entry. */
7759 lua_pushstring(gL.T, "__index");
7760 lua_newtable(gL.T);
7761
Baptiste Assmann84bb4932015-03-02 21:40:06 +01007762#ifdef USE_OPENSSL
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007763 hlua_class_function(gL.T, "connect_ssl", hlua_socket_connect_ssl);
Baptiste Assmann84bb4932015-03-02 21:40:06 +01007764#endif
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007765 hlua_class_function(gL.T, "connect", hlua_socket_connect);
7766 hlua_class_function(gL.T, "send", hlua_socket_send);
7767 hlua_class_function(gL.T, "receive", hlua_socket_receive);
7768 hlua_class_function(gL.T, "close", hlua_socket_close);
7769 hlua_class_function(gL.T, "getpeername", hlua_socket_getpeername);
7770 hlua_class_function(gL.T, "getsockname", hlua_socket_getsockname);
7771 hlua_class_function(gL.T, "setoption", hlua_socket_setoption);
7772 hlua_class_function(gL.T, "settimeout", hlua_socket_settimeout);
7773
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007774 lua_rawset(gL.T, -3); /* Push the last 2 entries in the table at index -3 */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007775
7776 /* Register the garbage collector entry. */
7777 lua_pushstring(gL.T, "__gc");
7778 lua_pushcclosure(gL.T, hlua_socket_gc, 0);
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007779 lua_rawset(gL.T, -3); /* Push the last 2 entries in the table at index -3 */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007780
7781 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007782 class_socket_ref = hlua_register_metatable(gL.T, CLASS_SOCKET);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007783
7784 /* Proxy and server configuration initialisation. */
7785 memset(&socket_proxy, 0, sizeof(socket_proxy));
7786 init_new_proxy(&socket_proxy);
7787 socket_proxy.parent = NULL;
7788 socket_proxy.last_change = now.tv_sec;
7789 socket_proxy.id = "LUA-SOCKET";
7790 socket_proxy.cap = PR_CAP_FE | PR_CAP_BE;
7791 socket_proxy.maxconn = 0;
7792 socket_proxy.accept = NULL;
7793 socket_proxy.options2 |= PR_O2_INDEPSTR;
7794 socket_proxy.srv = NULL;
7795 socket_proxy.conn_retries = 0;
7796 socket_proxy.timeout.connect = 5000; /* By default the timeout connection is 5s. */
7797
7798 /* Init TCP server: unchanged parameters */
7799 memset(&socket_tcp, 0, sizeof(socket_tcp));
7800 socket_tcp.next = NULL;
7801 socket_tcp.proxy = &socket_proxy;
7802 socket_tcp.obj_type = OBJ_TYPE_SERVER;
7803 LIST_INIT(&socket_tcp.actconns);
7804 LIST_INIT(&socket_tcp.pendconns);
Christopher Faulet40a007c2017-07-03 15:41:01 +02007805 socket_tcp.priv_conns = NULL;
7806 socket_tcp.idle_conns = NULL;
7807 socket_tcp.safe_conns = NULL;
Emeric Brun52a91d32017-08-31 14:41:55 +02007808 socket_tcp.next_state = SRV_ST_RUNNING; /* early server setup */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007809 socket_tcp.last_change = 0;
7810 socket_tcp.id = "LUA-TCP-CONN";
7811 socket_tcp.check.state &= ~CHK_ST_ENABLED; /* Disable health checks. */
7812 socket_tcp.agent.state &= ~CHK_ST_ENABLED; /* Disable health checks. */
7813 socket_tcp.pp_opts = 0; /* Remove proxy protocol. */
7814
7815 /* XXX: Copy default parameter from default server,
7816 * but the default server is not initialized.
7817 */
7818 socket_tcp.maxqueue = socket_proxy.defsrv.maxqueue;
7819 socket_tcp.minconn = socket_proxy.defsrv.minconn;
7820 socket_tcp.maxconn = socket_proxy.defsrv.maxconn;
7821 socket_tcp.slowstart = socket_proxy.defsrv.slowstart;
7822 socket_tcp.onerror = socket_proxy.defsrv.onerror;
7823 socket_tcp.onmarkeddown = socket_proxy.defsrv.onmarkeddown;
7824 socket_tcp.onmarkedup = socket_proxy.defsrv.onmarkedup;
7825 socket_tcp.consecutive_errors_limit = socket_proxy.defsrv.consecutive_errors_limit;
7826 socket_tcp.uweight = socket_proxy.defsrv.iweight;
7827 socket_tcp.iweight = socket_proxy.defsrv.iweight;
7828
7829 socket_tcp.check.status = HCHK_STATUS_INI;
7830 socket_tcp.check.rise = socket_proxy.defsrv.check.rise;
7831 socket_tcp.check.fall = socket_proxy.defsrv.check.fall;
7832 socket_tcp.check.health = socket_tcp.check.rise; /* socket, but will fall down at first failure */
7833 socket_tcp.check.server = &socket_tcp;
7834
7835 socket_tcp.agent.status = HCHK_STATUS_INI;
7836 socket_tcp.agent.rise = socket_proxy.defsrv.agent.rise;
7837 socket_tcp.agent.fall = socket_proxy.defsrv.agent.fall;
7838 socket_tcp.agent.health = socket_tcp.agent.rise; /* socket, but will fall down at first failure */
7839 socket_tcp.agent.server = &socket_tcp;
7840
Willy Tarreaua261e9b2016-12-22 20:44:00 +01007841 socket_tcp.xprt = xprt_get(XPRT_RAW);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007842
7843#ifdef USE_OPENSSL
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007844 /* Init TCP server: unchanged parameters */
7845 memset(&socket_ssl, 0, sizeof(socket_ssl));
7846 socket_ssl.next = NULL;
7847 socket_ssl.proxy = &socket_proxy;
7848 socket_ssl.obj_type = OBJ_TYPE_SERVER;
7849 LIST_INIT(&socket_ssl.actconns);
7850 LIST_INIT(&socket_ssl.pendconns);
Christopher Faulet40a007c2017-07-03 15:41:01 +02007851 socket_tcp.priv_conns = NULL;
7852 socket_tcp.idle_conns = NULL;
7853 socket_tcp.safe_conns = NULL;
Emeric Brun52a91d32017-08-31 14:41:55 +02007854 socket_ssl.next_state = SRV_ST_RUNNING; /* early server setup */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007855 socket_ssl.last_change = 0;
7856 socket_ssl.id = "LUA-SSL-CONN";
7857 socket_ssl.check.state &= ~CHK_ST_ENABLED; /* Disable health checks. */
7858 socket_ssl.agent.state &= ~CHK_ST_ENABLED; /* Disable health checks. */
7859 socket_ssl.pp_opts = 0; /* Remove proxy protocol. */
7860
7861 /* XXX: Copy default parameter from default server,
7862 * but the default server is not initialized.
7863 */
7864 socket_ssl.maxqueue = socket_proxy.defsrv.maxqueue;
7865 socket_ssl.minconn = socket_proxy.defsrv.minconn;
7866 socket_ssl.maxconn = socket_proxy.defsrv.maxconn;
7867 socket_ssl.slowstart = socket_proxy.defsrv.slowstart;
7868 socket_ssl.onerror = socket_proxy.defsrv.onerror;
7869 socket_ssl.onmarkeddown = socket_proxy.defsrv.onmarkeddown;
7870 socket_ssl.onmarkedup = socket_proxy.defsrv.onmarkedup;
7871 socket_ssl.consecutive_errors_limit = socket_proxy.defsrv.consecutive_errors_limit;
7872 socket_ssl.uweight = socket_proxy.defsrv.iweight;
7873 socket_ssl.iweight = socket_proxy.defsrv.iweight;
7874
7875 socket_ssl.check.status = HCHK_STATUS_INI;
7876 socket_ssl.check.rise = socket_proxy.defsrv.check.rise;
7877 socket_ssl.check.fall = socket_proxy.defsrv.check.fall;
7878 socket_ssl.check.health = socket_ssl.check.rise; /* socket, but will fall down at first failure */
7879 socket_ssl.check.server = &socket_ssl;
7880
7881 socket_ssl.agent.status = HCHK_STATUS_INI;
7882 socket_ssl.agent.rise = socket_proxy.defsrv.agent.rise;
7883 socket_ssl.agent.fall = socket_proxy.defsrv.agent.fall;
7884 socket_ssl.agent.health = socket_ssl.agent.rise; /* socket, but will fall down at first failure */
7885 socket_ssl.agent.server = &socket_ssl;
7886
Thierry FOURNIER36d13742015-03-17 16:48:53 +01007887 socket_ssl.use_ssl = 1;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01007888 socket_ssl.xprt = xprt_get(XPRT_SSL);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007889
Thierry FOURNIER36d13742015-03-17 16:48:53 +01007890 for (idx = 0; args[idx] != NULL; idx++) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007891 if ((kw = srv_find_kw(args[idx])) != NULL) { /* Maybe it's registered server keyword */
7892 /*
7893 *
7894 * If the keyword is not known, we can search in the registered
7895 * server keywords. This is usefull to configure special SSL
7896 * features like client certificates and ssl_verify.
7897 *
7898 */
7899 tmp_error = kw->parse(args, &idx, &socket_proxy, &socket_ssl, &error);
7900 if (tmp_error != 0) {
7901 fprintf(stderr, "INTERNAL ERROR: %s\n", error);
7902 abort(); /* This must be never arrives because the command line
7903 not editable by the user. */
7904 }
7905 idx += kw->skip;
7906 }
7907 }
7908
7909 /* Initialize SSL server. */
Willy Tarreau17d45382016-12-22 21:16:08 +01007910 if (socket_ssl.xprt->prepare_srv)
7911 socket_ssl.xprt->prepare_srv(&socket_ssl);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007912#endif
Thierry Fournier75933d42016-01-21 09:30:18 +01007913
7914 RESET_SAFE_LJMP(gL.T);
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01007915}
Willy Tarreaubb57d942016-12-21 19:04:56 +01007916
7917__attribute__((constructor))
7918static void __hlua_init(void)
7919{
7920 char *ptr = NULL;
7921 memprintf(&ptr, "Built with Lua version : %s", LUA_RELEASE);
7922 hap_register_build_opts(ptr, 1);
7923}