blob: 759e7b21e33d90f024f47ff9ad8d3ad1d9395406 [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>
Mark Lakes56cc1252018-03-27 09:48:06 +020014#include <limits.h>
Thierry FOURNIERbabae282015-09-17 11:36:37 +020015#include <setjmp.h>
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +010016
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +010017#include <lauxlib.h>
18#include <lua.h>
19#include <lualib.h>
20
Thierry FOURNIER463119c2015-03-10 00:35:36 +010021#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 503
22#error "Requires Lua 5.3 or later."
Cyril Bontédc0306e2015-03-02 00:08:40 +010023#endif
24
Thierry FOURNIER380d0932015-01-23 14:27:52 +010025#include <ebpttree.h>
26
27#include <common/cfgparse.h>
Thierry FOURNIER2da788e2017-09-11 18:37:23 +020028#include <common/xref.h>
Thierry FOURNIER61ba0e22017-07-12 11:41:21 +020029#include <common/hathreads.h>
Thierry FOURNIER380d0932015-01-23 14:27:52 +010030
William Lallemand9ed62032016-11-21 17:49:11 +010031#include <types/cli.h>
Thierry FOURNIER380d0932015-01-23 14:27:52 +010032#include <types/hlua.h>
33#include <types/proxy.h>
William Lallemand9ed62032016-11-21 17:49:11 +010034#include <types/stats.h>
Thierry FOURNIER380d0932015-01-23 14:27:52 +010035
Thierry FOURNIER55da1652015-01-23 11:36:30 +010036#include <proto/arg.h>
Willy Tarreau8a8d83b2015-04-13 13:24:54 +020037#include <proto/applet.h>
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +010038#include <proto/channel.h>
William Lallemand9ed62032016-11-21 17:49:11 +010039#include <proto/cli.h>
Willy Tarreaua71f6422016-11-16 17:00:14 +010040#include <proto/connection.h>
William Lallemand9ed62032016-11-21 17:49:11 +010041#include <proto/stats.h>
Thierry FOURNIER9a819e72015-02-16 20:22:55 +010042#include <proto/hdr_idx.h>
Thierry FOURNIERa097fdf2015-03-03 15:17:35 +010043#include <proto/hlua.h>
Thierry Fournierfb0b5462016-01-21 09:28:58 +010044#include <proto/hlua_fcn.h>
Thierry FOURNIER3def3932015-04-07 11:27:54 +020045#include <proto/map.h>
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +010046#include <proto/obj_type.h>
Patrick Hemmer268a7072018-05-11 12:52:31 -040047#include <proto/queue.h>
Thierry FOURNIER83758bb2015-02-04 13:21:04 +010048#include <proto/pattern.h>
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +010049#include <proto/payload.h>
50#include <proto/proto_http.h>
51#include <proto/sample.h>
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +010052#include <proto/server.h>
Willy Tarreaufeb76402015-04-03 14:10:06 +020053#include <proto/session.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020054#include <proto/stream.h>
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +010055#include <proto/stream_interface.h>
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +010056#include <proto/task.h>
Willy Tarreau39713102016-11-25 15:49:32 +010057#include <proto/tcp_rules.h>
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +020058#include <proto/vars.h>
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +010059
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +010060/* Lua uses longjmp to perform yield or throwing errors. This
61 * macro is used only for identifying the function that can
62 * not return because a longjmp is executed.
63 * __LJMP marks a prototype of hlua file that can use longjmp.
64 * WILL_LJMP() marks an lua function that will use longjmp.
65 * MAY_LJMP() marks an lua function that may use longjmp.
66 */
67#define __LJMP
68#define WILL_LJMP(func) func
69#define MAY_LJMP(func) func
70
Thierry FOURNIERbabae282015-09-17 11:36:37 +020071/* This couple of function executes securely some Lua calls outside of
72 * the lua runtime environment. Each Lua call can return a longjmp
73 * if it encounter a memory error.
74 *
75 * Lua documentation extract:
76 *
77 * If an error happens outside any protected environment, Lua calls
78 * a panic function (see lua_atpanic) and then calls abort, thus
79 * exiting the host application. Your panic function can avoid this
80 * exit by never returning (e.g., doing a long jump to your own
81 * recovery point outside Lua).
82 *
83 * The panic function runs as if it were a message handler (see
84 * §2.3); in particular, the error message is at the top of the
85 * stack. However, there is no guarantee about stack space. To push
86 * anything on the stack, the panic function must first check the
87 * available space (see §4.2).
88 *
89 * We must check all the Lua entry point. This includes:
90 * - The include/proto/hlua.h exported functions
91 * - the task wrapper function
92 * - The action wrapper function
93 * - The converters wrapper function
94 * - The sample-fetch wrapper functions
95 *
96 * It is tolerated that the initilisation function returns an abort.
97 * Before each Lua abort, an error message is writed on stderr.
98 *
99 * The macro SET_SAFE_LJMP initialise the longjmp. The Macro
100 * RESET_SAFE_LJMP reset the longjmp. These function must be macro
101 * because they must be exists in the program stack when the longjmp
102 * is called.
Thierry FOURNIER61ba0e22017-07-12 11:41:21 +0200103 *
104 * Note that the Lua processing is not really thread safe. It provides
105 * heavy system which consists to add our own lock function in the Lua
106 * code and recompile the library. This system will probably not accepted
107 * by maintainers of various distribs.
108 *
109 * Our main excution point of the Lua is the function lua_resume(). A
110 * quick looking on the Lua sources displays a lua_lock() a the start
111 * of function and a lua_unlock() at the end of the function. So I
112 * conclude that the Lua thread safe mode just perform a mutex around
113 * all execution. So I prefer to do this in the HAProxy code, it will be
114 * easier for distro maintainers.
115 *
116 * Note that the HAProxy lua functions rounded by the macro SET_SAFE_LJMP
117 * and RESET_SAFE_LJMP manipulates the Lua stack, so it will be careful
118 * to set mutex around these functions.
Thierry FOURNIERbabae282015-09-17 11:36:37 +0200119 */
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100120__decl_hathreads(HA_SPINLOCK_T hlua_global_lock);
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; \
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100128 HA_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; \
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100132 HA_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); \
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100146 HA_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
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100157/* The main Lua execution context. */
158struct hlua gL;
159
Thierry FOURNIERebed6e92016-12-16 11:54:07 +0100160/* This is the memory pool containing struct lua for applets
161 * (including cli).
162 */
Willy Tarreaubafbe012017-11-24 17:34:44 +0100163struct pool_head *pool_head_hlua;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +0100164
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +0100165/* Used for Socket connection. */
166static struct proxy socket_proxy;
167static struct server socket_tcp;
168#ifdef USE_OPENSSL
169static struct server socket_ssl;
170#endif
171
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +0100172/* List head of the function called at the initialisation time. */
173struct list hlua_init_functions = LIST_HEAD_INIT(hlua_init_functions);
174
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +0100175/* The following variables contains the reference of the different
176 * Lua classes. These references are useful for identify metadata
177 * associated with an object.
178 */
Thierry FOURNIER65f34c62015-02-16 20:11:43 +0100179static int class_txn_ref;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +0100180static int class_socket_ref;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +0100181static int class_channel_ref;
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +0100182static int class_fetches_ref;
Thierry FOURNIER594afe72015-03-10 23:58:30 +0100183static int class_converters_ref;
Thierry FOURNIER08504f42015-03-16 14:17:08 +0100184static int class_http_ref;
Thierry FOURNIER3def3932015-04-07 11:27:54 +0200185static int class_map_ref;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +0200186static int class_applet_tcp_ref;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +0200187static int class_applet_http_ref;
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +0100188
Thierry FOURNIERbd413492015-03-03 16:52:26 +0100189/* Global Lua execution timeout. By default Lua, execution linked
Willy Tarreau87b09662015-04-03 00:22:06 +0200190 * with stream (actions, sample-fetches and converters) have a
Thierry FOURNIERbd413492015-03-03 16:52:26 +0100191 * short timeout. Lua linked with tasks doesn't have a timeout
192 * because a task may remain alive during all the haproxy execution.
193 */
194static unsigned int hlua_timeout_session = 4000; /* session timeout. */
195static unsigned int hlua_timeout_task = TICK_ETERNITY; /* task timeout. */
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +0200196static unsigned int hlua_timeout_applet = 4000; /* applet timeout. */
Thierry FOURNIERbd413492015-03-03 16:52:26 +0100197
Thierry FOURNIERee9f8022015-03-03 17:37:37 +0100198/* Interrupts the Lua processing each "hlua_nb_instruction" instructions.
199 * it is used for preventing infinite loops.
200 *
201 * I test the scheer with an infinite loop containing one incrementation
202 * and one test. I run this loop between 10 seconds, I raise a ceil of
203 * 710M loops from one interrupt each 9000 instructions, so I fix the value
204 * to one interrupt each 10 000 instructions.
205 *
206 * configured | Number of
207 * instructions | loops executed
208 * between two | in milions
209 * forced yields |
210 * ---------------+---------------
211 * 10 | 160
212 * 500 | 670
213 * 1000 | 680
214 * 5000 | 700
215 * 7000 | 700
216 * 8000 | 700
217 * 9000 | 710 <- ceil
218 * 10000 | 710
219 * 100000 | 710
220 * 1000000 | 710
221 *
222 */
223static unsigned int hlua_nb_instruction = 10000;
224
Willy Tarreau32f61e22015-03-18 17:54:59 +0100225/* Descriptor for the memory allocation state. If limit is not null, it will
226 * be enforced on any memory allocation.
227 */
228struct hlua_mem_allocator {
229 size_t allocated;
230 size_t limit;
231};
232
233static struct hlua_mem_allocator hlua_global_allocator;
234
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +0200235static const char error_500[] =
Jarno Huuskonen16ad94a2017-01-09 14:17:10 +0200236 "HTTP/1.0 500 Internal Server Error\r\n"
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +0200237 "Cache-Control: no-cache\r\n"
238 "Connection: close\r\n"
239 "Content-Type: text/html\r\n"
240 "\r\n"
Jarno Huuskonen16ad94a2017-01-09 14:17:10 +0200241 "<html><body><h1>500 Internal Server Error</h1>\nAn internal server error occured.\n</body></html>\n";
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +0200242
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100243/* These functions converts types between HAProxy internal args or
244 * sample and LUA types. Another function permits to check if the
245 * LUA stack contains arguments according with an required ARG_T
246 * format.
247 */
248static int hlua_arg2lua(lua_State *L, const struct arg *arg);
249static int hlua_lua2arg(lua_State *L, int ud, struct arg *arg);
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100250__LJMP static int hlua_lua2arg_check(lua_State *L, int first, struct arg *argp,
David Carlier0c437f42016-04-27 16:21:56 +0100251 uint64_t mask, struct proxy *p);
Willy Tarreau5eadada2015-03-10 17:28:54 +0100252static int hlua_smp2lua(lua_State *L, struct sample *smp);
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100253static int hlua_smp2lua_str(lua_State *L, struct sample *smp);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100254static int hlua_lua2smp(lua_State *L, int ud, struct sample *smp);
255
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +0200256__LJMP static int hlua_http_get_headers(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg);
257
Thierry FOURNIER23bc3752015-09-11 19:15:43 +0200258#define SEND_ERR(__be, __fmt, __args...) \
259 do { \
260 send_log(__be, LOG_ERR, __fmt, ## __args); \
261 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) \
Christopher Faulet767a84b2017-11-24 16:50:31 +0100262 ha_alert(__fmt, ## __args); \
Thierry FOURNIER23bc3752015-09-11 19:15:43 +0200263 } while (0)
264
Thierry FOURNIERe8b9a402015-02-25 18:48:12 +0100265/* Used to check an Lua function type in the stack. It creates and
266 * returns a reference of the function. This function throws an
267 * error if the rgument is not a "function".
268 */
269__LJMP unsigned int hlua_checkfunction(lua_State *L, int argno)
270{
271 if (!lua_isfunction(L, argno)) {
Thierry FOURNIERfd1e9552018-02-23 18:41:18 +0100272 const char *msg = lua_pushfstring(L, "function expected, got %s", luaL_typename(L, argno));
Thierry FOURNIERe8b9a402015-02-25 18:48:12 +0100273 WILL_LJMP(luaL_argerror(L, argno, msg));
274 }
275 lua_pushvalue(L, argno);
276 return luaL_ref(L, LUA_REGISTRYINDEX);
277}
278
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +0200279/* Return the string that is of the top of the stack. */
280const char *hlua_get_top_error_string(lua_State *L)
281{
282 if (lua_gettop(L) < 1)
283 return "unknown error";
284 if (lua_type(L, -1) != LUA_TSTRING)
285 return "unknown error";
286 return lua_tostring(L, -1);
287}
288
Thierry FOURNIERfc044c92018-06-07 14:40:48 +0200289__LJMP static const char *hlua_traceback(lua_State *L)
290{
291 lua_Debug ar;
292 int level = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +0200293 struct buffer *msg = get_trash_chunk();
Thierry FOURNIERfc044c92018-06-07 14:40:48 +0200294 int filled = 0;
295
296 while (lua_getstack(L, level++, &ar)) {
297
298 /* Add separator */
299 if (filled)
300 chunk_appendf(msg, ", ");
301 filled = 1;
302
303 /* Fill fields:
304 * 'S': fills in the fields source, short_src, linedefined, lastlinedefined, and what;
305 * 'l': fills in the field currentline;
306 * 'n': fills in the field name and namewhat;
307 * 't': fills in the field istailcall;
308 */
309 lua_getinfo(L, "Slnt", &ar);
310
311 /* Append code localisation */
312 if (ar.currentline > 0)
313 chunk_appendf(msg, "%s:%d ", ar.short_src, ar.currentline);
314 else
315 chunk_appendf(msg, "%s ", ar.short_src);
316
317 /*
318 * Get function name
319 *
320 * if namewhat is no empty, name is defined.
321 * what contains "Lua" for Lua function, "C" for C function,
322 * or "main" for main code.
323 */
324 if (*ar.namewhat != '\0' && ar.name != NULL) /* is there a name from code? */
325 chunk_appendf(msg, "%s '%s'", ar.namewhat, ar.name); /* use it */
326
327 else if (*ar.what == 'm') /* "main", the code is not executed in a function */
328 chunk_appendf(msg, "main chunk");
329
330 else if (*ar.what != 'C') /* for Lua functions, use <file:line> */
331 chunk_appendf(msg, "C function line %d", ar.linedefined);
332
333 else /* nothing left... */
334 chunk_appendf(msg, "?");
335
336
337 /* Display tailed call */
338 if (ar.istailcall)
339 chunk_appendf(msg, " ...");
340 }
341
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200342 return msg->area;
Thierry FOURNIERfc044c92018-06-07 14:40:48 +0200343}
344
345
Thierry FOURNIERe8b9a402015-02-25 18:48:12 +0100346/* This function check the number of arguments available in the
347 * stack. If the number of arguments available is not the same
348 * then <nb> an error is throwed.
349 */
350__LJMP static inline void check_args(lua_State *L, int nb, char *fcn)
351{
352 if (lua_gettop(L) == nb)
353 return;
354 WILL_LJMP(luaL_error(L, "'%s' needs %d arguments", fcn, nb));
355}
356
Mark Lakes22154b42018-01-29 14:38:40 -0800357/* This function pushes an error string prefixed by the file name
Thierry FOURNIERe8b9a402015-02-25 18:48:12 +0100358 * and the line number where the error is encountered.
359 */
360static int hlua_pusherror(lua_State *L, const char *fmt, ...)
361{
362 va_list argp;
363 va_start(argp, fmt);
364 luaL_where(L, 1);
365 lua_pushvfstring(L, fmt, argp);
366 va_end(argp);
367 lua_concat(L, 2);
368 return 1;
369}
370
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100371/* This functions is used with sample fetch and converters. It
372 * converts the HAProxy configuration argument in a lua stack
373 * values.
374 *
375 * It takes an array of "arg", and each entry of the array is
376 * converted and pushed in the LUA stack.
377 */
378static int hlua_arg2lua(lua_State *L, const struct arg *arg)
379{
380 switch (arg->type) {
381 case ARGT_SINT:
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100382 case ARGT_TIME:
383 case ARGT_SIZE:
Thierry FOURNIERf90838b2015-03-06 13:48:32 +0100384 lua_pushinteger(L, arg->data.sint);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100385 break;
386
387 case ARGT_STR:
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200388 lua_pushlstring(L, arg->data.str.area, arg->data.str.data);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100389 break;
390
391 case ARGT_IPV4:
392 case ARGT_IPV6:
393 case ARGT_MSK4:
394 case ARGT_MSK6:
395 case ARGT_FE:
396 case ARGT_BE:
397 case ARGT_TAB:
398 case ARGT_SRV:
399 case ARGT_USR:
400 case ARGT_MAP:
401 default:
402 lua_pushnil(L);
403 break;
404 }
405 return 1;
406}
407
408/* This function take one entrie in an LUA stack at the index "ud",
409 * and try to convert it in an HAProxy argument entry. This is useful
410 * with sample fetch wrappers. The input arguments are gived to the
411 * lua wrapper and converted as arg list by thi function.
412 */
413static int hlua_lua2arg(lua_State *L, int ud, struct arg *arg)
414{
415 switch (lua_type(L, ud)) {
416
417 case LUA_TNUMBER:
418 case LUA_TBOOLEAN:
419 arg->type = ARGT_SINT;
420 arg->data.sint = lua_tointeger(L, ud);
421 break;
422
423 case LUA_TSTRING:
424 arg->type = ARGT_STR;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200425 arg->data.str.area = (char *)lua_tolstring(L, ud, (size_t *)&arg->data.str.data);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100426 break;
427
428 case LUA_TUSERDATA:
429 case LUA_TNIL:
430 case LUA_TTABLE:
431 case LUA_TFUNCTION:
432 case LUA_TTHREAD:
433 case LUA_TLIGHTUSERDATA:
434 arg->type = ARGT_SINT;
Thierry FOURNIERbf65cd42015-07-20 17:45:02 +0200435 arg->data.sint = 0;
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100436 break;
437 }
438 return 1;
439}
440
441/* the following functions are used to convert a struct sample
442 * in Lua type. This useful to convert the return of the
443 * fetchs or converters.
444 */
Willy Tarreau5eadada2015-03-10 17:28:54 +0100445static int hlua_smp2lua(lua_State *L, struct sample *smp)
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100446{
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200447 switch (smp->data.type) {
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100448 case SMP_T_SINT:
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100449 case SMP_T_BOOL:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200450 lua_pushinteger(L, smp->data.u.sint);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100451 break;
452
453 case SMP_T_BIN:
454 case SMP_T_STR:
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200455 lua_pushlstring(L, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100456 break;
457
458 case SMP_T_METH:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200459 switch (smp->data.u.meth.meth) {
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100460 case HTTP_METH_OPTIONS: lua_pushstring(L, "OPTIONS"); break;
461 case HTTP_METH_GET: lua_pushstring(L, "GET"); break;
462 case HTTP_METH_HEAD: lua_pushstring(L, "HEAD"); break;
463 case HTTP_METH_POST: lua_pushstring(L, "POST"); break;
464 case HTTP_METH_PUT: lua_pushstring(L, "PUT"); break;
465 case HTTP_METH_DELETE: lua_pushstring(L, "DELETE"); break;
466 case HTTP_METH_TRACE: lua_pushstring(L, "TRACE"); break;
467 case HTTP_METH_CONNECT: lua_pushstring(L, "CONNECT"); break;
468 case HTTP_METH_OTHER:
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200469 lua_pushlstring(L, smp->data.u.meth.str.area, smp->data.u.meth.str.data);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100470 break;
471 default:
472 lua_pushnil(L);
473 break;
474 }
475 break;
476
477 case SMP_T_IPV4:
478 case SMP_T_IPV6:
479 case SMP_T_ADDR: /* This type is never used to qualify a sample. */
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200480 if (sample_casts[smp->data.type][SMP_T_STR] &&
481 sample_casts[smp->data.type][SMP_T_STR](smp))
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200482 lua_pushlstring(L, smp->data.u.str.area, smp->data.u.str.data);
Willy Tarreau5eadada2015-03-10 17:28:54 +0100483 else
484 lua_pushnil(L);
485 break;
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100486 default:
487 lua_pushnil(L);
488 break;
489 }
490 return 1;
491}
492
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100493/* the following functions are used to convert a struct sample
494 * in Lua strings. This is useful to convert the return of the
495 * fetchs or converters.
496 */
497static int hlua_smp2lua_str(lua_State *L, struct sample *smp)
498{
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200499 switch (smp->data.type) {
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100500
501 case SMP_T_BIN:
502 case SMP_T_STR:
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200503 lua_pushlstring(L, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100504 break;
505
506 case SMP_T_METH:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200507 switch (smp->data.u.meth.meth) {
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100508 case HTTP_METH_OPTIONS: lua_pushstring(L, "OPTIONS"); break;
509 case HTTP_METH_GET: lua_pushstring(L, "GET"); break;
510 case HTTP_METH_HEAD: lua_pushstring(L, "HEAD"); break;
511 case HTTP_METH_POST: lua_pushstring(L, "POST"); break;
512 case HTTP_METH_PUT: lua_pushstring(L, "PUT"); break;
513 case HTTP_METH_DELETE: lua_pushstring(L, "DELETE"); break;
514 case HTTP_METH_TRACE: lua_pushstring(L, "TRACE"); break;
515 case HTTP_METH_CONNECT: lua_pushstring(L, "CONNECT"); break;
516 case HTTP_METH_OTHER:
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200517 lua_pushlstring(L, smp->data.u.meth.str.area, smp->data.u.meth.str.data);
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100518 break;
519 default:
520 lua_pushstring(L, "");
521 break;
522 }
523 break;
524
525 case SMP_T_SINT:
526 case SMP_T_BOOL:
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100527 case SMP_T_IPV4:
528 case SMP_T_IPV6:
529 case SMP_T_ADDR: /* This type is never used to qualify a sample. */
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200530 if (sample_casts[smp->data.type][SMP_T_STR] &&
531 sample_casts[smp->data.type][SMP_T_STR](smp))
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200532 lua_pushlstring(L, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100533 else
534 lua_pushstring(L, "");
535 break;
536 default:
537 lua_pushstring(L, "");
538 break;
539 }
540 return 1;
541}
542
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100543/* the following functions are used to convert an Lua type in a
544 * struct sample. This is useful to provide data from a converter
545 * to the LUA code.
546 */
547static int hlua_lua2smp(lua_State *L, int ud, struct sample *smp)
548{
549 switch (lua_type(L, ud)) {
550
551 case LUA_TNUMBER:
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200552 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200553 smp->data.u.sint = lua_tointeger(L, ud);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100554 break;
555
556
557 case LUA_TBOOLEAN:
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200558 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200559 smp->data.u.sint = lua_toboolean(L, ud);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100560 break;
561
562 case LUA_TSTRING:
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200563 smp->data.type = SMP_T_STR;
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100564 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200565 smp->data.u.str.area = (char *)lua_tolstring(L, ud, (size_t *)&smp->data.u.str.data);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100566 break;
567
568 case LUA_TUSERDATA:
569 case LUA_TNIL:
570 case LUA_TTABLE:
571 case LUA_TFUNCTION:
572 case LUA_TTHREAD:
573 case LUA_TLIGHTUSERDATA:
Thierry FOURNIER93405e12015-08-26 14:19:03 +0200574 case LUA_TNONE:
575 default:
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200576 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200577 smp->data.u.sint = 0;
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100578 break;
579 }
580 return 1;
581}
582
583/* This function check the "argp" builded by another conversion function
584 * is in accord with the expected argp defined by the "mask". The fucntion
585 * returns true or false. It can be adjust the types if there compatibles.
Thierry FOURNIER3caa0392015-03-13 13:38:17 +0100586 *
587 * This function assumes thant the argp argument contains ARGM_NBARGS + 1
588 * entries.
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100589 */
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100590__LJMP int hlua_lua2arg_check(lua_State *L, int first, struct arg *argp,
David Carlier0c437f42016-04-27 16:21:56 +0100591 uint64_t mask, struct proxy *p)
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100592{
593 int min_arg;
594 int idx;
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100595 struct proxy *px;
596 char *sname, *pname;
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100597
598 idx = 0;
599 min_arg = ARGM(mask);
600 mask >>= ARGM_BITS;
601
602 while (1) {
603
604 /* Check oversize. */
605 if (idx >= ARGM_NBARGS && argp[idx].type != ARGT_STOP) {
Cyril Bonté577a36a2015-03-02 00:08:38 +0100606 WILL_LJMP(luaL_argerror(L, first + idx, "Malformed argument mask"));
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100607 }
608
609 /* Check for mandatory arguments. */
610 if (argp[idx].type == ARGT_STOP) {
Thierry FOURNIER3caa0392015-03-13 13:38:17 +0100611 if (idx < min_arg) {
612
613 /* If miss other argument than the first one, we return an error. */
614 if (idx > 0)
615 WILL_LJMP(luaL_argerror(L, first + idx, "Mandatory argument expected"));
616
617 /* If first argument have a certain type, some default values
618 * may be used. See the function smp_resolve_args().
619 */
620 switch (mask & ARGT_MASK) {
621
622 case ARGT_FE:
623 if (!(p->cap & PR_CAP_FE))
624 WILL_LJMP(luaL_argerror(L, first + idx, "Mandatory argument expected"));
625 argp[idx].data.prx = p;
626 argp[idx].type = ARGT_FE;
627 argp[idx+1].type = ARGT_STOP;
628 break;
629
630 case ARGT_BE:
631 if (!(p->cap & PR_CAP_BE))
632 WILL_LJMP(luaL_argerror(L, first + idx, "Mandatory argument expected"));
633 argp[idx].data.prx = p;
634 argp[idx].type = ARGT_BE;
635 argp[idx+1].type = ARGT_STOP;
636 break;
637
638 case ARGT_TAB:
639 argp[idx].data.prx = p;
640 argp[idx].type = ARGT_TAB;
641 argp[idx+1].type = ARGT_STOP;
642 break;
643
644 default:
645 WILL_LJMP(luaL_argerror(L, first + idx, "Mandatory argument expected"));
646 break;
647 }
648 }
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100649 return 0;
650 }
651
652 /* Check for exceed the number of requiered argument. */
653 if ((mask & ARGT_MASK) == ARGT_STOP &&
654 argp[idx].type != ARGT_STOP) {
655 WILL_LJMP(luaL_argerror(L, first + idx, "Last argument expected"));
656 }
657
658 if ((mask & ARGT_MASK) == ARGT_STOP &&
659 argp[idx].type == ARGT_STOP) {
660 return 0;
661 }
662
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100663 /* Convert some argument types. */
664 switch (mask & ARGT_MASK) {
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100665 case ARGT_SINT:
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100666 if (argp[idx].type != ARGT_SINT)
667 WILL_LJMP(luaL_argerror(L, first + idx, "integer expected"));
668 argp[idx].type = ARGT_SINT;
669 break;
670
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100671 case ARGT_TIME:
672 if (argp[idx].type != ARGT_SINT)
673 WILL_LJMP(luaL_argerror(L, first + idx, "integer expected"));
Thierry FOURNIER29176f32015-07-07 00:41:29 +0200674 argp[idx].type = ARGT_TIME;
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100675 break;
676
677 case ARGT_SIZE:
678 if (argp[idx].type != ARGT_SINT)
679 WILL_LJMP(luaL_argerror(L, first + idx, "integer expected"));
Thierry FOURNIER29176f32015-07-07 00:41:29 +0200680 argp[idx].type = ARGT_SIZE;
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100681 break;
682
683 case ARGT_FE:
684 if (argp[idx].type != ARGT_STR)
685 WILL_LJMP(luaL_argerror(L, first + idx, "string expected"));
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200686 memcpy(trash.area, argp[idx].data.str.area,
687 argp[idx].data.str.data);
688 trash.area[argp[idx].data.str.data] = 0;
689 argp[idx].data.prx = proxy_fe_by_name(trash.area);
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100690 if (!argp[idx].data.prx)
691 WILL_LJMP(luaL_argerror(L, first + idx, "frontend doesn't exist"));
692 argp[idx].type = ARGT_FE;
693 break;
694
695 case ARGT_BE:
696 if (argp[idx].type != ARGT_STR)
697 WILL_LJMP(luaL_argerror(L, first + idx, "string expected"));
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200698 memcpy(trash.area, argp[idx].data.str.area,
699 argp[idx].data.str.data);
700 trash.area[argp[idx].data.str.data] = 0;
701 argp[idx].data.prx = proxy_be_by_name(trash.area);
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100702 if (!argp[idx].data.prx)
703 WILL_LJMP(luaL_argerror(L, first + idx, "backend doesn't exist"));
704 argp[idx].type = ARGT_BE;
705 break;
706
707 case ARGT_TAB:
708 if (argp[idx].type != ARGT_STR)
709 WILL_LJMP(luaL_argerror(L, first + idx, "string expected"));
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200710 memcpy(trash.area, argp[idx].data.str.area,
711 argp[idx].data.str.data);
712 trash.area[argp[idx].data.str.data] = 0;
713 argp[idx].data.prx = proxy_tbl_by_name(trash.area);
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100714 if (!argp[idx].data.prx)
715 WILL_LJMP(luaL_argerror(L, first + idx, "table doesn't exist"));
716 argp[idx].type = ARGT_TAB;
717 break;
718
719 case ARGT_SRV:
720 if (argp[idx].type != ARGT_STR)
721 WILL_LJMP(luaL_argerror(L, first + idx, "string expected"));
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200722 memcpy(trash.area, argp[idx].data.str.area,
723 argp[idx].data.str.data);
724 trash.area[argp[idx].data.str.data] = 0;
725 sname = strrchr(trash.area, '/');
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100726 if (sname) {
727 *sname++ = '\0';
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200728 pname = trash.area;
Willy Tarreau9e0bb102015-05-26 11:24:42 +0200729 px = proxy_be_by_name(pname);
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100730 if (!px)
731 WILL_LJMP(luaL_argerror(L, first + idx, "backend doesn't exist"));
732 }
733 else {
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200734 sname = trash.area;
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100735 px = p;
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100736 }
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100737 argp[idx].data.srv = findserver(px, sname);
738 if (!argp[idx].data.srv)
739 WILL_LJMP(luaL_argerror(L, first + idx, "server doesn't exist"));
740 argp[idx].type = ARGT_SRV;
741 break;
742
743 case ARGT_IPV4:
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200744 memcpy(trash.area, argp[idx].data.str.area,
745 argp[idx].data.str.data);
746 trash.area[argp[idx].data.str.data] = 0;
747 if (inet_pton(AF_INET, trash.area, &argp[idx].data.ipv4))
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100748 WILL_LJMP(luaL_argerror(L, first + idx, "invalid IPv4 address"));
749 argp[idx].type = ARGT_IPV4;
750 break;
751
752 case ARGT_MSK4:
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200753 memcpy(trash.area, argp[idx].data.str.area,
754 argp[idx].data.str.data);
755 trash.area[argp[idx].data.str.data] = 0;
756 if (!str2mask(trash.area, &argp[idx].data.ipv4))
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100757 WILL_LJMP(luaL_argerror(L, first + idx, "invalid IPv4 mask"));
758 argp[idx].type = ARGT_MSK4;
759 break;
760
761 case ARGT_IPV6:
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200762 memcpy(trash.area, argp[idx].data.str.area,
763 argp[idx].data.str.data);
764 trash.area[argp[idx].data.str.data] = 0;
765 if (inet_pton(AF_INET6, trash.area, &argp[idx].data.ipv6))
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100766 WILL_LJMP(luaL_argerror(L, first + idx, "invalid IPv6 address"));
767 argp[idx].type = ARGT_IPV6;
768 break;
769
770 case ARGT_MSK6:
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200771 memcpy(trash.area, argp[idx].data.str.area,
772 argp[idx].data.str.data);
773 trash.area[argp[idx].data.str.data] = 0;
774 if (!str2mask6(trash.area, &argp[idx].data.ipv6))
Tim Duesterhusb814da62018-01-25 16:24:50 +0100775 WILL_LJMP(luaL_argerror(L, first + idx, "invalid IPv6 mask"));
776 argp[idx].type = ARGT_MSK6;
777 break;
778
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100779 case ARGT_MAP:
780 case ARGT_REG:
781 case ARGT_USR:
782 WILL_LJMP(luaL_argerror(L, first + idx, "type not yet supported"));
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100783 break;
784 }
785
786 /* Check for type of argument. */
787 if ((mask & ARGT_MASK) != argp[idx].type) {
788 const char *msg = lua_pushfstring(L, "'%s' expected, got '%s'",
789 arg_type_names[(mask & ARGT_MASK)],
790 arg_type_names[argp[idx].type & ARGT_MASK]);
791 WILL_LJMP(luaL_argerror(L, first + idx, msg));
792 }
793
794 /* Next argument. */
795 mask >>= ARGT_BITS;
796 idx++;
797 }
798}
799
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100800/*
801 * The following functions are used to make correspondance between the the
802 * executed lua pointer and the "struct hlua *" that contain the context.
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100803 *
804 * - hlua_gethlua : return the hlua context associated with an lua_State.
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100805 * - hlua_sethlua : create the association between hlua context and lua_state.
806 */
807static inline struct hlua *hlua_gethlua(lua_State *L)
808{
Thierry FOURNIER38c5fd62015-03-10 02:40:29 +0100809 struct hlua **hlua = lua_getextraspace(L);
810 return *hlua;
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100811}
812static inline void hlua_sethlua(struct hlua *hlua)
813{
Thierry FOURNIER38c5fd62015-03-10 02:40:29 +0100814 struct hlua **hlua_store = lua_getextraspace(hlua->T);
815 *hlua_store = hlua;
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100816}
817
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +0100818/* This function is used to send logs. It try to send on screen (stderr)
819 * and on the default syslog server.
820 */
821static inline void hlua_sendlog(struct proxy *px, int level, const char *msg)
822{
823 struct tm tm;
824 char *p;
825
826 /* Cleanup the log message. */
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200827 p = trash.area;
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +0100828 for (; *msg != '\0'; msg++, p++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200829 if (p >= trash.area + trash.size - 1) {
Thierry FOURNIERccf00632015-09-16 12:47:03 +0200830 /* Break the message if exceed the buffer size. */
831 *(p-4) = ' ';
832 *(p-3) = '.';
833 *(p-2) = '.';
834 *(p-1) = '.';
835 break;
836 }
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +0100837 if (isprint(*msg))
838 *p = *msg;
839 else
840 *p = '.';
841 }
842 *p = '\0';
843
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200844 send_log(px, level, "%s\n", trash.area);
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +0100845 if (!(global.mode & MODE_QUIET) || (global.mode & (MODE_VERBOSE | MODE_STARTING))) {
Willy Tarreaua678b432015-08-28 10:14:59 +0200846 get_localtime(date.tv_sec, &tm);
847 fprintf(stderr, "[%s] %03d/%02d%02d%02d (%d) : %s\n",
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +0100848 log_levels[level], tm.tm_yday, tm.tm_hour, tm.tm_min, tm.tm_sec,
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200849 (int)getpid(), trash.area);
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +0100850 fflush(stderr);
851 }
852}
853
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +0100854/* This function just ensure that the yield will be always
855 * returned with a timeout and permit to set some flags
856 */
857__LJMP void hlua_yieldk(lua_State *L, int nresults, int ctx,
Thierry FOURNIERf90838b2015-03-06 13:48:32 +0100858 lua_KFunction k, int timeout, unsigned int flags)
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +0100859{
860 struct hlua *hlua = hlua_gethlua(L);
861
862 /* Set the wake timeout. If timeout is required, we set
863 * the expiration time.
864 */
Thierry FOURNIER10770fa2015-09-29 01:59:42 +0200865 hlua->wake_time = timeout;
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +0100866
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +0100867 hlua->flags |= flags;
868
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +0100869 /* Process the yield. */
870 WILL_LJMP(lua_yieldk(L, nresults, ctx, k));
871}
872
Willy Tarreau87b09662015-04-03 00:22:06 +0200873/* This function initialises the Lua environment stored in the stream.
874 * It must be called at the start of the stream. This function creates
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100875 * an LUA coroutine. It can not be use to crete the main LUA context.
Thierry FOURNIERbabae282015-09-17 11:36:37 +0200876 *
877 * This function is particular. it initialises a new Lua thread. If the
878 * initialisation fails (example: out of memory error), the lua function
879 * throws an error (longjmp).
880 *
881 * This function manipulates two Lua stack: the main and the thread. Only
882 * the main stack can fail. The thread is not manipulated. This function
883 * MUST NOT manipulate the created thread stack state, because is not
884 * proctected agains error throwed by the thread stack.
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100885 */
886int hlua_ctx_init(struct hlua *lua, struct task *task)
887{
Thierry FOURNIERbabae282015-09-17 11:36:37 +0200888 if (!SET_SAFE_LJMP(gL.T)) {
889 lua->Tref = LUA_REFNIL;
890 return 0;
891 }
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100892 lua->Mref = LUA_REFNIL;
Thierry FOURNIERa097fdf2015-03-03 15:17:35 +0100893 lua->flags = 0;
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +0100894 LIST_INIT(&lua->com);
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100895 lua->T = lua_newthread(gL.T);
896 if (!lua->T) {
897 lua->Tref = LUA_REFNIL;
Thierry FOURNIER0a976202017-07-12 11:18:00 +0200898 RESET_SAFE_LJMP(gL.T);
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100899 return 0;
900 }
901 hlua_sethlua(lua);
902 lua->Tref = luaL_ref(gL.T, LUA_REGISTRYINDEX);
903 lua->task = task;
Thierry FOURNIERbabae282015-09-17 11:36:37 +0200904 RESET_SAFE_LJMP(gL.T);
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100905 return 1;
906}
907
Willy Tarreau87b09662015-04-03 00:22:06 +0200908/* Used to destroy the Lua coroutine when the attached stream or task
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100909 * is destroyed. The destroy also the memory context. The struct "lua"
910 * is not freed.
911 */
912void hlua_ctx_destroy(struct hlua *lua)
913{
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +0100914 if (!lua)
Thierry FOURNIERa718b292015-03-04 16:48:34 +0100915 return;
916
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +0100917 if (!lua->T)
918 goto end;
919
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +0100920 /* Purge all the pending signals. */
Thierry FOURNIERd6975962017-07-12 14:31:10 +0200921 notification_purge(&lua->com);
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +0100922
Thierry FOURNIER75d02082017-07-12 13:41:33 +0200923 if (!SET_SAFE_LJMP(lua->T))
924 return;
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100925 luaL_unref(lua->T, LUA_REGISTRYINDEX, lua->Mref);
Thierry FOURNIER75d02082017-07-12 13:41:33 +0200926 RESET_SAFE_LJMP(lua->T);
Thierry FOURNIER5a50a852015-09-23 16:59:28 +0200927
Thierry FOURNIER75d02082017-07-12 13:41:33 +0200928 if (!SET_SAFE_LJMP(gL.T))
929 return;
930 luaL_unref(gL.T, LUA_REGISTRYINDEX, lua->Tref);
931 RESET_SAFE_LJMP(gL.T);
Thierry FOURNIER5a50a852015-09-23 16:59:28 +0200932 /* Forces a garbage collecting process. If the Lua program is finished
933 * without error, we run the GC on the thread pointer. Its freed all
934 * the unused memory.
935 * If the thread is finnish with an error or is currently yielded,
936 * it seems that the GC applied on the thread doesn't clean anything,
937 * so e run the GC on the main thread.
938 * NOTE: maybe this action locks all the Lua threads untiml the en of
939 * the garbage collection.
940 */
Thierry FOURNIER7c39ab42015-09-27 22:53:33 +0200941 if (lua->flags & HLUA_MUST_GC) {
Thierry FOURNIER7bd10d52017-07-17 00:44:40 +0200942 if (!SET_SAFE_LJMP(gL.T))
Thierry FOURNIER75d02082017-07-12 13:41:33 +0200943 return;
Thierry FOURNIER7bd10d52017-07-17 00:44:40 +0200944 lua_gc(gL.T, LUA_GCCOLLECT, 0);
945 RESET_SAFE_LJMP(gL.T);
Thierry FOURNIER7c39ab42015-09-27 22:53:33 +0200946 }
Thierry FOURNIER5a50a852015-09-23 16:59:28 +0200947
Thierry FOURNIERa7b536b2015-09-21 22:50:24 +0200948 lua->T = NULL;
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +0100949
950end:
Willy Tarreaubafbe012017-11-24 17:34:44 +0100951 pool_free(pool_head_hlua, lua);
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100952}
953
954/* This function is used to restore the Lua context when a coroutine
955 * fails. This function copy the common memory between old coroutine
956 * and the new coroutine. The old coroutine is destroyed, and its
957 * replaced by the new coroutine.
958 * If the flag "keep_msg" is set, the last entry of the old is assumed
959 * as string error message and it is copied in the new stack.
960 */
961static int hlua_ctx_renew(struct hlua *lua, int keep_msg)
962{
963 lua_State *T;
964 int new_ref;
965
966 /* Renew the main LUA stack doesn't have sense. */
967 if (lua == &gL)
968 return 0;
969
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100970 /* New Lua coroutine. */
971 T = lua_newthread(gL.T);
972 if (!T)
973 return 0;
974
975 /* Copy last error message. */
976 if (keep_msg)
977 lua_xmove(lua->T, T, 1);
978
979 /* Copy data between the coroutines. */
980 lua_rawgeti(lua->T, LUA_REGISTRYINDEX, lua->Mref);
981 lua_xmove(lua->T, T, 1);
982 new_ref = luaL_ref(T, LUA_REGISTRYINDEX); /* Valur poped. */
983
984 /* Destroy old data. */
985 luaL_unref(lua->T, LUA_REGISTRYINDEX, lua->Mref);
986
987 /* The thread is garbage collected by Lua. */
988 luaL_unref(gL.T, LUA_REGISTRYINDEX, lua->Tref);
989
990 /* Fill the struct with the new coroutine values. */
991 lua->Mref = new_ref;
992 lua->T = T;
993 lua->Tref = luaL_ref(gL.T, LUA_REGISTRYINDEX);
994
995 /* Set context. */
996 hlua_sethlua(lua);
997
998 return 1;
999}
1000
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01001001void hlua_hook(lua_State *L, lua_Debug *ar)
1002{
Thierry FOURNIERcae49c92015-03-06 14:05:24 +01001003 struct hlua *hlua = hlua_gethlua(L);
1004
1005 /* Lua cannot yield when its returning from a function,
1006 * so, we can fix the interrupt hook to 1 instruction,
1007 * expecting that the function is finnished.
1008 */
1009 if (lua_gethookmask(L) & LUA_MASKRET) {
1010 lua_sethook(hlua->T, hlua_hook, LUA_MASKCOUNT, 1);
1011 return;
1012 }
1013
1014 /* restore the interrupt condition. */
1015 lua_sethook(hlua->T, hlua_hook, LUA_MASKCOUNT, hlua_nb_instruction);
1016
1017 /* If we interrupt the Lua processing in yieldable state, we yield.
1018 * If the state is not yieldable, trying yield causes an error.
1019 */
1020 if (lua_isyieldable(L))
1021 WILL_LJMP(hlua_yieldk(L, 0, 0, NULL, TICK_ETERNITY, HLUA_CTRLYIELD));
1022
Thierry FOURNIERa85cfb12015-03-13 14:50:06 +01001023 /* If we cannot yield, update the clock and check the timeout. */
1024 tv_update_date(0, 1);
Thierry FOURNIER10770fa2015-09-29 01:59:42 +02001025 hlua->run_time += now_ms - hlua->start_time;
1026 if (hlua->max_time && hlua->run_time >= hlua->max_time) {
Thierry FOURNIERcae49c92015-03-06 14:05:24 +01001027 lua_pushfstring(L, "execution timeout");
1028 WILL_LJMP(lua_error(L));
1029 }
1030
Thierry FOURNIER10770fa2015-09-29 01:59:42 +02001031 /* Update the start time. */
1032 hlua->start_time = now_ms;
1033
Thierry FOURNIERcae49c92015-03-06 14:05:24 +01001034 /* Try to interrupt the process at the end of the current
1035 * unyieldable function.
1036 */
1037 lua_sethook(hlua->T, hlua_hook, LUA_MASKRET|LUA_MASKCOUNT, hlua_nb_instruction);
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01001038}
1039
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001040/* This function start or resumes the Lua stack execution. If the flag
1041 * "yield_allowed" if no set and the LUA stack execution returns a yield
1042 * The function return an error.
1043 *
1044 * The function can returns 4 values:
1045 * - HLUA_E_OK : The execution is terminated without any errors.
1046 * - HLUA_E_AGAIN : The execution must continue at the next associated
1047 * task wakeup.
1048 * - HLUA_E_ERRMSG : An error has occured, an error message is set in
1049 * the top of the stack.
1050 * - HLUA_E_ERR : An error has occured without error message.
1051 *
1052 * If an error occured, the stack is renewed and it is ready to run new
1053 * LUA code.
1054 */
1055static enum hlua_exec hlua_ctx_resume(struct hlua *lua, int yield_allowed)
1056{
1057 int ret;
1058 const char *msg;
Thierry FOURNIERfc044c92018-06-07 14:40:48 +02001059 const char *trace;
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001060
Thierry FOURNIER10770fa2015-09-29 01:59:42 +02001061 /* Initialise run time counter. */
1062 if (!HLUA_IS_RUNNING(lua))
1063 lua->run_time = 0;
Thierry FOURNIERdc9ca962015-03-05 11:16:52 +01001064
Thierry FOURNIER61ba0e22017-07-12 11:41:21 +02001065 /* Lock the whole Lua execution. This lock must be before the
1066 * label "resume_execution".
1067 */
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001068 HA_SPIN_LOCK(LUA_LOCK, &hlua_global_lock);
Thierry FOURNIER61ba0e22017-07-12 11:41:21 +02001069
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01001070resume_execution:
1071
1072 /* This hook interrupts the Lua processing each 'hlua_nb_instruction'
1073 * instructions. it is used for preventing infinite loops.
1074 */
1075 lua_sethook(lua->T, hlua_hook, LUA_MASKCOUNT, hlua_nb_instruction);
1076
Thierry FOURNIER1bfc09b2015-03-05 17:10:14 +01001077 /* Remove all flags except the running flags. */
Thierry FOURNIER2f3867f2015-09-28 01:02:01 +02001078 HLUA_SET_RUN(lua);
1079 HLUA_CLR_CTRLYIELD(lua);
1080 HLUA_CLR_WAKERESWR(lua);
1081 HLUA_CLR_WAKEREQWR(lua);
Thierry FOURNIER1bfc09b2015-03-05 17:10:14 +01001082
Thierry FOURNIER10770fa2015-09-29 01:59:42 +02001083 /* Update the start time. */
1084 lua->start_time = now_ms;
1085
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001086 /* Call the function. */
1087 ret = lua_resume(lua->T, gL.T, lua->nargs);
1088 switch (ret) {
1089
1090 case LUA_OK:
1091 ret = HLUA_E_OK;
1092 break;
1093
1094 case LUA_YIELD:
Thierry FOURNIERdc9ca962015-03-05 11:16:52 +01001095 /* Check if the execution timeout is expired. It it is the case, we
1096 * break the Lua execution.
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01001097 */
Thierry FOURNIER10770fa2015-09-29 01:59:42 +02001098 tv_update_date(0, 1);
1099 lua->run_time += now_ms - lua->start_time;
1100 if (lua->max_time && lua->run_time > lua->max_time) {
Thierry FOURNIERdc9ca962015-03-05 11:16:52 +01001101 lua_settop(lua->T, 0); /* Empty the stack. */
Thierry Fournierd5b073c2018-05-21 19:42:47 +02001102 ret = HLUA_E_ETMOUT;
Thierry FOURNIERdc9ca962015-03-05 11:16:52 +01001103 break;
1104 }
1105 /* Process the forced yield. if the general yield is not allowed or
1106 * if no task were associated this the current Lua execution
1107 * coroutine, we resume the execution. Else we want to return in the
1108 * scheduler and we want to be waked up again, to continue the
1109 * current Lua execution. So we schedule our own task.
1110 */
1111 if (HLUA_IS_CTRLYIELDING(lua)) {
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01001112 if (!yield_allowed || !lua->task)
1113 goto resume_execution;
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01001114 task_wakeup(lua->task, TASK_WOKEN_MSG);
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01001115 }
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001116 if (!yield_allowed) {
1117 lua_settop(lua->T, 0); /* Empty the stack. */
Thierry Fournierd5b073c2018-05-21 19:42:47 +02001118 ret = HLUA_E_YIELD;
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001119 break;
1120 }
1121 ret = HLUA_E_AGAIN;
1122 break;
1123
1124 case LUA_ERRRUN:
Thierry FOURNIER0a99b892015-08-26 00:14:17 +02001125
1126 /* Special exit case. The traditionnal exit is returned as an error
1127 * because the errors ares the only one mean to return immediately
1128 * from and lua execution.
1129 */
1130 if (lua->flags & HLUA_EXIT) {
1131 ret = HLUA_E_OK;
Thierry FOURNIERe1587b32015-08-28 09:54:13 +02001132 hlua_ctx_renew(lua, 0);
Thierry FOURNIER0a99b892015-08-26 00:14:17 +02001133 break;
1134 }
1135
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01001136 lua->wake_time = TICK_ETERNITY;
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001137 if (!lua_checkstack(lua->T, 1)) {
1138 ret = HLUA_E_ERR;
1139 break;
1140 }
1141 msg = lua_tostring(lua->T, -1);
1142 lua_settop(lua->T, 0); /* Empty the stack. */
1143 lua_pop(lua->T, 1);
Thierry FOURNIERfc044c92018-06-07 14:40:48 +02001144 trace = hlua_traceback(lua->T);
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001145 if (msg)
Thierry FOURNIERfc044c92018-06-07 14:40:48 +02001146 lua_pushfstring(lua->T, "runtime error: %s from %s", msg, trace);
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001147 else
Thierry FOURNIERfc044c92018-06-07 14:40:48 +02001148 lua_pushfstring(lua->T, "unknown runtime error from %s", trace);
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001149 ret = HLUA_E_ERRMSG;
1150 break;
1151
1152 case LUA_ERRMEM:
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01001153 lua->wake_time = TICK_ETERNITY;
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001154 lua_settop(lua->T, 0); /* Empty the stack. */
Thierry Fournierd5b073c2018-05-21 19:42:47 +02001155 ret = HLUA_E_NOMEM;
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001156 break;
1157
1158 case LUA_ERRERR:
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01001159 lua->wake_time = TICK_ETERNITY;
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001160 if (!lua_checkstack(lua->T, 1)) {
1161 ret = HLUA_E_ERR;
1162 break;
1163 }
1164 msg = lua_tostring(lua->T, -1);
1165 lua_settop(lua->T, 0); /* Empty the stack. */
1166 lua_pop(lua->T, 1);
1167 if (msg)
1168 lua_pushfstring(lua->T, "message handler error: %s", msg);
1169 else
1170 lua_pushfstring(lua->T, "message handler error");
1171 ret = HLUA_E_ERRMSG;
1172 break;
1173
1174 default:
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01001175 lua->wake_time = TICK_ETERNITY;
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001176 lua_settop(lua->T, 0); /* Empty the stack. */
Thierry Fournierd5b073c2018-05-21 19:42:47 +02001177 ret = HLUA_E_ERR;
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001178 break;
1179 }
1180
Thierry FOURNIER6ab4d8e2015-09-27 22:17:19 +02001181 /* This GC permits to destroy some object when a Lua timeout strikes. */
Thierry FOURNIER7c39ab42015-09-27 22:53:33 +02001182 if (lua->flags & HLUA_MUST_GC &&
1183 ret != HLUA_E_AGAIN)
Thierry FOURNIER6ab4d8e2015-09-27 22:17:19 +02001184 lua_gc(lua->T, LUA_GCCOLLECT, 0);
1185
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001186 switch (ret) {
1187 case HLUA_E_AGAIN:
1188 break;
1189
1190 case HLUA_E_ERRMSG:
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001191 notification_purge(&lua->com);
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001192 hlua_ctx_renew(lua, 1);
Thierry FOURNIERa097fdf2015-03-03 15:17:35 +01001193 HLUA_CLR_RUN(lua);
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001194 break;
1195
Thierry Fournierd5b073c2018-05-21 19:42:47 +02001196 case HLUA_E_ETMOUT:
1197 case HLUA_E_NOMEM:
1198 case HLUA_E_YIELD:
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001199 case HLUA_E_ERR:
Thierry FOURNIERa097fdf2015-03-03 15:17:35 +01001200 HLUA_CLR_RUN(lua);
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001201 notification_purge(&lua->com);
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001202 hlua_ctx_renew(lua, 0);
1203 break;
1204
1205 case HLUA_E_OK:
Thierry FOURNIERa097fdf2015-03-03 15:17:35 +01001206 HLUA_CLR_RUN(lua);
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001207 notification_purge(&lua->com);
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001208 break;
1209 }
1210
Thierry FOURNIER61ba0e22017-07-12 11:41:21 +02001211 /* This is the main exit point, remove the Lua lock. */
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001212 HA_SPIN_UNLOCK(LUA_LOCK, &hlua_global_lock);
Thierry FOURNIER61ba0e22017-07-12 11:41:21 +02001213
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001214 return ret;
1215}
1216
Thierry FOURNIER0a99b892015-08-26 00:14:17 +02001217/* This function exit the current code. */
1218__LJMP static int hlua_done(lua_State *L)
1219{
1220 struct hlua *hlua = hlua_gethlua(L);
1221
1222 hlua->flags |= HLUA_EXIT;
1223 WILL_LJMP(lua_error(L));
1224
1225 return 0;
1226}
1227
Thierry FOURNIER83758bb2015-02-04 13:21:04 +01001228/* This function is an LUA binding. It provides a function
1229 * for deleting ACL from a referenced ACL file.
1230 */
1231__LJMP static int hlua_del_acl(lua_State *L)
1232{
1233 const char *name;
1234 const char *key;
1235 struct pat_ref *ref;
1236
1237 MAY_LJMP(check_args(L, 2, "del_acl"));
1238
1239 name = MAY_LJMP(luaL_checkstring(L, 1));
1240 key = MAY_LJMP(luaL_checkstring(L, 2));
1241
1242 ref = pat_ref_lookup(name);
1243 if (!ref)
Vincent Bernata72db182015-10-06 16:05:59 +02001244 WILL_LJMP(luaL_error(L, "'del_acl': unknown acl file '%s'", name));
Thierry FOURNIER83758bb2015-02-04 13:21:04 +01001245
1246 pat_ref_delete(ref, key);
1247 return 0;
1248}
1249
1250/* This function is an LUA binding. It provides a function
1251 * for deleting map entry from a referenced map file.
1252 */
1253static int hlua_del_map(lua_State *L)
1254{
1255 const char *name;
1256 const char *key;
1257 struct pat_ref *ref;
1258
1259 MAY_LJMP(check_args(L, 2, "del_map"));
1260
1261 name = MAY_LJMP(luaL_checkstring(L, 1));
1262 key = MAY_LJMP(luaL_checkstring(L, 2));
1263
1264 ref = pat_ref_lookup(name);
1265 if (!ref)
Vincent Bernata72db182015-10-06 16:05:59 +02001266 WILL_LJMP(luaL_error(L, "'del_map': unknown acl file '%s'", name));
Thierry FOURNIER83758bb2015-02-04 13:21:04 +01001267
1268 pat_ref_delete(ref, key);
1269 return 0;
1270}
1271
1272/* This function is an LUA binding. It provides a function
1273 * for adding ACL pattern from a referenced ACL file.
1274 */
1275static int hlua_add_acl(lua_State *L)
1276{
1277 const char *name;
1278 const char *key;
1279 struct pat_ref *ref;
1280
1281 MAY_LJMP(check_args(L, 2, "add_acl"));
1282
1283 name = MAY_LJMP(luaL_checkstring(L, 1));
1284 key = MAY_LJMP(luaL_checkstring(L, 2));
1285
1286 ref = pat_ref_lookup(name);
1287 if (!ref)
Vincent Bernata72db182015-10-06 16:05:59 +02001288 WILL_LJMP(luaL_error(L, "'add_acl': unknown acl file '%s'", name));
Thierry FOURNIER83758bb2015-02-04 13:21:04 +01001289
1290 if (pat_ref_find_elt(ref, key) == NULL)
1291 pat_ref_add(ref, key, NULL, NULL);
1292 return 0;
1293}
1294
1295/* This function is an LUA binding. It provides a function
1296 * for setting map pattern and sample from a referenced map
1297 * file.
1298 */
1299static int hlua_set_map(lua_State *L)
1300{
1301 const char *name;
1302 const char *key;
1303 const char *value;
1304 struct pat_ref *ref;
1305
1306 MAY_LJMP(check_args(L, 3, "set_map"));
1307
1308 name = MAY_LJMP(luaL_checkstring(L, 1));
1309 key = MAY_LJMP(luaL_checkstring(L, 2));
1310 value = MAY_LJMP(luaL_checkstring(L, 3));
1311
1312 ref = pat_ref_lookup(name);
1313 if (!ref)
Vincent Bernata72db182015-10-06 16:05:59 +02001314 WILL_LJMP(luaL_error(L, "'set_map': unknown map file '%s'", name));
Thierry FOURNIER83758bb2015-02-04 13:21:04 +01001315
1316 if (pat_ref_find_elt(ref, key) != NULL)
1317 pat_ref_set(ref, key, value, NULL);
1318 else
1319 pat_ref_add(ref, key, value, NULL);
1320 return 0;
1321}
1322
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01001323/* A class is a lot of memory that contain data. This data can be a table,
1324 * an integer or user data. This data is associated with a metatable. This
1325 * metatable have an original version registred in the global context with
1326 * the name of the object (_G[<name>] = <metable> ).
1327 *
1328 * A metable is a table that modify the standard behavior of a standard
1329 * access to the associated data. The entries of this new metatable are
1330 * defined as is:
1331 *
1332 * http://lua-users.org/wiki/MetatableEvents
1333 *
1334 * __index
1335 *
1336 * we access an absent field in a table, the result is nil. This is
1337 * true, but it is not the whole truth. Actually, such access triggers
1338 * the interpreter to look for an __index metamethod: If there is no
1339 * such method, as usually happens, then the access results in nil;
1340 * otherwise, the metamethod will provide the result.
1341 *
1342 * Control 'prototype' inheritance. When accessing "myTable[key]" and
1343 * the key does not appear in the table, but the metatable has an __index
1344 * property:
1345 *
1346 * - if the value is a function, the function is called, passing in the
1347 * table and the key; the return value of that function is returned as
1348 * the result.
1349 *
1350 * - if the value is another table, the value of the key in that table is
1351 * asked for and returned (and if it doesn't exist in that table, but that
1352 * table's metatable has an __index property, then it continues on up)
1353 *
1354 * - Use "rawget(myTable,key)" to skip this metamethod.
1355 *
1356 * http://www.lua.org/pil/13.4.1.html
1357 *
1358 * __newindex
1359 *
1360 * Like __index, but control property assignment.
1361 *
1362 * __mode - Control weak references. A string value with one or both
1363 * of the characters 'k' and 'v' which specifies that the the
1364 * keys and/or values in the table are weak references.
1365 *
1366 * __call - Treat a table like a function. When a table is followed by
1367 * parenthesis such as "myTable( 'foo' )" and the metatable has
1368 * a __call key pointing to a function, that function is invoked
1369 * (passing any specified arguments) and the return value is
1370 * returned.
1371 *
1372 * __metatable - Hide the metatable. When "getmetatable( myTable )" is
1373 * called, if the metatable for myTable has a __metatable
1374 * key, the value of that key is returned instead of the
1375 * actual metatable.
1376 *
1377 * __tostring - Control string representation. When the builtin
1378 * "tostring( myTable )" function is called, if the metatable
1379 * for myTable has a __tostring property set to a function,
1380 * that function is invoked (passing myTable to it) and the
1381 * return value is used as the string representation.
1382 *
1383 * __len - Control table length. When the table length is requested using
1384 * the length operator ( '#' ), if the metatable for myTable has
1385 * a __len key pointing to a function, that function is invoked
1386 * (passing myTable to it) and the return value used as the value
1387 * of "#myTable".
1388 *
1389 * __gc - Userdata finalizer code. When userdata is set to be garbage
1390 * collected, if the metatable has a __gc field pointing to a
1391 * function, that function is first invoked, passing the userdata
1392 * to it. The __gc metamethod is not called for tables.
1393 * (See http://lua-users.org/lists/lua-l/2006-11/msg00508.html)
1394 *
1395 * Special metamethods for redefining standard operators:
1396 * http://www.lua.org/pil/13.1.html
1397 *
1398 * __add "+"
1399 * __sub "-"
1400 * __mul "*"
1401 * __div "/"
1402 * __unm "!"
1403 * __pow "^"
1404 * __concat ".."
1405 *
1406 * Special methods for redfining standar relations
1407 * http://www.lua.org/pil/13.2.html
1408 *
1409 * __eq "=="
1410 * __lt "<"
1411 * __le "<="
1412 */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001413
1414/*
1415 *
1416 *
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001417 * Class Map
1418 *
1419 *
1420 */
1421
1422/* Returns a struct hlua_map if the stack entry "ud" is
1423 * a class session, otherwise it throws an error.
1424 */
1425__LJMP static struct map_descriptor *hlua_checkmap(lua_State *L, int ud)
1426{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001427 return MAY_LJMP(hlua_checkudata(L, ud, class_map_ref));
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001428}
1429
1430/* This function is the map constructor. It don't need
1431 * the class Map object. It creates and return a new Map
1432 * object. It must be called only during "body" or "init"
1433 * context because it process some filesystem accesses.
1434 */
1435__LJMP static int hlua_map_new(struct lua_State *L)
1436{
1437 const char *fn;
1438 int match = PAT_MATCH_STR;
1439 struct sample_conv conv;
1440 const char *file = "";
1441 int line = 0;
1442 lua_Debug ar;
1443 char *err = NULL;
1444 struct arg args[2];
1445
1446 if (lua_gettop(L) < 1 || lua_gettop(L) > 2)
1447 WILL_LJMP(luaL_error(L, "'new' needs at least 1 argument."));
1448
1449 fn = MAY_LJMP(luaL_checkstring(L, 1));
1450
1451 if (lua_gettop(L) >= 2) {
1452 match = MAY_LJMP(luaL_checkinteger(L, 2));
1453 if (match < 0 || match >= PAT_MATCH_NUM)
1454 WILL_LJMP(luaL_error(L, "'new' needs a valid match method."));
1455 }
1456
1457 /* Get Lua filename and line number. */
1458 if (lua_getstack(L, 1, &ar)) { /* check function at level */
1459 lua_getinfo(L, "Sl", &ar); /* get info about it */
1460 if (ar.currentline > 0) { /* is there info? */
1461 file = ar.short_src;
1462 line = ar.currentline;
1463 }
1464 }
1465
1466 /* fill fake sample_conv struct. */
1467 conv.kw = ""; /* unused. */
1468 conv.process = NULL; /* unused. */
1469 conv.arg_mask = 0; /* unused. */
1470 conv.val_args = NULL; /* unused. */
1471 conv.out_type = SMP_T_STR;
1472 conv.private = (void *)(long)match;
1473 switch (match) {
1474 case PAT_MATCH_STR: conv.in_type = SMP_T_STR; break;
1475 case PAT_MATCH_BEG: conv.in_type = SMP_T_STR; break;
1476 case PAT_MATCH_SUB: conv.in_type = SMP_T_STR; break;
1477 case PAT_MATCH_DIR: conv.in_type = SMP_T_STR; break;
1478 case PAT_MATCH_DOM: conv.in_type = SMP_T_STR; break;
1479 case PAT_MATCH_END: conv.in_type = SMP_T_STR; break;
1480 case PAT_MATCH_REG: conv.in_type = SMP_T_STR; break;
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02001481 case PAT_MATCH_INT: conv.in_type = SMP_T_SINT; break;
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001482 case PAT_MATCH_IP: conv.in_type = SMP_T_ADDR; break;
1483 default:
1484 WILL_LJMP(luaL_error(L, "'new' doesn't support this match mode."));
1485 }
1486
1487 /* fill fake args. */
1488 args[0].type = ARGT_STR;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001489 args[0].data.str.area = (char *)fn;
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001490 args[1].type = ARGT_STOP;
1491
1492 /* load the map. */
1493 if (!sample_load_map(args, &conv, file, line, &err)) {
1494 /* error case: we cant use luaL_error because we must
1495 * free the err variable.
1496 */
1497 luaL_where(L, 1);
1498 lua_pushfstring(L, "'new': %s.", err);
1499 lua_concat(L, 2);
1500 free(err);
1501 WILL_LJMP(lua_error(L));
1502 }
1503
1504 /* create the lua object. */
1505 lua_newtable(L);
1506 lua_pushlightuserdata(L, args[0].data.map);
1507 lua_rawseti(L, -2, 0);
1508
1509 /* Pop a class Map metatable and affect it to the userdata. */
1510 lua_rawgeti(L, LUA_REGISTRYINDEX, class_map_ref);
1511 lua_setmetatable(L, -2);
1512
1513
1514 return 1;
1515}
1516
1517__LJMP static inline int _hlua_map_lookup(struct lua_State *L, int str)
1518{
1519 struct map_descriptor *desc;
1520 struct pattern *pat;
1521 struct sample smp;
1522
1523 MAY_LJMP(check_args(L, 2, "lookup"));
1524 desc = MAY_LJMP(hlua_checkmap(L, 1));
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02001525 if (desc->pat.expect_type == SMP_T_SINT) {
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02001526 smp.data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02001527 smp.data.u.sint = MAY_LJMP(luaL_checkinteger(L, 2));
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001528 }
1529 else {
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02001530 smp.data.type = SMP_T_STR;
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001531 smp.flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001532 smp.data.u.str.area = (char *)MAY_LJMP(luaL_checklstring(L, 2, (size_t *)&smp.data.u.str.data));
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001533 }
1534
1535 pat = pattern_exec_match(&desc->pat, &smp, 1);
Thierry FOURNIER503bb092015-08-19 08:35:43 +02001536 if (!pat || !pat->data) {
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001537 if (str)
1538 lua_pushstring(L, "");
1539 else
1540 lua_pushnil(L);
1541 return 1;
1542 }
1543
1544 /* The Lua pattern must return a string, so we can't check the returned type */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001545 lua_pushlstring(L, pat->data->u.str.area, pat->data->u.str.data);
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001546 return 1;
1547}
1548
1549__LJMP static int hlua_map_lookup(struct lua_State *L)
1550{
1551 return _hlua_map_lookup(L, 0);
1552}
1553
1554__LJMP static int hlua_map_slookup(struct lua_State *L)
1555{
1556 return _hlua_map_lookup(L, 1);
1557}
1558
1559/*
1560 *
1561 *
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001562 * Class Socket
1563 *
1564 *
1565 */
1566
1567__LJMP static struct hlua_socket *hlua_checksocket(lua_State *L, int ud)
1568{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001569 return MAY_LJMP(hlua_checkudata(L, ud, class_socket_ref));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001570}
1571
1572/* This function is the handler called for each I/O on the established
1573 * connection. It is used for notify space avalaible to send or data
1574 * received.
1575 */
Willy Tarreau00a37f02015-04-13 12:05:19 +02001576static void hlua_socket_handler(struct appctx *appctx)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001577{
Willy Tarreau00a37f02015-04-13 12:05:19 +02001578 struct stream_interface *si = appctx->owner;
Olivier Houchard9aaf7782017-09-13 18:30:23 +02001579 struct connection *c = cs_conn(objt_cs(si_opposite(si)->end));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001580
Thierry FOURNIERb13b20a2017-07-16 20:48:54 +02001581 if (appctx->ctx.hlua_cosocket.die) {
1582 si_shutw(si);
1583 si_shutr(si);
1584 si_ic(si)->flags |= CF_READ_NULL;
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001585 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_read);
1586 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_write);
Thierry FOURNIERb13b20a2017-07-16 20:48:54 +02001587 stream_shutdown(si_strm(si), SF_ERR_KILLED);
1588 }
1589
Thierry FOURNIER6d695e62015-09-27 19:29:38 +02001590 /* If the connection object is not avalaible, close all the
1591 * streams and wakeup everithing waiting for.
1592 */
1593 if (!c) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001594 si_shutw(si);
1595 si_shutr(si);
Willy Tarreau2bb4a962014-11-28 11:11:05 +01001596 si_ic(si)->flags |= CF_READ_NULL;
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001597 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_read);
1598 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_write);
Willy Tarreaud4da1962015-04-20 01:31:23 +02001599 return;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001600 }
1601
Thierry FOURNIER6d695e62015-09-27 19:29:38 +02001602 /* If we cant write, wakeup the pending write signals. */
1603 if (channel_output_closed(si_ic(si)))
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001604 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_write);
Thierry FOURNIER6d695e62015-09-27 19:29:38 +02001605
1606 /* If we cant read, wakeup the pending read signals. */
1607 if (channel_input_closed(si_oc(si)))
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001608 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_read);
Thierry FOURNIER6d695e62015-09-27 19:29:38 +02001609
Thierry FOURNIER316e3192015-09-04 18:25:53 +02001610 /* if the connection is not estabkished, inform the stream that we want
1611 * to be notified whenever the connection completes.
1612 */
1613 if (!(c->flags & CO_FL_CONNECTED)) {
1614 si_applet_cant_get(si);
1615 si_applet_cant_put(si);
Willy Tarreaud4da1962015-04-20 01:31:23 +02001616 return;
Thierry FOURNIER316e3192015-09-04 18:25:53 +02001617 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001618
1619 /* This function is called after the connect. */
Thierry FOURNIER18d09902016-12-16 09:25:38 +01001620 appctx->ctx.hlua_cosocket.connected = 1;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001621
1622 /* Wake the tasks which wants to write if the buffer have avalaible space. */
Thierry FOURNIEReba6f642015-09-26 22:01:07 +02001623 if (channel_may_recv(si_ic(si)))
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001624 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_write);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001625
1626 /* Wake the tasks which wants to read if the buffer contains data. */
Thierry FOURNIEReba6f642015-09-26 22:01:07 +02001627 if (!channel_is_empty(si_oc(si)))
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001628 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_read);
Thierry FOURNIER101b9762018-05-27 01:27:40 +02001629
1630 /* Some data were injected in the buffer, notify the stream
1631 * interface.
1632 */
1633 if (!channel_is_empty(si_ic(si)))
1634 stream_int_update(si);
1635
1636 /* If write notifications are registered, we considers we want
1637 * to write, so we set the flag cant put
1638 */
1639 if (notification_registered(&appctx->ctx.hlua_cosocket.wake_on_write))
1640 si_applet_cant_put(si);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001641}
1642
Willy Tarreau87b09662015-04-03 00:22:06 +02001643/* This function is called when the "struct stream" is destroyed.
1644 * Remove the link from the object to this stream.
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001645 * Wake all the pending signals.
1646 */
Willy Tarreau00a37f02015-04-13 12:05:19 +02001647static void hlua_socket_release(struct appctx *appctx)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001648{
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001649 struct xref *peer;
1650
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001651 /* Remove my link in the original object. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001652 peer = xref_get_peer_and_lock(&appctx->ctx.hlua_cosocket.xref);
1653 if (peer)
1654 xref_disconnect(&appctx->ctx.hlua_cosocket.xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001655
1656 /* Wake all the task waiting for me. */
Thierry FOURNIERd6975962017-07-12 14:31:10 +02001657 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_read);
1658 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_write);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001659}
1660
1661/* If the garbage collectio of the object is launch, nobody
Willy Tarreau87b09662015-04-03 00:22:06 +02001662 * uses this object. If the stream does not exists, just quit.
1663 * Send the shutdown signal to the stream. In some cases,
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001664 * pending signal can rest in the read and write lists. destroy
1665 * it.
1666 */
1667__LJMP static int hlua_socket_gc(lua_State *L)
1668{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001669 struct hlua_socket *socket;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001670 struct appctx *appctx;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001671 struct xref *peer;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001672
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001673 MAY_LJMP(check_args(L, 1, "__gc"));
1674
1675 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001676 peer = xref_get_peer_and_lock(&socket->xref);
1677 if (!peer)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001678 return 0;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001679 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001680
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001681 /* Set the flag which destroy the session. */
Thierry FOURNIERb13b20a2017-07-16 20:48:54 +02001682 appctx->ctx.hlua_cosocket.die = 1;
1683 appctx_wakeup(appctx);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001684
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001685 /* Remove all reference between the Lua stack and the coroutine stream. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001686 xref_disconnect(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001687 return 0;
1688}
1689
1690/* The close function send shutdown signal and break the
Willy Tarreau87b09662015-04-03 00:22:06 +02001691 * links between the stream and the object.
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001692 */
sada05ed3302018-05-11 11:48:18 -07001693__LJMP static int hlua_socket_close_helper(lua_State *L)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001694{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001695 struct hlua_socket *socket;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001696 struct appctx *appctx;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001697 struct xref *peer;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001698
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001699 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02001700
1701 /* Check if we run on the same thread than the xreator thread.
1702 * We cannot access to the socket if the thread is different.
1703 */
1704 if (socket->tid != tid)
1705 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
1706
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001707 peer = xref_get_peer_and_lock(&socket->xref);
1708 if (!peer)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001709 return 0;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001710 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001711
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001712 /* Set the flag which destroy the session. */
Thierry FOURNIERb13b20a2017-07-16 20:48:54 +02001713 appctx->ctx.hlua_cosocket.die = 1;
1714 appctx_wakeup(appctx);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001715
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001716 /* Remove all reference between the Lua stack and the coroutine stream. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001717 xref_disconnect(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001718 return 0;
1719}
1720
sada05ed3302018-05-11 11:48:18 -07001721/* The close function calls close_helper.
1722 */
1723__LJMP static int hlua_socket_close(lua_State *L)
1724{
1725 MAY_LJMP(check_args(L, 1, "close"));
1726 return hlua_socket_close_helper(L);
1727}
1728
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001729/* This Lua function assumes that the stack contain three parameters.
1730 * 1 - USERDATA containing a struct socket
1731 * 2 - INTEGER with values of the macro defined below
1732 * If the integer is -1, we must read at most one line.
1733 * If the integer is -2, we ust read all the data until the
1734 * end of the stream.
1735 * If the integer is positive value, we must read a number of
1736 * bytes corresponding to this value.
1737 */
1738#define HLSR_READ_LINE (-1)
1739#define HLSR_READ_ALL (-2)
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01001740__LJMP static int hlua_socket_receive_yield(struct lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001741{
1742 struct hlua_socket *socket = MAY_LJMP(hlua_checksocket(L, 1));
1743 int wanted = lua_tointeger(L, 2);
1744 struct hlua *hlua = hlua_gethlua(L);
1745 struct appctx *appctx;
Willy Tarreau55f3ce12018-07-18 11:49:27 +02001746 size_t len;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001747 int nblk;
Willy Tarreau206ba832018-06-14 15:27:31 +02001748 const char *blk1;
Willy Tarreau55f3ce12018-07-18 11:49:27 +02001749 size_t len1;
Willy Tarreau206ba832018-06-14 15:27:31 +02001750 const char *blk2;
Willy Tarreau55f3ce12018-07-18 11:49:27 +02001751 size_t len2;
Thierry FOURNIER00543922015-03-09 18:35:06 +01001752 int skip_at_end = 0;
Willy Tarreau81389672015-03-10 12:03:52 +01001753 struct channel *oc;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001754 struct stream_interface *si;
1755 struct stream *s;
1756 struct xref *peer;
Thierry FOURNIER8c126c72018-05-25 16:27:44 +02001757 int missing_bytes;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001758
1759 /* Check if this lua stack is schedulable. */
1760 if (!hlua || !hlua->task)
1761 WILL_LJMP(luaL_error(L, "The 'receive' function is only allowed in "
1762 "'frontend', 'backend' or 'task'"));
1763
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02001764 /* Check if we run on the same thread than the xreator thread.
1765 * We cannot access to the socket if the thread is different.
1766 */
1767 if (socket->tid != tid)
1768 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
1769
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001770 /* check for connection break. If some data where read, return it. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001771 peer = xref_get_peer_and_lock(&socket->xref);
1772 if (!peer)
1773 goto no_peer;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001774 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
1775 si = appctx->owner;
1776 s = si_strm(si);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001777
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001778 oc = &s->res;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001779 if (wanted == HLSR_READ_LINE) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001780 /* Read line. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02001781 nblk = co_getline_nc(oc, &blk1, &len1, &blk2, &len2);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001782 if (nblk < 0) /* Connection close. */
1783 goto connection_closed;
1784 if (nblk == 0) /* No data avalaible. */
1785 goto connection_empty;
Thierry FOURNIER00543922015-03-09 18:35:06 +01001786
1787 /* remove final \r\n. */
1788 if (nblk == 1) {
1789 if (blk1[len1-1] == '\n') {
1790 len1--;
1791 skip_at_end++;
1792 if (blk1[len1-1] == '\r') {
1793 len1--;
1794 skip_at_end++;
1795 }
1796 }
1797 }
1798 else {
1799 if (blk2[len2-1] == '\n') {
1800 len2--;
1801 skip_at_end++;
1802 if (blk2[len2-1] == '\r') {
1803 len2--;
1804 skip_at_end++;
1805 }
1806 }
1807 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001808 }
1809
1810 else if (wanted == HLSR_READ_ALL) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001811 /* Read all the available data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02001812 nblk = co_getblk_nc(oc, &blk1, &len1, &blk2, &len2);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001813 if (nblk < 0) /* Connection close. */
1814 goto connection_closed;
1815 if (nblk == 0) /* No data avalaible. */
1816 goto connection_empty;
1817 }
1818
1819 else {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001820 /* Read a block of data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02001821 nblk = co_getblk_nc(oc, &blk1, &len1, &blk2, &len2);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001822 if (nblk < 0) /* Connection close. */
1823 goto connection_closed;
1824 if (nblk == 0) /* No data avalaible. */
1825 goto connection_empty;
1826
Thierry FOURNIER8c126c72018-05-25 16:27:44 +02001827 missing_bytes = wanted - socket->b.n;
1828 if (len1 > missing_bytes) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001829 nblk = 1;
Thierry FOURNIER8c126c72018-05-25 16:27:44 +02001830 len1 = missing_bytes;
1831 } if (nblk == 2 && len1 + len2 > missing_bytes)
1832 len2 = missing_bytes - len1;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001833 }
1834
1835 len = len1;
1836
1837 luaL_addlstring(&socket->b, blk1, len1);
1838 if (nblk == 2) {
1839 len += len2;
1840 luaL_addlstring(&socket->b, blk2, len2);
1841 }
1842
1843 /* Consume data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02001844 co_skip(oc, len + skip_at_end);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001845
1846 /* Don't wait anything. */
Thierry FOURNIER7e4ee472018-05-25 15:03:50 +02001847 appctx_wakeup(appctx);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001848
1849 /* If the pattern reclaim to read all the data
1850 * in the connection, got out.
1851 */
1852 if (wanted == HLSR_READ_ALL)
1853 goto connection_empty;
Thierry FOURNIER8c126c72018-05-25 16:27:44 +02001854 else if (wanted >= 0 && socket->b.n < wanted)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001855 goto connection_empty;
1856
1857 /* Return result. */
1858 luaL_pushresult(&socket->b);
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001859 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001860 return 1;
1861
1862connection_closed:
1863
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001864 xref_unlock(&socket->xref, peer);
1865
1866no_peer:
1867
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001868 /* If the buffer containds data. */
1869 if (socket->b.n > 0) {
1870 luaL_pushresult(&socket->b);
1871 return 1;
1872 }
1873 lua_pushnil(L);
1874 lua_pushstring(L, "connection closed.");
1875 return 2;
1876
1877connection_empty:
1878
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001879 if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_read, hlua->task)) {
1880 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001881 WILL_LJMP(luaL_error(L, "out of memory"));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02001882 }
1883 xref_unlock(&socket->xref, peer);
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +01001884 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_receive_yield, TICK_ETERNITY, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001885 return 0;
1886}
1887
Tim Duesterhusb33754c2018-01-04 19:32:14 +01001888/* This Lua function gets two parameters. The first one can be string
1889 * or a number. If the string is "*l", the user requires one line. If
1890 * the string is "*a", the user requires all the contents of the stream.
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001891 * If the value is a number, the user require a number of bytes equal
1892 * to the value. The default value is "*l" (a line).
1893 *
Tim Duesterhusb33754c2018-01-04 19:32:14 +01001894 * This parameter with a variable type is converted in integer. This
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001895 * integer takes this values:
1896 * -1 : read a line
1897 * -2 : read all the stream
Tim Duesterhusb33754c2018-01-04 19:32:14 +01001898 * >0 : amount of bytes.
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001899 *
Tim Duesterhusb33754c2018-01-04 19:32:14 +01001900 * The second parameter is optional. It contains a string that must be
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001901 * concatenated with the read data.
1902 */
1903__LJMP static int hlua_socket_receive(struct lua_State *L)
1904{
1905 int wanted = HLSR_READ_LINE;
1906 const char *pattern;
1907 int type;
1908 char *error;
1909 size_t len;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001910 struct hlua_socket *socket;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001911
1912 if (lua_gettop(L) < 1 || lua_gettop(L) > 3)
1913 WILL_LJMP(luaL_error(L, "The 'receive' function requires between 1 and 3 arguments."));
1914
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001915 socket = MAY_LJMP(hlua_checksocket(L, 1));
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 FOURNIER7e7ac322015-02-16 19:27:16 +01001923 /* check for pattern. */
1924 if (lua_gettop(L) >= 2) {
1925 type = lua_type(L, 2);
1926 if (type == LUA_TSTRING) {
1927 pattern = lua_tostring(L, 2);
1928 if (strcmp(pattern, "*a") == 0)
1929 wanted = HLSR_READ_ALL;
1930 else if (strcmp(pattern, "*l") == 0)
1931 wanted = HLSR_READ_LINE;
1932 else {
1933 wanted = strtoll(pattern, &error, 10);
1934 if (*error != '\0')
1935 WILL_LJMP(luaL_error(L, "Unsupported pattern."));
1936 }
1937 }
1938 else if (type == LUA_TNUMBER) {
1939 wanted = lua_tointeger(L, 2);
1940 if (wanted < 0)
1941 WILL_LJMP(luaL_error(L, "Unsupported size."));
1942 }
1943 }
1944
1945 /* Set pattern. */
1946 lua_pushinteger(L, wanted);
Tim Duesterhusc6e377e2018-01-04 19:32:13 +01001947
1948 /* Check if we would replace the top by itself. */
1949 if (lua_gettop(L) != 2)
1950 lua_replace(L, 2);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001951
Tim Duesterhusb33754c2018-01-04 19:32:14 +01001952 /* init buffer, and fill it with prefix. */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001953 luaL_buffinit(L, &socket->b);
1954
1955 /* Check prefix. */
1956 if (lua_gettop(L) >= 3) {
1957 if (lua_type(L, 3) != LUA_TSTRING)
1958 WILL_LJMP(luaL_error(L, "Expect a 'string' for the prefix"));
1959 pattern = lua_tolstring(L, 3, &len);
1960 luaL_addlstring(&socket->b, pattern, len);
1961 }
1962
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01001963 return __LJMP(hlua_socket_receive_yield(L, 0, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001964}
1965
1966/* Write the Lua input string in the output buffer.
Mark Lakes22154b42018-01-29 14:38:40 -08001967 * This function returns a yield if no space is available.
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001968 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01001969static int hlua_socket_write_yield(struct lua_State *L,int status, lua_KContext ctx)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001970{
1971 struct hlua_socket *socket;
1972 struct hlua *hlua = hlua_gethlua(L);
1973 struct appctx *appctx;
1974 size_t buf_len;
1975 const char *buf;
1976 int len;
1977 int send_len;
1978 int sent;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001979 struct xref *peer;
1980 struct stream_interface *si;
1981 struct stream *s;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001982
1983 /* Check if this lua stack is schedulable. */
1984 if (!hlua || !hlua->task)
1985 WILL_LJMP(luaL_error(L, "The 'write' function is only allowed in "
1986 "'frontend', 'backend' or 'task'"));
1987
1988 /* Get object */
1989 socket = MAY_LJMP(hlua_checksocket(L, 1));
1990 buf = MAY_LJMP(luaL_checklstring(L, 2, &buf_len));
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01001991 sent = MAY_LJMP(luaL_checkinteger(L, 3));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001992
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02001993 /* Check if we run on the same thread than the xreator thread.
1994 * We cannot access to the socket if the thread is different.
1995 */
1996 if (socket->tid != tid)
1997 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
1998
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02001999 /* check for connection break. If some data where read, return it. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002000 peer = xref_get_peer_and_lock(&socket->xref);
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002001 if (!peer) {
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002002 lua_pushinteger(L, -1);
2003 return 1;
2004 }
2005 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2006 si = appctx->owner;
2007 s = si_strm(si);
2008
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002009 /* Check for connection close. */
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002010 if (channel_output_closed(&s->req)) {
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002011 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002012 lua_pushinteger(L, -1);
2013 return 1;
2014 }
2015
2016 /* Update the input buffer data. */
2017 buf += sent;
2018 send_len = buf_len - sent;
2019
2020 /* All the data are sent. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002021 if (sent >= buf_len) {
2022 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002023 return 1; /* Implicitly return the length sent. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002024 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002025
Thierry FOURNIER486d52a2015-03-09 17:51:43 +01002026 /* Check if the buffer is avalaible because HAProxy doesn't allocate
2027 * the request buffer if its not required.
2028 */
Willy Tarreauc9fa0482018-07-10 17:43:27 +02002029 if (s->req.buf.size == 0) {
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002030 if (!channel_alloc_buffer(&s->req, &appctx->buffer_wait))
Christopher Faulet33834b12016-12-19 09:29:06 +01002031 goto hlua_socket_write_yield_return;
Thierry FOURNIER486d52a2015-03-09 17:51:43 +01002032 }
2033
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002034 /* Check for avalaible space. */
Willy Tarreauc9fa0482018-07-10 17:43:27 +02002035 len = b_room(&s->req.buf);
Christopher Faulet33834b12016-12-19 09:29:06 +01002036 if (len <= 0) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002037 goto hlua_socket_write_yield_return;
Christopher Faulet33834b12016-12-19 09:29:06 +01002038 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002039
2040 /* send data */
2041 if (len < send_len)
2042 send_len = len;
Thierry FOURNIER66b89192018-05-27 01:14:47 +02002043 len = ci_putblk(&s->req, buf, send_len);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002044
2045 /* "Not enough space" (-1), "Buffer too little to contain
2046 * the data" (-2) are not expected because the available length
2047 * is tested.
2048 * Other unknown error are also not expected.
2049 */
2050 if (len <= 0) {
Willy Tarreaubc18da12015-03-13 14:00:47 +01002051 if (len == -1)
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002052 s->req.flags |= CF_WAKE_WRITE;
Willy Tarreaubc18da12015-03-13 14:00:47 +01002053
sada05ed3302018-05-11 11:48:18 -07002054 MAY_LJMP(hlua_socket_close_helper(L));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002055 lua_pop(L, 1);
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002056 lua_pushinteger(L, -1);
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002057 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002058 return 1;
2059 }
2060
2061 /* update buffers. */
Thierry FOURNIER101b9762018-05-27 01:27:40 +02002062 appctx_wakeup(appctx);
Willy Tarreaude70fa12015-09-26 11:25:05 +02002063
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002064 s->req.rex = TICK_ETERNITY;
2065 s->res.wex = TICK_ETERNITY;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002066
2067 /* Update length sent. */
2068 lua_pop(L, 1);
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002069 lua_pushinteger(L, sent + len);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002070
2071 /* All the data buffer is sent ? */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002072 if (sent + len >= buf_len) {
2073 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002074 return 1;
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002075 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002076
2077hlua_socket_write_yield_return:
Thierry FOURNIERba42fcd2018-05-27 00:59:48 +02002078 if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task)) {
2079 xref_unlock(&socket->xref, peer);
2080 WILL_LJMP(luaL_error(L, "out of memory"));
2081 }
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002082 xref_unlock(&socket->xref, peer);
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +01002083 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_write_yield, TICK_ETERNITY, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002084 return 0;
2085}
2086
2087/* This function initiate the send of data. It just check the input
2088 * parameters and push an integer in the Lua stack that contain the
2089 * amount of data writed in the buffer. This is used by the function
2090 * "hlua_socket_write_yield" that can yield.
2091 *
2092 * The Lua function gets between 3 and 4 parameters. The first one is
2093 * the associated object. The second is a string buffer. The third is
2094 * a facultative integer that represents where is the buffer position
2095 * of the start of the data that can send. The first byte is the
2096 * position "1". The default value is "1". The fourth argument is a
2097 * facultative integer that represents where is the buffer position
2098 * of the end of the data that can send. The default is the last byte.
2099 */
2100static int hlua_socket_send(struct lua_State *L)
2101{
2102 int i;
2103 int j;
2104 const char *buf;
2105 size_t buf_len;
2106
2107 /* Check number of arguments. */
2108 if (lua_gettop(L) < 2 || lua_gettop(L) > 4)
2109 WILL_LJMP(luaL_error(L, "'send' needs between 2 and 4 arguments"));
2110
2111 /* Get the string. */
2112 buf = MAY_LJMP(luaL_checklstring(L, 2, &buf_len));
2113
2114 /* Get and check j. */
2115 if (lua_gettop(L) == 4) {
2116 j = MAY_LJMP(luaL_checkinteger(L, 4));
2117 if (j < 0)
2118 j = buf_len + j + 1;
2119 if (j > buf_len)
2120 j = buf_len + 1;
2121 lua_pop(L, 1);
2122 }
2123 else
2124 j = buf_len;
2125
2126 /* Get and check i. */
2127 if (lua_gettop(L) == 3) {
2128 i = MAY_LJMP(luaL_checkinteger(L, 3));
2129 if (i < 0)
2130 i = buf_len + i + 1;
2131 if (i > buf_len)
2132 i = buf_len + 1;
2133 lua_pop(L, 1);
2134 } else
2135 i = 1;
2136
2137 /* Check bth i and j. */
2138 if (i > j) {
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002139 lua_pushinteger(L, 0);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002140 return 1;
2141 }
2142 if (i == 0 && j == 0) {
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002143 lua_pushinteger(L, 0);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002144 return 1;
2145 }
2146 if (i == 0)
2147 i = 1;
2148 if (j == 0)
2149 j = 1;
2150
2151 /* Pop the string. */
2152 lua_pop(L, 1);
2153
2154 /* Update the buffer length. */
2155 buf += i - 1;
2156 buf_len = j - i + 1;
2157 lua_pushlstring(L, buf, buf_len);
2158
2159 /* This unsigned is used to remember the amount of sent data. */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002160 lua_pushinteger(L, 0);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002161
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002162 return MAY_LJMP(hlua_socket_write_yield(L, 0, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002163}
2164
Willy Tarreau22b0a682015-06-17 19:43:49 +02002165#define SOCKET_INFO_MAX_LEN sizeof("[0000:0000:0000:0000:0000:0000:0000:0000]:12345")
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002166__LJMP static inline int hlua_socket_info(struct lua_State *L, struct sockaddr_storage *addr)
2167{
2168 static char buffer[SOCKET_INFO_MAX_LEN];
2169 int ret;
2170 int len;
2171 char *p;
2172
2173 ret = addr_to_str(addr, buffer+1, SOCKET_INFO_MAX_LEN-1);
2174 if (ret <= 0) {
2175 lua_pushnil(L);
2176 return 1;
2177 }
2178
2179 if (ret == AF_UNIX) {
2180 lua_pushstring(L, buffer+1);
2181 return 1;
2182 }
2183 else if (ret == AF_INET6) {
2184 buffer[0] = '[';
2185 len = strlen(buffer);
2186 buffer[len] = ']';
2187 len++;
2188 buffer[len] = ':';
2189 len++;
2190 p = buffer;
2191 }
2192 else if (ret == AF_INET) {
2193 p = buffer + 1;
2194 len = strlen(p);
2195 p[len] = ':';
2196 len++;
2197 }
2198 else {
2199 lua_pushnil(L);
2200 return 1;
2201 }
2202
2203 if (port_to_str(addr, p + len, SOCKET_INFO_MAX_LEN-1 - len) <= 0) {
2204 lua_pushnil(L);
2205 return 1;
2206 }
2207
2208 lua_pushstring(L, p);
2209 return 1;
2210}
2211
2212/* Returns information about the peer of the connection. */
2213__LJMP static int hlua_socket_getpeername(struct lua_State *L)
2214{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002215 struct hlua_socket *socket;
2216 struct connection *conn;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002217 struct xref *peer;
2218 struct appctx *appctx;
2219 struct stream_interface *si;
2220 struct stream *s;
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002221 int ret;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002222
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002223 MAY_LJMP(check_args(L, 1, "getpeername"));
2224
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002225 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002226
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02002227 /* Check if we run on the same thread than the xreator thread.
2228 * We cannot access to the socket if the thread is different.
2229 */
2230 if (socket->tid != tid)
2231 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
2232
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002233 /* check for connection break. If some data where read, return it. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002234 peer = xref_get_peer_and_lock(&socket->xref);
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002235 if (!peer) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002236 lua_pushnil(L);
2237 return 1;
2238 }
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002239 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2240 si = appctx->owner;
2241 s = si_strm(si);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002242
Olivier Houchard9aaf7782017-09-13 18:30:23 +02002243 conn = cs_conn(objt_cs(s->si[1].end));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002244 if (!conn) {
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002245 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002246 lua_pushnil(L);
2247 return 1;
2248 }
2249
Willy Tarreaua71f6422016-11-16 17:00:14 +01002250 conn_get_to_addr(conn);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002251 if (!(conn->flags & CO_FL_ADDR_TO_SET)) {
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002252 xref_unlock(&socket->xref, peer);
Willy Tarreaua71f6422016-11-16 17:00:14 +01002253 lua_pushnil(L);
2254 return 1;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002255 }
2256
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002257 ret = MAY_LJMP(hlua_socket_info(L, &conn->addr.to));
2258 xref_unlock(&socket->xref, peer);
2259 return ret;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002260}
2261
2262/* Returns information about my connection side. */
2263static int hlua_socket_getsockname(struct lua_State *L)
2264{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002265 struct hlua_socket *socket;
2266 struct connection *conn;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002267 struct appctx *appctx;
2268 struct xref *peer;
2269 struct stream_interface *si;
2270 struct stream *s;
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002271 int ret;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002272
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002273 MAY_LJMP(check_args(L, 1, "getsockname"));
2274
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002275 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002276
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02002277 /* Check if we run on the same thread than the xreator thread.
2278 * We cannot access to the socket if the thread is different.
2279 */
2280 if (socket->tid != tid)
2281 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
2282
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002283 /* check for connection break. If some data where read, return it. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002284 peer = xref_get_peer_and_lock(&socket->xref);
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002285 if (!peer) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002286 lua_pushnil(L);
2287 return 1;
2288 }
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002289 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2290 si = appctx->owner;
2291 s = si_strm(si);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002292
Olivier Houchard9aaf7782017-09-13 18:30:23 +02002293 conn = cs_conn(objt_cs(s->si[1].end));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002294 if (!conn) {
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002295 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002296 lua_pushnil(L);
2297 return 1;
2298 }
2299
Willy Tarreaua71f6422016-11-16 17:00:14 +01002300 conn_get_from_addr(conn);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002301 if (!(conn->flags & CO_FL_ADDR_FROM_SET)) {
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002302 xref_unlock(&socket->xref, peer);
Willy Tarreaua71f6422016-11-16 17:00:14 +01002303 lua_pushnil(L);
2304 return 1;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002305 }
2306
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002307 ret = hlua_socket_info(L, &conn->addr.from);
2308 xref_unlock(&socket->xref, peer);
2309 return ret;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002310}
2311
2312/* This struct define the applet. */
Willy Tarreau30576452015-04-13 13:50:30 +02002313static struct applet update_applet = {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002314 .obj_type = OBJ_TYPE_APPLET,
2315 .name = "<LUA_TCP>",
2316 .fct = hlua_socket_handler,
2317 .release = hlua_socket_release,
2318};
2319
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002320__LJMP static int hlua_socket_connect_yield(struct lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002321{
2322 struct hlua_socket *socket = MAY_LJMP(hlua_checksocket(L, 1));
2323 struct hlua *hlua = hlua_gethlua(L);
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002324 struct xref *peer;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002325 struct appctx *appctx;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002326 struct stream_interface *si;
2327 struct stream *s;
2328
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02002329 /* Check if we run on the same thread than the xreator thread.
2330 * We cannot access to the socket if the thread is different.
2331 */
2332 if (socket->tid != tid)
2333 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
2334
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002335 /* check for connection break. If some data where read, return it. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002336 peer = xref_get_peer_and_lock(&socket->xref);
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002337 if (!peer) {
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002338 lua_pushnil(L);
2339 lua_pushstring(L, "Can't connect");
2340 return 2;
2341 }
2342 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2343 si = appctx->owner;
2344 s = si_strm(si);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002345
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02002346 /* Check if we run on the same thread than the xreator thread.
2347 * We cannot access to the socket if the thread is different.
2348 */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002349 if (socket->tid != tid) {
2350 xref_unlock(&socket->xref, peer);
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02002351 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002352 }
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02002353
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002354 /* Check for connection close. */
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002355 if (!hlua || channel_output_closed(&s->req)) {
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002356 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002357 lua_pushnil(L);
2358 lua_pushstring(L, "Can't connect");
2359 return 2;
2360 }
2361
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002362 appctx = objt_appctx(s->si[0].end);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002363
2364 /* Check for connection established. */
Thierry FOURNIER18d09902016-12-16 09:25:38 +01002365 if (appctx->ctx.hlua_cosocket.connected) {
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002366 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002367 lua_pushinteger(L, 1);
2368 return 1;
2369 }
2370
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002371 if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task)) {
2372 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002373 WILL_LJMP(luaL_error(L, "out of memory error"));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002374 }
2375 xref_unlock(&socket->xref, peer);
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +01002376 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_connect_yield, TICK_ETERNITY, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002377 return 0;
2378}
2379
2380/* This function fail or initite the connection. */
2381__LJMP static int hlua_socket_connect(struct lua_State *L)
2382{
2383 struct hlua_socket *socket;
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002384 int port = -1;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002385 const char *ip;
2386 struct connection *conn;
Thierry FOURNIER95ad96a2015-03-09 18:12:40 +01002387 struct hlua *hlua;
2388 struct appctx *appctx;
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002389 int low, high;
2390 struct sockaddr_storage *addr;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002391 struct xref *peer;
2392 struct stream_interface *si;
2393 struct stream *s;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002394
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002395 if (lua_gettop(L) < 2)
2396 WILL_LJMP(luaL_error(L, "connect: need at least 2 arguments"));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002397
2398 /* Get args. */
2399 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02002400
2401 /* Check if we run on the same thread than the xreator thread.
2402 * We cannot access to the socket if the thread is different.
2403 */
2404 if (socket->tid != tid)
2405 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
2406
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002407 ip = MAY_LJMP(luaL_checkstring(L, 2));
Tim Duesterhus6edab862018-01-06 19:04:45 +01002408 if (lua_gettop(L) >= 3) {
2409 luaL_Buffer b;
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002410 port = MAY_LJMP(luaL_checkinteger(L, 3));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002411
Tim Duesterhus6edab862018-01-06 19:04:45 +01002412 /* Force the ip to end with a colon, to support IPv6 addresses
2413 * that are not enclosed within square brackets.
2414 */
2415 if (port > 0) {
2416 luaL_buffinit(L, &b);
2417 luaL_addstring(&b, ip);
2418 luaL_addchar(&b, ':');
2419 luaL_pushresult(&b);
2420 ip = lua_tolstring(L, lua_gettop(L), NULL);
2421 }
2422 }
2423
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002424 /* check for connection break. If some data where read, return it. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002425 peer = xref_get_peer_and_lock(&socket->xref);
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002426 if (!peer) {
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002427 lua_pushnil(L);
2428 return 1;
2429 }
2430 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2431 si = appctx->owner;
2432 s = si_strm(si);
2433
2434 /* Initialise connection. */
Olivier Houchard9aaf7782017-09-13 18:30:23 +02002435 conn = cs_conn(si_alloc_cs(&s->si[1], NULL));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002436 if (!conn) {
2437 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002438 WILL_LJMP(luaL_error(L, "connect: internal error"));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002439 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002440
Willy Tarreau3adac082015-09-26 17:51:09 +02002441 /* needed for the connection not to be closed */
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002442 conn->target = s->target;
Willy Tarreau3adac082015-09-26 17:51:09 +02002443
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002444 /* Parse ip address. */
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002445 addr = str2sa_range(ip, NULL, &low, &high, NULL, NULL, NULL, 0);
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002446 if (!addr) {
2447 xref_unlock(&socket->xref, peer);
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002448 WILL_LJMP(luaL_error(L, "connect: cannot parse destination address '%s'", ip));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002449 }
2450 if (low != high) {
2451 xref_unlock(&socket->xref, peer);
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002452 WILL_LJMP(luaL_error(L, "connect: port ranges not supported : address '%s'", ip));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002453 }
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002454 memcpy(&conn->addr.to, addr, sizeof(struct sockaddr_storage));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002455
2456 /* Set port. */
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002457 if (low == 0) {
2458 if (conn->addr.to.ss_family == AF_INET) {
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002459 if (port == -1) {
2460 xref_unlock(&socket->xref, peer);
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002461 WILL_LJMP(luaL_error(L, "connect: port missing"));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002462 }
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002463 ((struct sockaddr_in *)&conn->addr.to)->sin_port = htons(port);
2464 } else if (conn->addr.to.ss_family == AF_INET6) {
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002465 if (port == -1) {
2466 xref_unlock(&socket->xref, peer);
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002467 WILL_LJMP(luaL_error(L, "connect: port missing"));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002468 }
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002469 ((struct sockaddr_in6 *)&conn->addr.to)->sin6_port = htons(port);
2470 }
2471 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002472
Thierry FOURNIER95ad96a2015-03-09 18:12:40 +01002473 hlua = hlua_gethlua(L);
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002474 appctx = objt_appctx(s->si[0].end);
Willy Tarreaubdc97a82015-08-24 15:42:28 +02002475
2476 /* inform the stream that we want to be notified whenever the
2477 * connection completes.
2478 */
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002479 si_applet_cant_get(&s->si[0]);
2480 si_applet_cant_put(&s->si[0]);
Thierry FOURNIER8c8fbbe2015-09-26 17:02:35 +02002481 appctx_wakeup(appctx);
Willy Tarreaubdc97a82015-08-24 15:42:28 +02002482
Thierry FOURNIER7c39ab42015-09-27 22:53:33 +02002483 hlua->flags |= HLUA_MUST_GC;
2484
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002485 if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task)) {
2486 xref_unlock(&socket->xref, peer);
Thierry FOURNIER95ad96a2015-03-09 18:12:40 +01002487 WILL_LJMP(luaL_error(L, "out of memory"));
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002488 }
2489 xref_unlock(&socket->xref, peer);
PiBa-NL706d5ee2018-05-05 23:51:42 +02002490
2491 task_wakeup(s->task, TASK_WOKEN_INIT);
2492 /* Return yield waiting for connection. */
2493
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +01002494 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_connect_yield, TICK_ETERNITY, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002495
2496 return 0;
2497}
2498
Baptiste Assmann84bb4932015-03-02 21:40:06 +01002499#ifdef USE_OPENSSL
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002500__LJMP static int hlua_socket_connect_ssl(struct lua_State *L)
2501{
2502 struct hlua_socket *socket;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002503 struct xref *peer;
2504 struct appctx *appctx;
2505 struct stream_interface *si;
2506 struct stream *s;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002507
2508 MAY_LJMP(check_args(L, 3, "connect_ssl"));
2509 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002510
2511 /* check for connection break. If some data where read, return it. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002512 peer = xref_get_peer_and_lock(&socket->xref);
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002513 if (!peer) {
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002514 lua_pushnil(L);
2515 return 1;
2516 }
2517 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2518 si = appctx->owner;
2519 s = si_strm(si);
2520
2521 s->target = &socket_ssl.obj_type;
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002522 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002523 return MAY_LJMP(hlua_socket_connect(L));
2524}
Baptiste Assmann84bb4932015-03-02 21:40:06 +01002525#endif
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002526
2527__LJMP static int hlua_socket_setoption(struct lua_State *L)
2528{
2529 return 0;
2530}
2531
2532__LJMP static int hlua_socket_settimeout(struct lua_State *L)
2533{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002534 struct hlua_socket *socket;
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002535 int tmout;
Mark Lakes56cc1252018-03-27 09:48:06 +02002536 double dtmout;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002537 struct xref *peer;
2538 struct appctx *appctx;
2539 struct stream_interface *si;
2540 struct stream *s;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002541
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002542 MAY_LJMP(check_args(L, 2, "settimeout"));
2543
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002544 socket = MAY_LJMP(hlua_checksocket(L, 1));
Mark Lakes56cc1252018-03-27 09:48:06 +02002545
Cyril Bonté7ee465f2018-08-19 22:08:50 +02002546 /* convert the timeout to millis */
2547 dtmout = MAY_LJMP(luaL_checknumber(L, 2)) * 1000;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002548
Thierry Fournier17a921b2018-03-08 09:59:02 +01002549 /* Check for negative values */
Mark Lakes56cc1252018-03-27 09:48:06 +02002550 if (dtmout < 0)
Thierry Fournier17a921b2018-03-08 09:59:02 +01002551 WILL_LJMP(luaL_error(L, "settimeout: cannot set negatives values"));
2552
Mark Lakes56cc1252018-03-27 09:48:06 +02002553 if (dtmout > INT_MAX) /* overflow check */
Cyril Bonté7ee465f2018-08-19 22:08:50 +02002554 WILL_LJMP(luaL_error(L, "settimeout: cannot set values larger than %d ms", INT_MAX));
Mark Lakes56cc1252018-03-27 09:48:06 +02002555
2556 tmout = MS_TO_TICKS((int)dtmout);
Cyril Bonté7ee465f2018-08-19 22:08:50 +02002557 if (tmout == 0)
2558 tmout++; /* very small timeouts are adjusted to a minium of 1ms */
Mark Lakes56cc1252018-03-27 09:48:06 +02002559
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02002560 /* Check if we run on the same thread than the xreator thread.
2561 * We cannot access to the socket if the thread is different.
2562 */
2563 if (socket->tid != tid)
2564 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
2565
Mark Lakes56cc1252018-03-27 09:48:06 +02002566 /* check for connection break. If some data were read, return it. */
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002567 peer = xref_get_peer_and_lock(&socket->xref);
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002568 if (!peer) {
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002569 hlua_pusherror(L, "socket: not yet initialised, you can't set timeouts.");
2570 WILL_LJMP(lua_error(L));
2571 return 0;
2572 }
2573 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2574 si = appctx->owner;
2575 s = si_strm(si);
2576
Cyril Bonté7bb63452018-08-17 23:51:02 +02002577 s->sess->fe->timeout.connect = tmout;
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002578 s->req.rto = tmout;
2579 s->req.wto = tmout;
2580 s->res.rto = tmout;
2581 s->res.wto = tmout;
Cyril Bonté7bb63452018-08-17 23:51:02 +02002582 s->req.rex = tick_add_ifset(now_ms, tmout);
2583 s->req.wex = tick_add_ifset(now_ms, tmout);
2584 s->res.rex = tick_add_ifset(now_ms, tmout);
2585 s->res.wex = tick_add_ifset(now_ms, tmout);
2586
2587 s->task->expire = tick_add_ifset(now_ms, tmout);
2588 task_queue(s->task);
2589
Thierry FOURNIER952939d2017-09-01 14:17:32 +02002590 xref_unlock(&socket->xref, peer);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002591
Thierry Fourniere9636f12018-03-08 09:54:32 +01002592 lua_pushinteger(L, 1);
Tim Duesterhus119a5f12018-01-06 19:16:25 +01002593 return 1;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002594}
2595
2596__LJMP static int hlua_socket_new(lua_State *L)
2597{
2598 struct hlua_socket *socket;
2599 struct appctx *appctx;
Willy Tarreau15b5e142015-04-04 14:38:25 +02002600 struct session *sess;
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002601 struct stream *strm;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002602
2603 /* Check stack size. */
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002604 if (!lua_checkstack(L, 3)) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002605 hlua_pusherror(L, "socket: full stack");
2606 goto out_fail_conf;
2607 }
2608
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002609 /* Create the object: obj[0] = userdata. */
2610 lua_newtable(L);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002611 socket = MAY_LJMP(lua_newuserdata(L, sizeof(*socket)));
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002612 lua_rawseti(L, -2, 0);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002613 memset(socket, 0, sizeof(*socket));
Thierry FOURNIER94a6bfc2017-07-12 12:10:44 +02002614 socket->tid = tid;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002615
Thierry FOURNIER4a6170c2015-03-09 17:07:10 +01002616 /* Check if the various memory pools are intialized. */
Willy Tarreaubafbe012017-11-24 17:34:44 +01002617 if (!pool_head_stream || !pool_head_buffer) {
Thierry FOURNIER4a6170c2015-03-09 17:07:10 +01002618 hlua_pusherror(L, "socket: uninitialized pools.");
2619 goto out_fail_conf;
2620 }
2621
Willy Tarreau87b09662015-04-03 00:22:06 +02002622 /* Pop a class stream metatable and affect it to the userdata. */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002623 lua_rawgeti(L, LUA_REGISTRYINDEX, class_socket_ref);
2624 lua_setmetatable(L, -2);
2625
Willy Tarreaud420a972015-04-06 00:39:18 +02002626 /* Create the applet context */
Willy Tarreau5f4a47b2017-10-31 15:59:32 +01002627 appctx = appctx_new(&update_applet, tid_bit);
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002628 if (!appctx) {
2629 hlua_pusherror(L, "socket: out of memory");
Willy Tarreaufeb76402015-04-03 14:10:06 +02002630 goto out_fail_conf;
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002631 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002632
Thierry FOURNIER18d09902016-12-16 09:25:38 +01002633 appctx->ctx.hlua_cosocket.connected = 0;
Thierry FOURNIERb13b20a2017-07-16 20:48:54 +02002634 appctx->ctx.hlua_cosocket.die = 0;
Thierry FOURNIER18d09902016-12-16 09:25:38 +01002635 LIST_INIT(&appctx->ctx.hlua_cosocket.wake_on_write);
2636 LIST_INIT(&appctx->ctx.hlua_cosocket.wake_on_read);
Willy Tarreaub2bf8332015-04-04 15:58:58 +02002637
Willy Tarreaud420a972015-04-06 00:39:18 +02002638 /* Now create a session, task and stream for this applet */
2639 sess = session_new(&socket_proxy, NULL, &appctx->obj_type);
2640 if (!sess) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002641 hlua_pusherror(L, "socket: out of memory");
Willy Tarreaud420a972015-04-06 00:39:18 +02002642 goto out_fail_sess;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002643 }
2644
Willy Tarreau87787ac2017-08-28 16:22:54 +02002645 strm = stream_new(sess, &appctx->obj_type);
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002646 if (!strm) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002647 hlua_pusherror(L, "socket: out of memory");
Willy Tarreaud420a972015-04-06 00:39:18 +02002648 goto out_fail_stream;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002649 }
2650
Thierry FOURNIER2da788e2017-09-11 18:37:23 +02002651 /* Initialise cross reference between stream and Lua socket object. */
2652 xref_create(&socket->xref, &appctx->ctx.hlua_cosocket.xref);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002653
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002654 /* Configure "right" stream interface. this "si" is used to connect
2655 * and retrieve data from the server. The connection is initialized
2656 * with the "struct server".
2657 */
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002658 si_set_state(&strm->si[1], SI_ST_ASS);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002659
2660 /* Force destination server. */
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002661 strm->flags |= SF_DIRECT | SF_ASSIGNED | SF_ADDR_SET | SF_BE_ASSIGNED;
2662 strm->target = &socket_tcp.obj_type;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002663
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002664 return 1;
2665
Willy Tarreaud420a972015-04-06 00:39:18 +02002666 out_fail_stream:
Willy Tarreau11c36242015-04-04 15:54:03 +02002667 session_free(sess);
Willy Tarreaud420a972015-04-06 00:39:18 +02002668 out_fail_sess:
2669 appctx_free(appctx);
2670 out_fail_conf:
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002671 WILL_LJMP(lua_error(L));
2672 return 0;
2673}
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01002674
2675/*
2676 *
2677 *
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002678 * Class Channel
2679 *
2680 *
2681 */
2682
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002683/* The state between the channel data and the HTTP parser state can be
2684 * unconsistent, so reset the parser and call it again. Warning, this
2685 * action not revalidate the request and not send a 400 if the modified
2686 * resuest is not valid.
2687 *
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01002688 * This function never fails. The direction is set using dir, which equals
2689 * either SMP_OPT_DIR_REQ or SMP_OPT_DIR_RES.
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002690 */
2691static void hlua_resynchonize_proto(struct stream *stream, int dir)
2692{
2693 /* Protocol HTTP. */
2694 if (stream->be->mode == PR_MODE_HTTP) {
2695
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01002696 if (dir == SMP_OPT_DIR_REQ)
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002697 http_txn_reset_req(stream->txn);
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01002698 else if (dir == SMP_OPT_DIR_RES)
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002699 http_txn_reset_res(stream->txn);
2700
2701 if (stream->txn->hdr_idx.v)
2702 hdr_idx_init(&stream->txn->hdr_idx);
2703
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01002704 if (dir == SMP_OPT_DIR_REQ)
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002705 http_msg_analyzer(&stream->txn->req, &stream->txn->hdr_idx);
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01002706 else if (dir == SMP_OPT_DIR_RES)
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002707 http_msg_analyzer(&stream->txn->rsp, &stream->txn->hdr_idx);
2708 }
2709}
2710
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01002711/* This function is called before the Lua execution. It stores
2712 * the differents parsers state before executing some Lua code.
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002713 */
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01002714static inline void consistency_set(struct stream *stream, int opt, struct hlua_consistency *c)
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002715{
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01002716 c->mode = stream->be->mode;
2717 switch (c->mode) {
2718 case PR_MODE_HTTP:
2719 c->data.http.dir = opt & SMP_OPT_DIR;
2720 if (c->data.http.dir == SMP_OPT_DIR_REQ)
2721 c->data.http.state = stream->txn->req.msg_state;
2722 else
2723 c->data.http.state = stream->txn->rsp.msg_state;
2724 break;
2725 default:
2726 break;
2727 }
2728}
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002729
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01002730/* This function is called after the Lua execution. it
2731 * returns true if the parser state is consistent, otherwise,
2732 * it return false.
2733 *
2734 * In HTTP mode, the parser state must be in the same state
2735 * or greater when we exit the function. Even if we do a
2736 * control yield. This prevent to break the HTTP message
2737 * from the Lua code.
2738 */
2739static inline int consistency_check(struct stream *stream, int opt, struct hlua_consistency *c)
2740{
2741 if (c->mode != stream->be->mode)
2742 return 0;
2743
2744 switch (c->mode) {
2745 case PR_MODE_HTTP:
2746 if (c->data.http.dir != (opt & SMP_OPT_DIR))
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002747 return 0;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01002748 if (c->data.http.dir == SMP_OPT_DIR_REQ)
2749 return stream->txn->req.msg_state >= c->data.http.state;
2750 else
2751 return stream->txn->rsp.msg_state >= c->data.http.state;
2752 default:
2753 return 1;
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002754 }
2755 return 1;
2756}
2757
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002758/* Returns the struct hlua_channel join to the class channel in the
2759 * stack entry "ud" or throws an argument error.
2760 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002761__LJMP static struct channel *hlua_checkchannel(lua_State *L, int ud)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002762{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002763 return MAY_LJMP(hlua_checkudata(L, ud, class_channel_ref));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002764}
2765
Willy Tarreau47860ed2015-03-10 14:07:50 +01002766/* Pushes the channel onto the top of the stack. If the stask does not have a
2767 * free slots, the function fails and returns 0;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002768 */
Willy Tarreau2a71af42015-03-10 13:51:50 +01002769static int hlua_channel_new(lua_State *L, struct channel *channel)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002770{
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002771 /* Check stack size. */
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002772 if (!lua_checkstack(L, 3))
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002773 return 0;
2774
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002775 lua_newtable(L);
Willy Tarreau47860ed2015-03-10 14:07:50 +01002776 lua_pushlightuserdata(L, channel);
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002777 lua_rawseti(L, -2, 0);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002778
2779 /* Pop a class sesison metatable and affect it to the userdata. */
2780 lua_rawgeti(L, LUA_REGISTRYINDEX, class_channel_ref);
2781 lua_setmetatable(L, -2);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002782 return 1;
2783}
2784
2785/* Duplicate all the data present in the input channel and put it
2786 * in a string LUA variables. Returns -1 and push a nil value in
2787 * the stack if the channel is closed and all the data are consumed,
2788 * returns 0 if no data are available, otherwise it returns the length
2789 * of the builded string.
2790 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002791static inline int _hlua_channel_dup(struct channel *chn, lua_State *L)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002792{
2793 char *blk1;
2794 char *blk2;
Willy Tarreau55f3ce12018-07-18 11:49:27 +02002795 size_t len1;
2796 size_t len2;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002797 int ret;
2798 luaL_Buffer b;
2799
Willy Tarreau06d80a92017-10-19 14:32:15 +02002800 ret = ci_getblk_nc(chn, &blk1, &len1, &blk2, &len2);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002801 if (unlikely(ret == 0))
2802 return 0;
2803
2804 if (unlikely(ret < 0)) {
2805 lua_pushnil(L);
2806 return -1;
2807 }
2808
2809 luaL_buffinit(L, &b);
2810 luaL_addlstring(&b, blk1, len1);
2811 if (unlikely(ret == 2))
2812 luaL_addlstring(&b, blk2, len2);
2813 luaL_pushresult(&b);
2814
2815 if (unlikely(ret == 2))
2816 return len1 + len2;
2817 return len1;
2818}
2819
2820/* "_hlua_channel_dup" wrapper. If no data are available, it returns
2821 * a yield. This function keep the data in the buffer.
2822 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002823__LJMP static int hlua_channel_dup_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002824{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002825 struct channel *chn;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002826
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002827 chn = MAY_LJMP(hlua_checkchannel(L, 1));
2828
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002829 if (_hlua_channel_dup(chn, L) == 0)
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002830 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_dup_yield, TICK_ETERNITY, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002831 return 1;
2832}
2833
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002834/* Check arguments for the function "hlua_channel_dup_yield". */
2835__LJMP static int hlua_channel_dup(lua_State *L)
2836{
2837 MAY_LJMP(check_args(L, 1, "dup"));
2838 MAY_LJMP(hlua_checkchannel(L, 1));
2839 return MAY_LJMP(hlua_channel_dup_yield(L, 0, 0));
2840}
2841
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002842/* "_hlua_channel_dup" wrapper. If no data are available, it returns
2843 * a yield. This function consumes the data in the buffer. It returns
2844 * a string containing the data or a nil pointer if no data are available
2845 * and the channel is closed.
2846 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002847__LJMP static int hlua_channel_get_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002848{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002849 struct channel *chn;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002850 int ret;
2851
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002852 chn = MAY_LJMP(hlua_checkchannel(L, 1));
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002853
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002854 ret = _hlua_channel_dup(chn, L);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002855 if (unlikely(ret == 0))
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002856 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_get_yield, TICK_ETERNITY, 0));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002857
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002858 if (unlikely(ret == -1))
2859 return 1;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002860
Willy Tarreauc9fa0482018-07-10 17:43:27 +02002861 b_sub(&chn->buf, ret);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002862 hlua_resynchonize_proto(chn_strm(chn), !!(chn->flags & CF_ISRESP));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002863 return 1;
2864}
2865
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002866/* Check arguments for the fucntion "hlua_channel_get_yield". */
2867__LJMP static int hlua_channel_get(lua_State *L)
2868{
2869 MAY_LJMP(check_args(L, 1, "get"));
2870 MAY_LJMP(hlua_checkchannel(L, 1));
2871 return MAY_LJMP(hlua_channel_get_yield(L, 0, 0));
2872}
2873
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002874/* This functions consumes and returns one line. If the channel is closed,
2875 * and the last data does not contains a final '\n', the data are returned
2876 * without the final '\n'. When no more data are avalaible, it returns nil
2877 * value.
2878 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002879__LJMP static int hlua_channel_getline_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002880{
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002881 char *blk1;
2882 char *blk2;
Willy Tarreau55f3ce12018-07-18 11:49:27 +02002883 size_t len1;
2884 size_t len2;
2885 size_t len;
Willy Tarreau47860ed2015-03-10 14:07:50 +01002886 struct channel *chn;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002887 int ret;
2888 luaL_Buffer b;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002889
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002890 chn = MAY_LJMP(hlua_checkchannel(L, 1));
2891
Willy Tarreau06d80a92017-10-19 14:32:15 +02002892 ret = ci_getline_nc(chn, &blk1, &len1, &blk2, &len2);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002893 if (ret == 0)
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002894 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_getline_yield, TICK_ETERNITY, 0));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002895
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002896 if (ret == -1) {
2897 lua_pushnil(L);
2898 return 1;
2899 }
2900
2901 luaL_buffinit(L, &b);
2902 luaL_addlstring(&b, blk1, len1);
2903 len = len1;
2904 if (unlikely(ret == 2)) {
2905 luaL_addlstring(&b, blk2, len2);
2906 len += len2;
2907 }
2908 luaL_pushresult(&b);
Willy Tarreauc9fa0482018-07-10 17:43:27 +02002909 b_rep_blk(&chn->buf, ci_head(chn), ci_head(chn) + len, NULL, 0);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002910 hlua_resynchonize_proto(chn_strm(chn), !!(chn->flags & CF_ISRESP));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002911 return 1;
2912}
2913
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002914/* Check arguments for the fucntion "hlua_channel_getline_yield". */
2915__LJMP static int hlua_channel_getline(lua_State *L)
2916{
2917 MAY_LJMP(check_args(L, 1, "getline"));
2918 MAY_LJMP(hlua_checkchannel(L, 1));
2919 return MAY_LJMP(hlua_channel_getline_yield(L, 0, 0));
2920}
2921
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002922/* This function takes a string as input, and append it at the
2923 * input side of channel. If the data is too big, but a space
2924 * is probably available after sending some data, the function
2925 * yield. If the data is bigger than the buffer, or if the
2926 * channel is closed, it returns -1. otherwise, it returns the
2927 * amount of data writed.
2928 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002929__LJMP static int hlua_channel_append_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002930{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002931 struct channel *chn = MAY_LJMP(hlua_checkchannel(L, 1));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002932 size_t len;
2933 const char *str = MAY_LJMP(luaL_checklstring(L, 2, &len));
2934 int l = MAY_LJMP(luaL_checkinteger(L, 3));
2935 int ret;
2936 int max;
2937
Christopher Fauleta73e59b2016-12-09 17:30:18 +01002938 /* Check if the buffer is avalaible because HAProxy doesn't allocate
2939 * the request buffer if its not required.
2940 */
Willy Tarreauc9fa0482018-07-10 17:43:27 +02002941 if (chn->buf.size == 0) {
Christopher Fauleta73e59b2016-12-09 17:30:18 +01002942 si_applet_cant_put(chn_prod(chn));
2943 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_append_yield, TICK_ETERNITY, 0));
2944 }
2945
Willy Tarreauc9fa0482018-07-10 17:43:27 +02002946 max = channel_recv_limit(chn) - b_data(&chn->buf);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002947 if (max > len - l)
2948 max = len - l;
2949
Willy Tarreau06d80a92017-10-19 14:32:15 +02002950 ret = ci_putblk(chn, str + l, max);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002951 if (ret == -2 || ret == -3) {
2952 lua_pushinteger(L, -1);
2953 return 1;
2954 }
Willy Tarreaubc18da12015-03-13 14:00:47 +01002955 if (ret == -1) {
2956 chn->flags |= CF_WAKE_WRITE;
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002957 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_append_yield, TICK_ETERNITY, 0));
Willy Tarreaubc18da12015-03-13 14:00:47 +01002958 }
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002959 l += ret;
2960 lua_pop(L, 1);
2961 lua_pushinteger(L, l);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002962 hlua_resynchonize_proto(chn_strm(chn), !!(chn->flags & CF_ISRESP));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002963
Willy Tarreauc9fa0482018-07-10 17:43:27 +02002964 max = channel_recv_limit(chn) - b_data(&chn->buf);
Willy Tarreaua79021a2018-06-15 18:07:57 +02002965 if (max == 0 && co_data(chn) == 0) {
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002966 /* There are no space avalaible, and the output buffer is empty.
2967 * in this case, we cannot add more data, so we cannot yield,
2968 * we return the amount of copyied data.
2969 */
2970 return 1;
2971 }
2972 if (l < len)
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002973 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_append_yield, TICK_ETERNITY, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002974 return 1;
2975}
2976
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002977/* just a wrapper of "hlua_channel_append_yield". It returns the length
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002978 * of the writed string, or -1 if the channel is closed or if the
2979 * buffer size is too little for the data.
2980 */
2981__LJMP static int hlua_channel_append(lua_State *L)
2982{
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002983 size_t len;
2984
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002985 MAY_LJMP(check_args(L, 2, "append"));
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002986 MAY_LJMP(hlua_checkchannel(L, 1));
2987 MAY_LJMP(luaL_checklstring(L, 2, &len));
2988 MAY_LJMP(luaL_checkinteger(L, 3));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002989 lua_pushinteger(L, 0);
2990
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002991 return MAY_LJMP(hlua_channel_append_yield(L, 0, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002992}
2993
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002994/* just a wrapper of "hlua_channel_append_yield". This wrapper starts
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002995 * his process by cleaning the buffer. The result is a replacement
2996 * of the current data. It returns the length of the writed string,
2997 * or -1 if the channel is closed or if the buffer size is too
2998 * little for the data.
2999 */
3000__LJMP static int hlua_channel_set(lua_State *L)
3001{
Willy Tarreau47860ed2015-03-10 14:07:50 +01003002 struct channel *chn;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01003003
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003004 MAY_LJMP(check_args(L, 2, "set"));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01003005 chn = MAY_LJMP(hlua_checkchannel(L, 1));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003006 lua_pushinteger(L, 0);
3007
Willy Tarreauc9fa0482018-07-10 17:43:27 +02003008 b_set_data(&chn->buf, co_data(chn));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003009
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01003010 return MAY_LJMP(hlua_channel_append_yield(L, 0, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003011}
3012
3013/* Append data in the output side of the buffer. This data is immediatly
3014 * sent. The fcuntion returns the ammount of data writed. If the buffer
3015 * cannot contains the data, the function yield. The function returns -1
3016 * if the channel is closed.
3017 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01003018__LJMP static int hlua_channel_send_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003019{
Willy Tarreau47860ed2015-03-10 14:07:50 +01003020 struct channel *chn = MAY_LJMP(hlua_checkchannel(L, 1));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003021 size_t len;
3022 const char *str = MAY_LJMP(luaL_checklstring(L, 2, &len));
3023 int l = MAY_LJMP(luaL_checkinteger(L, 3));
3024 int max;
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01003025 struct hlua *hlua = hlua_gethlua(L);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003026
Willy Tarreau47860ed2015-03-10 14:07:50 +01003027 if (unlikely(channel_output_closed(chn))) {
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003028 lua_pushinteger(L, -1);
3029 return 1;
3030 }
3031
Thierry FOURNIER3e3a6082015-03-05 17:06:12 +01003032 /* Check if the buffer is avalaible because HAProxy doesn't allocate
3033 * the request buffer if its not required.
3034 */
Willy Tarreauc9fa0482018-07-10 17:43:27 +02003035 if (chn->buf.size == 0) {
Christopher Fauleta73e59b2016-12-09 17:30:18 +01003036 si_applet_cant_put(chn_prod(chn));
3037 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_send_yield, TICK_ETERNITY, 0));
Thierry FOURNIER3e3a6082015-03-05 17:06:12 +01003038 }
3039
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01003040 /* the writed data will be immediatly sent, so we can check
3041 * the avalaible space without taking in account the reserve.
3042 * The reserve is guaranted for the processing of incoming
3043 * data, because the buffer will be flushed.
3044 */
Willy Tarreauc9fa0482018-07-10 17:43:27 +02003045 max = b_room(&chn->buf);
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01003046
3047 /* If there are no space avalaible, and the output buffer is empty.
3048 * in this case, we cannot add more data, so we cannot yield,
3049 * we return the amount of copyied data.
3050 */
Willy Tarreaua79021a2018-06-15 18:07:57 +02003051 if (max == 0 && co_data(chn) == 0)
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01003052 return 1;
3053
3054 /* Adjust the real required length. */
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003055 if (max > len - l)
3056 max = len - l;
3057
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01003058 /* The buffer avalaible size may be not contiguous. This test
3059 * detects a non contiguous buffer and realign it.
3060 */
Willy Tarreau3f679992018-06-15 15:06:42 +02003061 if (ci_space_for_replace(chn) < max)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003062 channel_slow_realign(chn, trash.area);
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01003063
3064 /* Copy input data in the buffer. */
Willy Tarreauc9fa0482018-07-10 17:43:27 +02003065 max = b_rep_blk(&chn->buf, ci_head(chn), ci_head(chn), str + l, max);
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01003066
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003067 /* buffer replace considers that the input part is filled.
3068 * so, I must forward these new data in the output part.
3069 */
Willy Tarreaubcbd3932018-06-06 07:13:22 +02003070 c_adv(chn, max);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003071
3072 l += max;
3073 lua_pop(L, 1);
3074 lua_pushinteger(L, l);
3075
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01003076 /* If there are no space avalaible, and the output buffer is empty.
3077 * in this case, we cannot add more data, so we cannot yield,
3078 * we return the amount of copyied data.
3079 */
Willy Tarreauc9fa0482018-07-10 17:43:27 +02003080 max = b_room(&chn->buf);
Willy Tarreaua79021a2018-06-15 18:07:57 +02003081 if (max == 0 && co_data(chn) == 0)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003082 return 1;
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01003083
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01003084 if (l < len) {
3085 /* If we are waiting for space in the response buffer, we
3086 * must set the flag WAKERESWR. This flag required the task
3087 * wake up if any activity is detected on the response buffer.
3088 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01003089 if (chn->flags & CF_ISRESP)
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01003090 HLUA_SET_WAKERESWR(hlua);
Thierry FOURNIER53e08ec2015-03-06 00:35:53 +01003091 else
3092 HLUA_SET_WAKEREQWR(hlua);
3093 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_send_yield, TICK_ETERNITY, 0));
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01003094 }
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003095
3096 return 1;
3097}
3098
3099/* Just a wraper of "_hlua_channel_send". This wrapper permits
3100 * yield the LUA process, and resume it without checking the
3101 * input arguments.
3102 */
3103__LJMP static int hlua_channel_send(lua_State *L)
3104{
3105 MAY_LJMP(check_args(L, 2, "send"));
3106 lua_pushinteger(L, 0);
3107
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01003108 return MAY_LJMP(hlua_channel_send_yield(L, 0, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003109}
3110
3111/* This function forward and amount of butes. The data pass from
3112 * the input side of the buffer to the output side, and can be
3113 * forwarded. This function never fails.
3114 *
3115 * The Lua function takes an amount of bytes to be forwarded in
3116 * imput. It returns the number of bytes forwarded.
3117 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01003118__LJMP static int hlua_channel_forward_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003119{
Willy Tarreau47860ed2015-03-10 14:07:50 +01003120 struct channel *chn;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003121 int len;
3122 int l;
3123 int max;
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01003124 struct hlua *hlua = hlua_gethlua(L);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003125
3126 chn = MAY_LJMP(hlua_checkchannel(L, 1));
3127 len = MAY_LJMP(luaL_checkinteger(L, 2));
3128 l = MAY_LJMP(luaL_checkinteger(L, -1));
3129
3130 max = len - l;
Willy Tarreaua79021a2018-06-15 18:07:57 +02003131 if (max > ci_data(chn))
3132 max = ci_data(chn);
Willy Tarreau47860ed2015-03-10 14:07:50 +01003133 channel_forward(chn, max);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003134 l += max;
3135
3136 lua_pop(L, 1);
3137 lua_pushinteger(L, l);
3138
3139 /* Check if it miss bytes to forward. */
3140 if (l < len) {
3141 /* The the input channel or the output channel are closed, we
3142 * must return the amount of data forwarded.
3143 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01003144 if (channel_input_closed(chn) || channel_output_closed(chn))
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003145 return 1;
3146
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01003147 /* If we are waiting for space data in the response buffer, we
3148 * must set the flag WAKERESWR. This flag required the task
3149 * wake up if any activity is detected on the response buffer.
3150 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01003151 if (chn->flags & CF_ISRESP)
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01003152 HLUA_SET_WAKERESWR(hlua);
Thierry FOURNIER53e08ec2015-03-06 00:35:53 +01003153 else
3154 HLUA_SET_WAKEREQWR(hlua);
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01003155
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003156 /* Otherwise, we can yield waiting for new data in the inpout side. */
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +01003157 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_forward_yield, TICK_ETERNITY, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003158 }
3159
3160 return 1;
3161}
3162
3163/* Just check the input and prepare the stack for the previous
3164 * function "hlua_channel_forward_yield"
3165 */
3166__LJMP static int hlua_channel_forward(lua_State *L)
3167{
3168 MAY_LJMP(check_args(L, 2, "forward"));
3169 MAY_LJMP(hlua_checkchannel(L, 1));
3170 MAY_LJMP(luaL_checkinteger(L, 2));
3171
3172 lua_pushinteger(L, 0);
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01003173 return MAY_LJMP(hlua_channel_forward_yield(L, 0, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003174}
3175
3176/* Just returns the number of bytes available in the input
3177 * side of the buffer. This function never fails.
3178 */
3179__LJMP static int hlua_channel_get_in_len(lua_State *L)
3180{
Willy Tarreau47860ed2015-03-10 14:07:50 +01003181 struct channel *chn;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01003182
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003183 MAY_LJMP(check_args(L, 1, "get_in_len"));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01003184 chn = MAY_LJMP(hlua_checkchannel(L, 1));
Willy Tarreaua79021a2018-06-15 18:07:57 +02003185 lua_pushinteger(L, ci_data(chn));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003186 return 1;
3187}
3188
Thierry FOURNIER / OZON.IO65192f32016-11-07 15:28:40 +01003189/* Returns true if the channel is full. */
3190__LJMP static int hlua_channel_is_full(lua_State *L)
3191{
3192 struct channel *chn;
3193 int rem;
3194
3195 MAY_LJMP(check_args(L, 1, "is_full"));
3196 chn = MAY_LJMP(hlua_checkchannel(L, 1));
3197
Willy Tarreauc9fa0482018-07-10 17:43:27 +02003198 rem = b_room(&chn->buf);
Thierry FOURNIER / OZON.IO65192f32016-11-07 15:28:40 +01003199 rem -= global.tune.maxrewrite; /* Rewrite reserved size */
3200
3201 lua_pushboolean(L, rem <= 0);
3202 return 1;
3203}
3204
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003205/* Just returns the number of bytes available in the output
3206 * side of the buffer. This function never fails.
3207 */
3208__LJMP static int hlua_channel_get_out_len(lua_State *L)
3209{
Willy Tarreau47860ed2015-03-10 14:07:50 +01003210 struct channel *chn;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01003211
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003212 MAY_LJMP(check_args(L, 1, "get_out_len"));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01003213 chn = MAY_LJMP(hlua_checkchannel(L, 1));
Willy Tarreaua79021a2018-06-15 18:07:57 +02003214 lua_pushinteger(L, co_data(chn));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003215 return 1;
3216}
3217
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003218/*
3219 *
3220 *
3221 * Class Fetches
3222 *
3223 *
3224 */
3225
3226/* Returns a struct hlua_session if the stack entry "ud" is
Willy Tarreau87b09662015-04-03 00:22:06 +02003227 * a class stream, otherwise it throws an error.
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003228 */
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003229__LJMP static struct hlua_smp *hlua_checkfetches(lua_State *L, int ud)
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003230{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003231 return MAY_LJMP(hlua_checkudata(L, ud, class_fetches_ref));
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003232}
3233
3234/* This function creates and push in the stack a fetch object according
3235 * with a current TXN.
3236 */
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003237static int hlua_fetches_new(lua_State *L, struct hlua_txn *txn, unsigned int flags)
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003238{
Willy Tarreau7073c472015-04-06 11:15:40 +02003239 struct hlua_smp *hsmp;
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003240
3241 /* Check stack size. */
3242 if (!lua_checkstack(L, 3))
3243 return 0;
3244
3245 /* Create the object: obj[0] = userdata.
3246 * Note that the base of the Fetches object is the
3247 * transaction object.
3248 */
3249 lua_newtable(L);
Willy Tarreau7073c472015-04-06 11:15:40 +02003250 hsmp = lua_newuserdata(L, sizeof(*hsmp));
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003251 lua_rawseti(L, -2, 0);
3252
Willy Tarreau7073c472015-04-06 11:15:40 +02003253 hsmp->s = txn->s;
3254 hsmp->p = txn->p;
Thierry FOURNIERc4eebc82015-11-02 10:01:59 +01003255 hsmp->dir = txn->dir;
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003256 hsmp->flags = flags;
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003257
3258 /* Pop a class sesison metatable and affect it to the userdata. */
3259 lua_rawgeti(L, LUA_REGISTRYINDEX, class_fetches_ref);
3260 lua_setmetatable(L, -2);
3261
3262 return 1;
3263}
3264
3265/* This function is an LUA binding. It is called with each sample-fetch.
3266 * It uses closure argument to store the associated sample-fetch. It
3267 * returns only one argument or throws an error. An error is thrown
3268 * only if an error is encountered during the argument parsing. If
3269 * the "sample-fetch" function fails, nil is returned.
3270 */
3271__LJMP static int hlua_run_sample_fetch(lua_State *L)
3272{
Willy Tarreaub2ccb562015-04-06 11:11:15 +02003273 struct hlua_smp *hsmp;
Willy Tarreau2ec22742015-03-10 14:27:20 +01003274 struct sample_fetch *f;
Frédéric Lécaillef874a832018-06-15 13:56:04 +02003275 struct arg args[ARGM_NBARGS + 1] = {{0}};
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003276 int i;
3277 struct sample smp;
3278
3279 /* Get closure arguments. */
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003280 f = lua_touserdata(L, lua_upvalueindex(1));
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003281
3282 /* Get traditionnal arguments. */
Willy Tarreaub2ccb562015-04-06 11:11:15 +02003283 hsmp = MAY_LJMP(hlua_checkfetches(L, 1));
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003284
Thierry FOURNIERca988662015-12-20 18:43:03 +01003285 /* Check execution authorization. */
3286 if (f->use & SMP_USE_HTTP_ANY &&
3287 !(hsmp->flags & HLUA_F_MAY_USE_HTTP)) {
3288 lua_pushfstring(L, "the sample-fetch '%s' needs an HTTP parser which "
3289 "is not available in Lua services", f->kw);
3290 WILL_LJMP(lua_error(L));
3291 }
3292
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003293 /* Get extra arguments. */
3294 for (i = 0; i < lua_gettop(L) - 1; i++) {
3295 if (i >= ARGM_NBARGS)
3296 break;
3297 hlua_lua2arg(L, i + 2, &args[i]);
3298 }
3299 args[i].type = ARGT_STOP;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003300 args[i].data.str.area = NULL;
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003301
3302 /* Check arguments. */
Willy Tarreaub2ccb562015-04-06 11:11:15 +02003303 MAY_LJMP(hlua_lua2arg_check(L, 2, args, f->arg_mask, hsmp->p));
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003304
3305 /* Run the special args checker. */
Willy Tarreau2ec22742015-03-10 14:27:20 +01003306 if (f->val_args && !f->val_args(args, NULL)) {
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003307 lua_pushfstring(L, "error in arguments");
3308 WILL_LJMP(lua_error(L));
3309 }
3310
3311 /* Initialise the sample. */
3312 memset(&smp, 0, sizeof(smp));
3313
3314 /* Run the sample fetch process. */
Willy Tarreau1777ea62016-03-10 16:15:46 +01003315 smp_set_owner(&smp, hsmp->p, hsmp->s->sess, hsmp->s, hsmp->dir & SMP_OPT_DIR);
Thierry FOURNIER0786d052015-05-11 15:42:45 +02003316 if (!f->process(args, &smp, f->kw, f->private)) {
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003317 if (hsmp->flags & HLUA_F_AS_STRING)
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003318 lua_pushstring(L, "");
3319 else
3320 lua_pushnil(L);
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003321 return 1;
3322 }
3323
3324 /* Convert the returned sample in lua value. */
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003325 if (hsmp->flags & HLUA_F_AS_STRING)
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003326 hlua_smp2lua_str(L, &smp);
3327 else
3328 hlua_smp2lua(L, &smp);
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003329 return 1;
3330}
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003331
3332/*
3333 *
3334 *
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003335 * Class Converters
3336 *
3337 *
3338 */
3339
3340/* Returns a struct hlua_session if the stack entry "ud" is
Willy Tarreau87b09662015-04-03 00:22:06 +02003341 * a class stream, otherwise it throws an error.
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003342 */
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003343__LJMP static struct hlua_smp *hlua_checkconverters(lua_State *L, int ud)
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003344{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003345 return MAY_LJMP(hlua_checkudata(L, ud, class_converters_ref));
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003346}
3347
3348/* This function creates and push in the stack a Converters object
3349 * according with a current TXN.
3350 */
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003351static int hlua_converters_new(lua_State *L, struct hlua_txn *txn, unsigned int flags)
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003352{
Willy Tarreau7073c472015-04-06 11:15:40 +02003353 struct hlua_smp *hsmp;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003354
3355 /* Check stack size. */
3356 if (!lua_checkstack(L, 3))
3357 return 0;
3358
3359 /* Create the object: obj[0] = userdata.
3360 * Note that the base of the Converters object is the
3361 * same than the TXN object.
3362 */
3363 lua_newtable(L);
Willy Tarreau7073c472015-04-06 11:15:40 +02003364 hsmp = lua_newuserdata(L, sizeof(*hsmp));
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003365 lua_rawseti(L, -2, 0);
3366
Willy Tarreau7073c472015-04-06 11:15:40 +02003367 hsmp->s = txn->s;
3368 hsmp->p = txn->p;
Thierry FOURNIERc4eebc82015-11-02 10:01:59 +01003369 hsmp->dir = txn->dir;
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003370 hsmp->flags = flags;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003371
Willy Tarreau87b09662015-04-03 00:22:06 +02003372 /* Pop a class stream metatable and affect it to the table. */
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003373 lua_rawgeti(L, LUA_REGISTRYINDEX, class_converters_ref);
3374 lua_setmetatable(L, -2);
3375
3376 return 1;
3377}
3378
3379/* This function is an LUA binding. It is called with each converter.
3380 * It uses closure argument to store the associated converter. It
3381 * returns only one argument or throws an error. An error is thrown
3382 * only if an error is encountered during the argument parsing. If
3383 * the converter function function fails, nil is returned.
3384 */
3385__LJMP static int hlua_run_sample_conv(lua_State *L)
3386{
Willy Tarreauda5f1082015-04-06 11:17:13 +02003387 struct hlua_smp *hsmp;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003388 struct sample_conv *conv;
Frédéric Lécaillef874a832018-06-15 13:56:04 +02003389 struct arg args[ARGM_NBARGS + 1] = {{0}};
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003390 int i;
3391 struct sample smp;
3392
3393 /* Get closure arguments. */
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003394 conv = lua_touserdata(L, lua_upvalueindex(1));
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003395
3396 /* Get traditionnal arguments. */
Willy Tarreauda5f1082015-04-06 11:17:13 +02003397 hsmp = MAY_LJMP(hlua_checkconverters(L, 1));
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003398
3399 /* Get extra arguments. */
3400 for (i = 0; i < lua_gettop(L) - 2; i++) {
3401 if (i >= ARGM_NBARGS)
3402 break;
3403 hlua_lua2arg(L, i + 3, &args[i]);
3404 }
3405 args[i].type = ARGT_STOP;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003406 args[i].data.str.area = NULL;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003407
3408 /* Check arguments. */
Willy Tarreauda5f1082015-04-06 11:17:13 +02003409 MAY_LJMP(hlua_lua2arg_check(L, 3, args, conv->arg_mask, hsmp->p));
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003410
3411 /* Run the special args checker. */
3412 if (conv->val_args && !conv->val_args(args, conv, "", 0, NULL)) {
3413 hlua_pusherror(L, "error in arguments");
3414 WILL_LJMP(lua_error(L));
3415 }
3416
3417 /* Initialise the sample. */
3418 if (!hlua_lua2smp(L, 2, &smp)) {
3419 hlua_pusherror(L, "error in the input argument");
3420 WILL_LJMP(lua_error(L));
3421 }
3422
Willy Tarreau1777ea62016-03-10 16:15:46 +01003423 smp_set_owner(&smp, hsmp->p, hsmp->s->sess, hsmp->s, hsmp->dir & SMP_OPT_DIR);
3424
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003425 /* Apply expected cast. */
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02003426 if (!sample_casts[smp.data.type][conv->in_type]) {
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003427 hlua_pusherror(L, "invalid input argument: cannot cast '%s' to '%s'",
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02003428 smp_to_type[smp.data.type], smp_to_type[conv->in_type]);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003429 WILL_LJMP(lua_error(L));
3430 }
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02003431 if (sample_casts[smp.data.type][conv->in_type] != c_none &&
3432 !sample_casts[smp.data.type][conv->in_type](&smp)) {
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003433 hlua_pusherror(L, "error during the input argument casting");
3434 WILL_LJMP(lua_error(L));
3435 }
3436
3437 /* Run the sample conversion process. */
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02003438 if (!conv->process(args, &smp, conv->private)) {
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003439 if (hsmp->flags & HLUA_F_AS_STRING)
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003440 lua_pushstring(L, "");
3441 else
Willy Tarreaua678b432015-08-28 10:14:59 +02003442 lua_pushnil(L);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003443 return 1;
3444 }
3445
3446 /* Convert the returned sample in lua value. */
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003447 if (hsmp->flags & HLUA_F_AS_STRING)
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003448 hlua_smp2lua_str(L, &smp);
3449 else
3450 hlua_smp2lua(L, &smp);
Willy Tarreaua678b432015-08-28 10:14:59 +02003451 return 1;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003452}
3453
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003454/*
3455 *
3456 *
3457 * Class AppletTCP
3458 *
3459 *
3460 */
3461
3462/* Returns a struct hlua_txn if the stack entry "ud" is
3463 * a class stream, otherwise it throws an error.
3464 */
3465__LJMP static struct hlua_appctx *hlua_checkapplet_tcp(lua_State *L, int ud)
3466{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003467 return MAY_LJMP(hlua_checkudata(L, ud, class_applet_tcp_ref));
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003468}
3469
3470/* This function creates and push in the stack an Applet object
3471 * according with a current TXN.
3472 */
3473static int hlua_applet_tcp_new(lua_State *L, struct appctx *ctx)
3474{
3475 struct hlua_appctx *appctx;
3476 struct stream_interface *si = ctx->owner;
3477 struct stream *s = si_strm(si);
3478 struct proxy *p = s->be;
3479
3480 /* Check stack size. */
3481 if (!lua_checkstack(L, 3))
3482 return 0;
3483
3484 /* Create the object: obj[0] = userdata.
3485 * Note that the base of the Converters object is the
3486 * same than the TXN object.
3487 */
3488 lua_newtable(L);
3489 appctx = lua_newuserdata(L, sizeof(*appctx));
3490 lua_rawseti(L, -2, 0);
3491 appctx->appctx = ctx;
3492 appctx->htxn.s = s;
3493 appctx->htxn.p = p;
3494
3495 /* Create the "f" field that contains a list of fetches. */
3496 lua_pushstring(L, "f");
3497 if (!hlua_fetches_new(L, &appctx->htxn, 0))
3498 return 0;
3499 lua_settable(L, -3);
3500
3501 /* Create the "sf" field that contains a list of stringsafe fetches. */
3502 lua_pushstring(L, "sf");
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003503 if (!hlua_fetches_new(L, &appctx->htxn, HLUA_F_AS_STRING))
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003504 return 0;
3505 lua_settable(L, -3);
3506
3507 /* Create the "c" field that contains a list of converters. */
3508 lua_pushstring(L, "c");
3509 if (!hlua_converters_new(L, &appctx->htxn, 0))
3510 return 0;
3511 lua_settable(L, -3);
3512
3513 /* Create the "sc" field that contains a list of stringsafe converters. */
3514 lua_pushstring(L, "sc");
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003515 if (!hlua_converters_new(L, &appctx->htxn, HLUA_F_AS_STRING))
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003516 return 0;
3517 lua_settable(L, -3);
3518
3519 /* Pop a class stream metatable and affect it to the table. */
3520 lua_rawgeti(L, LUA_REGISTRYINDEX, class_applet_tcp_ref);
3521 lua_setmetatable(L, -2);
3522
3523 return 1;
3524}
3525
Thierry FOURNIER / OZON.IO4394a2c2016-12-12 12:31:54 +01003526__LJMP static int hlua_applet_tcp_set_var(lua_State *L)
3527{
3528 struct hlua_appctx *appctx;
3529 struct stream *s;
3530 const char *name;
3531 size_t len;
3532 struct sample smp;
3533
3534 MAY_LJMP(check_args(L, 3, "set_var"));
3535
3536 /* It is useles to retrieve the stream, but this function
3537 * runs only in a stream context.
3538 */
3539 appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3540 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3541 s = appctx->htxn.s;
3542
3543 /* Converts the third argument in a sample. */
3544 hlua_lua2smp(L, 3, &smp);
3545
3546 /* Store the sample in a variable. */
3547 smp_set_owner(&smp, s->be, s->sess, s, 0);
3548 vars_set_by_name(name, len, &smp);
3549 return 0;
3550}
3551
3552__LJMP static int hlua_applet_tcp_unset_var(lua_State *L)
3553{
3554 struct hlua_appctx *appctx;
3555 struct stream *s;
3556 const char *name;
3557 size_t len;
3558 struct sample smp;
3559
3560 MAY_LJMP(check_args(L, 2, "unset_var"));
3561
3562 /* It is useles to retrieve the stream, but this function
3563 * runs only in a stream context.
3564 */
3565 appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3566 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3567 s = appctx->htxn.s;
3568
3569 /* Unset the variable. */
3570 smp_set_owner(&smp, s->be, s->sess, s, 0);
3571 vars_unset_by_name(name, len, &smp);
3572 return 0;
3573}
3574
3575__LJMP static int hlua_applet_tcp_get_var(lua_State *L)
3576{
3577 struct hlua_appctx *appctx;
3578 struct stream *s;
3579 const char *name;
3580 size_t len;
3581 struct sample smp;
3582
3583 MAY_LJMP(check_args(L, 2, "get_var"));
3584
3585 /* It is useles to retrieve the stream, but this function
3586 * runs only in a stream context.
3587 */
3588 appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3589 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3590 s = appctx->htxn.s;
3591
3592 smp_set_owner(&smp, s->be, s->sess, s, 0);
3593 if (!vars_get_by_name(name, len, &smp)) {
3594 lua_pushnil(L);
3595 return 1;
3596 }
3597
3598 return hlua_smp2lua(L, &smp);
3599}
3600
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003601__LJMP static int hlua_applet_tcp_set_priv(lua_State *L)
3602{
3603 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3604 struct stream *s = appctx->htxn.s;
Thierry FOURNIER3b0a6d42016-12-16 08:48:32 +01003605 struct hlua *hlua;
3606
3607 /* Note that this hlua struct is from the session and not from the applet. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01003608 if (!s->hlua)
3609 return 0;
3610 hlua = s->hlua;
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003611
3612 MAY_LJMP(check_args(L, 2, "set_priv"));
3613
3614 /* Remove previous value. */
Thierry FOURNIERe068b602017-04-26 13:27:05 +02003615 luaL_unref(L, LUA_REGISTRYINDEX, hlua->Mref);
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003616
3617 /* Get and store new value. */
3618 lua_pushvalue(L, 2); /* Copy the element 2 at the top of the stack. */
3619 hlua->Mref = luaL_ref(L, LUA_REGISTRYINDEX); /* pop the previously pushed value. */
3620
3621 return 0;
3622}
3623
3624__LJMP static int hlua_applet_tcp_get_priv(lua_State *L)
3625{
3626 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3627 struct stream *s = appctx->htxn.s;
Thierry FOURNIER3b0a6d42016-12-16 08:48:32 +01003628 struct hlua *hlua;
3629
3630 /* Note that this hlua struct is from the session and not from the applet. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01003631 if (!s->hlua) {
3632 lua_pushnil(L);
3633 return 1;
3634 }
3635 hlua = s->hlua;
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003636
3637 /* Push configuration index in the stack. */
3638 lua_rawgeti(L, LUA_REGISTRYINDEX, hlua->Mref);
3639
3640 return 1;
3641}
3642
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003643/* If expected data not yet available, it returns a yield. This function
3644 * consumes the data in the buffer. It returns a string containing the
3645 * data. This string can be empty.
3646 */
3647__LJMP static int hlua_applet_tcp_getline_yield(lua_State *L, int status, lua_KContext ctx)
3648{
3649 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3650 struct stream_interface *si = appctx->appctx->owner;
3651 int ret;
Willy Tarreau206ba832018-06-14 15:27:31 +02003652 const char *blk1;
Willy Tarreau55f3ce12018-07-18 11:49:27 +02003653 size_t len1;
Willy Tarreau206ba832018-06-14 15:27:31 +02003654 const char *blk2;
Willy Tarreau55f3ce12018-07-18 11:49:27 +02003655 size_t len2;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003656
3657 /* Read the maximum amount of data avalaible. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02003658 ret = co_getline_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003659
3660 /* Data not yet avalaible. return yield. */
3661 if (ret == 0) {
3662 si_applet_cant_get(si);
3663 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_getline_yield, TICK_ETERNITY, 0));
3664 }
3665
3666 /* End of data: commit the total strings and return. */
3667 if (ret < 0) {
3668 luaL_pushresult(&appctx->b);
3669 return 1;
3670 }
3671
3672 /* Ensure that the block 2 length is usable. */
3673 if (ret == 1)
3674 len2 = 0;
3675
3676 /* dont check the max length read and dont check. */
3677 luaL_addlstring(&appctx->b, blk1, len1);
3678 luaL_addlstring(&appctx->b, blk2, len2);
3679
3680 /* Consume input channel output buffer data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02003681 co_skip(si_oc(si), len1 + len2);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003682 luaL_pushresult(&appctx->b);
3683 return 1;
3684}
3685
3686/* Check arguments for the fucntion "hlua_channel_get_yield". */
3687__LJMP static int hlua_applet_tcp_getline(lua_State *L)
3688{
3689 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3690
3691 /* Initialise the string catenation. */
3692 luaL_buffinit(L, &appctx->b);
3693
3694 return MAY_LJMP(hlua_applet_tcp_getline_yield(L, 0, 0));
3695}
3696
3697/* If expected data not yet available, it returns a yield. This function
3698 * consumes the data in the buffer. It returns a string containing the
3699 * data. This string can be empty.
3700 */
3701__LJMP static int hlua_applet_tcp_recv_yield(lua_State *L, int status, lua_KContext ctx)
3702{
3703 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3704 struct stream_interface *si = appctx->appctx->owner;
Willy Tarreau55f3ce12018-07-18 11:49:27 +02003705 size_t len = MAY_LJMP(luaL_checkinteger(L, 2));
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003706 int ret;
Willy Tarreau206ba832018-06-14 15:27:31 +02003707 const char *blk1;
Willy Tarreau55f3ce12018-07-18 11:49:27 +02003708 size_t len1;
Willy Tarreau206ba832018-06-14 15:27:31 +02003709 const char *blk2;
Willy Tarreau55f3ce12018-07-18 11:49:27 +02003710 size_t len2;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003711
3712 /* Read the maximum amount of data avalaible. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02003713 ret = co_getblk_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003714
3715 /* Data not yet avalaible. return yield. */
3716 if (ret == 0) {
3717 si_applet_cant_get(si);
3718 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_recv_yield, TICK_ETERNITY, 0));
3719 }
3720
3721 /* End of data: commit the total strings and return. */
3722 if (ret < 0) {
3723 luaL_pushresult(&appctx->b);
3724 return 1;
3725 }
3726
3727 /* Ensure that the block 2 length is usable. */
3728 if (ret == 1)
3729 len2 = 0;
3730
3731 if (len == -1) {
3732
3733 /* If len == -1, catenate all the data avalaile and
3734 * yield because we want to get all the data until
3735 * the end of data stream.
3736 */
3737 luaL_addlstring(&appctx->b, blk1, len1);
3738 luaL_addlstring(&appctx->b, blk2, len2);
Willy Tarreau06d80a92017-10-19 14:32:15 +02003739 co_skip(si_oc(si), len1 + len2);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003740 si_applet_cant_get(si);
3741 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_recv_yield, TICK_ETERNITY, 0));
3742
3743 } else {
3744
3745 /* Copy the fisrt block caping to the length required. */
3746 if (len1 > len)
3747 len1 = len;
3748 luaL_addlstring(&appctx->b, blk1, len1);
3749 len -= len1;
3750
3751 /* Copy the second block. */
3752 if (len2 > len)
3753 len2 = len;
3754 luaL_addlstring(&appctx->b, blk2, len2);
3755 len -= len2;
3756
3757 /* Consume input channel output buffer data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02003758 co_skip(si_oc(si), len1 + len2);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003759
3760 /* If we are no other data avalaible, yield waiting for new data. */
3761 if (len > 0) {
3762 lua_pushinteger(L, len);
3763 lua_replace(L, 2);
3764 si_applet_cant_get(si);
3765 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_recv_yield, TICK_ETERNITY, 0));
3766 }
3767
3768 /* return the result. */
3769 luaL_pushresult(&appctx->b);
3770 return 1;
3771 }
3772
3773 /* we never executes this */
3774 hlua_pusherror(L, "Lua: internal error");
3775 WILL_LJMP(lua_error(L));
3776 return 0;
3777}
3778
3779/* Check arguments for the fucntion "hlua_channel_get_yield". */
3780__LJMP static int hlua_applet_tcp_recv(lua_State *L)
3781{
3782 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3783 int len = -1;
3784
3785 if (lua_gettop(L) > 2)
3786 WILL_LJMP(luaL_error(L, "The 'recv' function requires between 1 and 2 arguments."));
3787 if (lua_gettop(L) >= 2) {
3788 len = MAY_LJMP(luaL_checkinteger(L, 2));
3789 lua_pop(L, 1);
3790 }
3791
3792 /* Confirm or set the required length */
3793 lua_pushinteger(L, len);
3794
3795 /* Initialise the string catenation. */
3796 luaL_buffinit(L, &appctx->b);
3797
3798 return MAY_LJMP(hlua_applet_tcp_recv_yield(L, 0, 0));
3799}
3800
3801/* Append data in the output side of the buffer. This data is immediatly
3802 * sent. The fcuntion returns the ammount of data writed. If the buffer
3803 * cannot contains the data, the function yield. The function returns -1
3804 * if the channel is closed.
3805 */
3806__LJMP static int hlua_applet_tcp_send_yield(lua_State *L, int status, lua_KContext ctx)
3807{
3808 size_t len;
3809 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3810 const char *str = MAY_LJMP(luaL_checklstring(L, 2, &len));
3811 int l = MAY_LJMP(luaL_checkinteger(L, 3));
3812 struct stream_interface *si = appctx->appctx->owner;
3813 struct channel *chn = si_ic(si);
3814 int max;
3815
3816 /* Get the max amount of data which can write as input in the channel. */
3817 max = channel_recv_max(chn);
3818 if (max > (len - l))
3819 max = len - l;
3820
3821 /* Copy data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02003822 ci_putblk(chn, str + l, max);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003823
3824 /* update counters. */
3825 l += max;
3826 lua_pop(L, 1);
3827 lua_pushinteger(L, l);
3828
3829 /* If some data is not send, declares the situation to the
3830 * applet, and returns a yield.
3831 */
3832 if (l < len) {
3833 si_applet_cant_put(si);
3834 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_send_yield, TICK_ETERNITY, 0));
3835 }
3836
3837 return 1;
3838}
3839
3840/* Just a wraper of "hlua_applet_tcp_send_yield". This wrapper permits
3841 * yield the LUA process, and resume it without checking the
3842 * input arguments.
3843 */
3844__LJMP static int hlua_applet_tcp_send(lua_State *L)
3845{
3846 MAY_LJMP(check_args(L, 2, "send"));
3847 lua_pushinteger(L, 0);
3848
3849 return MAY_LJMP(hlua_applet_tcp_send_yield(L, 0, 0));
3850}
3851
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003852/*
3853 *
3854 *
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003855 * Class AppletHTTP
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003856 *
3857 *
3858 */
3859
3860/* Returns a struct hlua_txn if the stack entry "ud" is
Willy Tarreau87b09662015-04-03 00:22:06 +02003861 * a class stream, otherwise it throws an error.
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003862 */
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003863__LJMP static struct hlua_appctx *hlua_checkapplet_http(lua_State *L, int ud)
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003864{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003865 return MAY_LJMP(hlua_checkudata(L, ud, class_applet_http_ref));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003866}
3867
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003868/* This function creates and push in the stack an Applet object
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003869 * according with a current TXN.
3870 */
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003871static int hlua_applet_http_new(lua_State *L, struct appctx *ctx)
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003872{
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003873 struct hlua_appctx *appctx;
Thierry FOURNIER841475e2015-12-11 17:10:09 +01003874 struct hlua_txn htxn;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003875 struct stream_interface *si = ctx->owner;
3876 struct stream *s = si_strm(si);
3877 struct proxy *px = s->be;
3878 struct http_txn *txn = s->txn;
3879 const char *path;
3880 const char *end;
3881 const char *p;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003882
3883 /* Check stack size. */
3884 if (!lua_checkstack(L, 3))
3885 return 0;
3886
3887 /* Create the object: obj[0] = userdata.
3888 * Note that the base of the Converters object is the
3889 * same than the TXN object.
3890 */
3891 lua_newtable(L);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003892 appctx = lua_newuserdata(L, sizeof(*appctx));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003893 lua_rawseti(L, -2, 0);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003894 appctx->appctx = ctx;
3895 appctx->appctx->ctx.hlua_apphttp.status = 200; /* Default status code returned. */
Robin H. Johnson52f5db22017-01-01 13:10:52 -08003896 appctx->appctx->ctx.hlua_apphttp.reason = NULL; /* Use default reason based on status */
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003897 appctx->htxn.s = s;
3898 appctx->htxn.p = px;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003899
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003900 /* Create the "f" field that contains a list of fetches. */
3901 lua_pushstring(L, "f");
3902 if (!hlua_fetches_new(L, &appctx->htxn, 0))
3903 return 0;
3904 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003905
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003906 /* Create the "sf" field that contains a list of stringsafe fetches. */
3907 lua_pushstring(L, "sf");
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003908 if (!hlua_fetches_new(L, &appctx->htxn, HLUA_F_AS_STRING))
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003909 return 0;
3910 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003911
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003912 /* Create the "c" field that contains a list of converters. */
3913 lua_pushstring(L, "c");
3914 if (!hlua_converters_new(L, &appctx->htxn, 0))
3915 return 0;
3916 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003917
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003918 /* Create the "sc" field that contains a list of stringsafe converters. */
3919 lua_pushstring(L, "sc");
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003920 if (!hlua_converters_new(L, &appctx->htxn, HLUA_F_AS_STRING))
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003921 return 0;
3922 lua_settable(L, -3);
Willy Tarreaueee5b512015-04-03 23:46:31 +02003923
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003924 /* Stores the request method. */
3925 lua_pushstring(L, "method");
Willy Tarreaua79021a2018-06-15 18:07:57 +02003926 lua_pushlstring(L, ci_head(txn->req.chn), txn->req.sl.rq.m_l);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003927 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003928
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003929 /* Stores the http version. */
3930 lua_pushstring(L, "version");
Willy Tarreaua79021a2018-06-15 18:07:57 +02003931 lua_pushlstring(L, ci_head(txn->req.chn) + txn->req.sl.rq.v, txn->req.sl.rq.v_l);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003932 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003933
Thierry FOURNIER841475e2015-12-11 17:10:09 +01003934 /* creates an array of headers. hlua_http_get_headers() crates and push
3935 * the array on the top of the stack.
3936 */
3937 lua_pushstring(L, "headers");
3938 htxn.s = s;
3939 htxn.p = px;
3940 htxn.dir = SMP_OPT_DIR_REQ;
3941 if (!hlua_http_get_headers(L, &htxn, &htxn.s->txn->req))
3942 return 0;
3943 lua_settable(L, -3);
3944
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003945 /* Get path and qs */
Willy Tarreau6b952c82018-09-10 17:45:34 +02003946 path = http_txn_get_path(txn);
Thierry FOURNIER7d388632017-02-22 02:06:16 +01003947 if (path) {
Willy Tarreaua79021a2018-06-15 18:07:57 +02003948 end = ci_head(txn->req.chn) + txn->req.sl.rq.u + txn->req.sl.rq.u_l;
Thierry FOURNIER7d388632017-02-22 02:06:16 +01003949 p = path;
3950 while (p < end && *p != '?')
3951 p++;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003952
Thierry FOURNIER7d388632017-02-22 02:06:16 +01003953 /* Stores the request path. */
3954 lua_pushstring(L, "path");
3955 lua_pushlstring(L, path, p - path);
3956 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003957
Thierry FOURNIER7d388632017-02-22 02:06:16 +01003958 /* Stores the query string. */
3959 lua_pushstring(L, "qs");
3960 if (*p == '?')
3961 p++;
3962 lua_pushlstring(L, p, end - p);
3963 lua_settable(L, -3);
3964 }
Thierry FOURNIER04c57b32015-03-18 13:43:10 +01003965
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003966 /* Stores the request path. */
3967 lua_pushstring(L, "length");
3968 lua_pushinteger(L, txn->req.body_len);
3969 lua_settable(L, -3);
Thierry FOURNIER04c57b32015-03-18 13:43:10 +01003970
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003971 /* Create an array of HTTP request headers. */
3972 lua_pushstring(L, "headers");
3973 MAY_LJMP(hlua_http_get_headers(L, &appctx->htxn, &appctx->htxn.s->txn->req));
3974 lua_settable(L, -3);
Thierry FOURNIER04c57b32015-03-18 13:43:10 +01003975
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003976 /* Create an empty array of HTTP request headers. */
3977 lua_pushstring(L, "response");
3978 lua_newtable(L);
3979 lua_settable(L, -3);
Thierry FOURNIER04c57b32015-03-18 13:43:10 +01003980
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003981 /* Pop a class stream metatable and affect it to the table. */
3982 lua_rawgeti(L, LUA_REGISTRYINDEX, class_applet_http_ref);
3983 lua_setmetatable(L, -2);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003984
3985 return 1;
3986}
3987
Thierry FOURNIER / OZON.IO4394a2c2016-12-12 12:31:54 +01003988__LJMP static int hlua_applet_http_set_var(lua_State *L)
3989{
3990 struct hlua_appctx *appctx;
3991 struct stream *s;
3992 const char *name;
3993 size_t len;
3994 struct sample smp;
3995
3996 MAY_LJMP(check_args(L, 3, "set_var"));
3997
3998 /* It is useles to retrieve the stream, but this function
3999 * runs only in a stream context.
4000 */
4001 appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4002 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
4003 s = appctx->htxn.s;
4004
4005 /* Converts the third argument in a sample. */
4006 hlua_lua2smp(L, 3, &smp);
4007
4008 /* Store the sample in a variable. */
4009 smp_set_owner(&smp, s->be, s->sess, s, 0);
4010 vars_set_by_name(name, len, &smp);
4011 return 0;
4012}
4013
4014__LJMP static int hlua_applet_http_unset_var(lua_State *L)
4015{
4016 struct hlua_appctx *appctx;
4017 struct stream *s;
4018 const char *name;
4019 size_t len;
4020 struct sample smp;
4021
4022 MAY_LJMP(check_args(L, 2, "unset_var"));
4023
4024 /* It is useles to retrieve the stream, but this function
4025 * runs only in a stream context.
4026 */
4027 appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4028 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
4029 s = appctx->htxn.s;
4030
4031 /* Unset the variable. */
4032 smp_set_owner(&smp, s->be, s->sess, s, 0);
4033 vars_unset_by_name(name, len, &smp);
4034 return 0;
4035}
4036
4037__LJMP static int hlua_applet_http_get_var(lua_State *L)
4038{
4039 struct hlua_appctx *appctx;
4040 struct stream *s;
4041 const char *name;
4042 size_t len;
4043 struct sample smp;
4044
4045 MAY_LJMP(check_args(L, 2, "get_var"));
4046
4047 /* It is useles to retrieve the stream, but this function
4048 * runs only in a stream context.
4049 */
4050 appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4051 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
4052 s = appctx->htxn.s;
4053
4054 smp_set_owner(&smp, s->be, s->sess, s, 0);
4055 if (!vars_get_by_name(name, len, &smp)) {
4056 lua_pushnil(L);
4057 return 1;
4058 }
4059
4060 return hlua_smp2lua(L, &smp);
4061}
4062
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01004063__LJMP static int hlua_applet_http_set_priv(lua_State *L)
4064{
4065 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4066 struct stream *s = appctx->htxn.s;
Thierry FOURNIER3b0a6d42016-12-16 08:48:32 +01004067 struct hlua *hlua;
4068
4069 /* Note that this hlua struct is from the session and not from the applet. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01004070 if (!s->hlua)
4071 return 0;
4072 hlua = s->hlua;
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01004073
4074 MAY_LJMP(check_args(L, 2, "set_priv"));
4075
4076 /* Remove previous value. */
Thierry FOURNIERe068b602017-04-26 13:27:05 +02004077 luaL_unref(L, LUA_REGISTRYINDEX, hlua->Mref);
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01004078
4079 /* Get and store new value. */
4080 lua_pushvalue(L, 2); /* Copy the element 2 at the top of the stack. */
4081 hlua->Mref = luaL_ref(L, LUA_REGISTRYINDEX); /* pop the previously pushed value. */
4082
4083 return 0;
4084}
4085
4086__LJMP static int hlua_applet_http_get_priv(lua_State *L)
4087{
4088 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4089 struct stream *s = appctx->htxn.s;
Thierry FOURNIER3b0a6d42016-12-16 08:48:32 +01004090 struct hlua *hlua;
4091
4092 /* Note that this hlua struct is from the session and not from the applet. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01004093 if (!s->hlua) {
4094 lua_pushnil(L);
4095 return 1;
4096 }
4097 hlua = s->hlua;
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01004098
4099 /* Push configuration index in the stack. */
4100 lua_rawgeti(L, LUA_REGISTRYINDEX, hlua->Mref);
4101
4102 return 1;
4103}
4104
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004105/* If expected data not yet available, it returns a yield. This function
4106 * consumes the data in the buffer. It returns a string containing the
4107 * data. This string can be empty.
4108 */
4109__LJMP static int hlua_applet_http_getline_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004110{
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004111 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4112 struct stream_interface *si = appctx->appctx->owner;
4113 struct channel *chn = si_ic(si);
4114 int ret;
Willy Tarreau206ba832018-06-14 15:27:31 +02004115 const char *blk1;
Willy Tarreau55f3ce12018-07-18 11:49:27 +02004116 size_t len1;
Willy Tarreau206ba832018-06-14 15:27:31 +02004117 const char *blk2;
Willy Tarreau55f3ce12018-07-18 11:49:27 +02004118 size_t len2;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004119
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004120 /* Maybe we cant send a 100-continue ? */
4121 if (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_100C) {
Willy Tarreau04f1e2d2018-09-10 18:04:24 +02004122 ret = ci_putblk(chn, HTTP_100.ptr, HTTP_100.len);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004123 /* if ret == -2 or -3 the channel closed or the message si too
4124 * big for the buffers. We cant send anything. So, we ignoring
4125 * the error, considers that the 100-continue is sent, and try
4126 * to receive.
4127 * If ret is -1, we dont have room in the buffer, so we yield.
4128 */
4129 if (ret == -1) {
4130 si_applet_cant_put(si);
4131 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_getline_yield, TICK_ETERNITY, 0));
4132 }
4133 appctx->appctx->ctx.hlua_apphttp.flags &= ~APPLET_100C;
4134 }
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004135
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004136 /* Check for the end of the data. */
4137 if (appctx->appctx->ctx.hlua_apphttp.left_bytes <= 0) {
4138 luaL_pushresult(&appctx->b);
4139 return 1;
4140 }
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004141
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004142 /* Read the maximum amount of data avalaible. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02004143 ret = co_getline_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004144
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004145 /* Data not yet avalaible. return yield. */
4146 if (ret == 0) {
4147 si_applet_cant_get(si);
4148 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_getline_yield, TICK_ETERNITY, 0));
4149 }
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004150
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004151 /* End of data: commit the total strings and return. */
4152 if (ret < 0) {
4153 luaL_pushresult(&appctx->b);
4154 return 1;
4155 }
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004156
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004157 /* Ensure that the block 2 length is usable. */
4158 if (ret == 1)
4159 len2 = 0;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004160
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004161 /* Copy the fisrt block caping to the length required. */
4162 if (len1 > appctx->appctx->ctx.hlua_apphttp.left_bytes)
4163 len1 = appctx->appctx->ctx.hlua_apphttp.left_bytes;
4164 luaL_addlstring(&appctx->b, blk1, len1);
4165 appctx->appctx->ctx.hlua_apphttp.left_bytes -= len1;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004166
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004167 /* Copy the second block. */
4168 if (len2 > appctx->appctx->ctx.hlua_apphttp.left_bytes)
4169 len2 = appctx->appctx->ctx.hlua_apphttp.left_bytes;
4170 luaL_addlstring(&appctx->b, blk2, len2);
4171 appctx->appctx->ctx.hlua_apphttp.left_bytes -= len2;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004172
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004173 /* Consume input channel output buffer data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02004174 co_skip(si_oc(si), len1 + len2);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004175 luaL_pushresult(&appctx->b);
4176 return 1;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004177}
4178
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004179/* Check arguments for the fucntion "hlua_channel_get_yield". */
4180__LJMP static int hlua_applet_http_getline(lua_State *L)
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004181{
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004182 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004183
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004184 /* Initialise the string catenation. */
4185 luaL_buffinit(L, &appctx->b);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004186
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004187 return MAY_LJMP(hlua_applet_http_getline_yield(L, 0, 0));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004188}
4189
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004190/* If expected data not yet available, it returns a yield. This function
4191 * consumes the data in the buffer. It returns a string containing the
4192 * data. This string can be empty.
4193 */
4194__LJMP static int hlua_applet_http_recv_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004195{
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004196 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4197 struct stream_interface *si = appctx->appctx->owner;
4198 int len = MAY_LJMP(luaL_checkinteger(L, 2));
4199 struct channel *chn = si_ic(si);
4200 int ret;
Willy Tarreau206ba832018-06-14 15:27:31 +02004201 const char *blk1;
Willy Tarreau55f3ce12018-07-18 11:49:27 +02004202 size_t len1;
Willy Tarreau206ba832018-06-14 15:27:31 +02004203 const char *blk2;
Willy Tarreau55f3ce12018-07-18 11:49:27 +02004204 size_t len2;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004205
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004206 /* Maybe we cant send a 100-continue ? */
4207 if (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_100C) {
Willy Tarreau04f1e2d2018-09-10 18:04:24 +02004208 ret = ci_putblk(chn, HTTP_100.ptr, HTTP_100.len);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004209 /* if ret == -2 or -3 the channel closed or the message si too
4210 * big for the buffers. We cant send anything. So, we ignoring
4211 * the error, considers that the 100-continue is sent, and try
4212 * to receive.
4213 * If ret is -1, we dont have room in the buffer, so we yield.
4214 */
4215 if (ret == -1) {
4216 si_applet_cant_put(si);
4217 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_recv_yield, TICK_ETERNITY, 0));
4218 }
4219 appctx->appctx->ctx.hlua_apphttp.flags &= ~APPLET_100C;
4220 }
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004221
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004222 /* Read the maximum amount of data avalaible. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02004223 ret = co_getblk_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004224
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004225 /* Data not yet avalaible. return yield. */
4226 if (ret == 0) {
4227 si_applet_cant_get(si);
4228 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_recv_yield, TICK_ETERNITY, 0));
4229 }
4230
4231 /* End of data: commit the total strings and return. */
4232 if (ret < 0) {
4233 luaL_pushresult(&appctx->b);
4234 return 1;
4235 }
4236
4237 /* Ensure that the block 2 length is usable. */
4238 if (ret == 1)
4239 len2 = 0;
4240
4241 /* Copy the fisrt block caping to the length required. */
4242 if (len1 > len)
4243 len1 = len;
4244 luaL_addlstring(&appctx->b, blk1, len1);
4245 len -= len1;
4246
4247 /* Copy the second block. */
4248 if (len2 > len)
4249 len2 = len;
4250 luaL_addlstring(&appctx->b, blk2, len2);
4251 len -= len2;
4252
4253 /* Consume input channel output buffer data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02004254 co_skip(si_oc(si), len1 + len2);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004255 if (appctx->appctx->ctx.hlua_apphttp.left_bytes != -1)
4256 appctx->appctx->ctx.hlua_apphttp.left_bytes -= len;
4257
4258 /* If we are no other data avalaible, yield waiting for new data. */
4259 if (len > 0) {
4260 lua_pushinteger(L, len);
4261 lua_replace(L, 2);
4262 si_applet_cant_get(si);
4263 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_recv_yield, TICK_ETERNITY, 0));
4264 }
4265
4266 /* return the result. */
4267 luaL_pushresult(&appctx->b);
4268 return 1;
4269}
4270
4271/* Check arguments for the fucntion "hlua_channel_get_yield". */
4272__LJMP static int hlua_applet_http_recv(lua_State *L)
4273{
4274 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4275 int len = -1;
4276
4277 /* Check arguments. */
4278 if (lua_gettop(L) > 2)
4279 WILL_LJMP(luaL_error(L, "The 'recv' function requires between 1 and 2 arguments."));
4280 if (lua_gettop(L) >= 2) {
4281 len = MAY_LJMP(luaL_checkinteger(L, 2));
4282 lua_pop(L, 1);
4283 }
4284
4285 /* Check the required length */
4286 if (len == -1 || len > appctx->appctx->ctx.hlua_apphttp.left_bytes)
4287 len = appctx->appctx->ctx.hlua_apphttp.left_bytes;
4288 lua_pushinteger(L, len);
4289
4290 /* Initialise the string catenation. */
4291 luaL_buffinit(L, &appctx->b);
4292
4293 return MAY_LJMP(hlua_applet_http_recv_yield(L, 0, 0));
4294}
4295
4296/* Append data in the output side of the buffer. This data is immediatly
4297 * sent. The fcuntion returns the ammount of data writed. If the buffer
4298 * cannot contains the data, the function yield. The function returns -1
4299 * if the channel is closed.
4300 */
4301__LJMP static int hlua_applet_http_send_yield(lua_State *L, int status, lua_KContext ctx)
4302{
4303 size_t len;
4304 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4305 const char *str = MAY_LJMP(luaL_checklstring(L, 2, &len));
4306 int l = MAY_LJMP(luaL_checkinteger(L, 3));
4307 struct stream_interface *si = appctx->appctx->owner;
4308 struct channel *chn = si_ic(si);
4309 int max;
4310
4311 /* Get the max amount of data which can write as input in the channel. */
4312 max = channel_recv_max(chn);
4313 if (max > (len - l))
4314 max = len - l;
4315
4316 /* Copy data. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02004317 ci_putblk(chn, str + l, max);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004318
4319 /* update counters. */
4320 l += max;
4321 lua_pop(L, 1);
4322 lua_pushinteger(L, l);
4323
4324 /* If some data is not send, declares the situation to the
4325 * applet, and returns a yield.
4326 */
4327 if (l < len) {
4328 si_applet_cant_put(si);
4329 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_send_yield, TICK_ETERNITY, 0));
4330 }
4331
4332 return 1;
4333}
4334
4335/* Just a wraper of "hlua_applet_send_yield". This wrapper permits
4336 * yield the LUA process, and resume it without checking the
4337 * input arguments.
4338 */
4339__LJMP static int hlua_applet_http_send(lua_State *L)
4340{
4341 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4342 size_t len;
4343 char hex[10];
4344
4345 MAY_LJMP(luaL_checklstring(L, 2, &len));
4346
4347 /* If transfer encoding chunked is selected, we surround the data
4348 * by chunk data.
4349 */
4350 if (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_CHUNKED) {
4351 snprintf(hex, 9, "%x", (unsigned int)len);
4352 lua_pushfstring(L, "%s\r\n", hex);
4353 lua_insert(L, 2); /* swap the last 2 entries. */
4354 lua_pushstring(L, "\r\n");
4355 lua_concat(L, 3);
4356 }
4357
4358 /* This interger is used for followinf the amount of data sent. */
4359 lua_pushinteger(L, 0);
4360
4361 /* We want to send some data. Headers must be sent. */
4362 if (!(appctx->appctx->ctx.hlua_apphttp.flags & APPLET_HDR_SENT)) {
4363 hlua_pusherror(L, "Lua: 'send' you must call start_response() before sending data.");
4364 WILL_LJMP(lua_error(L));
4365 }
4366
4367 return MAY_LJMP(hlua_applet_http_send_yield(L, 0, 0));
4368}
4369
4370__LJMP static int hlua_applet_http_addheader(lua_State *L)
4371{
4372 const char *name;
4373 int ret;
4374
4375 MAY_LJMP(hlua_checkapplet_http(L, 1));
4376 name = MAY_LJMP(luaL_checkstring(L, 2));
4377 MAY_LJMP(luaL_checkstring(L, 3));
4378
4379 /* Push in the stack the "response" entry. */
4380 ret = lua_getfield(L, 1, "response");
4381 if (ret != LUA_TTABLE) {
4382 hlua_pusherror(L, "Lua: 'add_header' internal error: AppletHTTP['response'] "
4383 "is expected as an array. %s found", lua_typename(L, ret));
4384 WILL_LJMP(lua_error(L));
4385 }
4386
4387 /* check if the header is already registered if it is not
4388 * the case, register it.
4389 */
4390 ret = lua_getfield(L, -1, name);
4391 if (ret == LUA_TNIL) {
4392
4393 /* Entry not found. */
4394 lua_pop(L, 1); /* remove the nil. The "response" table is the top of the stack. */
4395
4396 /* Insert the new header name in the array in the top of the stack.
4397 * It left the new array in the top of the stack.
4398 */
4399 lua_newtable(L);
4400 lua_pushvalue(L, 2);
4401 lua_pushvalue(L, -2);
4402 lua_settable(L, -4);
4403
4404 } else if (ret != LUA_TTABLE) {
4405
4406 /* corruption error. */
4407 hlua_pusherror(L, "Lua: 'add_header' internal error: AppletHTTP['response']['%s'] "
4408 "is expected as an array. %s found", name, lua_typename(L, ret));
4409 WILL_LJMP(lua_error(L));
4410 }
4411
4412 /* Now the top od thestack is an array of values. We push
4413 * the header value as new entry.
4414 */
4415 lua_pushvalue(L, 3);
4416 ret = lua_rawlen(L, -2);
4417 lua_rawseti(L, -2, ret + 1);
4418 lua_pushboolean(L, 1);
4419 return 1;
4420}
4421
4422__LJMP static int hlua_applet_http_status(lua_State *L)
4423{
4424 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4425 int status = MAY_LJMP(luaL_checkinteger(L, 2));
Robin H. Johnson52f5db22017-01-01 13:10:52 -08004426 const char *reason = MAY_LJMP(luaL_optlstring(L, 3, NULL, NULL));
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004427
4428 if (status < 100 || status > 599) {
4429 lua_pushboolean(L, 0);
4430 return 1;
4431 }
4432
4433 appctx->appctx->ctx.hlua_apphttp.status = status;
Robin H. Johnson52f5db22017-01-01 13:10:52 -08004434 appctx->appctx->ctx.hlua_apphttp.reason = reason;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004435 lua_pushboolean(L, 1);
4436 return 1;
4437}
4438
4439/* We will build the status line and the headers of the HTTP response.
4440 * We will try send at once if its not possible, we give back the hand
4441 * waiting for more room.
4442 */
4443__LJMP static int hlua_applet_http_start_response_yield(lua_State *L, int status, lua_KContext ctx)
4444{
4445 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4446 struct stream_interface *si = appctx->appctx->owner;
4447 struct channel *chn = si_ic(si);
4448 int ret;
4449 size_t len;
4450 const char *msg;
4451
4452 /* Get the message as the first argument on the stack. */
4453 msg = MAY_LJMP(luaL_checklstring(L, 2, &len));
4454
4455 /* Send the message at once. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02004456 ret = ci_putblk(chn, msg, len);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004457
4458 /* if ret == -2 or -3 the channel closed or the message si too
4459 * big for the buffers.
4460 */
4461 if (ret == -2 || ret == -3) {
4462 hlua_pusherror(L, "Lua: 'start_response': response header block too big");
4463 WILL_LJMP(lua_error(L));
4464 }
4465
4466 /* If ret is -1, we dont have room in the buffer, so we yield. */
4467 if (ret == -1) {
4468 si_applet_cant_put(si);
4469 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_start_response_yield, TICK_ETERNITY, 0));
4470 }
4471
4472 /* Headers sent, set the flag. */
4473 appctx->appctx->ctx.hlua_apphttp.flags |= APPLET_HDR_SENT;
4474 return 0;
4475}
4476
4477__LJMP static int hlua_applet_http_start_response(lua_State *L)
4478{
Willy Tarreau83061a82018-07-13 11:56:34 +02004479 struct buffer *tmp = get_trash_chunk();
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004480 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004481 const char *name;
Willy Tarreaua3294632017-08-23 11:24:47 +02004482 size_t name_len;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004483 const char *value;
Willy Tarreaua3294632017-08-23 11:24:47 +02004484 size_t value_len;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004485 int id;
Willy Tarreauc9f4ea02017-08-23 09:32:06 +02004486 long long hdr_contentlength = -1;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004487 int hdr_chunked = 0;
Robin H. Johnson52f5db22017-01-01 13:10:52 -08004488 const char *reason = appctx->appctx->ctx.hlua_apphttp.reason;
4489
4490 if (reason == NULL)
Willy Tarreau04f1e2d2018-09-10 18:04:24 +02004491 reason = http_get_reason(appctx->appctx->ctx.hlua_apphttp.status);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004492
4493 /* Use the same http version than the request. */
4494 chunk_appendf(tmp, "HTTP/1.%c %d %s\r\n",
Thierry FOURNIERd93ea2b2015-12-20 19:14:52 +01004495 appctx->appctx->ctx.hlua_apphttp.flags & APPLET_HTTP11 ? '1' : '0',
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004496 appctx->appctx->ctx.hlua_apphttp.status,
Robin H. Johnson52f5db22017-01-01 13:10:52 -08004497 reason);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004498
4499 /* Get the array associated to the field "response" in the object AppletHTTP. */
4500 lua_pushvalue(L, 0);
4501 if (lua_getfield(L, 1, "response") != LUA_TTABLE) {
4502 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response'] missing.\n",
4503 appctx->appctx->rule->arg.hlua_rule->fcn.name);
4504 WILL_LJMP(lua_error(L));
4505 }
4506
4507 /* Browse the list of headers. */
4508 lua_pushnil(L);
4509 while(lua_next(L, -2) != 0) {
4510
4511 /* We expect a string as -2. */
4512 if (lua_type(L, -2) != LUA_TSTRING) {
4513 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response'][] element must be a string. got %s.\n",
4514 appctx->appctx->rule->arg.hlua_rule->fcn.name,
4515 lua_typename(L, lua_type(L, -2)));
4516 WILL_LJMP(lua_error(L));
4517 }
Willy Tarreaua3294632017-08-23 11:24:47 +02004518 name = lua_tolstring(L, -2, &name_len);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004519
4520 /* We expect an array as -1. */
4521 if (lua_type(L, -1) != LUA_TTABLE) {
4522 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response']['%s'] element must be an table. got %s.\n",
4523 appctx->appctx->rule->arg.hlua_rule->fcn.name,
4524 name,
4525 lua_typename(L, lua_type(L, -1)));
4526 WILL_LJMP(lua_error(L));
4527 }
4528
4529 /* Browse the table who is on the top of the stack. */
4530 lua_pushnil(L);
4531 while(lua_next(L, -2) != 0) {
4532
4533 /* We expect a number as -2. */
4534 if (lua_type(L, -2) != LUA_TNUMBER) {
4535 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response']['%s'][] element must be a number. got %s.\n",
4536 appctx->appctx->rule->arg.hlua_rule->fcn.name,
4537 name,
4538 lua_typename(L, lua_type(L, -2)));
4539 WILL_LJMP(lua_error(L));
4540 }
4541 id = lua_tointeger(L, -2);
4542
4543 /* We expect a string as -2. */
4544 if (lua_type(L, -1) != LUA_TSTRING) {
4545 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response']['%s'][%d] element must be a string. got %s.\n",
4546 appctx->appctx->rule->arg.hlua_rule->fcn.name,
4547 name, id,
4548 lua_typename(L, lua_type(L, -1)));
4549 WILL_LJMP(lua_error(L));
4550 }
Willy Tarreaua3294632017-08-23 11:24:47 +02004551 value = lua_tolstring(L, -1, &value_len);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004552
4553 /* Catenate a new header. */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02004554 if (tmp->data + name_len + 2 + value_len + 2 < tmp->size) {
4555 memcpy(tmp->area + tmp->data, name, name_len);
4556 tmp->data += name_len;
4557 tmp->area[tmp->data++] = ':';
4558 tmp->area[tmp->data++] = ' ';
Willy Tarreaua3294632017-08-23 11:24:47 +02004559
Willy Tarreau843b7cb2018-07-13 10:54:26 +02004560 memcpy(tmp->area + tmp->data, value,
4561 value_len);
4562 tmp->data += value_len;
4563 tmp->area[tmp->data++] = '\r';
4564 tmp->area[tmp->data++] = '\n';
Willy Tarreaua3294632017-08-23 11:24:47 +02004565 }
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004566
4567 /* Protocol checks. */
4568
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004569 /* Copy the header content length. The length conversion
Willy Tarreauc9f4ea02017-08-23 09:32:06 +02004570 * is done without control. If it contains a bad value,
4571 * the content-length remains negative so that we can
4572 * switch to either chunked encoding or close.
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004573 */
Willy Tarreaua3294632017-08-23 11:24:47 +02004574 if (name_len == 14 && strcasecmp("content-length", name) == 0)
Willy Tarreauc9f4ea02017-08-23 09:32:06 +02004575 strl2llrc(value, strlen(value), &hdr_contentlength);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004576
4577 /* Check if the client annouces a transfer-encoding chunked it self. */
Willy Tarreaua3294632017-08-23 11:24:47 +02004578 if (name_len == 17 && value_len == 7 &&
4579 strcasecmp("transfer-encoding", name) == 0 &&
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004580 strcasecmp("chunked", value) == 0)
4581 hdr_chunked = 1;
4582
4583 /* Remove the array from the stack, and get next element with a remaining string. */
4584 lua_pop(L, 1);
4585 }
4586
4587 /* Remove the array from the stack, and get next element with a remaining string. */
4588 lua_pop(L, 1);
4589 }
4590
Willy Tarreau06c75fe2017-08-23 09:10:38 +02004591 /* If we dont have a content-length set, and the HTTP version is 1.1
4592 * and the status code implies the presence of a message body, we must
4593 * announce a transfer encoding chunked. This is required by haproxy
4594 * for the keepalive compliance. If the applet annouces a transfer-encoding
4595 * chunked itslef, don't do anything.
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004596 */
Willy Tarreauc9f4ea02017-08-23 09:32:06 +02004597 if (hdr_contentlength < 0 && hdr_chunked == 0 &&
Willy Tarreau06c75fe2017-08-23 09:10:38 +02004598 (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_HTTP11) &&
4599 appctx->appctx->ctx.hlua_apphttp.status >= 200 &&
4600 appctx->appctx->ctx.hlua_apphttp.status != 204 &&
4601 appctx->appctx->ctx.hlua_apphttp.status != 304) {
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004602 chunk_appendf(tmp, "Transfer-encoding: chunked\r\n");
4603 appctx->appctx->ctx.hlua_apphttp.flags |= APPLET_CHUNKED;
4604 }
4605
4606 /* Finalize headers. */
4607 chunk_appendf(tmp, "\r\n");
4608
4609 /* Remove the last entry and the array of headers */
4610 lua_pop(L, 2);
4611
4612 /* Push the headers block. */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02004613 lua_pushlstring(L, tmp->area, tmp->data);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004614
4615 return MAY_LJMP(hlua_applet_http_start_response_yield(L, 0, 0));
4616}
4617
4618/*
4619 *
4620 *
4621 * Class HTTP
4622 *
4623 *
4624 */
4625
4626/* Returns a struct hlua_txn if the stack entry "ud" is
4627 * a class stream, otherwise it throws an error.
4628 */
4629__LJMP static struct hlua_txn *hlua_checkhttp(lua_State *L, int ud)
4630{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004631 return MAY_LJMP(hlua_checkudata(L, ud, class_http_ref));
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004632}
4633
4634/* This function creates and push in the stack a HTTP object
4635 * according with a current TXN.
4636 */
4637static int hlua_http_new(lua_State *L, struct hlua_txn *txn)
4638{
4639 struct hlua_txn *htxn;
4640
4641 /* Check stack size. */
4642 if (!lua_checkstack(L, 3))
4643 return 0;
4644
4645 /* Create the object: obj[0] = userdata.
4646 * Note that the base of the Converters object is the
4647 * same than the TXN object.
4648 */
4649 lua_newtable(L);
4650 htxn = lua_newuserdata(L, sizeof(*htxn));
4651 lua_rawseti(L, -2, 0);
4652
4653 htxn->s = txn->s;
4654 htxn->p = txn->p;
4655
4656 /* Pop a class stream metatable and affect it to the table. */
4657 lua_rawgeti(L, LUA_REGISTRYINDEX, class_http_ref);
4658 lua_setmetatable(L, -2);
4659
4660 return 1;
4661}
4662
4663/* This function creates ans returns an array of HTTP headers.
4664 * This function does not fails. It is used as wrapper with the
4665 * 2 following functions.
4666 */
4667__LJMP static int hlua_http_get_headers(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg)
4668{
4669 const char *cur_ptr, *cur_next, *p;
4670 int old_idx, cur_idx;
4671 struct hdr_idx_elem *cur_hdr;
4672 const char *hn, *hv;
4673 int hnl, hvl;
4674 int type;
4675 const char *in;
4676 char *out;
4677 int len;
4678
4679 /* Create the table. */
4680 lua_newtable(L);
4681
4682 if (!htxn->s->txn)
4683 return 1;
4684
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004685 /* Check if a valid response is parsed */
4686 if (unlikely(msg->msg_state < HTTP_MSG_BODY))
4687 return 1;
4688
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004689 /* Build array of headers. */
4690 old_idx = 0;
Willy Tarreaua79021a2018-06-15 18:07:57 +02004691 cur_next = ci_head(msg->chn) + hdr_idx_first_pos(&htxn->s->txn->hdr_idx);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004692
4693 while (1) {
4694 cur_idx = htxn->s->txn->hdr_idx.v[old_idx].next;
4695 if (!cur_idx)
4696 break;
4697 old_idx = cur_idx;
4698
4699 cur_hdr = &htxn->s->txn->hdr_idx.v[cur_idx];
4700 cur_ptr = cur_next;
4701 cur_next = cur_ptr + cur_hdr->len + cur_hdr->cr + 1;
4702
4703 /* Now we have one full header at cur_ptr of len cur_hdr->len,
4704 * and the next header starts at cur_next. We'll check
4705 * this header in the list as well as against the default
4706 * rule.
4707 */
4708
4709 /* look for ': *'. */
4710 hn = cur_ptr;
4711 for (p = cur_ptr; p < cur_ptr + cur_hdr->len && *p != ':'; p++);
4712 if (p >= cur_ptr+cur_hdr->len)
4713 continue;
4714 hnl = p - hn;
4715 p++;
4716 while (p < cur_ptr+cur_hdr->len && ( *p == ' ' || *p == '\t' ))
4717 p++;
4718 if (p >= cur_ptr+cur_hdr->len)
4719 continue;
4720 hv = p;
4721 hvl = cur_ptr+cur_hdr->len-p;
4722
4723 /* Lowercase the key. Don't check the size of trash, it have
4724 * the size of one buffer and the input data contains in one
4725 * buffer.
4726 */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02004727 out = trash.area;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004728 for (in=hn; in<hn+hnl; in++, out++)
4729 *out = tolower(*in);
4730 *out = '\0';
4731
4732 /* Check for existing entry:
4733 * assume that the table is on the top of the stack, and
4734 * push the key in the stack, the function lua_gettable()
4735 * perform the lookup.
4736 */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02004737 lua_pushlstring(L, trash.area, hnl);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004738 lua_gettable(L, -2);
4739 type = lua_type(L, -1);
4740
4741 switch (type) {
4742 case LUA_TNIL:
4743 /* Table not found, create it. */
4744 lua_pop(L, 1); /* remove the nil value. */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02004745 lua_pushlstring(L, trash.area, hnl); /* push the header name as key. */
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004746 lua_newtable(L); /* create and push empty table. */
4747 lua_pushlstring(L, hv, hvl); /* push header value. */
4748 lua_rawseti(L, -2, 0); /* index header value (pop it). */
4749 lua_rawset(L, -3); /* index new table with header name (pop the values). */
4750 break;
4751
4752 case LUA_TTABLE:
4753 /* Entry found: push the value in the table. */
4754 len = lua_rawlen(L, -1);
4755 lua_pushlstring(L, hv, hvl); /* push header value. */
4756 lua_rawseti(L, -2, len+1); /* index header value (pop it). */
4757 lua_pop(L, 1); /* remove the table (it is stored in the main table). */
4758 break;
4759
4760 default:
4761 /* Other cases are errors. */
4762 hlua_pusherror(L, "internal error during the parsing of headers.");
4763 WILL_LJMP(lua_error(L));
4764 }
4765 }
4766
4767 return 1;
4768}
4769
4770__LJMP static int hlua_http_req_get_headers(lua_State *L)
4771{
4772 struct hlua_txn *htxn;
4773
4774 MAY_LJMP(check_args(L, 1, "req_get_headers"));
4775 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4776
4777 return hlua_http_get_headers(L, htxn, &htxn->s->txn->req);
4778}
4779
4780__LJMP static int hlua_http_res_get_headers(lua_State *L)
4781{
4782 struct hlua_txn *htxn;
4783
4784 MAY_LJMP(check_args(L, 1, "res_get_headers"));
4785 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4786
4787 return hlua_http_get_headers(L, htxn, &htxn->s->txn->rsp);
4788}
4789
4790/* This function replace full header, or just a value in
4791 * the request or in the response. It is a wrapper fir the
4792 * 4 following functions.
4793 */
4794__LJMP static inline int hlua_http_rep_hdr(lua_State *L, struct hlua_txn *htxn,
4795 struct http_msg *msg, int action)
4796{
4797 size_t name_len;
4798 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
4799 const char *reg = MAY_LJMP(luaL_checkstring(L, 3));
4800 const char *value = MAY_LJMP(luaL_checkstring(L, 4));
4801 struct my_regex re;
4802
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004803 /* Check if a valid response is parsed */
4804 if (unlikely(msg->msg_state < HTTP_MSG_BODY))
4805 return 0;
4806
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004807 if (!regex_comp(reg, &re, 1, 1, NULL))
4808 WILL_LJMP(luaL_argerror(L, 3, "invalid regex"));
4809
4810 http_transform_header_str(htxn->s, msg, name, name_len, value, &re, action);
4811 regex_free(&re);
4812 return 0;
4813}
4814
4815__LJMP static int hlua_http_req_rep_hdr(lua_State *L)
4816{
4817 struct hlua_txn *htxn;
4818
4819 MAY_LJMP(check_args(L, 4, "req_rep_hdr"));
4820 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4821
4822 return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->req, ACT_HTTP_REPLACE_HDR));
4823}
4824
4825__LJMP static int hlua_http_res_rep_hdr(lua_State *L)
4826{
4827 struct hlua_txn *htxn;
4828
4829 MAY_LJMP(check_args(L, 4, "res_rep_hdr"));
4830 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4831
4832 return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->rsp, ACT_HTTP_REPLACE_HDR));
4833}
4834
4835__LJMP static int hlua_http_req_rep_val(lua_State *L)
4836{
4837 struct hlua_txn *htxn;
4838
4839 MAY_LJMP(check_args(L, 4, "req_rep_hdr"));
4840 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4841
4842 return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->req, ACT_HTTP_REPLACE_VAL));
4843}
4844
4845__LJMP static int hlua_http_res_rep_val(lua_State *L)
4846{
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004847 struct hlua_txn *htxn;
4848
4849 MAY_LJMP(check_args(L, 4, "res_rep_val"));
4850 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4851
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02004852 return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->rsp, ACT_HTTP_REPLACE_VAL));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004853}
4854
4855/* This function deletes all the occurences of an header.
4856 * It is a wrapper for the 2 following functions.
4857 */
4858__LJMP static inline int hlua_http_del_hdr(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg)
4859{
4860 size_t len;
4861 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &len));
4862 struct hdr_ctx ctx;
Willy Tarreaueee5b512015-04-03 23:46:31 +02004863 struct http_txn *txn = htxn->s->txn;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004864
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004865 /* Check if a valid response is parsed */
4866 if (unlikely(msg->msg_state < HTTP_MSG_BODY))
4867 return 0;
4868
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004869 ctx.idx = 0;
Willy Tarreaua79021a2018-06-15 18:07:57 +02004870 while (http_find_header2(name, len, ci_head(msg->chn), &txn->hdr_idx, &ctx))
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004871 http_remove_header2(msg, &txn->hdr_idx, &ctx);
4872 return 0;
4873}
4874
4875__LJMP static int hlua_http_req_del_hdr(lua_State *L)
4876{
4877 struct hlua_txn *htxn;
4878
4879 MAY_LJMP(check_args(L, 2, "req_del_hdr"));
4880 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4881
Willy Tarreaueee5b512015-04-03 23:46:31 +02004882 return hlua_http_del_hdr(L, htxn, &htxn->s->txn->req);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004883}
4884
4885__LJMP static int hlua_http_res_del_hdr(lua_State *L)
4886{
4887 struct hlua_txn *htxn;
4888
4889 MAY_LJMP(check_args(L, 2, "req_del_hdr"));
4890 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4891
Willy Tarreaueee5b512015-04-03 23:46:31 +02004892 return hlua_http_del_hdr(L, htxn, &htxn->s->txn->rsp);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004893}
4894
4895/* This function adds an header. It is a wrapper used by
4896 * the 2 following functions.
4897 */
4898__LJMP static inline int hlua_http_add_hdr(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg)
4899{
4900 size_t name_len;
4901 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
4902 size_t value_len;
4903 const char *value = MAY_LJMP(luaL_checklstring(L, 3, &value_len));
4904 char *p;
4905
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004906 /* Check if a valid message is parsed */
4907 if (unlikely(msg->msg_state < HTTP_MSG_BODY))
4908 return 0;
4909
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004910 /* Check length. */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02004911 trash.data = value_len + name_len + 2;
4912 if (trash.data > trash.size)
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004913 return 0;
4914
4915 /* Creates the header string. */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02004916 p = trash.area;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004917 memcpy(p, name, name_len);
4918 p += name_len;
4919 *p = ':';
4920 p++;
4921 *p = ' ';
4922 p++;
4923 memcpy(p, value, value_len);
4924
Willy Tarreaueee5b512015-04-03 23:46:31 +02004925 lua_pushboolean(L, http_header_add_tail2(msg, &htxn->s->txn->hdr_idx,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02004926 trash.area, trash.data) != 0);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004927
4928 return 0;
4929}
4930
4931__LJMP static int hlua_http_req_add_hdr(lua_State *L)
4932{
4933 struct hlua_txn *htxn;
4934
4935 MAY_LJMP(check_args(L, 3, "req_add_hdr"));
4936 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4937
Willy Tarreaueee5b512015-04-03 23:46:31 +02004938 return hlua_http_add_hdr(L, htxn, &htxn->s->txn->req);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004939}
4940
4941__LJMP static int hlua_http_res_add_hdr(lua_State *L)
4942{
4943 struct hlua_txn *htxn;
4944
4945 MAY_LJMP(check_args(L, 3, "res_add_hdr"));
4946 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4947
Willy Tarreaueee5b512015-04-03 23:46:31 +02004948 return hlua_http_add_hdr(L, htxn, &htxn->s->txn->rsp);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004949}
4950
4951static int hlua_http_req_set_hdr(lua_State *L)
4952{
4953 struct hlua_txn *htxn;
4954
4955 MAY_LJMP(check_args(L, 3, "req_set_hdr"));
4956 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4957
Willy Tarreaueee5b512015-04-03 23:46:31 +02004958 hlua_http_del_hdr(L, htxn, &htxn->s->txn->req);
4959 return hlua_http_add_hdr(L, htxn, &htxn->s->txn->req);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004960}
4961
4962static int hlua_http_res_set_hdr(lua_State *L)
4963{
4964 struct hlua_txn *htxn;
4965
4966 MAY_LJMP(check_args(L, 3, "res_set_hdr"));
4967 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4968
Willy Tarreaueee5b512015-04-03 23:46:31 +02004969 hlua_http_del_hdr(L, htxn, &htxn->s->txn->rsp);
4970 return hlua_http_add_hdr(L, htxn, &htxn->s->txn->rsp);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004971}
4972
4973/* This function set the method. */
4974static int hlua_http_req_set_meth(lua_State *L)
4975{
Willy Tarreaubcb39cc2015-04-06 11:21:44 +02004976 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004977 size_t name_len;
4978 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004979
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004980 /* Check if a valid request is parsed */
4981 if (unlikely(htxn->s->txn->req.msg_state < HTTP_MSG_BODY)) {
4982 lua_pushboolean(L, 0);
4983 return 1;
4984 }
4985
Willy Tarreau987e3fb2015-04-04 01:09:08 +02004986 lua_pushboolean(L, http_replace_req_line(0, name, name_len, htxn->p, htxn->s) != -1);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004987 return 1;
4988}
4989
4990/* This function set the method. */
4991static int hlua_http_req_set_path(lua_State *L)
4992{
Willy Tarreaubcb39cc2015-04-06 11:21:44 +02004993 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004994 size_t name_len;
4995 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004996
4997 /* Check if a valid request is parsed */
4998 if (unlikely(htxn->s->txn->req.msg_state < HTTP_MSG_BODY)) {
4999 lua_pushboolean(L, 0);
5000 return 1;
5001 }
5002
Willy Tarreau987e3fb2015-04-04 01:09:08 +02005003 lua_pushboolean(L, http_replace_req_line(1, name, name_len, htxn->p, htxn->s) != -1);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01005004 return 1;
5005}
5006
5007/* This function set the query-string. */
5008static int hlua_http_req_set_query(lua_State *L)
5009{
Willy Tarreaubcb39cc2015-04-06 11:21:44 +02005010 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01005011 size_t name_len;
5012 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01005013
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02005014 /* Check if a valid request is parsed */
5015 if (unlikely(htxn->s->txn->req.msg_state < HTTP_MSG_BODY)) {
5016 lua_pushboolean(L, 0);
5017 return 1;
5018 }
5019
Thierry FOURNIER08504f42015-03-16 14:17:08 +01005020 /* Check length. */
5021 if (name_len > trash.size - 1) {
5022 lua_pushboolean(L, 0);
5023 return 1;
5024 }
5025
5026 /* Add the mark question as prefix. */
5027 chunk_reset(&trash);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005028 trash.area[trash.data++] = '?';
5029 memcpy(trash.area + trash.data, name, name_len);
5030 trash.data += name_len;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01005031
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005032 lua_pushboolean(L,
5033 http_replace_req_line(2, trash.area, trash.data, htxn->p, htxn->s) != -1);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01005034 return 1;
5035}
5036
5037/* This function set the uri. */
5038static int hlua_http_req_set_uri(lua_State *L)
5039{
Willy Tarreaubcb39cc2015-04-06 11:21:44 +02005040 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01005041 size_t name_len;
5042 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01005043
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02005044 /* Check if a valid request is parsed */
5045 if (unlikely(htxn->s->txn->req.msg_state < HTTP_MSG_BODY)) {
5046 lua_pushboolean(L, 0);
5047 return 1;
5048 }
5049
Willy Tarreau987e3fb2015-04-04 01:09:08 +02005050 lua_pushboolean(L, http_replace_req_line(3, name, name_len, htxn->p, htxn->s) != -1);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01005051 return 1;
5052}
5053
Robin H. Johnson52f5db22017-01-01 13:10:52 -08005054/* This function set the response code & optionally reason. */
Thierry FOURNIER35d70ef2015-08-26 16:21:56 +02005055static int hlua_http_res_set_status(lua_State *L)
5056{
5057 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
5058 unsigned int code = MAY_LJMP(luaL_checkinteger(L, 2));
Robin H. Johnson52f5db22017-01-01 13:10:52 -08005059 const char *reason = MAY_LJMP(luaL_optlstring(L, 3, NULL, NULL));
Thierry FOURNIER35d70ef2015-08-26 16:21:56 +02005060
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02005061 /* Check if a valid response is parsed */
5062 if (unlikely(htxn->s->txn->rsp.msg_state < HTTP_MSG_BODY))
5063 return 0;
5064
Robin H. Johnson52f5db22017-01-01 13:10:52 -08005065 http_set_status(code, reason, htxn->s);
Thierry FOURNIER35d70ef2015-08-26 16:21:56 +02005066 return 0;
5067}
5068
Thierry FOURNIER08504f42015-03-16 14:17:08 +01005069/*
5070 *
5071 *
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01005072 * Class TXN
5073 *
5074 *
5075 */
5076
5077/* Returns a struct hlua_session if the stack entry "ud" is
Willy Tarreau87b09662015-04-03 00:22:06 +02005078 * a class stream, otherwise it throws an error.
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01005079 */
5080__LJMP static struct hlua_txn *hlua_checktxn(lua_State *L, int ud)
5081{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005082 return MAY_LJMP(hlua_checkudata(L, ud, class_txn_ref));
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01005083}
5084
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +02005085__LJMP static int hlua_set_var(lua_State *L)
5086{
5087 struct hlua_txn *htxn;
5088 const char *name;
5089 size_t len;
5090 struct sample smp;
5091
5092 MAY_LJMP(check_args(L, 3, "set_var"));
5093
5094 /* It is useles to retrieve the stream, but this function
5095 * runs only in a stream context.
5096 */
5097 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5098 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
5099
5100 /* Converts the third argument in a sample. */
5101 hlua_lua2smp(L, 3, &smp);
5102
5103 /* Store the sample in a variable. */
Willy Tarreau7560dd42016-03-10 16:28:58 +01005104 smp_set_owner(&smp, htxn->p, htxn->s->sess, htxn->s, htxn->dir & SMP_OPT_DIR);
Willy Tarreau6204cd92016-03-10 16:33:04 +01005105 vars_set_by_name(name, len, &smp);
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +02005106 return 0;
5107}
5108
Christopher Faulet85d79c92016-11-09 16:54:56 +01005109__LJMP static int hlua_unset_var(lua_State *L)
5110{
5111 struct hlua_txn *htxn;
5112 const char *name;
5113 size_t len;
5114 struct sample smp;
5115
5116 MAY_LJMP(check_args(L, 2, "unset_var"));
5117
5118 /* It is useles to retrieve the stream, but this function
5119 * runs only in a stream context.
5120 */
5121 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5122 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
5123
5124 /* Unset the variable. */
5125 smp_set_owner(&smp, htxn->p, htxn->s->sess, htxn->s, htxn->dir & SMP_OPT_DIR);
5126 vars_unset_by_name(name, len, &smp);
5127 return 0;
5128}
5129
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +02005130__LJMP static int hlua_get_var(lua_State *L)
5131{
5132 struct hlua_txn *htxn;
5133 const char *name;
5134 size_t len;
5135 struct sample smp;
5136
5137 MAY_LJMP(check_args(L, 2, "get_var"));
5138
5139 /* It is useles to retrieve the stream, but this function
5140 * runs only in a stream context.
5141 */
5142 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5143 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
5144
Willy Tarreau7560dd42016-03-10 16:28:58 +01005145 smp_set_owner(&smp, htxn->p, htxn->s->sess, htxn->s, htxn->dir & SMP_OPT_DIR);
Willy Tarreau6204cd92016-03-10 16:33:04 +01005146 if (!vars_get_by_name(name, len, &smp)) {
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +02005147 lua_pushnil(L);
5148 return 1;
5149 }
5150
5151 return hlua_smp2lua(L, &smp);
5152}
5153
Willy Tarreau59551662015-03-10 14:23:13 +01005154__LJMP static int hlua_set_priv(lua_State *L)
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01005155{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005156 struct hlua *hlua;
5157
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01005158 MAY_LJMP(check_args(L, 2, "set_priv"));
5159
Willy Tarreau87b09662015-04-03 00:22:06 +02005160 /* It is useles to retrieve the stream, but this function
5161 * runs only in a stream context.
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01005162 */
5163 MAY_LJMP(hlua_checktxn(L, 1));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005164 hlua = hlua_gethlua(L);
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01005165
5166 /* Remove previous value. */
Thierry FOURNIERe068b602017-04-26 13:27:05 +02005167 luaL_unref(L, LUA_REGISTRYINDEX, hlua->Mref);
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01005168
5169 /* Get and store new value. */
5170 lua_pushvalue(L, 2); /* Copy the element 2 at the top of the stack. */
5171 hlua->Mref = luaL_ref(L, LUA_REGISTRYINDEX); /* pop the previously pushed value. */
5172
5173 return 0;
5174}
5175
Willy Tarreau59551662015-03-10 14:23:13 +01005176__LJMP static int hlua_get_priv(lua_State *L)
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01005177{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005178 struct hlua *hlua;
5179
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01005180 MAY_LJMP(check_args(L, 1, "get_priv"));
5181
Willy Tarreau87b09662015-04-03 00:22:06 +02005182 /* It is useles to retrieve the stream, but this function
5183 * runs only in a stream context.
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01005184 */
5185 MAY_LJMP(hlua_checktxn(L, 1));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005186 hlua = hlua_gethlua(L);
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01005187
5188 /* Push configuration index in the stack. */
5189 lua_rawgeti(L, LUA_REGISTRYINDEX, hlua->Mref);
5190
5191 return 1;
5192}
5193
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01005194/* Create stack entry containing a class TXN. This function
5195 * return 0 if the stack does not contains free slots,
5196 * otherwise it returns 1.
5197 */
Thierry FOURNIERab00df62016-07-14 11:42:37 +02005198static int hlua_txn_new(lua_State *L, struct stream *s, struct proxy *p, int dir, int flags)
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01005199{
Willy Tarreaude491382015-04-06 11:04:28 +02005200 struct hlua_txn *htxn;
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01005201
5202 /* Check stack size. */
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01005203 if (!lua_checkstack(L, 3))
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01005204 return 0;
5205
5206 /* NOTE: The allocation never fails. The failure
5207 * throw an error, and the function never returns.
5208 * if the throw is not avalaible, the process is aborted.
5209 */
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01005210 /* Create the object: obj[0] = userdata. */
5211 lua_newtable(L);
Willy Tarreaude491382015-04-06 11:04:28 +02005212 htxn = lua_newuserdata(L, sizeof(*htxn));
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01005213 lua_rawseti(L, -2, 0);
5214
Willy Tarreaude491382015-04-06 11:04:28 +02005215 htxn->s = s;
5216 htxn->p = p;
Thierry FOURNIERc4eebc82015-11-02 10:01:59 +01005217 htxn->dir = dir;
Thierry FOURNIERab00df62016-07-14 11:42:37 +02005218 htxn->flags = flags;
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01005219
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01005220 /* Create the "f" field that contains a list of fetches. */
5221 lua_pushstring(L, "f");
Thierry FOURNIERca988662015-12-20 18:43:03 +01005222 if (!hlua_fetches_new(L, htxn, HLUA_F_MAY_USE_HTTP))
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01005223 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02005224 lua_rawset(L, -3);
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01005225
5226 /* Create the "sf" field that contains a list of stringsafe fetches. */
5227 lua_pushstring(L, "sf");
Thierry FOURNIERca988662015-12-20 18:43:03 +01005228 if (!hlua_fetches_new(L, htxn, HLUA_F_MAY_USE_HTTP | HLUA_F_AS_STRING))
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01005229 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02005230 lua_rawset(L, -3);
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01005231
Thierry FOURNIER594afe72015-03-10 23:58:30 +01005232 /* Create the "c" field that contains a list of converters. */
5233 lua_pushstring(L, "c");
Willy Tarreaude491382015-04-06 11:04:28 +02005234 if (!hlua_converters_new(L, htxn, 0))
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01005235 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02005236 lua_rawset(L, -3);
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01005237
5238 /* Create the "sc" field that contains a list of stringsafe converters. */
5239 lua_pushstring(L, "sc");
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01005240 if (!hlua_converters_new(L, htxn, HLUA_F_AS_STRING))
Thierry FOURNIER594afe72015-03-10 23:58:30 +01005241 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02005242 lua_rawset(L, -3);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01005243
Thierry FOURNIER397826a2015-03-11 19:39:09 +01005244 /* Create the "req" field that contains the request channel object. */
5245 lua_pushstring(L, "req");
Willy Tarreau2a71af42015-03-10 13:51:50 +01005246 if (!hlua_channel_new(L, &s->req))
Thierry FOURNIER397826a2015-03-11 19:39:09 +01005247 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02005248 lua_rawset(L, -3);
Thierry FOURNIER397826a2015-03-11 19:39:09 +01005249
5250 /* Create the "res" field that contains the response channel object. */
5251 lua_pushstring(L, "res");
Willy Tarreau2a71af42015-03-10 13:51:50 +01005252 if (!hlua_channel_new(L, &s->res))
Thierry FOURNIER397826a2015-03-11 19:39:09 +01005253 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02005254 lua_rawset(L, -3);
Thierry FOURNIER397826a2015-03-11 19:39:09 +01005255
Thierry FOURNIER08504f42015-03-16 14:17:08 +01005256 /* Creates the HTTP object is the current proxy allows http. */
5257 lua_pushstring(L, "http");
5258 if (p->mode == PR_MODE_HTTP) {
Willy Tarreaude491382015-04-06 11:04:28 +02005259 if (!hlua_http_new(L, htxn))
Thierry FOURNIER08504f42015-03-16 14:17:08 +01005260 return 0;
5261 }
5262 else
5263 lua_pushnil(L);
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02005264 lua_rawset(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01005265
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01005266 /* Pop a class sesison metatable and affect it to the userdata. */
5267 lua_rawgeti(L, LUA_REGISTRYINDEX, class_txn_ref);
5268 lua_setmetatable(L, -2);
5269
5270 return 1;
5271}
5272
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +01005273__LJMP static int hlua_txn_deflog(lua_State *L)
5274{
5275 const char *msg;
5276 struct hlua_txn *htxn;
5277
5278 MAY_LJMP(check_args(L, 2, "deflog"));
5279 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5280 msg = MAY_LJMP(luaL_checkstring(L, 2));
5281
5282 hlua_sendlog(htxn->s->be, htxn->s->logs.level, msg);
5283 return 0;
5284}
5285
5286__LJMP static int hlua_txn_log(lua_State *L)
5287{
5288 int level;
5289 const char *msg;
5290 struct hlua_txn *htxn;
5291
5292 MAY_LJMP(check_args(L, 3, "log"));
5293 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5294 level = MAY_LJMP(luaL_checkinteger(L, 2));
5295 msg = MAY_LJMP(luaL_checkstring(L, 3));
5296
5297 if (level < 0 || level >= NB_LOG_LEVELS)
5298 WILL_LJMP(luaL_argerror(L, 1, "Invalid loglevel."));
5299
5300 hlua_sendlog(htxn->s->be, level, msg);
5301 return 0;
5302}
5303
5304__LJMP static int hlua_txn_log_debug(lua_State *L)
5305{
5306 const char *msg;
5307 struct hlua_txn *htxn;
5308
5309 MAY_LJMP(check_args(L, 2, "Debug"));
5310 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5311 msg = MAY_LJMP(luaL_checkstring(L, 2));
5312 hlua_sendlog(htxn->s->be, LOG_DEBUG, msg);
5313 return 0;
5314}
5315
5316__LJMP static int hlua_txn_log_info(lua_State *L)
5317{
5318 const char *msg;
5319 struct hlua_txn *htxn;
5320
5321 MAY_LJMP(check_args(L, 2, "Info"));
5322 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5323 msg = MAY_LJMP(luaL_checkstring(L, 2));
5324 hlua_sendlog(htxn->s->be, LOG_INFO, msg);
5325 return 0;
5326}
5327
5328__LJMP static int hlua_txn_log_warning(lua_State *L)
5329{
5330 const char *msg;
5331 struct hlua_txn *htxn;
5332
5333 MAY_LJMP(check_args(L, 2, "Warning"));
5334 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5335 msg = MAY_LJMP(luaL_checkstring(L, 2));
5336 hlua_sendlog(htxn->s->be, LOG_WARNING, msg);
5337 return 0;
5338}
5339
5340__LJMP static int hlua_txn_log_alert(lua_State *L)
5341{
5342 const char *msg;
5343 struct hlua_txn *htxn;
5344
5345 MAY_LJMP(check_args(L, 2, "Alert"));
5346 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5347 msg = MAY_LJMP(luaL_checkstring(L, 2));
5348 hlua_sendlog(htxn->s->be, LOG_ALERT, msg);
5349 return 0;
5350}
5351
Thierry FOURNIER2cce3532015-03-16 12:04:16 +01005352__LJMP static int hlua_txn_set_loglevel(lua_State *L)
5353{
5354 struct hlua_txn *htxn;
5355 int ll;
5356
5357 MAY_LJMP(check_args(L, 2, "set_loglevel"));
5358 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5359 ll = MAY_LJMP(luaL_checkinteger(L, 2));
5360
5361 if (ll < 0 || ll > 7)
5362 WILL_LJMP(luaL_argerror(L, 2, "Bad log level. It must be between 0 and 7"));
5363
5364 htxn->s->logs.level = ll;
5365 return 0;
5366}
5367
5368__LJMP static int hlua_txn_set_tos(lua_State *L)
5369{
5370 struct hlua_txn *htxn;
5371 struct connection *cli_conn;
5372 int tos;
5373
5374 MAY_LJMP(check_args(L, 2, "set_tos"));
5375 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5376 tos = MAY_LJMP(luaL_checkinteger(L, 2));
5377
Willy Tarreau9ad7bd42015-04-03 19:19:59 +02005378 if ((cli_conn = objt_conn(htxn->s->sess->origin)) && conn_ctrl_ready(cli_conn))
Willy Tarreau585744b2017-08-24 14:31:19 +02005379 inet_set_tos(cli_conn->handle.fd, &cli_conn->addr.from, tos);
Thierry FOURNIER2cce3532015-03-16 12:04:16 +01005380
5381 return 0;
5382}
5383
5384__LJMP static int hlua_txn_set_mark(lua_State *L)
5385{
5386#ifdef SO_MARK
5387 struct hlua_txn *htxn;
5388 struct connection *cli_conn;
5389 int mark;
5390
5391 MAY_LJMP(check_args(L, 2, "set_mark"));
5392 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5393 mark = MAY_LJMP(luaL_checkinteger(L, 2));
5394
Willy Tarreau9ad7bd42015-04-03 19:19:59 +02005395 if ((cli_conn = objt_conn(htxn->s->sess->origin)) && conn_ctrl_ready(cli_conn))
Willy Tarreau585744b2017-08-24 14:31:19 +02005396 setsockopt(cli_conn->handle.fd, SOL_SOCKET, SO_MARK, &mark, sizeof(mark));
Thierry FOURNIER2cce3532015-03-16 12:04:16 +01005397#endif
5398 return 0;
5399}
5400
Patrick Hemmer268a7072018-05-11 12:52:31 -04005401__LJMP static int hlua_txn_set_priority_class(lua_State *L)
5402{
5403 struct hlua_txn *htxn;
5404
5405 MAY_LJMP(check_args(L, 2, "set_priority_class"));
5406 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5407 htxn->s->priority_class = queue_limit_class(MAY_LJMP(luaL_checkinteger(L, 2)));
5408 return 0;
5409}
5410
5411__LJMP static int hlua_txn_set_priority_offset(lua_State *L)
5412{
5413 struct hlua_txn *htxn;
5414
5415 MAY_LJMP(check_args(L, 2, "set_priority_offset"));
5416 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5417 htxn->s->priority_offset = queue_limit_offset(MAY_LJMP(luaL_checkinteger(L, 2)));
5418 return 0;
5419}
5420
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005421/* This function is an Lua binding that send pending data
5422 * to the client, and close the stream interface.
5423 */
Thierry FOURNIER4bb375c2015-08-26 08:42:21 +02005424__LJMP static int hlua_txn_done(lua_State *L)
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005425{
Willy Tarreaub2ccb562015-04-06 11:11:15 +02005426 struct hlua_txn *htxn;
Thierry FOURNIER9bd52d42016-07-14 11:45:33 +02005427 struct hlua *hlua;
Willy Tarreau81389672015-03-10 12:03:52 +01005428 struct channel *ic, *oc;
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005429
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005430 MAY_LJMP(check_args(L, 1, "close"));
Willy Tarreaub2ccb562015-04-06 11:11:15 +02005431 htxn = MAY_LJMP(hlua_checktxn(L, 1));
Thierry FOURNIER9bd52d42016-07-14 11:45:33 +02005432 hlua = hlua_gethlua(L);
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005433
Thierry FOURNIERab00df62016-07-14 11:42:37 +02005434 /* If the flags NOTERM is set, we cannot terminate the http
5435 * session, so we just end the execution of the current
5436 * lua code.
5437 */
5438 if (htxn->flags & HLUA_TXN_NOTERM) {
5439 WILL_LJMP(hlua_done(L));
5440 return 0;
5441 }
5442
Willy Tarreaub2ccb562015-04-06 11:11:15 +02005443 ic = &htxn->s->req;
5444 oc = &htxn->s->res;
Willy Tarreau81389672015-03-10 12:03:52 +01005445
Willy Tarreau630ef452015-08-28 10:06:15 +02005446 if (htxn->s->txn) {
5447 /* HTTP mode, let's stay in sync with the stream */
Willy Tarreauc9fa0482018-07-10 17:43:27 +02005448 b_del(&ic->buf, htxn->s->txn->req.sov);
Willy Tarreau630ef452015-08-28 10:06:15 +02005449 htxn->s->txn->req.next -= htxn->s->txn->req.sov;
5450 htxn->s->txn->req.sov = 0;
5451 ic->analysers &= AN_REQ_HTTP_XFER_BODY;
5452 oc->analysers = AN_RES_HTTP_XFER_BODY;
5453 htxn->s->txn->req.msg_state = HTTP_MSG_CLOSED;
5454 htxn->s->txn->rsp.msg_state = HTTP_MSG_DONE;
5455
Willy Tarreau630ef452015-08-28 10:06:15 +02005456 /* Note that if we want to support keep-alive, we need
5457 * to bypass the close/shutr_now calls below, but that
5458 * may only be done if the HTTP request was already
5459 * processed and the connection header is known (ie
5460 * not during TCP rules).
5461 */
5462 }
5463
Thierry FOURNIER10ec2142015-08-24 17:23:45 +02005464 channel_auto_read(ic);
Willy Tarreau81389672015-03-10 12:03:52 +01005465 channel_abort(ic);
5466 channel_auto_close(ic);
5467 channel_erase(ic);
Thierry FOURNIER10ec2142015-08-24 17:23:45 +02005468
5469 oc->wex = tick_add_ifset(now_ms, oc->wto);
Willy Tarreau81389672015-03-10 12:03:52 +01005470 channel_auto_read(oc);
5471 channel_auto_close(oc);
5472 channel_shutr_now(oc);
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005473
Willy Tarreau0458b082015-08-28 09:40:04 +02005474 ic->analysers = 0;
Thierry FOURNIER4bb375c2015-08-26 08:42:21 +02005475
Thierry FOURNIER9bd52d42016-07-14 11:45:33 +02005476 hlua->flags |= HLUA_STOP;
Thierry FOURNIER4bb375c2015-08-26 08:42:21 +02005477 WILL_LJMP(hlua_done(L));
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +01005478 return 0;
5479}
5480
5481__LJMP static int hlua_log(lua_State *L)
5482{
5483 int level;
5484 const char *msg;
5485
5486 MAY_LJMP(check_args(L, 2, "log"));
5487 level = MAY_LJMP(luaL_checkinteger(L, 1));
5488 msg = MAY_LJMP(luaL_checkstring(L, 2));
5489
5490 if (level < 0 || level >= NB_LOG_LEVELS)
5491 WILL_LJMP(luaL_argerror(L, 1, "Invalid loglevel."));
5492
5493 hlua_sendlog(NULL, level, msg);
5494 return 0;
5495}
5496
5497__LJMP static int hlua_log_debug(lua_State *L)
5498{
5499 const char *msg;
5500
5501 MAY_LJMP(check_args(L, 1, "debug"));
5502 msg = MAY_LJMP(luaL_checkstring(L, 1));
5503 hlua_sendlog(NULL, LOG_DEBUG, msg);
5504 return 0;
5505}
5506
5507__LJMP static int hlua_log_info(lua_State *L)
5508{
5509 const char *msg;
5510
5511 MAY_LJMP(check_args(L, 1, "info"));
5512 msg = MAY_LJMP(luaL_checkstring(L, 1));
5513 hlua_sendlog(NULL, LOG_INFO, msg);
5514 return 0;
5515}
5516
5517__LJMP static int hlua_log_warning(lua_State *L)
5518{
5519 const char *msg;
5520
5521 MAY_LJMP(check_args(L, 1, "warning"));
5522 msg = MAY_LJMP(luaL_checkstring(L, 1));
5523 hlua_sendlog(NULL, LOG_WARNING, msg);
5524 return 0;
5525}
5526
5527__LJMP static int hlua_log_alert(lua_State *L)
5528{
5529 const char *msg;
5530
5531 MAY_LJMP(check_args(L, 1, "alert"));
5532 msg = MAY_LJMP(luaL_checkstring(L, 1));
5533 hlua_sendlog(NULL, LOG_ALERT, msg);
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005534 return 0;
5535}
5536
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01005537__LJMP static int hlua_sleep_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005538{
5539 int wakeup_ms = lua_tointeger(L, -1);
5540 if (now_ms < wakeup_ms)
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005541 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_sleep_yield, wakeup_ms, 0));
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005542 return 0;
5543}
5544
5545__LJMP static int hlua_sleep(lua_State *L)
5546{
5547 unsigned int delay;
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005548 unsigned int wakeup_ms;
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005549
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005550 MAY_LJMP(check_args(L, 1, "sleep"));
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005551
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01005552 delay = MAY_LJMP(luaL_checkinteger(L, 1)) * 1000;
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005553 wakeup_ms = tick_add(now_ms, delay);
5554 lua_pushinteger(L, wakeup_ms);
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005555
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005556 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_sleep_yield, wakeup_ms, 0));
5557 return 0;
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005558}
5559
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005560__LJMP static int hlua_msleep(lua_State *L)
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005561{
5562 unsigned int delay;
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005563 unsigned int wakeup_ms;
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005564
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005565 MAY_LJMP(check_args(L, 1, "msleep"));
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005566
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01005567 delay = MAY_LJMP(luaL_checkinteger(L, 1));
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005568 wakeup_ms = tick_add(now_ms, delay);
5569 lua_pushinteger(L, wakeup_ms);
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005570
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005571 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_sleep_yield, wakeup_ms, 0));
5572 return 0;
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005573}
5574
Thierry FOURNIER13416fe2015-02-17 15:01:59 +01005575/* This functionis an LUA binding. it permits to give back
5576 * the hand at the HAProxy scheduler. It is used when the
5577 * LUA processing consumes a lot of time.
5578 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01005579__LJMP static int hlua_yield_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005580{
5581 return 0;
5582}
5583
Thierry FOURNIER13416fe2015-02-17 15:01:59 +01005584__LJMP static int hlua_yield(lua_State *L)
5585{
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005586 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_yield_yield, TICK_ETERNITY, HLUA_CTRLYIELD));
5587 return 0;
Thierry FOURNIER13416fe2015-02-17 15:01:59 +01005588}
5589
Thierry FOURNIER37196f42015-02-16 19:34:56 +01005590/* This function change the nice of the currently executed
5591 * task. It is used set low or high priority at the current
5592 * task.
5593 */
Willy Tarreau59551662015-03-10 14:23:13 +01005594__LJMP static int hlua_set_nice(lua_State *L)
Thierry FOURNIER37196f42015-02-16 19:34:56 +01005595{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005596 struct hlua *hlua;
5597 int nice;
Thierry FOURNIER37196f42015-02-16 19:34:56 +01005598
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005599 MAY_LJMP(check_args(L, 1, "set_nice"));
5600 hlua = hlua_gethlua(L);
5601 nice = MAY_LJMP(luaL_checkinteger(L, 1));
Thierry FOURNIER37196f42015-02-16 19:34:56 +01005602
5603 /* If he task is not set, I'm in a start mode. */
5604 if (!hlua || !hlua->task)
5605 return 0;
5606
5607 if (nice < -1024)
5608 nice = -1024;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005609 else if (nice > 1024)
Thierry FOURNIER37196f42015-02-16 19:34:56 +01005610 nice = 1024;
5611
5612 hlua->task->nice = nice;
5613 return 0;
5614}
5615
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005616/* This function is used as a calback of a task. It is called by the
5617 * HAProxy task subsystem when the task is awaked. The LUA runtime can
5618 * return an E_AGAIN signal, the emmiter of this signal must set a
5619 * signal to wake the task.
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005620 *
5621 * Task wrapper are longjmp safe because the only one Lua code
5622 * executed is the safe hlua_ctx_resume();
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005623 */
Olivier Houchard9f6af332018-05-25 14:04:04 +02005624static struct task *hlua_process_task(struct task *task, void *context, unsigned short state)
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005625{
Olivier Houchard9f6af332018-05-25 14:04:04 +02005626 struct hlua *hlua = context;
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005627 enum hlua_exec status;
5628
Christopher Faulet5bc99722018-04-25 10:34:45 +02005629 if (task->thread_mask == MAX_THREADS_MASK)
5630 task_set_affinity(task, tid_bit);
5631
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005632 /* If it is the first call to the task, we must initialize the
5633 * execution timeouts.
5634 */
5635 if (!HLUA_IS_RUNNING(hlua))
Thierry FOURNIER10770fa2015-09-29 01:59:42 +02005636 hlua->max_time = hlua_timeout_task;
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005637
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005638 /* Execute the Lua code. */
5639 status = hlua_ctx_resume(hlua, 1);
5640
5641 switch (status) {
5642 /* finished or yield */
5643 case HLUA_E_OK:
5644 hlua_ctx_destroy(hlua);
5645 task_delete(task);
5646 task_free(task);
Tim Duesterhuscd235c62018-04-24 13:56:01 +02005647 task = NULL;
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005648 break;
5649
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01005650 case HLUA_E_AGAIN: /* co process or timeout wake me later. */
Thierry FOURNIERcb146882017-12-10 17:10:57 +01005651 notification_gc(&hlua->com);
PiBa-NLfe971b32018-05-02 22:27:14 +02005652 task->expire = hlua->wake_time;
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005653 break;
5654
5655 /* finished with error. */
5656 case HLUA_E_ERRMSG:
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005657 SEND_ERR(NULL, "Lua task: %s.\n", lua_tostring(hlua->T, -1));
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005658 hlua_ctx_destroy(hlua);
5659 task_delete(task);
5660 task_free(task);
Emeric Brun253e53e2017-10-17 18:58:40 +02005661 task = NULL;
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005662 break;
5663
5664 case HLUA_E_ERR:
5665 default:
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005666 SEND_ERR(NULL, "Lua task: unknown error.\n");
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005667 hlua_ctx_destroy(hlua);
5668 task_delete(task);
5669 task_free(task);
Emeric Brun253e53e2017-10-17 18:58:40 +02005670 task = NULL;
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005671 break;
5672 }
Emeric Brun253e53e2017-10-17 18:58:40 +02005673 return task;
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005674}
5675
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01005676/* This function is an LUA binding that register LUA function to be
5677 * executed after the HAProxy configuration parsing and before the
5678 * HAProxy scheduler starts. This function expect only one LUA
5679 * argument that is a function. This function returns nothing, but
5680 * throws if an error is encountered.
5681 */
5682__LJMP static int hlua_register_init(lua_State *L)
5683{
5684 struct hlua_init_function *init;
5685 int ref;
5686
5687 MAY_LJMP(check_args(L, 1, "register_init"));
5688
5689 ref = MAY_LJMP(hlua_checkfunction(L, 1));
5690
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02005691 init = calloc(1, sizeof(*init));
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01005692 if (!init)
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01005693 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01005694
5695 init->function_ref = ref;
5696 LIST_ADDQ(&hlua_init_functions, &init->l);
5697 return 0;
5698}
5699
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005700/* This functio is an LUA binding. It permits to register a task
5701 * executed in parallel of the main HAroxy activity. The task is
5702 * created and it is set in the HAProxy scheduler. It can be called
5703 * from the "init" section, "post init" or during the runtime.
5704 *
5705 * Lua prototype:
5706 *
5707 * <none> core.register_task(<function>)
5708 */
5709static int hlua_register_task(lua_State *L)
5710{
5711 struct hlua *hlua;
5712 struct task *task;
5713 int ref;
5714
5715 MAY_LJMP(check_args(L, 1, "register_task"));
5716
5717 ref = MAY_LJMP(hlua_checkfunction(L, 1));
5718
Willy Tarreaubafbe012017-11-24 17:34:44 +01005719 hlua = pool_alloc(pool_head_hlua);
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005720 if (!hlua)
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01005721 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005722
Emeric Brunc60def82017-09-27 14:59:38 +02005723 task = task_new(MAX_THREADS_MASK);
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005724 task->context = hlua;
5725 task->process = hlua_process_task;
5726
5727 if (!hlua_ctx_init(hlua, task))
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01005728 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005729
5730 /* Restore the function in the stack. */
5731 lua_rawgeti(hlua->T, LUA_REGISTRYINDEX, ref);
5732 hlua->nargs = 0;
5733
5734 /* Schedule task. */
5735 task_schedule(task, now_ms);
5736
5737 return 0;
5738}
5739
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005740/* Wrapper called by HAProxy to execute an LUA converter. This wrapper
5741 * doesn't allow "yield" functions because the HAProxy engine cannot
5742 * resume converters.
5743 */
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005744static int hlua_sample_conv_wrapper(const struct arg *arg_p, struct sample *smp, void *private)
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005745{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005746 struct hlua_function *fcn = private;
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005747 struct stream *stream = smp->strm;
Thierry Fournierfd107a22016-02-19 19:57:23 +01005748 const char *error;
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005749
Willy Tarreaube508f12016-03-10 11:47:01 +01005750 if (!stream)
5751 return 0;
5752
Willy Tarreau87b09662015-04-03 00:22:06 +02005753 /* In the execution wrappers linked with a stream, the
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01005754 * Lua context can be not initialized. This behavior
5755 * permits to save performances because a systematic
5756 * Lua initialization cause 5% performances loss.
5757 */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005758 if (!stream->hlua) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005759 stream->hlua = pool_alloc(pool_head_hlua);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005760 if (!stream->hlua) {
5761 SEND_ERR(stream->be, "Lua converter '%s': can't initialize Lua context.\n", fcn->name);
5762 return 0;
5763 }
5764 if (!hlua_ctx_init(stream->hlua, stream->task)) {
5765 SEND_ERR(stream->be, "Lua converter '%s': can't initialize Lua context.\n", fcn->name);
5766 return 0;
5767 }
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01005768 }
5769
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005770 /* If it is the first run, initialize the data for the call. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005771 if (!HLUA_IS_RUNNING(stream->hlua)) {
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005772
5773 /* The following Lua calls can fail. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005774 if (!SET_SAFE_LJMP(stream->hlua->T)) {
5775 if (lua_type(stream->hlua->T, -1) == LUA_TSTRING)
5776 error = lua_tostring(stream->hlua->T, -1);
Thierry Fournierfd107a22016-02-19 19:57:23 +01005777 else
5778 error = "critical error";
5779 SEND_ERR(stream->be, "Lua converter '%s': %s.\n", fcn->name, error);
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005780 return 0;
5781 }
5782
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005783 /* Check stack available size. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005784 if (!lua_checkstack(stream->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005785 SEND_ERR(stream->be, "Lua converter '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005786 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005787 return 0;
5788 }
5789
5790 /* Restore the function in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005791 lua_rawgeti(stream->hlua->T, LUA_REGISTRYINDEX, fcn->function_ref);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005792
5793 /* convert input sample and pust-it in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005794 if (!lua_checkstack(stream->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005795 SEND_ERR(stream->be, "Lua converter '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005796 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005797 return 0;
5798 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005799 hlua_smp2lua(stream->hlua->T, smp);
5800 stream->hlua->nargs = 1;
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005801
5802 /* push keywords in the stack. */
5803 if (arg_p) {
5804 for (; arg_p->type != ARGT_STOP; arg_p++) {
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005805 if (!lua_checkstack(stream->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005806 SEND_ERR(stream->be, "Lua converter '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005807 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005808 return 0;
5809 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005810 hlua_arg2lua(stream->hlua->T, arg_p);
5811 stream->hlua->nargs++;
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005812 }
5813 }
5814
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005815 /* We must initialize the execution timeouts. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005816 stream->hlua->max_time = hlua_timeout_session;
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005817
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005818 /* At this point the execution is safe. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005819 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005820 }
5821
5822 /* Execute the function. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005823 switch (hlua_ctx_resume(stream->hlua, 0)) {
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005824 /* finished. */
5825 case HLUA_E_OK:
Thierry FOURNIERfd80df12017-05-12 16:32:20 +02005826 /* If the stack is empty, the function fails. */
5827 if (lua_gettop(stream->hlua->T) <= 0)
5828 return 0;
5829
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005830 /* Convert the returned value in sample. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005831 hlua_lua2smp(stream->hlua->T, -1, smp);
5832 lua_pop(stream->hlua->T, 1);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005833 return 1;
5834
5835 /* yield. */
5836 case HLUA_E_AGAIN:
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005837 SEND_ERR(stream->be, "Lua converter '%s': cannot use yielded functions.\n", fcn->name);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005838 return 0;
5839
5840 /* finished with error. */
5841 case HLUA_E_ERRMSG:
5842 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005843 SEND_ERR(stream->be, "Lua converter '%s': %s.\n",
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005844 fcn->name, lua_tostring(stream->hlua->T, -1));
5845 lua_pop(stream->hlua->T, 1);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005846 return 0;
5847
Thierry Fournierd5b073c2018-05-21 19:42:47 +02005848 case HLUA_E_ETMOUT:
5849 SEND_ERR(stream->be, "Lua converter '%s': execution timeout.\n", fcn->name);
5850 return 0;
5851
5852 case HLUA_E_NOMEM:
5853 SEND_ERR(stream->be, "Lua converter '%s': out of memory error.\n", fcn->name);
5854 return 0;
5855
5856 case HLUA_E_YIELD:
5857 SEND_ERR(stream->be, "Lua converter '%s': yield functions like core.tcp() or core.sleep() are not allowed.\n", fcn->name);
5858 return 0;
5859
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005860 case HLUA_E_ERR:
5861 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005862 SEND_ERR(stream->be, "Lua converter '%s' returns an unknown error.\n", fcn->name);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005863
5864 default:
5865 return 0;
5866 }
5867}
5868
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005869/* Wrapper called by HAProxy to execute a sample-fetch. this wrapper
5870 * doesn't allow "yield" functions because the HAProxy engine cannot
Willy Tarreaube508f12016-03-10 11:47:01 +01005871 * resume sample-fetches. This function will be called by the sample
5872 * fetch engine to call lua-based fetch operations.
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005873 */
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005874static int hlua_sample_fetch_wrapper(const struct arg *arg_p, struct sample *smp,
5875 const char *kw, void *private)
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005876{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005877 struct hlua_function *fcn = private;
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005878 struct stream *stream = smp->strm;
Thierry Fournierfd107a22016-02-19 19:57:23 +01005879 const char *error;
Willy Tarreau83061a82018-07-13 11:56:34 +02005880 const struct buffer msg = { };
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005881
Willy Tarreaube508f12016-03-10 11:47:01 +01005882 if (!stream)
5883 return 0;
5884
Willy Tarreau87b09662015-04-03 00:22:06 +02005885 /* In the execution wrappers linked with a stream, the
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01005886 * Lua context can be not initialized. This behavior
5887 * permits to save performances because a systematic
5888 * Lua initialization cause 5% performances loss.
5889 */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005890 if (!stream->hlua) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005891 stream->hlua = pool_alloc(pool_head_hlua);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005892 if (!stream->hlua) {
5893 SEND_ERR(stream->be, "Lua sample-fetch '%s': can't initialize Lua context.\n", fcn->name);
5894 return 0;
5895 }
5896 if (!hlua_ctx_init(stream->hlua, stream->task)) {
5897 SEND_ERR(stream->be, "Lua sample-fetch '%s': can't initialize Lua context.\n", fcn->name);
5898 return 0;
5899 }
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01005900 }
5901
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005902 consistency_set(stream, smp->opt, &stream->hlua->cons);
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005903
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005904 /* If it is the first run, initialize the data for the call. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005905 if (!HLUA_IS_RUNNING(stream->hlua)) {
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005906
5907 /* The following Lua calls can fail. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005908 if (!SET_SAFE_LJMP(stream->hlua->T)) {
5909 if (lua_type(stream->hlua->T, -1) == LUA_TSTRING)
5910 error = lua_tostring(stream->hlua->T, -1);
Thierry Fournierfd107a22016-02-19 19:57:23 +01005911 else
5912 error = "critical error";
5913 SEND_ERR(smp->px, "Lua sample-fetch '%s': %s.\n", fcn->name, error);
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005914 return 0;
5915 }
5916
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005917 /* Check stack available size. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005918 if (!lua_checkstack(stream->hlua->T, 2)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005919 SEND_ERR(smp->px, "Lua sample-fetch '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005920 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005921 return 0;
5922 }
5923
5924 /* Restore the function in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005925 lua_rawgeti(stream->hlua->T, LUA_REGISTRYINDEX, fcn->function_ref);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005926
5927 /* push arguments in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005928 if (!hlua_txn_new(stream->hlua->T, stream, smp->px, smp->opt & SMP_OPT_DIR,
Thierry FOURNIERab00df62016-07-14 11:42:37 +02005929 HLUA_TXN_NOTERM)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005930 SEND_ERR(smp->px, "Lua sample-fetch '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005931 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005932 return 0;
5933 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005934 stream->hlua->nargs = 1;
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005935
5936 /* push keywords in the stack. */
5937 for (; arg_p && arg_p->type != ARGT_STOP; arg_p++) {
5938 /* Check stack available size. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005939 if (!lua_checkstack(stream->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005940 SEND_ERR(smp->px, "Lua sample-fetch '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005941 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005942 return 0;
5943 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005944 hlua_arg2lua(stream->hlua->T, arg_p);
5945 stream->hlua->nargs++;
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005946 }
5947
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005948 /* We must initialize the execution timeouts. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005949 stream->hlua->max_time = hlua_timeout_session;
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005950
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005951 /* At this point the execution is safe. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005952 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005953 }
5954
5955 /* Execute the function. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005956 switch (hlua_ctx_resume(stream->hlua, 0)) {
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005957 /* finished. */
5958 case HLUA_E_OK:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005959 if (!consistency_check(stream, smp->opt, &stream->hlua->cons)) {
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005960 stream_int_retnclose(&stream->si[0], &msg);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02005961 return 0;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005962 }
Thierry FOURNIERfd80df12017-05-12 16:32:20 +02005963 /* If the stack is empty, the function fails. */
5964 if (lua_gettop(stream->hlua->T) <= 0)
5965 return 0;
5966
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005967 /* Convert the returned value in sample. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005968 hlua_lua2smp(stream->hlua->T, -1, smp);
5969 lua_pop(stream->hlua->T, 1);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005970
5971 /* Set the end of execution flag. */
5972 smp->flags &= ~SMP_F_MAY_CHANGE;
5973 return 1;
5974
5975 /* yield. */
5976 case HLUA_E_AGAIN:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005977 if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005978 stream_int_retnclose(&stream->si[0], &msg);
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005979 SEND_ERR(smp->px, "Lua sample-fetch '%s': cannot use yielded functions.\n", fcn->name);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005980 return 0;
5981
5982 /* finished with error. */
5983 case HLUA_E_ERRMSG:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005984 if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005985 stream_int_retnclose(&stream->si[0], &msg);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005986 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005987 SEND_ERR(smp->px, "Lua sample-fetch '%s': %s.\n",
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005988 fcn->name, lua_tostring(stream->hlua->T, -1));
5989 lua_pop(stream->hlua->T, 1);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005990 return 0;
5991
Thierry Fournierd5b073c2018-05-21 19:42:47 +02005992 case HLUA_E_ETMOUT:
5993 if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
5994 stream_int_retnclose(&stream->si[0], &msg);
5995 SEND_ERR(smp->px, "Lua sample-fetch '%s': execution timeout.\n", fcn->name);
5996 return 0;
5997
5998 case HLUA_E_NOMEM:
5999 if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
6000 stream_int_retnclose(&stream->si[0], &msg);
6001 SEND_ERR(smp->px, "Lua sample-fetch '%s': out of memory error.\n", fcn->name);
6002 return 0;
6003
6004 case HLUA_E_YIELD:
6005 if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
6006 stream_int_retnclose(&stream->si[0], &msg);
6007 SEND_ERR(smp->px, "Lua sample-fetch '%s': yield not allowed.\n", fcn->name);
6008 return 0;
6009
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01006010 case HLUA_E_ERR:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006011 if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01006012 stream_int_retnclose(&stream->si[0], &msg);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01006013 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02006014 SEND_ERR(smp->px, "Lua sample-fetch '%s' returns an unknown error.\n", fcn->name);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01006015
6016 default:
6017 return 0;
6018 }
6019}
6020
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01006021/* This function is an LUA binding used for registering
6022 * "sample-conv" functions. It expects a converter name used
6023 * in the haproxy configuration file, and an LUA function.
6024 */
6025__LJMP static int hlua_register_converters(lua_State *L)
6026{
6027 struct sample_conv_kw_list *sck;
6028 const char *name;
6029 int ref;
6030 int len;
6031 struct hlua_function *fcn;
6032
6033 MAY_LJMP(check_args(L, 2, "register_converters"));
6034
6035 /* First argument : converter name. */
6036 name = MAY_LJMP(luaL_checkstring(L, 1));
6037
6038 /* Second argument : lua function. */
6039 ref = MAY_LJMP(hlua_checkfunction(L, 2));
6040
6041 /* Allocate and fill the sample fetch keyword struct. */
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02006042 sck = calloc(1, sizeof(*sck) + sizeof(struct sample_conv) * 2);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01006043 if (!sck)
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01006044 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02006045 fcn = calloc(1, sizeof(*fcn));
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01006046 if (!fcn)
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01006047 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01006048
6049 /* Fill fcn. */
6050 fcn->name = strdup(name);
6051 if (!fcn->name)
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01006052 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01006053 fcn->function_ref = ref;
6054
6055 /* List head */
6056 sck->list.n = sck->list.p = NULL;
6057
6058 /* converter keyword. */
6059 len = strlen("lua.") + strlen(name) + 1;
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02006060 sck->kw[0].kw = calloc(1, len);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01006061 if (!sck->kw[0].kw)
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01006062 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01006063
6064 snprintf((char *)sck->kw[0].kw, len, "lua.%s", name);
6065 sck->kw[0].process = hlua_sample_conv_wrapper;
David Carlier0c437f42016-04-27 16:21:56 +01006066 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 +01006067 sck->kw[0].val_args = NULL;
6068 sck->kw[0].in_type = SMP_T_STR;
6069 sck->kw[0].out_type = SMP_T_STR;
6070 sck->kw[0].private = fcn;
6071
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01006072 /* Register this new converter */
6073 sample_register_convs(sck);
6074
6075 return 0;
6076}
6077
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01006078/* This fucntion is an LUA binding used for registering
6079 * "sample-fetch" functions. It expects a converter name used
6080 * in the haproxy configuration file, and an LUA function.
6081 */
6082__LJMP static int hlua_register_fetches(lua_State *L)
6083{
6084 const char *name;
6085 int ref;
6086 int len;
6087 struct sample_fetch_kw_list *sfk;
6088 struct hlua_function *fcn;
6089
6090 MAY_LJMP(check_args(L, 2, "register_fetches"));
6091
6092 /* First argument : sample-fetch name. */
6093 name = MAY_LJMP(luaL_checkstring(L, 1));
6094
6095 /* Second argument : lua function. */
6096 ref = MAY_LJMP(hlua_checkfunction(L, 2));
6097
6098 /* Allocate and fill the sample fetch keyword struct. */
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02006099 sfk = calloc(1, sizeof(*sfk) + sizeof(struct sample_fetch) * 2);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01006100 if (!sfk)
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01006101 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02006102 fcn = calloc(1, sizeof(*fcn));
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01006103 if (!fcn)
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01006104 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01006105
6106 /* Fill fcn. */
6107 fcn->name = strdup(name);
6108 if (!fcn->name)
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01006109 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01006110 fcn->function_ref = ref;
6111
6112 /* List head */
6113 sfk->list.n = sfk->list.p = NULL;
6114
6115 /* sample-fetch keyword. */
6116 len = strlen("lua.") + strlen(name) + 1;
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02006117 sfk->kw[0].kw = calloc(1, len);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01006118 if (!sfk->kw[0].kw)
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01006119 return luaL_error(L, "Lua out of memory error.");
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01006120
6121 snprintf((char *)sfk->kw[0].kw, len, "lua.%s", name);
6122 sfk->kw[0].process = hlua_sample_fetch_wrapper;
David Carlier0c437f42016-04-27 16:21:56 +01006123 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 +01006124 sfk->kw[0].val_args = NULL;
6125 sfk->kw[0].out_type = SMP_T_STR;
6126 sfk->kw[0].use = SMP_USE_HTTP_ANY;
6127 sfk->kw[0].val = 0;
6128 sfk->kw[0].private = fcn;
6129
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01006130 /* Register this new fetch. */
6131 sample_register_fetches(sfk);
6132
6133 return 0;
6134}
6135
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006136/* This function is a wrapper to execute each LUA function declared
6137 * as an action wrapper during the initialisation period. This function
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006138 * return ACT_RET_CONT if the processing is finished (with or without
6139 * error) and return ACT_RET_YIELD if the function must be called again
6140 * because the LUA returns a yield.
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006141 */
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006142static enum act_return hlua_action(struct act_rule *rule, struct proxy *px,
Willy Tarreau658b85b2015-09-27 10:00:49 +02006143 struct session *sess, struct stream *s, int flags)
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006144{
6145 char **arg;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006146 unsigned int analyzer;
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02006147 int dir;
Thierry Fournierfd107a22016-02-19 19:57:23 +01006148 const char *error;
Willy Tarreau83061a82018-07-13 11:56:34 +02006149 const struct buffer msg = { };
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006150
6151 switch (rule->from) {
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01006152 case ACT_F_TCP_REQ_CNT: analyzer = AN_REQ_INSPECT_FE ; dir = SMP_OPT_DIR_REQ; break;
6153 case ACT_F_TCP_RES_CNT: analyzer = AN_RES_INSPECT ; dir = SMP_OPT_DIR_RES; break;
6154 case ACT_F_HTTP_REQ: analyzer = AN_REQ_HTTP_PROCESS_FE; dir = SMP_OPT_DIR_REQ; break;
6155 case ACT_F_HTTP_RES: analyzer = AN_RES_HTTP_PROCESS_BE; dir = SMP_OPT_DIR_RES; break;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006156 default:
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02006157 SEND_ERR(px, "Lua: internal error while execute action.\n");
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006158 return ACT_RET_CONT;
6159 }
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006160
Willy Tarreau87b09662015-04-03 00:22:06 +02006161 /* In the execution wrappers linked with a stream, the
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01006162 * Lua context can be not initialized. This behavior
6163 * permits to save performances because a systematic
6164 * Lua initialization cause 5% performances loss.
6165 */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006166 if (!s->hlua) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01006167 s->hlua = pool_alloc(pool_head_hlua);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006168 if (!s->hlua) {
6169 SEND_ERR(px, "Lua action '%s': can't initialize Lua context.\n",
6170 rule->arg.hlua_rule->fcn.name);
6171 return ACT_RET_CONT;
6172 }
6173 if (!hlua_ctx_init(s->hlua, s->task)) {
6174 SEND_ERR(px, "Lua action '%s': can't initialize Lua context.\n",
6175 rule->arg.hlua_rule->fcn.name);
6176 return ACT_RET_CONT;
6177 }
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01006178 }
6179
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006180 consistency_set(s, dir, &s->hlua->cons);
6181
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006182 /* If it is the first run, initialize the data for the call. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006183 if (!HLUA_IS_RUNNING(s->hlua)) {
Thierry FOURNIERbabae282015-09-17 11:36:37 +02006184
6185 /* The following Lua calls can fail. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006186 if (!SET_SAFE_LJMP(s->hlua->T)) {
6187 if (lua_type(s->hlua->T, -1) == LUA_TSTRING)
6188 error = lua_tostring(s->hlua->T, -1);
Thierry Fournierfd107a22016-02-19 19:57:23 +01006189 else
6190 error = "critical error";
6191 SEND_ERR(px, "Lua function '%s': %s.\n",
6192 rule->arg.hlua_rule->fcn.name, error);
Thierry FOURNIERbabae282015-09-17 11:36:37 +02006193 return ACT_RET_CONT;
6194 }
6195
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006196 /* Check stack available size. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006197 if (!lua_checkstack(s->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02006198 SEND_ERR(px, "Lua function '%s': full stack.\n",
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006199 rule->arg.hlua_rule->fcn.name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006200 RESET_SAFE_LJMP(s->hlua->T);
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02006201 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006202 }
6203
6204 /* Restore the function in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006205 lua_rawgeti(s->hlua->T, LUA_REGISTRYINDEX, rule->arg.hlua_rule->fcn.function_ref);
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006206
Willy Tarreau87b09662015-04-03 00:22:06 +02006207 /* Create and and push object stream in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006208 if (!hlua_txn_new(s->hlua->T, s, px, dir, 0)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02006209 SEND_ERR(px, "Lua function '%s': full stack.\n",
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006210 rule->arg.hlua_rule->fcn.name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006211 RESET_SAFE_LJMP(s->hlua->T);
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02006212 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006213 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006214 s->hlua->nargs = 1;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006215
6216 /* push keywords in the stack. */
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006217 for (arg = rule->arg.hlua_rule->args; arg && *arg; arg++) {
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006218 if (!lua_checkstack(s->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02006219 SEND_ERR(px, "Lua function '%s': full stack.\n",
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006220 rule->arg.hlua_rule->fcn.name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006221 RESET_SAFE_LJMP(s->hlua->T);
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02006222 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006223 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006224 lua_pushstring(s->hlua->T, *arg);
6225 s->hlua->nargs++;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006226 }
6227
Thierry FOURNIERbabae282015-09-17 11:36:37 +02006228 /* Now the execution is safe. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006229 RESET_SAFE_LJMP(s->hlua->T);
Thierry FOURNIERbabae282015-09-17 11:36:37 +02006230
Thierry FOURNIERbd413492015-03-03 16:52:26 +01006231 /* We must initialize the execution timeouts. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006232 s->hlua->max_time = hlua_timeout_session;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006233 }
6234
6235 /* Execute the function. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006236 switch (hlua_ctx_resume(s->hlua, !(flags & ACT_FLAG_FINAL))) {
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006237 /* finished. */
6238 case HLUA_E_OK:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006239 if (!consistency_check(s, dir, &s->hlua->cons)) {
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01006240 stream_int_retnclose(&s->si[0], &msg);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02006241 return ACT_RET_ERR;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01006242 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006243 if (s->hlua->flags & HLUA_STOP)
Thierry FOURNIER9bd52d42016-07-14 11:45:33 +02006244 return ACT_RET_STOP;
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02006245 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006246
6247 /* yield. */
6248 case HLUA_E_AGAIN:
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01006249 /* Set timeout in the required channel. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006250 if (s->hlua->wake_time != TICK_ETERNITY) {
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01006251 if (analyzer & (AN_REQ_INSPECT_FE|AN_REQ_HTTP_PROCESS_FE))
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006252 s->req.analyse_exp = s->hlua->wake_time;
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01006253 else if (analyzer & (AN_RES_INSPECT|AN_RES_HTTP_PROCESS_BE))
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006254 s->res.analyse_exp = s->hlua->wake_time;
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01006255 }
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006256 /* Some actions can be wake up when a "write" event
6257 * is detected on a response channel. This is useful
6258 * only for actions targetted on the requests.
6259 */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006260 if (HLUA_IS_WAKERESWR(s->hlua)) {
Willy Tarreau22ec1ea2014-11-27 20:45:39 +01006261 s->res.flags |= CF_WAKE_WRITE;
Willy Tarreau76bd97f2015-03-10 17:16:10 +01006262 if ((analyzer & (AN_REQ_INSPECT_FE|AN_REQ_HTTP_PROCESS_FE)))
Willy Tarreau22ec1ea2014-11-27 20:45:39 +01006263 s->res.analysers |= analyzer;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006264 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006265 if (HLUA_IS_WAKEREQWR(s->hlua))
Willy Tarreau22ec1ea2014-11-27 20:45:39 +01006266 s->req.flags |= CF_WAKE_WRITE;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01006267 /* We can quit the fcuntion without consistency check
6268 * because HAProxy is not able to manipulate data, it
6269 * is only allowed to call me again. */
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02006270 return ACT_RET_YIELD;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006271
6272 /* finished with error. */
6273 case HLUA_E_ERRMSG:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006274 if (!consistency_check(s, dir, &s->hlua->cons)) {
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01006275 stream_int_retnclose(&s->si[0], &msg);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02006276 return ACT_RET_ERR;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01006277 }
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006278 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02006279 SEND_ERR(px, "Lua function '%s': %s.\n",
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006280 rule->arg.hlua_rule->fcn.name, lua_tostring(s->hlua->T, -1));
6281 lua_pop(s->hlua->T, 1);
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02006282 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006283
Thierry Fournierd5b073c2018-05-21 19:42:47 +02006284 case HLUA_E_ETMOUT:
6285 if (!consistency_check(s, dir, &s->hlua->cons)) {
6286 stream_int_retnclose(&s->si[0], &msg);
6287 return ACT_RET_ERR;
6288 }
6289 SEND_ERR(px, "Lua function '%s': execution timeout.\n", rule->arg.hlua_rule->fcn.name);
6290 return 0;
6291
6292 case HLUA_E_NOMEM:
6293 if (!consistency_check(s, dir, &s->hlua->cons)) {
6294 stream_int_retnclose(&s->si[0], &msg);
6295 return ACT_RET_ERR;
6296 }
6297 SEND_ERR(px, "Lua function '%s': out of memory error.\n", rule->arg.hlua_rule->fcn.name);
6298 return 0;
6299
6300 case HLUA_E_YIELD:
6301 if (!consistency_check(s, dir, &s->hlua->cons)) {
6302 stream_int_retnclose(&s->si[0], &msg);
6303 return ACT_RET_ERR;
6304 }
6305 SEND_ERR(px, "Lua function '%s': aborting Lua processing on expired timeout.\n",
6306 rule->arg.hlua_rule->fcn.name);
6307 return 0;
6308
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006309 case HLUA_E_ERR:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01006310 if (!consistency_check(s, dir, &s->hlua->cons)) {
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01006311 stream_int_retnclose(&s->si[0], &msg);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02006312 return ACT_RET_ERR;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01006313 }
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006314 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02006315 SEND_ERR(px, "Lua function '%s' return an unknown error.\n",
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006316 rule->arg.hlua_rule->fcn.name);
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006317
6318 default:
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02006319 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006320 }
6321}
6322
Olivier Houchard9f6af332018-05-25 14:04:04 +02006323struct task *hlua_applet_wakeup(struct task *t, void *context, unsigned short state)
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006324{
Olivier Houchard9f6af332018-05-25 14:04:04 +02006325 struct appctx *ctx = context;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006326 struct stream_interface *si = ctx->owner;
6327
6328 /* If the applet is wake up without any expected work, the sheduler
6329 * remove it from the run queue. This flag indicate that the applet
6330 * is waiting for write. If the buffer is full, the main processing
6331 * will send some data and after call the applet, otherwise it call
6332 * the applet ASAP.
6333 */
6334 si_applet_cant_put(si);
6335 appctx_wakeup(ctx);
Willy Tarreaud9587412017-08-23 16:07:33 +02006336 t->expire = TICK_ETERNITY;
Willy Tarreaud1aa41f2017-07-21 16:41:56 +02006337 return t;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006338}
6339
6340static int hlua_applet_tcp_init(struct appctx *ctx, struct proxy *px, struct stream *strm)
6341{
6342 struct stream_interface *si = ctx->owner;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006343 struct hlua *hlua;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006344 struct task *task;
6345 char **arg;
Thierry Fournierfd107a22016-02-19 19:57:23 +01006346 const char *error;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006347
Willy Tarreaubafbe012017-11-24 17:34:44 +01006348 hlua = pool_alloc(pool_head_hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006349 if (!hlua) {
6350 SEND_ERR(px, "Lua applet tcp '%s': out of memory.\n",
6351 ctx->rule->arg.hlua_rule->fcn.name);
6352 return 0;
6353 }
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006354 HLUA_INIT(hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006355 ctx->ctx.hlua_apptcp.hlua = hlua;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006356 ctx->ctx.hlua_apptcp.flags = 0;
6357
6358 /* Create task used by signal to wakeup applets. */
Willy Tarreau5f4a47b2017-10-31 15:59:32 +01006359 task = task_new(tid_bit);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006360 if (!task) {
6361 SEND_ERR(px, "Lua applet tcp '%s': out of memory.\n",
6362 ctx->rule->arg.hlua_rule->fcn.name);
6363 return 0;
6364 }
6365 task->nice = 0;
6366 task->context = ctx;
6367 task->process = hlua_applet_wakeup;
6368 ctx->ctx.hlua_apptcp.task = task;
6369
6370 /* In the execution wrappers linked with a stream, the
6371 * Lua context can be not initialized. This behavior
6372 * permits to save performances because a systematic
6373 * Lua initialization cause 5% performances loss.
6374 */
6375 if (!hlua_ctx_init(hlua, task)) {
6376 SEND_ERR(px, "Lua applet tcp '%s': can't initialize Lua context.\n",
6377 ctx->rule->arg.hlua_rule->fcn.name);
6378 return 0;
6379 }
6380
6381 /* Set timeout according with the applet configuration. */
Thierry FOURNIER10770fa2015-09-29 01:59:42 +02006382 hlua->max_time = ctx->applet->timeout;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006383
6384 /* The following Lua calls can fail. */
6385 if (!SET_SAFE_LJMP(hlua->T)) {
Thierry Fournierfd107a22016-02-19 19:57:23 +01006386 if (lua_type(hlua->T, -1) == LUA_TSTRING)
6387 error = lua_tostring(hlua->T, -1);
6388 else
6389 error = "critical error";
6390 SEND_ERR(px, "Lua applet tcp '%s': %s.\n",
6391 ctx->rule->arg.hlua_rule->fcn.name, error);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006392 return 0;
6393 }
6394
6395 /* Check stack available size. */
6396 if (!lua_checkstack(hlua->T, 1)) {
6397 SEND_ERR(px, "Lua applet tcp '%s': full stack.\n",
6398 ctx->rule->arg.hlua_rule->fcn.name);
6399 RESET_SAFE_LJMP(hlua->T);
6400 return 0;
6401 }
6402
6403 /* Restore the function in the stack. */
6404 lua_rawgeti(hlua->T, LUA_REGISTRYINDEX, ctx->rule->arg.hlua_rule->fcn.function_ref);
6405
6406 /* Create and and push object stream in the stack. */
6407 if (!hlua_applet_tcp_new(hlua->T, ctx)) {
6408 SEND_ERR(px, "Lua applet tcp '%s': full stack.\n",
6409 ctx->rule->arg.hlua_rule->fcn.name);
6410 RESET_SAFE_LJMP(hlua->T);
6411 return 0;
6412 }
6413 hlua->nargs = 1;
6414
6415 /* push keywords in the stack. */
6416 for (arg = ctx->rule->arg.hlua_rule->args; arg && *arg; arg++) {
6417 if (!lua_checkstack(hlua->T, 1)) {
6418 SEND_ERR(px, "Lua applet tcp '%s': full stack.\n",
6419 ctx->rule->arg.hlua_rule->fcn.name);
6420 RESET_SAFE_LJMP(hlua->T);
6421 return 0;
6422 }
6423 lua_pushstring(hlua->T, *arg);
6424 hlua->nargs++;
6425 }
6426
6427 RESET_SAFE_LJMP(hlua->T);
6428
6429 /* Wakeup the applet ASAP. */
6430 si_applet_cant_get(si);
6431 si_applet_cant_put(si);
6432
6433 return 1;
6434}
6435
6436static void hlua_applet_tcp_fct(struct appctx *ctx)
6437{
6438 struct stream_interface *si = ctx->owner;
6439 struct stream *strm = si_strm(si);
6440 struct channel *res = si_ic(si);
6441 struct act_rule *rule = ctx->rule;
6442 struct proxy *px = strm->be;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006443 struct hlua *hlua = ctx->ctx.hlua_apptcp.hlua;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006444
6445 /* The applet execution is already done. */
Olivier Houchard594c8c52018-08-28 14:41:31 +02006446 if (ctx->ctx.hlua_apptcp.flags & APPLET_DONE) {
6447 /* eat the whole request */
6448 co_skip(si_oc(si), co_data(si_oc(si)));
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006449 return;
Olivier Houchard594c8c52018-08-28 14:41:31 +02006450 }
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006451
6452 /* If the stream is disconnect or closed, ldo nothing. */
6453 if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO))
6454 return;
6455
6456 /* Execute the function. */
6457 switch (hlua_ctx_resume(hlua, 1)) {
6458 /* finished. */
6459 case HLUA_E_OK:
6460 ctx->ctx.hlua_apptcp.flags |= APPLET_DONE;
6461
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006462 /* eat the whole request */
Willy Tarreaua79021a2018-06-15 18:07:57 +02006463 co_skip(si_oc(si), co_data(si_oc(si)));
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006464 res->flags |= CF_READ_NULL;
6465 si_shutr(si);
6466 return;
6467
6468 /* yield. */
6469 case HLUA_E_AGAIN:
Thierry Fournier0164f202016-02-20 17:47:43 +01006470 if (hlua->wake_time != TICK_ETERNITY)
6471 task_schedule(ctx->ctx.hlua_apptcp.task, hlua->wake_time);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006472 return;
6473
6474 /* finished with error. */
6475 case HLUA_E_ERRMSG:
6476 /* Display log. */
6477 SEND_ERR(px, "Lua applet tcp '%s': %s.\n",
6478 rule->arg.hlua_rule->fcn.name, lua_tostring(hlua->T, -1));
6479 lua_pop(hlua->T, 1);
6480 goto error;
6481
Thierry Fournierd5b073c2018-05-21 19:42:47 +02006482 case HLUA_E_ETMOUT:
6483 SEND_ERR(px, "Lua applet tcp '%s': execution timeout.\n",
6484 rule->arg.hlua_rule->fcn.name);
6485 goto error;
6486
6487 case HLUA_E_NOMEM:
6488 SEND_ERR(px, "Lua applet tcp '%s': out of memory error.\n",
6489 rule->arg.hlua_rule->fcn.name);
6490 goto error;
6491
6492 case HLUA_E_YIELD: /* unexpected */
6493 SEND_ERR(px, "Lua applet tcp '%s': yield not allowed.\n",
6494 rule->arg.hlua_rule->fcn.name);
6495 goto error;
6496
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006497 case HLUA_E_ERR:
6498 /* Display log. */
6499 SEND_ERR(px, "Lua applet tcp '%s' return an unknown error.\n",
6500 rule->arg.hlua_rule->fcn.name);
6501 goto error;
6502
6503 default:
6504 goto error;
6505 }
6506
6507error:
6508
6509 /* For all other cases, just close the stream. */
6510 si_shutw(si);
6511 si_shutr(si);
6512 ctx->ctx.hlua_apptcp.flags |= APPLET_DONE;
6513}
6514
6515static void hlua_applet_tcp_release(struct appctx *ctx)
6516{
Willy Tarreaubd7fc952017-07-24 17:35:27 +02006517 task_delete(ctx->ctx.hlua_apptcp.task);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006518 task_free(ctx->ctx.hlua_apptcp.task);
6519 ctx->ctx.hlua_apptcp.task = NULL;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006520 hlua_ctx_destroy(ctx->ctx.hlua_apptcp.hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006521 ctx->ctx.hlua_apptcp.hlua = NULL;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006522}
6523
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006524/* The function returns 1 if the initialisation is complete, 0 if
6525 * an errors occurs and -1 if more data are required for initializing
6526 * the applet.
6527 */
6528static int hlua_applet_http_init(struct appctx *ctx, struct proxy *px, struct stream *strm)
6529{
6530 struct stream_interface *si = ctx->owner;
6531 struct channel *req = si_oc(si);
6532 struct http_msg *msg;
6533 struct http_txn *txn;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006534 struct hlua *hlua;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006535 char **arg;
6536 struct hdr_ctx hdr;
6537 struct task *task;
6538 struct sample smp; /* just used for a valid call to smp_prefetch_http. */
Thierry Fournierfd107a22016-02-19 19:57:23 +01006539 const char *error;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006540
6541 /* Wait for a full HTTP request. */
6542 if (!smp_prefetch_http(px, strm, 0, NULL, &smp, 0)) {
6543 if (smp.flags & SMP_F_MAY_CHANGE)
6544 return -1;
6545 return 0;
6546 }
6547 txn = strm->txn;
6548 msg = &txn->req;
6549
Willy Tarreau0078bfc2015-10-07 20:20:28 +02006550 /* We want two things in HTTP mode :
6551 * - enforce server-close mode if we were in keep-alive, so that the
6552 * applet is released after each response ;
6553 * - enable request body transfer to the applet in order to resync
6554 * with the response body.
6555 */
6556 if ((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL)
6557 txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | TX_CON_WANT_SCL;
Willy Tarreau0078bfc2015-10-07 20:20:28 +02006558
Willy Tarreaubafbe012017-11-24 17:34:44 +01006559 hlua = pool_alloc(pool_head_hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006560 if (!hlua) {
6561 SEND_ERR(px, "Lua applet http '%s': out of memory.\n",
6562 ctx->rule->arg.hlua_rule->fcn.name);
6563 return 0;
6564 }
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006565 HLUA_INIT(hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006566 ctx->ctx.hlua_apphttp.hlua = hlua;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006567 ctx->ctx.hlua_apphttp.left_bytes = -1;
6568 ctx->ctx.hlua_apphttp.flags = 0;
6569
Thierry FOURNIERd93ea2b2015-12-20 19:14:52 +01006570 if (txn->req.flags & HTTP_MSGF_VER_11)
6571 ctx->ctx.hlua_apphttp.flags |= APPLET_HTTP11;
6572
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006573 /* Create task used by signal to wakeup applets. */
Willy Tarreau5f4a47b2017-10-31 15:59:32 +01006574 task = task_new(tid_bit);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006575 if (!task) {
6576 SEND_ERR(px, "Lua applet http '%s': out of memory.\n",
6577 ctx->rule->arg.hlua_rule->fcn.name);
6578 return 0;
6579 }
6580 task->nice = 0;
6581 task->context = ctx;
6582 task->process = hlua_applet_wakeup;
6583 ctx->ctx.hlua_apphttp.task = task;
6584
6585 /* In the execution wrappers linked with a stream, the
6586 * Lua context can be not initialized. This behavior
6587 * permits to save performances because a systematic
6588 * Lua initialization cause 5% performances loss.
6589 */
6590 if (!hlua_ctx_init(hlua, task)) {
6591 SEND_ERR(px, "Lua applet http '%s': can't initialize Lua context.\n",
6592 ctx->rule->arg.hlua_rule->fcn.name);
6593 return 0;
6594 }
6595
6596 /* Set timeout according with the applet configuration. */
Thierry FOURNIER10770fa2015-09-29 01:59:42 +02006597 hlua->max_time = ctx->applet->timeout;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006598
6599 /* The following Lua calls can fail. */
6600 if (!SET_SAFE_LJMP(hlua->T)) {
Thierry Fournierfd107a22016-02-19 19:57:23 +01006601 if (lua_type(hlua->T, -1) == LUA_TSTRING)
6602 error = lua_tostring(hlua->T, -1);
6603 else
6604 error = "critical error";
6605 SEND_ERR(px, "Lua applet http '%s': %s.\n",
6606 ctx->rule->arg.hlua_rule->fcn.name, error);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006607 return 0;
6608 }
6609
6610 /* Check stack available size. */
6611 if (!lua_checkstack(hlua->T, 1)) {
6612 SEND_ERR(px, "Lua applet http '%s': full stack.\n",
6613 ctx->rule->arg.hlua_rule->fcn.name);
6614 RESET_SAFE_LJMP(hlua->T);
6615 return 0;
6616 }
6617
6618 /* Restore the function in the stack. */
6619 lua_rawgeti(hlua->T, LUA_REGISTRYINDEX, ctx->rule->arg.hlua_rule->fcn.function_ref);
6620
6621 /* Create and and push object stream in the stack. */
6622 if (!hlua_applet_http_new(hlua->T, ctx)) {
6623 SEND_ERR(px, "Lua applet http '%s': full stack.\n",
6624 ctx->rule->arg.hlua_rule->fcn.name);
6625 RESET_SAFE_LJMP(hlua->T);
6626 return 0;
6627 }
6628 hlua->nargs = 1;
6629
6630 /* Look for a 100-continue expected. */
6631 if (msg->flags & HTTP_MSGF_VER_11) {
6632 hdr.idx = 0;
Willy Tarreaua79021a2018-06-15 18:07:57 +02006633 if (http_find_header2("Expect", 6, ci_head(req), &txn->hdr_idx, &hdr) &&
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006634 unlikely(hdr.vlen == 12 && strncasecmp(hdr.line+hdr.val, "100-continue", 12) == 0))
6635 ctx->ctx.hlua_apphttp.flags |= APPLET_100C;
6636 }
6637
6638 /* push keywords in the stack. */
6639 for (arg = ctx->rule->arg.hlua_rule->args; arg && *arg; arg++) {
6640 if (!lua_checkstack(hlua->T, 1)) {
6641 SEND_ERR(px, "Lua applet http '%s': full stack.\n",
6642 ctx->rule->arg.hlua_rule->fcn.name);
6643 RESET_SAFE_LJMP(hlua->T);
6644 return 0;
6645 }
6646 lua_pushstring(hlua->T, *arg);
6647 hlua->nargs++;
6648 }
6649
6650 RESET_SAFE_LJMP(hlua->T);
6651
6652 /* Wakeup the applet when data is ready for read. */
6653 si_applet_cant_get(si);
6654
6655 return 1;
6656}
6657
6658static void hlua_applet_http_fct(struct appctx *ctx)
6659{
6660 struct stream_interface *si = ctx->owner;
6661 struct stream *strm = si_strm(si);
6662 struct channel *res = si_ic(si);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006663 struct act_rule *rule = ctx->rule;
6664 struct proxy *px = strm->be;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006665 struct hlua *hlua = ctx->ctx.hlua_apphttp.hlua;
Willy Tarreau206ba832018-06-14 15:27:31 +02006666 const char *blk1;
Willy Tarreau55f3ce12018-07-18 11:49:27 +02006667 size_t len1;
Willy Tarreau206ba832018-06-14 15:27:31 +02006668 const char *blk2;
Willy Tarreau55f3ce12018-07-18 11:49:27 +02006669 size_t len2;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006670 int ret;
6671
6672 /* If the stream is disconnect or closed, ldo nothing. */
6673 if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO))
6674 return;
6675
6676 /* Set the currently running flag. */
6677 if (!HLUA_IS_RUNNING(hlua) &&
6678 !(ctx->ctx.hlua_apphttp.flags & APPLET_DONE)) {
6679
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006680 /* Wait for full HTTP analysys. */
6681 if (unlikely(strm->txn->req.msg_state < HTTP_MSG_BODY)) {
6682 si_applet_cant_get(si);
6683 return;
6684 }
6685
6686 /* Store the max amount of bytes that we can read. */
6687 ctx->ctx.hlua_apphttp.left_bytes = strm->txn->req.body_len;
6688
6689 /* We need to flush the request header. This left the body
6690 * for the Lua.
6691 */
6692
6693 /* Read the maximum amount of data avalaible. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02006694 ret = co_getblk_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006695 if (ret == -1)
6696 return;
6697
6698 /* No data available, ask for more data. */
6699 if (ret == 1)
6700 len2 = 0;
6701 if (ret == 0)
6702 len1 = 0;
Thierry FOURNIER70d318c2018-06-30 10:37:33 +02006703 if (len1 + len2 < strm->txn->req.eoh + strm->txn->req.eol) {
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006704 si_applet_cant_get(si);
6705 return;
6706 }
6707
6708 /* skip the requests bytes. */
Thierry FOURNIER70d318c2018-06-30 10:37:33 +02006709 co_skip(si_oc(si), strm->txn->req.eoh + strm->txn->req.eol);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006710 }
6711
6712 /* Executes The applet if it is not done. */
6713 if (!(ctx->ctx.hlua_apphttp.flags & APPLET_DONE)) {
6714
6715 /* Execute the function. */
6716 switch (hlua_ctx_resume(hlua, 1)) {
6717 /* finished. */
6718 case HLUA_E_OK:
6719 ctx->ctx.hlua_apphttp.flags |= APPLET_DONE;
6720 break;
6721
6722 /* yield. */
6723 case HLUA_E_AGAIN:
Thierry Fournier0164f202016-02-20 17:47:43 +01006724 if (hlua->wake_time != TICK_ETERNITY)
6725 task_schedule(ctx->ctx.hlua_apphttp.task, hlua->wake_time);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006726 return;
6727
6728 /* finished with error. */
6729 case HLUA_E_ERRMSG:
6730 /* Display log. */
6731 SEND_ERR(px, "Lua applet http '%s': %s.\n",
6732 rule->arg.hlua_rule->fcn.name, lua_tostring(hlua->T, -1));
6733 lua_pop(hlua->T, 1);
6734 goto error;
6735
Thierry Fournierd5b073c2018-05-21 19:42:47 +02006736 case HLUA_E_ETMOUT:
6737 SEND_ERR(px, "Lua applet http '%s': execution timeout.\n",
6738 rule->arg.hlua_rule->fcn.name);
6739 goto error;
6740
6741 case HLUA_E_NOMEM:
6742 SEND_ERR(px, "Lua applet http '%s': out of memory error.\n",
6743 rule->arg.hlua_rule->fcn.name);
6744 goto error;
6745
6746 case HLUA_E_YIELD: /* unexpected */
6747 SEND_ERR(px, "Lua applet http '%s': yield not allowed.\n",
6748 rule->arg.hlua_rule->fcn.name);
6749 goto error;
6750
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006751 case HLUA_E_ERR:
6752 /* Display log. */
6753 SEND_ERR(px, "Lua applet http '%s' return an unknown error.\n",
6754 rule->arg.hlua_rule->fcn.name);
6755 goto error;
6756
6757 default:
6758 goto error;
6759 }
6760 }
6761
6762 if (ctx->ctx.hlua_apphttp.flags & APPLET_DONE) {
6763
6764 /* We must send the final chunk. */
6765 if (ctx->ctx.hlua_apphttp.flags & APPLET_CHUNKED &&
6766 !(ctx->ctx.hlua_apphttp.flags & APPLET_LAST_CHK)) {
6767
6768 /* sent last chunk at once. */
Willy Tarreau06d80a92017-10-19 14:32:15 +02006769 ret = ci_putblk(res, "0\r\n\r\n", 5);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006770
6771 /* critical error. */
6772 if (ret == -2 || ret == -3) {
6773 SEND_ERR(px, "Lua applet http '%s'cannont send last chunk.\n",
6774 rule->arg.hlua_rule->fcn.name);
6775 goto error;
6776 }
6777
6778 /* no enough space error. */
6779 if (ret == -1) {
6780 si_applet_cant_put(si);
6781 return;
6782 }
6783
6784 /* set the last chunk sent. */
6785 ctx->ctx.hlua_apphttp.flags |= APPLET_LAST_CHK;
6786 }
6787
6788 /* close the connection. */
6789
Frédéric Lécaille83ed5d52018-07-18 14:25:26 +02006790 /* status */
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006791 strm->txn->status = ctx->ctx.hlua_apphttp.status;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006792
6793 /* eat the whole request */
Willy Tarreaua79021a2018-06-15 18:07:57 +02006794 co_skip(si_oc(si), co_data(si_oc(si)));
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006795 res->flags |= CF_READ_NULL;
6796 si_shutr(si);
6797
6798 return;
6799 }
6800
6801error:
6802
6803 /* If we are in HTTP mode, and we are not send any
6804 * data, return a 500 server error in best effort:
6805 * if there are no room avalaible in the buffer,
6806 * just close the connection.
6807 */
Willy Tarreau06d80a92017-10-19 14:32:15 +02006808 ci_putblk(res, error_500, strlen(error_500));
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006809 if (!(strm->flags & SF_ERR_MASK))
6810 strm->flags |= SF_ERR_RESOURCE;
6811 si_shutw(si);
6812 si_shutr(si);
6813 ctx->ctx.hlua_apphttp.flags |= APPLET_DONE;
6814}
6815
6816static void hlua_applet_http_release(struct appctx *ctx)
6817{
Willy Tarreaubd7fc952017-07-24 17:35:27 +02006818 task_delete(ctx->ctx.hlua_apphttp.task);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006819 task_free(ctx->ctx.hlua_apphttp.task);
6820 ctx->ctx.hlua_apphttp.task = NULL;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006821 hlua_ctx_destroy(ctx->ctx.hlua_apphttp.hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006822 ctx->ctx.hlua_apphttp.hlua = NULL;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006823}
6824
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006825/* global {tcp|http}-request parser. Return ACT_RET_PRS_OK in
6826 * succes case, else return ACT_RET_PRS_ERR.
Thierry FOURNIERbabae282015-09-17 11:36:37 +02006827 *
6828 * This function can fail with an abort() due to an Lua critical error.
6829 * We are in the configuration parsing process of HAProxy, this abort() is
6830 * tolerated.
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006831 */
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006832static enum act_parse_ret action_register_lua(const char **args, int *cur_arg, struct proxy *px,
6833 struct act_rule *rule, char **err)
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006834{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02006835 struct hlua_function *fcn = rule->kw->private;
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006836 int i;
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006837
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006838 /* Memory for the rule. */
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02006839 rule->arg.hlua_rule = calloc(1, sizeof(*rule->arg.hlua_rule));
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006840 if (!rule->arg.hlua_rule) {
6841 memprintf(err, "out of memory error");
Thierry FOURNIERafa80492015-08-19 09:04:15 +02006842 return ACT_RET_PRS_ERR;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006843 }
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006844
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006845 /* Memory for arguments. */
6846 rule->arg.hlua_rule->args = calloc(fcn->nargs + 1, sizeof(char *));
6847 if (!rule->arg.hlua_rule->args) {
6848 memprintf(err, "out of memory error");
6849 return ACT_RET_PRS_ERR;
6850 }
6851
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006852 /* Reference the Lua function and store the reference. */
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006853 rule->arg.hlua_rule->fcn = *fcn;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006854
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006855 /* Expect some arguments */
6856 for (i = 0; i < fcn->nargs; i++) {
6857 if (*args[i+1] == '\0') {
6858 memprintf(err, "expect %d arguments", fcn->nargs);
6859 return ACT_RET_PRS_ERR;
6860 }
6861 rule->arg.hlua_rule->args[i] = strdup(args[i + 1]);
6862 if (!rule->arg.hlua_rule->args[i]) {
6863 memprintf(err, "out of memory error");
6864 return ACT_RET_PRS_ERR;
6865 }
6866 (*cur_arg)++;
6867 }
6868 rule->arg.hlua_rule->args[i] = NULL;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006869
Thierry FOURNIER42148732015-09-02 17:17:33 +02006870 rule->action = ACT_CUSTOM;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006871 rule->action_ptr = hlua_action;
Thierry FOURNIERafa80492015-08-19 09:04:15 +02006872 return ACT_RET_PRS_OK;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006873}
6874
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006875static enum act_parse_ret action_register_service_http(const char **args, int *cur_arg, struct proxy *px,
6876 struct act_rule *rule, char **err)
6877{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02006878 struct hlua_function *fcn = rule->kw->private;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006879
Thierry FOURNIER718e2a72015-12-20 20:13:14 +01006880 /* HTTP applets are forbidden in tcp-request rules.
6881 * HTTP applet request requires everything initilized by
6882 * "http_process_request" (analyzer flag AN_REQ_HTTP_INNER).
6883 * The applet will be immediately initilized, but its before
6884 * the call of this analyzer.
6885 */
6886 if (rule->from != ACT_F_HTTP_REQ) {
6887 memprintf(err, "HTTP applets are forbidden from 'tcp-request' rulesets");
6888 return ACT_RET_PRS_ERR;
6889 }
6890
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006891 /* Memory for the rule. */
6892 rule->arg.hlua_rule = calloc(1, sizeof(*rule->arg.hlua_rule));
6893 if (!rule->arg.hlua_rule) {
6894 memprintf(err, "out of memory error");
6895 return ACT_RET_PRS_ERR;
6896 }
6897
6898 /* Reference the Lua function and store the reference. */
6899 rule->arg.hlua_rule->fcn = *fcn;
6900
6901 /* TODO: later accept arguments. */
6902 rule->arg.hlua_rule->args = NULL;
6903
6904 /* Add applet pointer in the rule. */
6905 rule->applet.obj_type = OBJ_TYPE_APPLET;
6906 rule->applet.name = fcn->name;
6907 rule->applet.init = hlua_applet_http_init;
6908 rule->applet.fct = hlua_applet_http_fct;
6909 rule->applet.release = hlua_applet_http_release;
6910 rule->applet.timeout = hlua_timeout_applet;
6911
6912 return ACT_RET_PRS_OK;
6913}
6914
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006915/* This function is an LUA binding used for registering
6916 * "sample-conv" functions. It expects a converter name used
6917 * in the haproxy configuration file, and an LUA function.
6918 */
6919__LJMP static int hlua_register_action(lua_State *L)
6920{
6921 struct action_kw_list *akl;
6922 const char *name;
6923 int ref;
6924 int len;
6925 struct hlua_function *fcn;
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006926 int nargs;
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006927
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006928 /* Initialise the number of expected arguments at 0. */
6929 nargs = 0;
6930
6931 if (lua_gettop(L) < 3 || lua_gettop(L) > 4)
6932 WILL_LJMP(luaL_error(L, "'register_action' needs between 3 and 4 arguments"));
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006933
6934 /* First argument : converter name. */
6935 name = MAY_LJMP(luaL_checkstring(L, 1));
6936
6937 /* Second argument : environment. */
6938 if (lua_type(L, 2) != LUA_TTABLE)
6939 WILL_LJMP(luaL_error(L, "register_action: second argument must be a table of strings"));
6940
6941 /* Third argument : lua function. */
6942 ref = MAY_LJMP(hlua_checkfunction(L, 3));
6943
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006944 /* Fouth argument : number of mandatories arguments expected on the configuration line. */
6945 if (lua_gettop(L) >= 4)
6946 nargs = MAY_LJMP(luaL_checkinteger(L, 4));
6947
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006948 /* browse the second argulent as an array. */
6949 lua_pushnil(L);
6950 while (lua_next(L, 2) != 0) {
6951 if (lua_type(L, -1) != LUA_TSTRING)
6952 WILL_LJMP(luaL_error(L, "register_action: second argument must be a table of strings"));
6953
6954 /* Check required environment. Only accepted "http" or "tcp". */
6955 /* Allocate and fill the sample fetch keyword struct. */
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02006956 akl = calloc(1, sizeof(*akl) + sizeof(struct action_kw) * 2);
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006957 if (!akl)
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01006958 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02006959 fcn = calloc(1, sizeof(*fcn));
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006960 if (!fcn)
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01006961 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006962
6963 /* Fill fcn. */
6964 fcn->name = strdup(name);
6965 if (!fcn->name)
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01006966 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006967 fcn->function_ref = ref;
6968
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006969 /* Set the expected number od arguments. */
6970 fcn->nargs = nargs;
6971
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006972 /* List head */
6973 akl->list.n = akl->list.p = NULL;
6974
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006975 /* action keyword. */
6976 len = strlen("lua.") + strlen(name) + 1;
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02006977 akl->kw[0].kw = calloc(1, len);
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006978 if (!akl->kw[0].kw)
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01006979 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006980
6981 snprintf((char *)akl->kw[0].kw, len, "lua.%s", name);
6982
6983 akl->kw[0].match_pfx = 0;
6984 akl->kw[0].private = fcn;
6985 akl->kw[0].parse = action_register_lua;
6986
6987 /* select the action registering point. */
6988 if (strcmp(lua_tostring(L, -1), "tcp-req") == 0)
6989 tcp_req_cont_keywords_register(akl);
6990 else if (strcmp(lua_tostring(L, -1), "tcp-res") == 0)
6991 tcp_res_cont_keywords_register(akl);
6992 else if (strcmp(lua_tostring(L, -1), "http-req") == 0)
6993 http_req_keywords_register(akl);
6994 else if (strcmp(lua_tostring(L, -1), "http-res") == 0)
6995 http_res_keywords_register(akl);
6996 else
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01006997 WILL_LJMP(luaL_error(L, "Lua action environment '%s' is unknown. "
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006998 "'tcp-req', 'tcp-res', 'http-req' or 'http-res' "
6999 "are expected.", lua_tostring(L, -1)));
7000
7001 /* pop the environment string. */
7002 lua_pop(L, 1);
7003 }
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007004 return ACT_RET_PRS_OK;
7005}
7006
7007static enum act_parse_ret action_register_service_tcp(const char **args, int *cur_arg, struct proxy *px,
7008 struct act_rule *rule, char **err)
7009{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02007010 struct hlua_function *fcn = rule->kw->private;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007011
7012 /* Memory for the rule. */
7013 rule->arg.hlua_rule = calloc(1, sizeof(*rule->arg.hlua_rule));
7014 if (!rule->arg.hlua_rule) {
7015 memprintf(err, "out of memory error");
7016 return ACT_RET_PRS_ERR;
7017 }
Thierry FOURNIER8255a752015-09-23 21:03:35 +02007018
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007019 /* Reference the Lua function and store the reference. */
7020 rule->arg.hlua_rule->fcn = *fcn;
7021
7022 /* TODO: later accept arguments. */
7023 rule->arg.hlua_rule->args = NULL;
7024
7025 /* Add applet pointer in the rule. */
7026 rule->applet.obj_type = OBJ_TYPE_APPLET;
7027 rule->applet.name = fcn->name;
7028 rule->applet.init = hlua_applet_tcp_init;
7029 rule->applet.fct = hlua_applet_tcp_fct;
7030 rule->applet.release = hlua_applet_tcp_release;
7031 rule->applet.timeout = hlua_timeout_applet;
7032
7033 return 0;
7034}
7035
7036/* This function is an LUA binding used for registering
7037 * "sample-conv" functions. It expects a converter name used
7038 * in the haproxy configuration file, and an LUA function.
7039 */
7040__LJMP static int hlua_register_service(lua_State *L)
7041{
7042 struct action_kw_list *akl;
7043 const char *name;
7044 const char *env;
7045 int ref;
7046 int len;
7047 struct hlua_function *fcn;
7048
7049 MAY_LJMP(check_args(L, 3, "register_service"));
7050
7051 /* First argument : converter name. */
7052 name = MAY_LJMP(luaL_checkstring(L, 1));
7053
7054 /* Second argument : environment. */
7055 env = MAY_LJMP(luaL_checkstring(L, 2));
7056
7057 /* Third argument : lua function. */
7058 ref = MAY_LJMP(hlua_checkfunction(L, 3));
7059
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007060 /* Allocate and fill the sample fetch keyword struct. */
7061 akl = calloc(1, sizeof(*akl) + sizeof(struct action_kw) * 2);
7062 if (!akl)
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01007063 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007064 fcn = calloc(1, sizeof(*fcn));
7065 if (!fcn)
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01007066 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007067
7068 /* Fill fcn. */
7069 len = strlen("<lua.>") + strlen(name) + 1;
7070 fcn->name = calloc(1, len);
7071 if (!fcn->name)
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01007072 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007073 snprintf((char *)fcn->name, len, "<lua.%s>", name);
7074 fcn->function_ref = ref;
7075
7076 /* List head */
7077 akl->list.n = akl->list.p = NULL;
7078
7079 /* converter keyword. */
7080 len = strlen("lua.") + strlen(name) + 1;
7081 akl->kw[0].kw = calloc(1, len);
7082 if (!akl->kw[0].kw)
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01007083 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007084
7085 snprintf((char *)akl->kw[0].kw, len, "lua.%s", name);
7086
Thierry FOURNIER / OZON.IO02564fd2016-11-12 11:07:05 +01007087 /* Check required environment. Only accepted "http" or "tcp". */
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007088 if (strcmp(env, "tcp") == 0)
7089 akl->kw[0].parse = action_register_service_tcp;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02007090 else if (strcmp(env, "http") == 0)
7091 akl->kw[0].parse = action_register_service_http;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007092 else
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01007093 WILL_LJMP(luaL_error(L, "Lua service environment '%s' is unknown. "
Eric Salamafe7456f2017-12-21 14:30:07 +01007094 "'tcp' or 'http' are expected.", env));
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007095
7096 akl->kw[0].match_pfx = 0;
7097 akl->kw[0].private = fcn;
7098
7099 /* End of array. */
7100 memset(&akl->kw[1], 0, sizeof(*akl->kw));
7101
7102 /* Register this new converter */
7103 service_keywords_register(akl);
7104
Thierry FOURNIER8255a752015-09-23 21:03:35 +02007105 return 0;
7106}
7107
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007108/* This function initialises Lua cli handler. It copies the
7109 * arguments in the Lua stack and create channel IO objects.
7110 */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02007111static int hlua_cli_parse_fct(char **args, char *payload, struct appctx *appctx, void *private)
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007112{
7113 struct hlua *hlua;
7114 struct hlua_function *fcn;
7115 int i;
7116 const char *error;
7117
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007118 fcn = private;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01007119 appctx->ctx.hlua_cli.fcn = private;
7120
Willy Tarreaubafbe012017-11-24 17:34:44 +01007121 hlua = pool_alloc(pool_head_hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01007122 if (!hlua) {
7123 SEND_ERR(NULL, "Lua cli '%s': out of memory.\n", fcn->name);
Thierry FOURNIER1be34152016-12-17 12:09:51 +01007124 return 1;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01007125 }
7126 HLUA_INIT(hlua);
7127 appctx->ctx.hlua_cli.hlua = hlua;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007128
7129 /* Create task used by signal to wakeup applets.
7130 * We use the same wakeup fonction than the Lua applet_tcp and
7131 * applet_http. It is absolutely compatible.
7132 */
Willy Tarreau5f4a47b2017-10-31 15:59:32 +01007133 appctx->ctx.hlua_cli.task = task_new(tid_bit);
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007134 if (!appctx->ctx.hlua_cli.task) {
Thierry FOURNIERffbf5692016-12-16 11:14:06 +01007135 SEND_ERR(NULL, "Lua cli '%s': out of memory.\n", fcn->name);
Thierry FOURNIER1be34152016-12-17 12:09:51 +01007136 goto error;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007137 }
7138 appctx->ctx.hlua_cli.task->nice = 0;
7139 appctx->ctx.hlua_cli.task->context = appctx;
7140 appctx->ctx.hlua_cli.task->process = hlua_applet_wakeup;
7141
7142 /* Initialises the Lua context */
7143 if (!hlua_ctx_init(hlua, appctx->ctx.hlua_cli.task)) {
7144 SEND_ERR(NULL, "Lua cli '%s': can't initialize Lua context.\n", fcn->name);
Thierry FOURNIER1be34152016-12-17 12:09:51 +01007145 goto error;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007146 }
7147
7148 /* The following Lua calls can fail. */
7149 if (!SET_SAFE_LJMP(hlua->T)) {
7150 if (lua_type(hlua->T, -1) == LUA_TSTRING)
7151 error = lua_tostring(hlua->T, -1);
7152 else
7153 error = "critical error";
7154 SEND_ERR(NULL, "Lua cli '%s': %s.\n", fcn->name, error);
7155 goto error;
7156 }
7157
7158 /* Check stack available size. */
7159 if (!lua_checkstack(hlua->T, 2)) {
7160 SEND_ERR(NULL, "Lua cli '%s': full stack.\n", fcn->name);
7161 goto error;
7162 }
7163
7164 /* Restore the function in the stack. */
7165 lua_rawgeti(hlua->T, LUA_REGISTRYINDEX, fcn->function_ref);
7166
7167 /* Once the arguments parsed, the CLI is like an AppletTCP,
7168 * so push AppletTCP in the stack.
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007169 */
7170 if (!hlua_applet_tcp_new(hlua->T, appctx)) {
7171 SEND_ERR(NULL, "Lua cli '%s': full stack.\n", fcn->name);
7172 goto error;
7173 }
7174 hlua->nargs = 1;
7175
7176 /* push keywords in the stack. */
7177 for (i = 0; *args[i]; i++) {
7178 /* Check stack available size. */
7179 if (!lua_checkstack(hlua->T, 1)) {
7180 SEND_ERR(NULL, "Lua cli '%s': full stack.\n", fcn->name);
7181 goto error;
7182 }
7183 lua_pushstring(hlua->T, args[i]);
7184 hlua->nargs++;
7185 }
7186
7187 /* We must initialize the execution timeouts. */
7188 hlua->max_time = hlua_timeout_session;
7189
7190 /* At this point the execution is safe. */
7191 RESET_SAFE_LJMP(hlua->T);
7192
7193 /* It's ok */
7194 return 0;
7195
7196 /* It's not ok. */
7197error:
7198 RESET_SAFE_LJMP(hlua->T);
7199 hlua_ctx_destroy(hlua);
Thierry FOURNIER1be34152016-12-17 12:09:51 +01007200 appctx->ctx.hlua_cli.hlua = NULL;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007201 return 1;
7202}
7203
7204static int hlua_cli_io_handler_fct(struct appctx *appctx)
7205{
7206 struct hlua *hlua;
7207 struct stream_interface *si;
7208 struct hlua_function *fcn;
7209
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01007210 hlua = appctx->ctx.hlua_cli.hlua;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007211 si = appctx->owner;
Willy Tarreau8ae4f752016-12-14 15:41:45 +01007212 fcn = appctx->ctx.hlua_cli.fcn;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007213
7214 /* If the stream is disconnect or closed, ldo nothing. */
7215 if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO))
7216 return 1;
7217
7218 /* Execute the function. */
7219 switch (hlua_ctx_resume(hlua, 1)) {
7220
7221 /* finished. */
7222 case HLUA_E_OK:
7223 return 1;
7224
7225 /* yield. */
7226 case HLUA_E_AGAIN:
7227 /* We want write. */
7228 if (HLUA_IS_WAKERESWR(hlua))
7229 si_applet_cant_put(si);
7230 /* Set the timeout. */
7231 if (hlua->wake_time != TICK_ETERNITY)
7232 task_schedule(hlua->task, hlua->wake_time);
7233 return 0;
7234
7235 /* finished with error. */
7236 case HLUA_E_ERRMSG:
7237 /* Display log. */
7238 SEND_ERR(NULL, "Lua cli '%s': %s.\n",
7239 fcn->name, lua_tostring(hlua->T, -1));
7240 lua_pop(hlua->T, 1);
7241 return 1;
7242
Thierry Fournierd5b073c2018-05-21 19:42:47 +02007243 case HLUA_E_ETMOUT:
7244 SEND_ERR(NULL, "Lua converter '%s': execution timeout.\n",
7245 fcn->name);
7246 return 1;
7247
7248 case HLUA_E_NOMEM:
7249 SEND_ERR(NULL, "Lua converter '%s': out of memory error.\n",
7250 fcn->name);
7251 return 1;
7252
7253 case HLUA_E_YIELD: /* unexpected */
7254 SEND_ERR(NULL, "Lua converter '%s': yield not allowed.\n",
7255 fcn->name);
7256 return 1;
7257
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007258 case HLUA_E_ERR:
7259 /* Display log. */
7260 SEND_ERR(NULL, "Lua cli '%s' return an unknown error.\n",
7261 fcn->name);
7262 return 1;
7263
7264 default:
7265 return 1;
7266 }
7267
7268 return 1;
7269}
7270
7271static void hlua_cli_io_release_fct(struct appctx *appctx)
7272{
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01007273 hlua_ctx_destroy(appctx->ctx.hlua_cli.hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01007274 appctx->ctx.hlua_cli.hlua = NULL;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007275}
7276
7277/* This function is an LUA binding used for registering
7278 * new keywords in the cli. It expects a list of keywords
7279 * which are the "path". It is limited to 5 keywords. A
7280 * description of the command, a function to be executed
7281 * for the parsing and a function for io handlers.
7282 */
7283__LJMP static int hlua_register_cli(lua_State *L)
7284{
7285 struct cli_kw_list *cli_kws;
7286 const char *message;
7287 int ref_io;
7288 int len;
7289 struct hlua_function *fcn;
7290 int index;
7291 int i;
7292
7293 MAY_LJMP(check_args(L, 3, "register_cli"));
7294
7295 /* First argument : an array of maximum 5 keywords. */
7296 if (!lua_istable(L, 1))
7297 WILL_LJMP(luaL_argerror(L, 1, "1st argument must be a table"));
7298
7299 /* Second argument : string with contextual message. */
7300 message = MAY_LJMP(luaL_checkstring(L, 2));
7301
7302 /* Third and fourth argument : lua function. */
7303 ref_io = MAY_LJMP(hlua_checkfunction(L, 3));
7304
7305 /* Allocate and fill the sample fetch keyword struct. */
7306 cli_kws = calloc(1, sizeof(*cli_kws) + sizeof(struct cli_kw) * 2);
7307 if (!cli_kws)
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01007308 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007309 fcn = calloc(1, sizeof(*fcn));
7310 if (!fcn)
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01007311 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007312
7313 /* Fill path. */
7314 index = 0;
7315 lua_pushnil(L);
7316 while(lua_next(L, 1) != 0) {
7317 if (index >= 5)
7318 WILL_LJMP(luaL_argerror(L, 1, "1st argument must be a table with a maximum of 5 entries"));
7319 if (lua_type(L, -1) != LUA_TSTRING)
7320 WILL_LJMP(luaL_argerror(L, 1, "1st argument must be a table filled with strings"));
7321 cli_kws->kw[0].str_kw[index] = strdup(lua_tostring(L, -1));
7322 if (!cli_kws->kw[0].str_kw[index])
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01007323 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007324 index++;
7325 lua_pop(L, 1);
7326 }
7327
7328 /* Copy help message. */
7329 cli_kws->kw[0].usage = strdup(message);
7330 if (!cli_kws->kw[0].usage)
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01007331 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007332
7333 /* Fill fcn io handler. */
7334 len = strlen("<lua.cli>") + 1;
7335 for (i = 0; i < index; i++)
7336 len += strlen(cli_kws->kw[0].str_kw[i]) + 1;
7337 fcn->name = calloc(1, len);
7338 if (!fcn->name)
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01007339 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007340 strncat((char *)fcn->name, "<lua.cli", len);
7341 for (i = 0; i < index; i++) {
7342 strncat((char *)fcn->name, ".", len);
7343 strncat((char *)fcn->name, cli_kws->kw[0].str_kw[i], len);
7344 }
7345 strncat((char *)fcn->name, ">", len);
7346 fcn->function_ref = ref_io;
7347
7348 /* Fill last entries. */
7349 cli_kws->kw[0].private = fcn;
7350 cli_kws->kw[0].parse = hlua_cli_parse_fct;
7351 cli_kws->kw[0].io_handler = hlua_cli_io_handler_fct;
7352 cli_kws->kw[0].io_release = hlua_cli_io_release_fct;
7353
7354 /* Register this new converter */
7355 cli_register_kw(cli_kws);
7356
7357 return 0;
7358}
7359
Thierry FOURNIERbd413492015-03-03 16:52:26 +01007360static int hlua_read_timeout(char **args, int section_type, struct proxy *curpx,
7361 struct proxy *defpx, const char *file, int line,
7362 char **err, unsigned int *timeout)
7363{
7364 const char *error;
7365
7366 error = parse_time_err(args[1], timeout, TIME_UNIT_MS);
7367 if (error && *error != '\0') {
7368 memprintf(err, "%s: invalid timeout", args[0]);
7369 return -1;
7370 }
7371 return 0;
7372}
7373
7374static int hlua_session_timeout(char **args, int section_type, struct proxy *curpx,
7375 struct proxy *defpx, const char *file, int line,
7376 char **err)
7377{
7378 return hlua_read_timeout(args, section_type, curpx, defpx,
7379 file, line, err, &hlua_timeout_session);
7380}
7381
7382static int hlua_task_timeout(char **args, int section_type, struct proxy *curpx,
7383 struct proxy *defpx, const char *file, int line,
7384 char **err)
7385{
7386 return hlua_read_timeout(args, section_type, curpx, defpx,
7387 file, line, err, &hlua_timeout_task);
7388}
7389
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007390static int hlua_applet_timeout(char **args, int section_type, struct proxy *curpx,
7391 struct proxy *defpx, const char *file, int line,
7392 char **err)
7393{
7394 return hlua_read_timeout(args, section_type, curpx, defpx,
7395 file, line, err, &hlua_timeout_applet);
7396}
7397
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01007398static int hlua_forced_yield(char **args, int section_type, struct proxy *curpx,
7399 struct proxy *defpx, const char *file, int line,
7400 char **err)
7401{
7402 char *error;
7403
7404 hlua_nb_instruction = strtoll(args[1], &error, 10);
7405 if (*error != '\0') {
7406 memprintf(err, "%s: invalid number", args[0]);
7407 return -1;
7408 }
7409 return 0;
7410}
7411
Willy Tarreau32f61e22015-03-18 17:54:59 +01007412static int hlua_parse_maxmem(char **args, int section_type, struct proxy *curpx,
7413 struct proxy *defpx, const char *file, int line,
7414 char **err)
7415{
7416 char *error;
7417
7418 if (*(args[1]) == 0) {
7419 memprintf(err, "'%s' expects an integer argument (Lua memory size in MB).\n", args[0]);
7420 return -1;
7421 }
7422 hlua_global_allocator.limit = strtoll(args[1], &error, 10) * 1024L * 1024L;
7423 if (*error != '\0') {
7424 memprintf(err, "%s: invalid number %s (error at '%c')", args[0], args[1], *error);
7425 return -1;
7426 }
7427 return 0;
7428}
7429
7430
Thierry FOURNIER6c9b52c2015-01-23 15:57:06 +01007431/* This function is called by the main configuration key "lua-load". It loads and
7432 * execute an lua file during the parsing of the HAProxy configuration file. It is
7433 * the main lua entry point.
7434 *
7435 * This funtion runs with the HAProxy keywords API. It returns -1 if an error is
7436 * occured, otherwise it returns 0.
7437 *
7438 * In some error case, LUA set an error message in top of the stack. This function
7439 * returns this error message in the HAProxy logs and pop it from the stack.
Thierry FOURNIERbabae282015-09-17 11:36:37 +02007440 *
7441 * This function can fail with an abort() due to an Lua critical error.
7442 * We are in the configuration parsing process of HAProxy, this abort() is
7443 * tolerated.
Thierry FOURNIER6c9b52c2015-01-23 15:57:06 +01007444 */
7445static int hlua_load(char **args, int section_type, struct proxy *curpx,
7446 struct proxy *defpx, const char *file, int line,
7447 char **err)
7448{
7449 int error;
7450
7451 /* Just load and compile the file. */
7452 error = luaL_loadfile(gL.T, args[1]);
7453 if (error) {
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01007454 memprintf(err, "error in Lua file '%s': %s", args[1], lua_tostring(gL.T, -1));
Thierry FOURNIER6c9b52c2015-01-23 15:57:06 +01007455 lua_pop(gL.T, 1);
7456 return -1;
7457 }
7458
7459 /* If no syntax error where detected, execute the code. */
7460 error = lua_pcall(gL.T, 0, LUA_MULTRET, 0);
7461 switch (error) {
7462 case LUA_OK:
7463 break;
7464 case LUA_ERRRUN:
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01007465 memprintf(err, "Lua runtime error: %s\n", lua_tostring(gL.T, -1));
Thierry FOURNIER6c9b52c2015-01-23 15:57:06 +01007466 lua_pop(gL.T, 1);
7467 return -1;
7468 case LUA_ERRMEM:
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01007469 memprintf(err, "Lua out of memory error.n");
Thierry FOURNIER6c9b52c2015-01-23 15:57:06 +01007470 return -1;
7471 case LUA_ERRERR:
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01007472 memprintf(err, "Lua message handler error: %s\n", lua_tostring(gL.T, -1));
Thierry FOURNIER6c9b52c2015-01-23 15:57:06 +01007473 lua_pop(gL.T, 1);
7474 return -1;
7475 case LUA_ERRGCMM:
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01007476 memprintf(err, "Lua garbage collector error: %s\n", lua_tostring(gL.T, -1));
Thierry FOURNIER6c9b52c2015-01-23 15:57:06 +01007477 lua_pop(gL.T, 1);
7478 return -1;
7479 default:
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01007480 memprintf(err, "Lua unknonwn error: %s\n", lua_tostring(gL.T, -1));
Thierry FOURNIER6c9b52c2015-01-23 15:57:06 +01007481 lua_pop(gL.T, 1);
7482 return -1;
7483 }
7484
7485 return 0;
7486}
7487
7488/* configuration keywords declaration */
7489static struct cfg_kw_list cfg_kws = {{ },{
Thierry FOURNIERbd413492015-03-03 16:52:26 +01007490 { CFG_GLOBAL, "lua-load", hlua_load },
7491 { CFG_GLOBAL, "tune.lua.session-timeout", hlua_session_timeout },
7492 { CFG_GLOBAL, "tune.lua.task-timeout", hlua_task_timeout },
Thierry FOURNIER56da1012015-10-01 08:42:31 +02007493 { CFG_GLOBAL, "tune.lua.service-timeout", hlua_applet_timeout },
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01007494 { CFG_GLOBAL, "tune.lua.forced-yield", hlua_forced_yield },
Willy Tarreau32f61e22015-03-18 17:54:59 +01007495 { CFG_GLOBAL, "tune.lua.maxmem", hlua_parse_maxmem },
Thierry FOURNIER6c9b52c2015-01-23 15:57:06 +01007496 { 0, NULL, NULL },
7497}};
7498
Thierry FOURNIERbabae282015-09-17 11:36:37 +02007499/* This function can fail with an abort() due to an Lua critical error.
7500 * We are in the initialisation process of HAProxy, this abort() is
7501 * tolerated.
7502 */
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007503int hlua_post_init()
7504{
7505 struct hlua_init_function *init;
7506 const char *msg;
7507 enum hlua_exec ret;
Thierry Fournierfd107a22016-02-19 19:57:23 +01007508 const char *error;
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007509
Thierry Fournier3d4a6752016-02-19 20:53:30 +01007510 /* Call post initialisation function in safe environement. */
7511 if (!SET_SAFE_LJMP(gL.T)) {
7512 if (lua_type(gL.T, -1) == LUA_TSTRING)
7513 error = lua_tostring(gL.T, -1);
7514 else
7515 error = "critical error";
7516 fprintf(stderr, "Lua post-init: %s.\n", error);
7517 exit(1);
7518 }
Frédéric Lécaille54f2bcf2018-08-29 13:46:24 +02007519
7520#if USE_OPENSSL
7521 /* Initialize SSL server. */
7522 if (socket_ssl.xprt->prepare_srv) {
7523 int saved_used_backed = global.ssl_used_backend;
7524 // don't affect maxconn automatic computation
7525 socket_ssl.xprt->prepare_srv(&socket_ssl);
7526 global.ssl_used_backend = saved_used_backed;
7527 }
7528#endif
7529
Thierry Fournier3d4a6752016-02-19 20:53:30 +01007530 hlua_fcn_post_init(gL.T);
7531 RESET_SAFE_LJMP(gL.T);
7532
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007533 list_for_each_entry(init, &hlua_init_functions, l) {
7534 lua_rawgeti(gL.T, LUA_REGISTRYINDEX, init->function_ref);
7535 ret = hlua_ctx_resume(&gL, 0);
7536 switch (ret) {
7537 case HLUA_E_OK:
7538 lua_pop(gL.T, -1);
7539 return 1;
7540 case HLUA_E_AGAIN:
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01007541 ha_alert("Lua init: yield not allowed.\n");
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007542 return 0;
7543 case HLUA_E_ERRMSG:
7544 msg = lua_tostring(gL.T, -1);
Christopher Faulet767a84b2017-11-24 16:50:31 +01007545 ha_alert("lua init: %s.\n", msg);
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007546 return 0;
7547 case HLUA_E_ERR:
7548 default:
Thierry FOURNIER2986c0d2018-02-25 14:32:36 +01007549 ha_alert("Lua init: unknown runtime error.\n");
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007550 return 0;
7551 }
7552 }
7553 return 1;
7554}
7555
Willy Tarreau32f61e22015-03-18 17:54:59 +01007556/* The memory allocator used by the Lua stack. <ud> is a pointer to the
7557 * allocator's context. <ptr> is the pointer to alloc/free/realloc. <osize>
7558 * is the previously allocated size or the kind of object in case of a new
7559 * allocation. <nsize> is the requested new size.
7560 */
7561static void *hlua_alloc(void *ud, void *ptr, size_t osize, size_t nsize)
7562{
7563 struct hlua_mem_allocator *zone = ud;
7564
7565 if (nsize == 0) {
7566 /* it's a free */
7567 if (ptr)
7568 zone->allocated -= osize;
7569 free(ptr);
7570 return NULL;
7571 }
7572
7573 if (!ptr) {
7574 /* it's a new allocation */
7575 if (zone->limit && zone->allocated + nsize > zone->limit)
7576 return NULL;
7577
7578 ptr = malloc(nsize);
7579 if (ptr)
7580 zone->allocated += nsize;
7581 return ptr;
7582 }
7583
7584 /* it's a realloc */
7585 if (zone->limit && zone->allocated + nsize - osize > zone->limit)
7586 return NULL;
7587
7588 ptr = realloc(ptr, nsize);
7589 if (ptr)
7590 zone->allocated += nsize - osize;
7591 return ptr;
7592}
7593
Thierry FOURNIERbabae282015-09-17 11:36:37 +02007594/* Ithis function can fail with an abort() due to an Lua critical error.
7595 * We are in the initialisation process of HAProxy, this abort() is
7596 * tolerated.
7597 */
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01007598void hlua_init(void)
7599{
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007600 int i;
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +01007601 int idx;
7602 struct sample_fetch *sf;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01007603 struct sample_conv *sc;
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +01007604 char *p;
Thierry Fournierfd107a22016-02-19 19:57:23 +01007605 const char *error_msg;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01007606#ifdef USE_OPENSSL
Willy Tarreau80f5fae2015-02-27 16:38:20 +01007607 struct srv_kw *kw;
7608 int tmp_error;
7609 char *error;
Thierry FOURNIER36d13742015-03-17 16:48:53 +01007610 char *args[] = { /* SSL client configuration. */
7611 "ssl",
7612 "verify",
7613 "none",
Thierry FOURNIER36d13742015-03-17 16:48:53 +01007614 NULL
7615 };
Willy Tarreau80f5fae2015-02-27 16:38:20 +01007616#endif
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007617
Christopher Faulet2a944ee2017-11-07 10:42:54 +01007618 HA_SPIN_INIT(&hlua_global_lock);
Thierry FOURNIER61ba0e22017-07-12 11:41:21 +02007619
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01007620 /* Initialise struct hlua and com signals pool */
Willy Tarreaubafbe012017-11-24 17:34:44 +01007621 pool_head_hlua = create_pool("hlua", sizeof(struct hlua), MEM_F_SHARED);
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +01007622
Thierry FOURNIER6c9b52c2015-01-23 15:57:06 +01007623 /* Register configuration keywords. */
7624 cfg_register_keywords(&cfg_kws);
7625
Thierry FOURNIER380d0932015-01-23 14:27:52 +01007626 /* Init main lua stack. */
7627 gL.Mref = LUA_REFNIL;
Thierry FOURNIERa097fdf2015-03-03 15:17:35 +01007628 gL.flags = 0;
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +01007629 LIST_INIT(&gL.com);
Willy Tarreau42ef75f2017-04-12 21:40:29 +02007630 gL.T = lua_newstate(hlua_alloc, &hlua_global_allocator);
Thierry FOURNIER380d0932015-01-23 14:27:52 +01007631 hlua_sethlua(&gL);
7632 gL.Tref = LUA_REFNIL;
7633 gL.task = NULL;
7634
Thierry FOURNIERbabae282015-09-17 11:36:37 +02007635 /* From this point, until the end of the initialisation fucntion,
7636 * the Lua function can fail with an abort. We are in the initialisation
7637 * process of HAProxy, this abort() is tolerated.
7638 */
7639
Thierry FOURNIER380d0932015-01-23 14:27:52 +01007640 /* Initialise lua. */
7641 luaL_openlibs(gL.T);
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007642
Thierry Fournier75933d42016-01-21 09:30:18 +01007643 /* Set safe environment for the initialisation. */
7644 if (!SET_SAFE_LJMP(gL.T)) {
Thierry Fournierfd107a22016-02-19 19:57:23 +01007645 if (lua_type(gL.T, -1) == LUA_TSTRING)
7646 error_msg = lua_tostring(gL.T, -1);
7647 else
7648 error_msg = "critical error";
7649 fprintf(stderr, "Lua init: %s.\n", error_msg);
Thierry Fournier75933d42016-01-21 09:30:18 +01007650 exit(1);
7651 }
7652
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007653 /*
7654 *
7655 * Create "core" object.
7656 *
7657 */
7658
Thierry FOURNIERa2d8c652015-03-11 17:29:39 +01007659 /* This table entry is the object "core" base. */
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007660 lua_newtable(gL.T);
7661
7662 /* Push the loglevel constants. */
Willy Tarreau80f5fae2015-02-27 16:38:20 +01007663 for (i = 0; i < NB_LOG_LEVELS; i++)
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007664 hlua_class_const_int(gL.T, log_levels[i], i);
7665
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007666 /* Register special functions. */
7667 hlua_class_function(gL.T, "register_init", hlua_register_init);
Thierry FOURNIER24f33532015-01-23 12:13:00 +01007668 hlua_class_function(gL.T, "register_task", hlua_register_task);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01007669 hlua_class_function(gL.T, "register_fetches", hlua_register_fetches);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01007670 hlua_class_function(gL.T, "register_converters", hlua_register_converters);
Thierry FOURNIER8255a752015-09-23 21:03:35 +02007671 hlua_class_function(gL.T, "register_action", hlua_register_action);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007672 hlua_class_function(gL.T, "register_service", hlua_register_service);
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007673 hlua_class_function(gL.T, "register_cli", hlua_register_cli);
Thierry FOURNIER13416fe2015-02-17 15:01:59 +01007674 hlua_class_function(gL.T, "yield", hlua_yield);
Willy Tarreau59551662015-03-10 14:23:13 +01007675 hlua_class_function(gL.T, "set_nice", hlua_set_nice);
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01007676 hlua_class_function(gL.T, "sleep", hlua_sleep);
7677 hlua_class_function(gL.T, "msleep", hlua_msleep);
Thierry FOURNIER83758bb2015-02-04 13:21:04 +01007678 hlua_class_function(gL.T, "add_acl", hlua_add_acl);
7679 hlua_class_function(gL.T, "del_acl", hlua_del_acl);
7680 hlua_class_function(gL.T, "set_map", hlua_set_map);
7681 hlua_class_function(gL.T, "del_map", hlua_del_map);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007682 hlua_class_function(gL.T, "tcp", hlua_socket_new);
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +01007683 hlua_class_function(gL.T, "log", hlua_log);
7684 hlua_class_function(gL.T, "Debug", hlua_log_debug);
7685 hlua_class_function(gL.T, "Info", hlua_log_info);
7686 hlua_class_function(gL.T, "Warning", hlua_log_warning);
7687 hlua_class_function(gL.T, "Alert", hlua_log_alert);
Thierry FOURNIER0a99b892015-08-26 00:14:17 +02007688 hlua_class_function(gL.T, "done", hlua_done);
Thierry Fournierfb0b5462016-01-21 09:28:58 +01007689 hlua_fcn_reg_core_fcn(gL.T);
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007690
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007691 lua_setglobal(gL.T, "core");
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01007692
7693 /*
7694 *
Thierry FOURNIER3def3932015-04-07 11:27:54 +02007695 * Register class Map
7696 *
7697 */
7698
7699 /* This table entry is the object "Map" base. */
7700 lua_newtable(gL.T);
7701
7702 /* register pattern types. */
7703 for (i=0; i<PAT_MATCH_NUM; i++)
7704 hlua_class_const_int(gL.T, pat_match_names[i], i);
Thierry FOURNIER4dc71972017-01-28 08:33:08 +01007705 for (i=0; i<PAT_MATCH_NUM; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007706 snprintf(trash.area, trash.size, "_%s", pat_match_names[i]);
7707 hlua_class_const_int(gL.T, trash.area, i);
Thierry FOURNIER4dc71972017-01-28 08:33:08 +01007708 }
Thierry FOURNIER3def3932015-04-07 11:27:54 +02007709
7710 /* register constructor. */
7711 hlua_class_function(gL.T, "new", hlua_map_new);
7712
7713 /* Create and fill the metatable. */
7714 lua_newtable(gL.T);
7715
7716 /* Create and fille the __index entry. */
7717 lua_pushstring(gL.T, "__index");
7718 lua_newtable(gL.T);
7719
7720 /* Register . */
7721 hlua_class_function(gL.T, "lookup", hlua_map_lookup);
7722 hlua_class_function(gL.T, "slookup", hlua_map_slookup);
7723
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007724 lua_rawset(gL.T, -3);
Thierry FOURNIER3def3932015-04-07 11:27:54 +02007725
Thierry Fournier45e78d72016-02-19 18:34:46 +01007726 /* Register previous table in the registry with reference and named entry.
7727 * The function hlua_register_metatable() pops the stack, so we
7728 * previously create a copy of the table.
7729 */
Thierry FOURNIER3def3932015-04-07 11:27:54 +02007730 lua_pushvalue(gL.T, -1); /* Copy the -1 entry and push it on the stack. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007731 class_map_ref = hlua_register_metatable(gL.T, CLASS_MAP);
Thierry FOURNIER3def3932015-04-07 11:27:54 +02007732
7733 /* Assign the metatable to the mai Map object. */
7734 lua_setmetatable(gL.T, -2);
7735
7736 /* Set a name to the table. */
7737 lua_setglobal(gL.T, "Map");
7738
7739 /*
7740 *
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01007741 * Register class Channel
7742 *
7743 */
7744
7745 /* Create and fill the metatable. */
7746 lua_newtable(gL.T);
7747
7748 /* Create and fille the __index entry. */
7749 lua_pushstring(gL.T, "__index");
7750 lua_newtable(gL.T);
7751
7752 /* Register . */
7753 hlua_class_function(gL.T, "get", hlua_channel_get);
7754 hlua_class_function(gL.T, "dup", hlua_channel_dup);
7755 hlua_class_function(gL.T, "getline", hlua_channel_getline);
7756 hlua_class_function(gL.T, "set", hlua_channel_set);
7757 hlua_class_function(gL.T, "append", hlua_channel_append);
7758 hlua_class_function(gL.T, "send", hlua_channel_send);
7759 hlua_class_function(gL.T, "forward", hlua_channel_forward);
7760 hlua_class_function(gL.T, "get_in_len", hlua_channel_get_in_len);
7761 hlua_class_function(gL.T, "get_out_len", hlua_channel_get_out_len);
Thierry FOURNIER / OZON.IO65192f32016-11-07 15:28:40 +01007762 hlua_class_function(gL.T, "is_full", hlua_channel_is_full);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01007763
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007764 lua_rawset(gL.T, -3);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01007765
7766 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007767 class_channel_ref = hlua_register_metatable(gL.T, CLASS_CHANNEL);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01007768
7769 /*
7770 *
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01007771 * Register class Fetches
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01007772 *
7773 */
7774
7775 /* Create and fill the metatable. */
7776 lua_newtable(gL.T);
7777
7778 /* Create and fille the __index entry. */
7779 lua_pushstring(gL.T, "__index");
7780 lua_newtable(gL.T);
7781
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +01007782 /* Browse existing fetches and create the associated
7783 * object method.
7784 */
7785 sf = NULL;
7786 while ((sf = sample_fetch_getnext(sf, &idx)) != NULL) {
7787
7788 /* Dont register the keywork if the arguments check function are
7789 * not safe during the runtime.
7790 */
7791 if ((sf->val_args != NULL) &&
7792 (sf->val_args != val_payload_lv) &&
7793 (sf->val_args != val_hdr))
7794 continue;
7795
7796 /* gL.Tua doesn't support '.' and '-' in the function names, replace it
7797 * by an underscore.
7798 */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007799 strncpy(trash.area, sf->kw, trash.size);
7800 trash.area[trash.size - 1] = '\0';
7801 for (p = trash.area; *p; p++)
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +01007802 if (*p == '.' || *p == '-' || *p == '+')
7803 *p = '_';
7804
7805 /* Register the function. */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007806 lua_pushstring(gL.T, trash.area);
Willy Tarreau2ec22742015-03-10 14:27:20 +01007807 lua_pushlightuserdata(gL.T, sf);
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +01007808 lua_pushcclosure(gL.T, hlua_run_sample_fetch, 1);
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007809 lua_rawset(gL.T, -3);
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +01007810 }
7811
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007812 lua_rawset(gL.T, -3);
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01007813
7814 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007815 class_fetches_ref = hlua_register_metatable(gL.T, CLASS_FETCHES);
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01007816
7817 /*
7818 *
Thierry FOURNIER594afe72015-03-10 23:58:30 +01007819 * Register class Converters
7820 *
7821 */
7822
7823 /* Create and fill the metatable. */
7824 lua_newtable(gL.T);
7825
7826 /* Create and fill the __index entry. */
7827 lua_pushstring(gL.T, "__index");
7828 lua_newtable(gL.T);
7829
7830 /* Browse existing converters and create the associated
7831 * object method.
7832 */
7833 sc = NULL;
7834 while ((sc = sample_conv_getnext(sc, &idx)) != NULL) {
7835 /* Dont register the keywork if the arguments check function are
7836 * not safe during the runtime.
7837 */
7838 if (sc->val_args != NULL)
7839 continue;
7840
7841 /* gL.Tua doesn't support '.' and '-' in the function names, replace it
7842 * by an underscore.
7843 */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007844 strncpy(trash.area, sc->kw, trash.size);
7845 trash.area[trash.size - 1] = '\0';
7846 for (p = trash.area; *p; p++)
Thierry FOURNIER594afe72015-03-10 23:58:30 +01007847 if (*p == '.' || *p == '-' || *p == '+')
7848 *p = '_';
7849
7850 /* Register the function. */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007851 lua_pushstring(gL.T, trash.area);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01007852 lua_pushlightuserdata(gL.T, sc);
7853 lua_pushcclosure(gL.T, hlua_run_sample_conv, 1);
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007854 lua_rawset(gL.T, -3);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01007855 }
7856
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007857 lua_rawset(gL.T, -3);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01007858
7859 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007860 class_converters_ref = hlua_register_metatable(gL.T, CLASS_CONVERTERS);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01007861
7862 /*
7863 *
Thierry FOURNIER08504f42015-03-16 14:17:08 +01007864 * Register class HTTP
7865 *
7866 */
7867
7868 /* Create and fill the metatable. */
7869 lua_newtable(gL.T);
7870
7871 /* Create and fille the __index entry. */
7872 lua_pushstring(gL.T, "__index");
7873 lua_newtable(gL.T);
7874
7875 /* Register Lua functions. */
7876 hlua_class_function(gL.T, "req_get_headers",hlua_http_req_get_headers);
7877 hlua_class_function(gL.T, "req_del_header", hlua_http_req_del_hdr);
7878 hlua_class_function(gL.T, "req_rep_header", hlua_http_req_rep_hdr);
7879 hlua_class_function(gL.T, "req_rep_value", hlua_http_req_rep_val);
7880 hlua_class_function(gL.T, "req_add_header", hlua_http_req_add_hdr);
7881 hlua_class_function(gL.T, "req_set_header", hlua_http_req_set_hdr);
7882 hlua_class_function(gL.T, "req_set_method", hlua_http_req_set_meth);
7883 hlua_class_function(gL.T, "req_set_path", hlua_http_req_set_path);
7884 hlua_class_function(gL.T, "req_set_query", hlua_http_req_set_query);
7885 hlua_class_function(gL.T, "req_set_uri", hlua_http_req_set_uri);
7886
7887 hlua_class_function(gL.T, "res_get_headers",hlua_http_res_get_headers);
7888 hlua_class_function(gL.T, "res_del_header", hlua_http_res_del_hdr);
7889 hlua_class_function(gL.T, "res_rep_header", hlua_http_res_rep_hdr);
7890 hlua_class_function(gL.T, "res_rep_value", hlua_http_res_rep_val);
7891 hlua_class_function(gL.T, "res_add_header", hlua_http_res_add_hdr);
7892 hlua_class_function(gL.T, "res_set_header", hlua_http_res_set_hdr);
Thierry FOURNIER35d70ef2015-08-26 16:21:56 +02007893 hlua_class_function(gL.T, "res_set_status", hlua_http_res_set_status);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01007894
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007895 lua_rawset(gL.T, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01007896
7897 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007898 class_http_ref = hlua_register_metatable(gL.T, CLASS_HTTP);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01007899
7900 /*
7901 *
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007902 * Register class AppletTCP
7903 *
7904 */
7905
7906 /* Create and fill the metatable. */
7907 lua_newtable(gL.T);
7908
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007909 /* Create and fille the __index entry. */
7910 lua_pushstring(gL.T, "__index");
7911 lua_newtable(gL.T);
7912
7913 /* Register Lua functions. */
Thierry FOURNIER / OZON.IO3e1d7912016-12-12 12:29:34 +01007914 hlua_class_function(gL.T, "getline", hlua_applet_tcp_getline);
7915 hlua_class_function(gL.T, "receive", hlua_applet_tcp_recv);
7916 hlua_class_function(gL.T, "send", hlua_applet_tcp_send);
7917 hlua_class_function(gL.T, "set_priv", hlua_applet_tcp_set_priv);
7918 hlua_class_function(gL.T, "get_priv", hlua_applet_tcp_get_priv);
Thierry FOURNIER / OZON.IO4394a2c2016-12-12 12:31:54 +01007919 hlua_class_function(gL.T, "set_var", hlua_applet_tcp_set_var);
7920 hlua_class_function(gL.T, "unset_var", hlua_applet_tcp_unset_var);
7921 hlua_class_function(gL.T, "get_var", hlua_applet_tcp_get_var);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007922
7923 lua_settable(gL.T, -3);
7924
7925 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007926 class_applet_tcp_ref = hlua_register_metatable(gL.T, CLASS_APPLET_TCP);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007927
7928 /*
7929 *
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02007930 * Register class AppletHTTP
7931 *
7932 */
7933
7934 /* Create and fill the metatable. */
7935 lua_newtable(gL.T);
7936
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02007937 /* Create and fille the __index entry. */
7938 lua_pushstring(gL.T, "__index");
7939 lua_newtable(gL.T);
7940
7941 /* Register Lua functions. */
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01007942 hlua_class_function(gL.T, "set_priv", hlua_applet_http_set_priv);
7943 hlua_class_function(gL.T, "get_priv", hlua_applet_http_get_priv);
Thierry FOURNIER / OZON.IO4394a2c2016-12-12 12:31:54 +01007944 hlua_class_function(gL.T, "set_var", hlua_applet_http_set_var);
7945 hlua_class_function(gL.T, "unset_var", hlua_applet_http_unset_var);
7946 hlua_class_function(gL.T, "get_var", hlua_applet_http_get_var);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02007947 hlua_class_function(gL.T, "getline", hlua_applet_http_getline);
7948 hlua_class_function(gL.T, "receive", hlua_applet_http_recv);
7949 hlua_class_function(gL.T, "send", hlua_applet_http_send);
7950 hlua_class_function(gL.T, "add_header", hlua_applet_http_addheader);
7951 hlua_class_function(gL.T, "set_status", hlua_applet_http_status);
7952 hlua_class_function(gL.T, "start_response", hlua_applet_http_start_response);
7953
7954 lua_settable(gL.T, -3);
7955
7956 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007957 class_applet_http_ref = hlua_register_metatable(gL.T, CLASS_APPLET_HTTP);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02007958
7959 /*
7960 *
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01007961 * Register class TXN
7962 *
7963 */
7964
7965 /* Create and fill the metatable. */
7966 lua_newtable(gL.T);
7967
7968 /* Create and fille the __index entry. */
7969 lua_pushstring(gL.T, "__index");
7970 lua_newtable(gL.T);
7971
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01007972 /* Register Lua functions. */
Patrick Hemmer268a7072018-05-11 12:52:31 -04007973 hlua_class_function(gL.T, "set_priv", hlua_set_priv);
7974 hlua_class_function(gL.T, "get_priv", hlua_get_priv);
7975 hlua_class_function(gL.T, "set_var", hlua_set_var);
7976 hlua_class_function(gL.T, "unset_var", hlua_unset_var);
7977 hlua_class_function(gL.T, "get_var", hlua_get_var);
7978 hlua_class_function(gL.T, "done", hlua_txn_done);
7979 hlua_class_function(gL.T, "set_loglevel", hlua_txn_set_loglevel);
7980 hlua_class_function(gL.T, "set_tos", hlua_txn_set_tos);
7981 hlua_class_function(gL.T, "set_mark", hlua_txn_set_mark);
7982 hlua_class_function(gL.T, "set_priority_class", hlua_txn_set_priority_class);
7983 hlua_class_function(gL.T, "set_priority_offset", hlua_txn_set_priority_offset);
7984 hlua_class_function(gL.T, "deflog", hlua_txn_deflog);
7985 hlua_class_function(gL.T, "log", hlua_txn_log);
7986 hlua_class_function(gL.T, "Debug", hlua_txn_log_debug);
7987 hlua_class_function(gL.T, "Info", hlua_txn_log_info);
7988 hlua_class_function(gL.T, "Warning", hlua_txn_log_warning);
7989 hlua_class_function(gL.T, "Alert", hlua_txn_log_alert);
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01007990
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007991 lua_rawset(gL.T, -3);
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01007992
7993 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007994 class_txn_ref = hlua_register_metatable(gL.T, CLASS_TXN);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007995
7996 /*
7997 *
7998 * Register class Socket
7999 *
8000 */
8001
8002 /* Create and fill the metatable. */
8003 lua_newtable(gL.T);
8004
8005 /* Create and fille the __index entry. */
8006 lua_pushstring(gL.T, "__index");
8007 lua_newtable(gL.T);
8008
Baptiste Assmann84bb4932015-03-02 21:40:06 +01008009#ifdef USE_OPENSSL
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01008010 hlua_class_function(gL.T, "connect_ssl", hlua_socket_connect_ssl);
Baptiste Assmann84bb4932015-03-02 21:40:06 +01008011#endif
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01008012 hlua_class_function(gL.T, "connect", hlua_socket_connect);
8013 hlua_class_function(gL.T, "send", hlua_socket_send);
8014 hlua_class_function(gL.T, "receive", hlua_socket_receive);
8015 hlua_class_function(gL.T, "close", hlua_socket_close);
8016 hlua_class_function(gL.T, "getpeername", hlua_socket_getpeername);
8017 hlua_class_function(gL.T, "getsockname", hlua_socket_getsockname);
8018 hlua_class_function(gL.T, "setoption", hlua_socket_setoption);
8019 hlua_class_function(gL.T, "settimeout", hlua_socket_settimeout);
8020
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02008021 lua_rawset(gL.T, -3); /* Push the last 2 entries in the table at index -3 */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01008022
8023 /* Register the garbage collector entry. */
8024 lua_pushstring(gL.T, "__gc");
8025 lua_pushcclosure(gL.T, hlua_socket_gc, 0);
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02008026 lua_rawset(gL.T, -3); /* Push the last 2 entries in the table at index -3 */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01008027
8028 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01008029 class_socket_ref = hlua_register_metatable(gL.T, CLASS_SOCKET);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01008030
8031 /* Proxy and server configuration initialisation. */
8032 memset(&socket_proxy, 0, sizeof(socket_proxy));
8033 init_new_proxy(&socket_proxy);
8034 socket_proxy.parent = NULL;
8035 socket_proxy.last_change = now.tv_sec;
8036 socket_proxy.id = "LUA-SOCKET";
8037 socket_proxy.cap = PR_CAP_FE | PR_CAP_BE;
8038 socket_proxy.maxconn = 0;
8039 socket_proxy.accept = NULL;
8040 socket_proxy.options2 |= PR_O2_INDEPSTR;
8041 socket_proxy.srv = NULL;
8042 socket_proxy.conn_retries = 0;
8043 socket_proxy.timeout.connect = 5000; /* By default the timeout connection is 5s. */
8044
8045 /* Init TCP server: unchanged parameters */
8046 memset(&socket_tcp, 0, sizeof(socket_tcp));
8047 socket_tcp.next = NULL;
8048 socket_tcp.proxy = &socket_proxy;
8049 socket_tcp.obj_type = OBJ_TYPE_SERVER;
8050 LIST_INIT(&socket_tcp.actconns);
Patrick Hemmer0355dab2018-05-11 12:52:31 -04008051 socket_tcp.pendconns = EB_ROOT;
Christopher Faulet40a007c2017-07-03 15:41:01 +02008052 socket_tcp.priv_conns = NULL;
8053 socket_tcp.idle_conns = NULL;
8054 socket_tcp.safe_conns = NULL;
Emeric Brun52a91d32017-08-31 14:41:55 +02008055 socket_tcp.next_state = SRV_ST_RUNNING; /* early server setup */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01008056 socket_tcp.last_change = 0;
8057 socket_tcp.id = "LUA-TCP-CONN";
8058 socket_tcp.check.state &= ~CHK_ST_ENABLED; /* Disable health checks. */
8059 socket_tcp.agent.state &= ~CHK_ST_ENABLED; /* Disable health checks. */
8060 socket_tcp.pp_opts = 0; /* Remove proxy protocol. */
8061
8062 /* XXX: Copy default parameter from default server,
8063 * but the default server is not initialized.
8064 */
8065 socket_tcp.maxqueue = socket_proxy.defsrv.maxqueue;
8066 socket_tcp.minconn = socket_proxy.defsrv.minconn;
8067 socket_tcp.maxconn = socket_proxy.defsrv.maxconn;
8068 socket_tcp.slowstart = socket_proxy.defsrv.slowstart;
8069 socket_tcp.onerror = socket_proxy.defsrv.onerror;
8070 socket_tcp.onmarkeddown = socket_proxy.defsrv.onmarkeddown;
8071 socket_tcp.onmarkedup = socket_proxy.defsrv.onmarkedup;
8072 socket_tcp.consecutive_errors_limit = socket_proxy.defsrv.consecutive_errors_limit;
8073 socket_tcp.uweight = socket_proxy.defsrv.iweight;
8074 socket_tcp.iweight = socket_proxy.defsrv.iweight;
8075
8076 socket_tcp.check.status = HCHK_STATUS_INI;
8077 socket_tcp.check.rise = socket_proxy.defsrv.check.rise;
8078 socket_tcp.check.fall = socket_proxy.defsrv.check.fall;
8079 socket_tcp.check.health = socket_tcp.check.rise; /* socket, but will fall down at first failure */
8080 socket_tcp.check.server = &socket_tcp;
8081
8082 socket_tcp.agent.status = HCHK_STATUS_INI;
8083 socket_tcp.agent.rise = socket_proxy.defsrv.agent.rise;
8084 socket_tcp.agent.fall = socket_proxy.defsrv.agent.fall;
8085 socket_tcp.agent.health = socket_tcp.agent.rise; /* socket, but will fall down at first failure */
8086 socket_tcp.agent.server = &socket_tcp;
8087
Willy Tarreaua261e9b2016-12-22 20:44:00 +01008088 socket_tcp.xprt = xprt_get(XPRT_RAW);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01008089
8090#ifdef USE_OPENSSL
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01008091 /* Init TCP server: unchanged parameters */
8092 memset(&socket_ssl, 0, sizeof(socket_ssl));
8093 socket_ssl.next = NULL;
8094 socket_ssl.proxy = &socket_proxy;
8095 socket_ssl.obj_type = OBJ_TYPE_SERVER;
8096 LIST_INIT(&socket_ssl.actconns);
Patrick Hemmer0355dab2018-05-11 12:52:31 -04008097 socket_ssl.pendconns = EB_ROOT;
Christopher Faulet40a007c2017-07-03 15:41:01 +02008098 socket_tcp.priv_conns = NULL;
8099 socket_tcp.idle_conns = NULL;
8100 socket_tcp.safe_conns = NULL;
Emeric Brun52a91d32017-08-31 14:41:55 +02008101 socket_ssl.next_state = SRV_ST_RUNNING; /* early server setup */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01008102 socket_ssl.last_change = 0;
8103 socket_ssl.id = "LUA-SSL-CONN";
8104 socket_ssl.check.state &= ~CHK_ST_ENABLED; /* Disable health checks. */
8105 socket_ssl.agent.state &= ~CHK_ST_ENABLED; /* Disable health checks. */
8106 socket_ssl.pp_opts = 0; /* Remove proxy protocol. */
8107
8108 /* XXX: Copy default parameter from default server,
8109 * but the default server is not initialized.
8110 */
8111 socket_ssl.maxqueue = socket_proxy.defsrv.maxqueue;
8112 socket_ssl.minconn = socket_proxy.defsrv.minconn;
8113 socket_ssl.maxconn = socket_proxy.defsrv.maxconn;
8114 socket_ssl.slowstart = socket_proxy.defsrv.slowstart;
8115 socket_ssl.onerror = socket_proxy.defsrv.onerror;
8116 socket_ssl.onmarkeddown = socket_proxy.defsrv.onmarkeddown;
8117 socket_ssl.onmarkedup = socket_proxy.defsrv.onmarkedup;
8118 socket_ssl.consecutive_errors_limit = socket_proxy.defsrv.consecutive_errors_limit;
8119 socket_ssl.uweight = socket_proxy.defsrv.iweight;
8120 socket_ssl.iweight = socket_proxy.defsrv.iweight;
8121
8122 socket_ssl.check.status = HCHK_STATUS_INI;
8123 socket_ssl.check.rise = socket_proxy.defsrv.check.rise;
8124 socket_ssl.check.fall = socket_proxy.defsrv.check.fall;
8125 socket_ssl.check.health = socket_ssl.check.rise; /* socket, but will fall down at first failure */
8126 socket_ssl.check.server = &socket_ssl;
8127
8128 socket_ssl.agent.status = HCHK_STATUS_INI;
8129 socket_ssl.agent.rise = socket_proxy.defsrv.agent.rise;
8130 socket_ssl.agent.fall = socket_proxy.defsrv.agent.fall;
8131 socket_ssl.agent.health = socket_ssl.agent.rise; /* socket, but will fall down at first failure */
8132 socket_ssl.agent.server = &socket_ssl;
8133
Thierry FOURNIER36d13742015-03-17 16:48:53 +01008134 socket_ssl.use_ssl = 1;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01008135 socket_ssl.xprt = xprt_get(XPRT_SSL);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01008136
Thierry FOURNIER36d13742015-03-17 16:48:53 +01008137 for (idx = 0; args[idx] != NULL; idx++) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01008138 if ((kw = srv_find_kw(args[idx])) != NULL) { /* Maybe it's registered server keyword */
8139 /*
8140 *
8141 * If the keyword is not known, we can search in the registered
8142 * server keywords. This is usefull to configure special SSL
8143 * features like client certificates and ssl_verify.
8144 *
8145 */
8146 tmp_error = kw->parse(args, &idx, &socket_proxy, &socket_ssl, &error);
8147 if (tmp_error != 0) {
8148 fprintf(stderr, "INTERNAL ERROR: %s\n", error);
8149 abort(); /* This must be never arrives because the command line
8150 not editable by the user. */
8151 }
8152 idx += kw->skip;
8153 }
8154 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01008155#endif
Thierry Fournier75933d42016-01-21 09:30:18 +01008156
8157 RESET_SAFE_LJMP(gL.T);
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01008158}
Willy Tarreaubb57d942016-12-21 19:04:56 +01008159
8160__attribute__((constructor))
8161static void __hlua_init(void)
8162{
8163 char *ptr = NULL;
8164 memprintf(&ptr, "Built with Lua version : %s", LUA_RELEASE);
8165 hap_register_build_opts(ptr, 1);
8166}