blob: f423c6da3ce00e746929b971a86164edba79aee4 [file] [log] [blame]
Thierry Fourniere726b142016-02-11 17:57:57 +01001/*
2 * Lua unsafe core engine
3 *
4 * Copyright 2015-2016 Thierry Fournier <tfournier@arpalert.org>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +010013#include <ctype.h>
Thierry FOURNIERbabae282015-09-17 11:36:37 +020014#include <setjmp.h>
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +010015
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +010016#include <lauxlib.h>
17#include <lua.h>
18#include <lualib.h>
19
Thierry FOURNIER463119c2015-03-10 00:35:36 +010020#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 503
21#error "Requires Lua 5.3 or later."
Cyril Bontédc0306e2015-03-02 00:08:40 +010022#endif
23
Thierry FOURNIER380d0932015-01-23 14:27:52 +010024#include <ebpttree.h>
25
26#include <common/cfgparse.h>
27
William Lallemand9ed62032016-11-21 17:49:11 +010028#include <types/cli.h>
Thierry FOURNIER380d0932015-01-23 14:27:52 +010029#include <types/hlua.h>
30#include <types/proxy.h>
William Lallemand9ed62032016-11-21 17:49:11 +010031#include <types/stats.h>
Thierry FOURNIER380d0932015-01-23 14:27:52 +010032
Thierry FOURNIER55da1652015-01-23 11:36:30 +010033#include <proto/arg.h>
Willy Tarreau8a8d83b2015-04-13 13:24:54 +020034#include <proto/applet.h>
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +010035#include <proto/channel.h>
William Lallemand9ed62032016-11-21 17:49:11 +010036#include <proto/cli.h>
Willy Tarreaua71f6422016-11-16 17:00:14 +010037#include <proto/connection.h>
William Lallemand9ed62032016-11-21 17:49:11 +010038#include <proto/stats.h>
Thierry FOURNIER9a819e72015-02-16 20:22:55 +010039#include <proto/hdr_idx.h>
Thierry FOURNIERa097fdf2015-03-03 15:17:35 +010040#include <proto/hlua.h>
Thierry Fournierfb0b5462016-01-21 09:28:58 +010041#include <proto/hlua_fcn.h>
Thierry FOURNIER3def3932015-04-07 11:27:54 +020042#include <proto/map.h>
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +010043#include <proto/obj_type.h>
Thierry FOURNIER83758bb2015-02-04 13:21:04 +010044#include <proto/pattern.h>
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +010045#include <proto/payload.h>
46#include <proto/proto_http.h>
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +010047#include <proto/raw_sock.h>
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +010048#include <proto/sample.h>
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +010049#include <proto/server.h>
Willy Tarreaufeb76402015-04-03 14:10:06 +020050#include <proto/session.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020051#include <proto/stream.h>
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +010052#include <proto/ssl_sock.h>
53#include <proto/stream_interface.h>
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +010054#include <proto/task.h>
Willy Tarreau39713102016-11-25 15:49:32 +010055#include <proto/tcp_rules.h>
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +020056#include <proto/vars.h>
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +010057
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +010058/* Lua uses longjmp to perform yield or throwing errors. This
59 * macro is used only for identifying the function that can
60 * not return because a longjmp is executed.
61 * __LJMP marks a prototype of hlua file that can use longjmp.
62 * WILL_LJMP() marks an lua function that will use longjmp.
63 * MAY_LJMP() marks an lua function that may use longjmp.
64 */
65#define __LJMP
66#define WILL_LJMP(func) func
67#define MAY_LJMP(func) func
68
Thierry FOURNIERbabae282015-09-17 11:36:37 +020069/* This couple of function executes securely some Lua calls outside of
70 * the lua runtime environment. Each Lua call can return a longjmp
71 * if it encounter a memory error.
72 *
73 * Lua documentation extract:
74 *
75 * If an error happens outside any protected environment, Lua calls
76 * a panic function (see lua_atpanic) and then calls abort, thus
77 * exiting the host application. Your panic function can avoid this
78 * exit by never returning (e.g., doing a long jump to your own
79 * recovery point outside Lua).
80 *
81 * The panic function runs as if it were a message handler (see
82 * §2.3); in particular, the error message is at the top of the
83 * stack. However, there is no guarantee about stack space. To push
84 * anything on the stack, the panic function must first check the
85 * available space (see §4.2).
86 *
87 * We must check all the Lua entry point. This includes:
88 * - The include/proto/hlua.h exported functions
89 * - the task wrapper function
90 * - The action wrapper function
91 * - The converters wrapper function
92 * - The sample-fetch wrapper functions
93 *
94 * It is tolerated that the initilisation function returns an abort.
95 * Before each Lua abort, an error message is writed on stderr.
96 *
97 * The macro SET_SAFE_LJMP initialise the longjmp. The Macro
98 * RESET_SAFE_LJMP reset the longjmp. These function must be macro
99 * because they must be exists in the program stack when the longjmp
100 * is called.
101 */
102jmp_buf safe_ljmp_env;
103static int hlua_panic_safe(lua_State *L) { return 0; }
104static int hlua_panic_ljmp(lua_State *L) { longjmp(safe_ljmp_env, 1); }
105
106#define SET_SAFE_LJMP(__L) \
107 ({ \
108 int ret; \
109 if (setjmp(safe_ljmp_env) != 0) { \
110 lua_atpanic(__L, hlua_panic_safe); \
111 ret = 0; \
112 } else { \
113 lua_atpanic(__L, hlua_panic_ljmp); \
114 ret = 1; \
115 } \
116 ret; \
117 })
118
119/* If we are the last function catching Lua errors, we
120 * must reset the panic function.
121 */
122#define RESET_SAFE_LJMP(__L) \
123 do { \
124 lua_atpanic(__L, hlua_panic_safe); \
125 } while(0)
126
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +0200127/* Applet status flags */
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +0200128#define APPLET_DONE 0x01 /* applet processing is done. */
129#define APPLET_100C 0x02 /* 100 continue expected. */
130#define APPLET_HDR_SENT 0x04 /* Response header sent. */
131#define APPLET_CHUNKED 0x08 /* Use transfer encoding chunked. */
132#define APPLET_LAST_CHK 0x10 /* Last chunk sent. */
Thierry FOURNIERd93ea2b2015-12-20 19:14:52 +0100133#define APPLET_HTTP11 0x20 /* Last chunk sent. */
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +0200134
135#define HTTP_100C "HTTP/1.1 100 Continue\r\n\r\n"
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +0200136
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100137/* The main Lua execution context. */
138struct hlua gL;
139
Thierry FOURNIERebed6e92016-12-16 11:54:07 +0100140/* This is the memory pool containing struct lua for applets
141 * (including cli).
142 */
143struct pool_head *pool2_hlua;
144
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +0100145/* This is the memory pool containing all the signal structs. These
146 * struct are used to store each requiered signal between two tasks.
147 */
148struct pool_head *pool2_hlua_com;
149
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +0100150/* Used for Socket connection. */
151static struct proxy socket_proxy;
152static struct server socket_tcp;
153#ifdef USE_OPENSSL
154static struct server socket_ssl;
155#endif
156
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +0100157/* List head of the function called at the initialisation time. */
158struct list hlua_init_functions = LIST_HEAD_INIT(hlua_init_functions);
159
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +0100160/* The following variables contains the reference of the different
161 * Lua classes. These references are useful for identify metadata
162 * associated with an object.
163 */
Thierry FOURNIER65f34c62015-02-16 20:11:43 +0100164static int class_txn_ref;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +0100165static int class_socket_ref;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +0100166static int class_channel_ref;
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +0100167static int class_fetches_ref;
Thierry FOURNIER594afe72015-03-10 23:58:30 +0100168static int class_converters_ref;
Thierry FOURNIER08504f42015-03-16 14:17:08 +0100169static int class_http_ref;
Thierry FOURNIER3def3932015-04-07 11:27:54 +0200170static int class_map_ref;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +0200171static int class_applet_tcp_ref;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +0200172static int class_applet_http_ref;
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +0100173
Thierry FOURNIERbd413492015-03-03 16:52:26 +0100174/* Global Lua execution timeout. By default Lua, execution linked
Willy Tarreau87b09662015-04-03 00:22:06 +0200175 * with stream (actions, sample-fetches and converters) have a
Thierry FOURNIERbd413492015-03-03 16:52:26 +0100176 * short timeout. Lua linked with tasks doesn't have a timeout
177 * because a task may remain alive during all the haproxy execution.
178 */
179static unsigned int hlua_timeout_session = 4000; /* session timeout. */
180static unsigned int hlua_timeout_task = TICK_ETERNITY; /* task timeout. */
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +0200181static unsigned int hlua_timeout_applet = 4000; /* applet timeout. */
Thierry FOURNIERbd413492015-03-03 16:52:26 +0100182
Thierry FOURNIERee9f8022015-03-03 17:37:37 +0100183/* Interrupts the Lua processing each "hlua_nb_instruction" instructions.
184 * it is used for preventing infinite loops.
185 *
186 * I test the scheer with an infinite loop containing one incrementation
187 * and one test. I run this loop between 10 seconds, I raise a ceil of
188 * 710M loops from one interrupt each 9000 instructions, so I fix the value
189 * to one interrupt each 10 000 instructions.
190 *
191 * configured | Number of
192 * instructions | loops executed
193 * between two | in milions
194 * forced yields |
195 * ---------------+---------------
196 * 10 | 160
197 * 500 | 670
198 * 1000 | 680
199 * 5000 | 700
200 * 7000 | 700
201 * 8000 | 700
202 * 9000 | 710 <- ceil
203 * 10000 | 710
204 * 100000 | 710
205 * 1000000 | 710
206 *
207 */
208static unsigned int hlua_nb_instruction = 10000;
209
Willy Tarreau32f61e22015-03-18 17:54:59 +0100210/* Descriptor for the memory allocation state. If limit is not null, it will
211 * be enforced on any memory allocation.
212 */
213struct hlua_mem_allocator {
214 size_t allocated;
215 size_t limit;
216};
217
218static struct hlua_mem_allocator hlua_global_allocator;
219
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +0200220static const char error_500[] =
221 "HTTP/1.0 500 Server Error\r\n"
222 "Cache-Control: no-cache\r\n"
223 "Connection: close\r\n"
224 "Content-Type: text/html\r\n"
225 "\r\n"
226 "<html><body><h1>500 Server Error</h1>\nAn internal server error occured.\n</body></html>\n";
227
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100228/* These functions converts types between HAProxy internal args or
229 * sample and LUA types. Another function permits to check if the
230 * LUA stack contains arguments according with an required ARG_T
231 * format.
232 */
233static int hlua_arg2lua(lua_State *L, const struct arg *arg);
234static int hlua_lua2arg(lua_State *L, int ud, struct arg *arg);
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100235__LJMP static int hlua_lua2arg_check(lua_State *L, int first, struct arg *argp,
David Carlier0c437f42016-04-27 16:21:56 +0100236 uint64_t mask, struct proxy *p);
Willy Tarreau5eadada2015-03-10 17:28:54 +0100237static int hlua_smp2lua(lua_State *L, struct sample *smp);
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100238static int hlua_smp2lua_str(lua_State *L, struct sample *smp);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100239static int hlua_lua2smp(lua_State *L, int ud, struct sample *smp);
240
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +0200241__LJMP static int hlua_http_get_headers(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg);
242
Thierry FOURNIER23bc3752015-09-11 19:15:43 +0200243#define SEND_ERR(__be, __fmt, __args...) \
244 do { \
245 send_log(__be, LOG_ERR, __fmt, ## __args); \
246 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) \
247 Alert(__fmt, ## __args); \
248 } while (0)
249
Thierry FOURNIERe8b9a402015-02-25 18:48:12 +0100250/* Used to check an Lua function type in the stack. It creates and
251 * returns a reference of the function. This function throws an
252 * error if the rgument is not a "function".
253 */
254__LJMP unsigned int hlua_checkfunction(lua_State *L, int argno)
255{
256 if (!lua_isfunction(L, argno)) {
257 const char *msg = lua_pushfstring(L, "function expected, got %s", luaL_typename(L, -1));
258 WILL_LJMP(luaL_argerror(L, argno, msg));
259 }
260 lua_pushvalue(L, argno);
261 return luaL_ref(L, LUA_REGISTRYINDEX);
262}
263
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +0200264/* Return the string that is of the top of the stack. */
265const char *hlua_get_top_error_string(lua_State *L)
266{
267 if (lua_gettop(L) < 1)
268 return "unknown error";
269 if (lua_type(L, -1) != LUA_TSTRING)
270 return "unknown error";
271 return lua_tostring(L, -1);
272}
273
Thierry FOURNIERe8b9a402015-02-25 18:48:12 +0100274/* This function check the number of arguments available in the
275 * stack. If the number of arguments available is not the same
276 * then <nb> an error is throwed.
277 */
278__LJMP static inline void check_args(lua_State *L, int nb, char *fcn)
279{
280 if (lua_gettop(L) == nb)
281 return;
282 WILL_LJMP(luaL_error(L, "'%s' needs %d arguments", fcn, nb));
283}
284
Thierry FOURNIERe8b9a402015-02-25 18:48:12 +0100285/* This fucntion push an error string prefixed by the file name
286 * and the line number where the error is encountered.
287 */
288static int hlua_pusherror(lua_State *L, const char *fmt, ...)
289{
290 va_list argp;
291 va_start(argp, fmt);
292 luaL_where(L, 1);
293 lua_pushvfstring(L, fmt, argp);
294 va_end(argp);
295 lua_concat(L, 2);
296 return 1;
297}
298
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +0100299/* This function register a new signal. "lua" is the current lua
300 * execution context. It contains a pointer to the associated task.
301 * "link" is a list head attached to an other task that must be wake
302 * the lua task if an event occurs. This is useful with external
303 * events like TCP I/O or sleep functions. This funcion allocate
304 * memory for the signal.
305 */
Thierry FOURNIER847ca662016-12-16 13:07:22 +0100306static struct hlua_com *hlua_com_new(struct list *purge, struct list *event, struct task *wakeup)
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +0100307{
308 struct hlua_com *com = pool_alloc2(pool2_hlua_com);
309 if (!com)
Thierry FOURNIER847ca662016-12-16 13:07:22 +0100310 return NULL;
311 LIST_ADDQ(purge, &com->purge_me);
312 LIST_ADDQ(event, &com->wake_me);
313 com->task = wakeup;
314 return com;
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +0100315}
316
317/* This function purge all the pending signals when the LUA execution
318 * is finished. This prevent than a coprocess try to wake a deleted
319 * task. This function remove the memory associated to the signal.
320 */
Thierry FOURNIER847ca662016-12-16 13:07:22 +0100321static void hlua_com_purge(struct list *purge)
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +0100322{
323 struct hlua_com *com, *back;
324
325 /* Delete all pending communication signals. */
Thierry FOURNIER847ca662016-12-16 13:07:22 +0100326 list_for_each_entry_safe(com, back, purge, purge_me) {
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +0100327 LIST_DEL(&com->purge_me);
328 LIST_DEL(&com->wake_me);
329 pool_free2(pool2_hlua_com, com);
330 }
331}
332
333/* This function sends signals. It wakes all the tasks attached
334 * to a list head, and remove the signal, and free the used
335 * memory.
336 */
337static void hlua_com_wake(struct list *wake)
338{
339 struct hlua_com *com, *back;
340
341 /* Wake task and delete all pending communication signals. */
342 list_for_each_entry_safe(com, back, wake, wake_me) {
343 LIST_DEL(&com->purge_me);
344 LIST_DEL(&com->wake_me);
345 task_wakeup(com->task, TASK_WOKEN_MSG);
346 pool_free2(pool2_hlua_com, com);
347 }
348}
349
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100350/* This functions is used with sample fetch and converters. It
351 * converts the HAProxy configuration argument in a lua stack
352 * values.
353 *
354 * It takes an array of "arg", and each entry of the array is
355 * converted and pushed in the LUA stack.
356 */
357static int hlua_arg2lua(lua_State *L, const struct arg *arg)
358{
359 switch (arg->type) {
360 case ARGT_SINT:
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100361 case ARGT_TIME:
362 case ARGT_SIZE:
Thierry FOURNIERf90838b2015-03-06 13:48:32 +0100363 lua_pushinteger(L, arg->data.sint);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100364 break;
365
366 case ARGT_STR:
367 lua_pushlstring(L, arg->data.str.str, arg->data.str.len);
368 break;
369
370 case ARGT_IPV4:
371 case ARGT_IPV6:
372 case ARGT_MSK4:
373 case ARGT_MSK6:
374 case ARGT_FE:
375 case ARGT_BE:
376 case ARGT_TAB:
377 case ARGT_SRV:
378 case ARGT_USR:
379 case ARGT_MAP:
380 default:
381 lua_pushnil(L);
382 break;
383 }
384 return 1;
385}
386
387/* This function take one entrie in an LUA stack at the index "ud",
388 * and try to convert it in an HAProxy argument entry. This is useful
389 * with sample fetch wrappers. The input arguments are gived to the
390 * lua wrapper and converted as arg list by thi function.
391 */
392static int hlua_lua2arg(lua_State *L, int ud, struct arg *arg)
393{
394 switch (lua_type(L, ud)) {
395
396 case LUA_TNUMBER:
397 case LUA_TBOOLEAN:
398 arg->type = ARGT_SINT;
399 arg->data.sint = lua_tointeger(L, ud);
400 break;
401
402 case LUA_TSTRING:
403 arg->type = ARGT_STR;
404 arg->data.str.str = (char *)lua_tolstring(L, ud, (size_t *)&arg->data.str.len);
405 break;
406
407 case LUA_TUSERDATA:
408 case LUA_TNIL:
409 case LUA_TTABLE:
410 case LUA_TFUNCTION:
411 case LUA_TTHREAD:
412 case LUA_TLIGHTUSERDATA:
413 arg->type = ARGT_SINT;
Thierry FOURNIERbf65cd42015-07-20 17:45:02 +0200414 arg->data.sint = 0;
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100415 break;
416 }
417 return 1;
418}
419
420/* the following functions are used to convert a struct sample
421 * in Lua type. This useful to convert the return of the
422 * fetchs or converters.
423 */
Willy Tarreau5eadada2015-03-10 17:28:54 +0100424static int hlua_smp2lua(lua_State *L, struct sample *smp)
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100425{
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200426 switch (smp->data.type) {
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100427 case SMP_T_SINT:
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100428 case SMP_T_BOOL:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200429 lua_pushinteger(L, smp->data.u.sint);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100430 break;
431
432 case SMP_T_BIN:
433 case SMP_T_STR:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200434 lua_pushlstring(L, smp->data.u.str.str, smp->data.u.str.len);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100435 break;
436
437 case SMP_T_METH:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200438 switch (smp->data.u.meth.meth) {
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100439 case HTTP_METH_OPTIONS: lua_pushstring(L, "OPTIONS"); break;
440 case HTTP_METH_GET: lua_pushstring(L, "GET"); break;
441 case HTTP_METH_HEAD: lua_pushstring(L, "HEAD"); break;
442 case HTTP_METH_POST: lua_pushstring(L, "POST"); break;
443 case HTTP_METH_PUT: lua_pushstring(L, "PUT"); break;
444 case HTTP_METH_DELETE: lua_pushstring(L, "DELETE"); break;
445 case HTTP_METH_TRACE: lua_pushstring(L, "TRACE"); break;
446 case HTTP_METH_CONNECT: lua_pushstring(L, "CONNECT"); break;
447 case HTTP_METH_OTHER:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200448 lua_pushlstring(L, smp->data.u.meth.str.str, smp->data.u.meth.str.len);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100449 break;
450 default:
451 lua_pushnil(L);
452 break;
453 }
454 break;
455
456 case SMP_T_IPV4:
457 case SMP_T_IPV6:
458 case SMP_T_ADDR: /* This type is never used to qualify a sample. */
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200459 if (sample_casts[smp->data.type][SMP_T_STR] &&
460 sample_casts[smp->data.type][SMP_T_STR](smp))
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200461 lua_pushlstring(L, smp->data.u.str.str, smp->data.u.str.len);
Willy Tarreau5eadada2015-03-10 17:28:54 +0100462 else
463 lua_pushnil(L);
464 break;
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100465 default:
466 lua_pushnil(L);
467 break;
468 }
469 return 1;
470}
471
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100472/* the following functions are used to convert a struct sample
473 * in Lua strings. This is useful to convert the return of the
474 * fetchs or converters.
475 */
476static int hlua_smp2lua_str(lua_State *L, struct sample *smp)
477{
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200478 switch (smp->data.type) {
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100479
480 case SMP_T_BIN:
481 case SMP_T_STR:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200482 lua_pushlstring(L, smp->data.u.str.str, smp->data.u.str.len);
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100483 break;
484
485 case SMP_T_METH:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200486 switch (smp->data.u.meth.meth) {
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100487 case HTTP_METH_OPTIONS: lua_pushstring(L, "OPTIONS"); break;
488 case HTTP_METH_GET: lua_pushstring(L, "GET"); break;
489 case HTTP_METH_HEAD: lua_pushstring(L, "HEAD"); break;
490 case HTTP_METH_POST: lua_pushstring(L, "POST"); break;
491 case HTTP_METH_PUT: lua_pushstring(L, "PUT"); break;
492 case HTTP_METH_DELETE: lua_pushstring(L, "DELETE"); break;
493 case HTTP_METH_TRACE: lua_pushstring(L, "TRACE"); break;
494 case HTTP_METH_CONNECT: lua_pushstring(L, "CONNECT"); break;
495 case HTTP_METH_OTHER:
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200496 lua_pushlstring(L, smp->data.u.meth.str.str, smp->data.u.meth.str.len);
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100497 break;
498 default:
499 lua_pushstring(L, "");
500 break;
501 }
502 break;
503
504 case SMP_T_SINT:
505 case SMP_T_BOOL:
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100506 case SMP_T_IPV4:
507 case SMP_T_IPV6:
508 case SMP_T_ADDR: /* This type is never used to qualify a sample. */
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200509 if (sample_casts[smp->data.type][SMP_T_STR] &&
510 sample_casts[smp->data.type][SMP_T_STR](smp))
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200511 lua_pushlstring(L, smp->data.u.str.str, smp->data.u.str.len);
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +0100512 else
513 lua_pushstring(L, "");
514 break;
515 default:
516 lua_pushstring(L, "");
517 break;
518 }
519 return 1;
520}
521
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100522/* the following functions are used to convert an Lua type in a
523 * struct sample. This is useful to provide data from a converter
524 * to the LUA code.
525 */
526static int hlua_lua2smp(lua_State *L, int ud, struct sample *smp)
527{
528 switch (lua_type(L, ud)) {
529
530 case LUA_TNUMBER:
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200531 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200532 smp->data.u.sint = lua_tointeger(L, ud);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100533 break;
534
535
536 case LUA_TBOOLEAN:
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200537 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200538 smp->data.u.sint = lua_toboolean(L, ud);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100539 break;
540
541 case LUA_TSTRING:
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200542 smp->data.type = SMP_T_STR;
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100543 smp->flags |= SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200544 smp->data.u.str.str = (char *)lua_tolstring(L, ud, (size_t *)&smp->data.u.str.len);
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100545 break;
546
547 case LUA_TUSERDATA:
548 case LUA_TNIL:
549 case LUA_TTABLE:
550 case LUA_TFUNCTION:
551 case LUA_TTHREAD:
552 case LUA_TLIGHTUSERDATA:
Thierry FOURNIER93405e12015-08-26 14:19:03 +0200553 case LUA_TNONE:
554 default:
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +0200555 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +0200556 smp->data.u.sint = 0;
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100557 break;
558 }
559 return 1;
560}
561
562/* This function check the "argp" builded by another conversion function
563 * is in accord with the expected argp defined by the "mask". The fucntion
564 * returns true or false. It can be adjust the types if there compatibles.
Thierry FOURNIER3caa0392015-03-13 13:38:17 +0100565 *
566 * This function assumes thant the argp argument contains ARGM_NBARGS + 1
567 * entries.
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100568 */
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100569__LJMP int hlua_lua2arg_check(lua_State *L, int first, struct arg *argp,
David Carlier0c437f42016-04-27 16:21:56 +0100570 uint64_t mask, struct proxy *p)
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100571{
572 int min_arg;
573 int idx;
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100574 struct proxy *px;
575 char *sname, *pname;
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100576
577 idx = 0;
578 min_arg = ARGM(mask);
579 mask >>= ARGM_BITS;
580
581 while (1) {
582
583 /* Check oversize. */
584 if (idx >= ARGM_NBARGS && argp[idx].type != ARGT_STOP) {
Cyril Bonté577a36a2015-03-02 00:08:38 +0100585 WILL_LJMP(luaL_argerror(L, first + idx, "Malformed argument mask"));
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100586 }
587
588 /* Check for mandatory arguments. */
589 if (argp[idx].type == ARGT_STOP) {
Thierry FOURNIER3caa0392015-03-13 13:38:17 +0100590 if (idx < min_arg) {
591
592 /* If miss other argument than the first one, we return an error. */
593 if (idx > 0)
594 WILL_LJMP(luaL_argerror(L, first + idx, "Mandatory argument expected"));
595
596 /* If first argument have a certain type, some default values
597 * may be used. See the function smp_resolve_args().
598 */
599 switch (mask & ARGT_MASK) {
600
601 case ARGT_FE:
602 if (!(p->cap & PR_CAP_FE))
603 WILL_LJMP(luaL_argerror(L, first + idx, "Mandatory argument expected"));
604 argp[idx].data.prx = p;
605 argp[idx].type = ARGT_FE;
606 argp[idx+1].type = ARGT_STOP;
607 break;
608
609 case ARGT_BE:
610 if (!(p->cap & PR_CAP_BE))
611 WILL_LJMP(luaL_argerror(L, first + idx, "Mandatory argument expected"));
612 argp[idx].data.prx = p;
613 argp[idx].type = ARGT_BE;
614 argp[idx+1].type = ARGT_STOP;
615 break;
616
617 case ARGT_TAB:
618 argp[idx].data.prx = p;
619 argp[idx].type = ARGT_TAB;
620 argp[idx+1].type = ARGT_STOP;
621 break;
622
623 default:
624 WILL_LJMP(luaL_argerror(L, first + idx, "Mandatory argument expected"));
625 break;
626 }
627 }
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100628 return 0;
629 }
630
631 /* Check for exceed the number of requiered argument. */
632 if ((mask & ARGT_MASK) == ARGT_STOP &&
633 argp[idx].type != ARGT_STOP) {
634 WILL_LJMP(luaL_argerror(L, first + idx, "Last argument expected"));
635 }
636
637 if ((mask & ARGT_MASK) == ARGT_STOP &&
638 argp[idx].type == ARGT_STOP) {
639 return 0;
640 }
641
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100642 /* Convert some argument types. */
643 switch (mask & ARGT_MASK) {
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100644 case ARGT_SINT:
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100645 if (argp[idx].type != ARGT_SINT)
646 WILL_LJMP(luaL_argerror(L, first + idx, "integer expected"));
647 argp[idx].type = ARGT_SINT;
648 break;
649
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100650 case ARGT_TIME:
651 if (argp[idx].type != ARGT_SINT)
652 WILL_LJMP(luaL_argerror(L, first + idx, "integer expected"));
Thierry FOURNIER29176f32015-07-07 00:41:29 +0200653 argp[idx].type = ARGT_TIME;
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100654 break;
655
656 case ARGT_SIZE:
657 if (argp[idx].type != ARGT_SINT)
658 WILL_LJMP(luaL_argerror(L, first + idx, "integer expected"));
Thierry FOURNIER29176f32015-07-07 00:41:29 +0200659 argp[idx].type = ARGT_SIZE;
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100660 break;
661
662 case ARGT_FE:
663 if (argp[idx].type != ARGT_STR)
664 WILL_LJMP(luaL_argerror(L, first + idx, "string expected"));
665 memcpy(trash.str, argp[idx].data.str.str, argp[idx].data.str.len);
666 trash.str[argp[idx].data.str.len] = 0;
Willy Tarreau9e0bb102015-05-26 11:24:42 +0200667 argp[idx].data.prx = proxy_fe_by_name(trash.str);
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100668 if (!argp[idx].data.prx)
669 WILL_LJMP(luaL_argerror(L, first + idx, "frontend doesn't exist"));
670 argp[idx].type = ARGT_FE;
671 break;
672
673 case ARGT_BE:
674 if (argp[idx].type != ARGT_STR)
675 WILL_LJMP(luaL_argerror(L, first + idx, "string expected"));
676 memcpy(trash.str, argp[idx].data.str.str, argp[idx].data.str.len);
677 trash.str[argp[idx].data.str.len] = 0;
Willy Tarreau9e0bb102015-05-26 11:24:42 +0200678 argp[idx].data.prx = proxy_be_by_name(trash.str);
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100679 if (!argp[idx].data.prx)
680 WILL_LJMP(luaL_argerror(L, first + idx, "backend doesn't exist"));
681 argp[idx].type = ARGT_BE;
682 break;
683
684 case ARGT_TAB:
685 if (argp[idx].type != ARGT_STR)
686 WILL_LJMP(luaL_argerror(L, first + idx, "string expected"));
687 memcpy(trash.str, argp[idx].data.str.str, argp[idx].data.str.len);
688 trash.str[argp[idx].data.str.len] = 0;
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +0200689 argp[idx].data.prx = proxy_tbl_by_name(trash.str);
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100690 if (!argp[idx].data.prx)
691 WILL_LJMP(luaL_argerror(L, first + idx, "table doesn't exist"));
692 argp[idx].type = ARGT_TAB;
693 break;
694
695 case ARGT_SRV:
696 if (argp[idx].type != ARGT_STR)
697 WILL_LJMP(luaL_argerror(L, first + idx, "string expected"));
698 memcpy(trash.str, argp[idx].data.str.str, argp[idx].data.str.len);
699 trash.str[argp[idx].data.str.len] = 0;
700 sname = strrchr(trash.str, '/');
701 if (sname) {
702 *sname++ = '\0';
703 pname = trash.str;
Willy Tarreau9e0bb102015-05-26 11:24:42 +0200704 px = proxy_be_by_name(pname);
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100705 if (!px)
706 WILL_LJMP(luaL_argerror(L, first + idx, "backend doesn't exist"));
707 }
708 else {
709 sname = trash.str;
710 px = p;
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100711 }
Thierry FOURNIER7f4942a2015-03-12 18:28:50 +0100712 argp[idx].data.srv = findserver(px, sname);
713 if (!argp[idx].data.srv)
714 WILL_LJMP(luaL_argerror(L, first + idx, "server doesn't exist"));
715 argp[idx].type = ARGT_SRV;
716 break;
717
718 case ARGT_IPV4:
719 memcpy(trash.str, argp[idx].data.str.str, argp[idx].data.str.len);
720 trash.str[argp[idx].data.str.len] = 0;
721 if (inet_pton(AF_INET, trash.str, &argp[idx].data.ipv4))
722 WILL_LJMP(luaL_argerror(L, first + idx, "invalid IPv4 address"));
723 argp[idx].type = ARGT_IPV4;
724 break;
725
726 case ARGT_MSK4:
727 memcpy(trash.str, argp[idx].data.str.str, argp[idx].data.str.len);
728 trash.str[argp[idx].data.str.len] = 0;
729 if (!str2mask(trash.str, &argp[idx].data.ipv4))
730 WILL_LJMP(luaL_argerror(L, first + idx, "invalid IPv4 mask"));
731 argp[idx].type = ARGT_MSK4;
732 break;
733
734 case ARGT_IPV6:
735 memcpy(trash.str, argp[idx].data.str.str, argp[idx].data.str.len);
736 trash.str[argp[idx].data.str.len] = 0;
737 if (inet_pton(AF_INET6, trash.str, &argp[idx].data.ipv6))
738 WILL_LJMP(luaL_argerror(L, first + idx, "invalid IPv6 address"));
739 argp[idx].type = ARGT_IPV6;
740 break;
741
742 case ARGT_MSK6:
743 case ARGT_MAP:
744 case ARGT_REG:
745 case ARGT_USR:
746 WILL_LJMP(luaL_argerror(L, first + idx, "type not yet supported"));
Thierry FOURNIER55da1652015-01-23 11:36:30 +0100747 break;
748 }
749
750 /* Check for type of argument. */
751 if ((mask & ARGT_MASK) != argp[idx].type) {
752 const char *msg = lua_pushfstring(L, "'%s' expected, got '%s'",
753 arg_type_names[(mask & ARGT_MASK)],
754 arg_type_names[argp[idx].type & ARGT_MASK]);
755 WILL_LJMP(luaL_argerror(L, first + idx, msg));
756 }
757
758 /* Next argument. */
759 mask >>= ARGT_BITS;
760 idx++;
761 }
762}
763
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100764/*
765 * The following functions are used to make correspondance between the the
766 * executed lua pointer and the "struct hlua *" that contain the context.
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100767 *
768 * - hlua_gethlua : return the hlua context associated with an lua_State.
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100769 * - hlua_sethlua : create the association between hlua context and lua_state.
770 */
771static inline struct hlua *hlua_gethlua(lua_State *L)
772{
Thierry FOURNIER38c5fd62015-03-10 02:40:29 +0100773 struct hlua **hlua = lua_getextraspace(L);
774 return *hlua;
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100775}
776static inline void hlua_sethlua(struct hlua *hlua)
777{
Thierry FOURNIER38c5fd62015-03-10 02:40:29 +0100778 struct hlua **hlua_store = lua_getextraspace(hlua->T);
779 *hlua_store = hlua;
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100780}
781
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +0100782/* This function is used to send logs. It try to send on screen (stderr)
783 * and on the default syslog server.
784 */
785static inline void hlua_sendlog(struct proxy *px, int level, const char *msg)
786{
787 struct tm tm;
788 char *p;
789
790 /* Cleanup the log message. */
791 p = trash.str;
792 for (; *msg != '\0'; msg++, p++) {
Thierry FOURNIERccf00632015-09-16 12:47:03 +0200793 if (p >= trash.str + trash.size - 1) {
794 /* Break the message if exceed the buffer size. */
795 *(p-4) = ' ';
796 *(p-3) = '.';
797 *(p-2) = '.';
798 *(p-1) = '.';
799 break;
800 }
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +0100801 if (isprint(*msg))
802 *p = *msg;
803 else
804 *p = '.';
805 }
806 *p = '\0';
807
Thierry FOURNIER5554e292015-09-09 11:21:37 +0200808 send_log(px, level, "%s\n", trash.str);
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +0100809 if (!(global.mode & MODE_QUIET) || (global.mode & (MODE_VERBOSE | MODE_STARTING))) {
Willy Tarreaua678b432015-08-28 10:14:59 +0200810 get_localtime(date.tv_sec, &tm);
811 fprintf(stderr, "[%s] %03d/%02d%02d%02d (%d) : %s\n",
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +0100812 log_levels[level], tm.tm_yday, tm.tm_hour, tm.tm_min, tm.tm_sec,
813 (int)getpid(), trash.str);
814 fflush(stderr);
815 }
816}
817
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +0100818/* This function just ensure that the yield will be always
819 * returned with a timeout and permit to set some flags
820 */
821__LJMP void hlua_yieldk(lua_State *L, int nresults, int ctx,
Thierry FOURNIERf90838b2015-03-06 13:48:32 +0100822 lua_KFunction k, int timeout, unsigned int flags)
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +0100823{
824 struct hlua *hlua = hlua_gethlua(L);
825
826 /* Set the wake timeout. If timeout is required, we set
827 * the expiration time.
828 */
Thierry FOURNIER10770fa2015-09-29 01:59:42 +0200829 hlua->wake_time = timeout;
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +0100830
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +0100831 hlua->flags |= flags;
832
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +0100833 /* Process the yield. */
834 WILL_LJMP(lua_yieldk(L, nresults, ctx, k));
835}
836
Willy Tarreau87b09662015-04-03 00:22:06 +0200837/* This function initialises the Lua environment stored in the stream.
838 * It must be called at the start of the stream. This function creates
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100839 * an LUA coroutine. It can not be use to crete the main LUA context.
Thierry FOURNIERbabae282015-09-17 11:36:37 +0200840 *
841 * This function is particular. it initialises a new Lua thread. If the
842 * initialisation fails (example: out of memory error), the lua function
843 * throws an error (longjmp).
844 *
845 * This function manipulates two Lua stack: the main and the thread. Only
846 * the main stack can fail. The thread is not manipulated. This function
847 * MUST NOT manipulate the created thread stack state, because is not
848 * proctected agains error throwed by the thread stack.
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100849 */
850int hlua_ctx_init(struct hlua *lua, struct task *task)
851{
Thierry FOURNIERbabae282015-09-17 11:36:37 +0200852 if (!SET_SAFE_LJMP(gL.T)) {
853 lua->Tref = LUA_REFNIL;
854 return 0;
855 }
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100856 lua->Mref = LUA_REFNIL;
Thierry FOURNIERa097fdf2015-03-03 15:17:35 +0100857 lua->flags = 0;
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +0100858 LIST_INIT(&lua->com);
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100859 lua->T = lua_newthread(gL.T);
860 if (!lua->T) {
861 lua->Tref = LUA_REFNIL;
862 return 0;
863 }
864 hlua_sethlua(lua);
865 lua->Tref = luaL_ref(gL.T, LUA_REGISTRYINDEX);
866 lua->task = task;
Thierry FOURNIERbabae282015-09-17 11:36:37 +0200867 RESET_SAFE_LJMP(gL.T);
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100868 return 1;
869}
870
Willy Tarreau87b09662015-04-03 00:22:06 +0200871/* Used to destroy the Lua coroutine when the attached stream or task
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100872 * is destroyed. The destroy also the memory context. The struct "lua"
873 * is not freed.
874 */
875void hlua_ctx_destroy(struct hlua *lua)
876{
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +0100877 if (!lua)
Thierry FOURNIERa718b292015-03-04 16:48:34 +0100878 return;
879
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +0100880 if (!lua->T)
881 goto end;
882
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +0100883 /* Purge all the pending signals. */
Thierry FOURNIER847ca662016-12-16 13:07:22 +0100884 hlua_com_purge(&lua->com);
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +0100885
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100886 luaL_unref(lua->T, LUA_REGISTRYINDEX, lua->Mref);
887 luaL_unref(gL.T, LUA_REGISTRYINDEX, lua->Tref);
Thierry FOURNIER5a50a852015-09-23 16:59:28 +0200888
889 /* Forces a garbage collecting process. If the Lua program is finished
890 * without error, we run the GC on the thread pointer. Its freed all
891 * the unused memory.
892 * If the thread is finnish with an error or is currently yielded,
893 * it seems that the GC applied on the thread doesn't clean anything,
894 * so e run the GC on the main thread.
895 * NOTE: maybe this action locks all the Lua threads untiml the en of
896 * the garbage collection.
897 */
Thierry FOURNIER7c39ab42015-09-27 22:53:33 +0200898 if (lua->flags & HLUA_MUST_GC) {
899 lua_gc(lua->T, LUA_GCCOLLECT, 0);
900 if (lua_status(lua->T) != LUA_OK)
901 lua_gc(gL.T, LUA_GCCOLLECT, 0);
902 }
Thierry FOURNIER5a50a852015-09-23 16:59:28 +0200903
Thierry FOURNIERa7b536b2015-09-21 22:50:24 +0200904 lua->T = NULL;
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +0100905
906end:
907 pool_free2(pool2_hlua, lua);
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100908}
909
910/* This function is used to restore the Lua context when a coroutine
911 * fails. This function copy the common memory between old coroutine
912 * and the new coroutine. The old coroutine is destroyed, and its
913 * replaced by the new coroutine.
914 * If the flag "keep_msg" is set, the last entry of the old is assumed
915 * as string error message and it is copied in the new stack.
916 */
917static int hlua_ctx_renew(struct hlua *lua, int keep_msg)
918{
919 lua_State *T;
920 int new_ref;
921
922 /* Renew the main LUA stack doesn't have sense. */
923 if (lua == &gL)
924 return 0;
925
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100926 /* New Lua coroutine. */
927 T = lua_newthread(gL.T);
928 if (!T)
929 return 0;
930
931 /* Copy last error message. */
932 if (keep_msg)
933 lua_xmove(lua->T, T, 1);
934
935 /* Copy data between the coroutines. */
936 lua_rawgeti(lua->T, LUA_REGISTRYINDEX, lua->Mref);
937 lua_xmove(lua->T, T, 1);
938 new_ref = luaL_ref(T, LUA_REGISTRYINDEX); /* Valur poped. */
939
940 /* Destroy old data. */
941 luaL_unref(lua->T, LUA_REGISTRYINDEX, lua->Mref);
942
943 /* The thread is garbage collected by Lua. */
944 luaL_unref(gL.T, LUA_REGISTRYINDEX, lua->Tref);
945
946 /* Fill the struct with the new coroutine values. */
947 lua->Mref = new_ref;
948 lua->T = T;
949 lua->Tref = luaL_ref(gL.T, LUA_REGISTRYINDEX);
950
951 /* Set context. */
952 hlua_sethlua(lua);
953
954 return 1;
955}
956
Thierry FOURNIERee9f8022015-03-03 17:37:37 +0100957void hlua_hook(lua_State *L, lua_Debug *ar)
958{
Thierry FOURNIERcae49c92015-03-06 14:05:24 +0100959 struct hlua *hlua = hlua_gethlua(L);
960
961 /* Lua cannot yield when its returning from a function,
962 * so, we can fix the interrupt hook to 1 instruction,
963 * expecting that the function is finnished.
964 */
965 if (lua_gethookmask(L) & LUA_MASKRET) {
966 lua_sethook(hlua->T, hlua_hook, LUA_MASKCOUNT, 1);
967 return;
968 }
969
970 /* restore the interrupt condition. */
971 lua_sethook(hlua->T, hlua_hook, LUA_MASKCOUNT, hlua_nb_instruction);
972
973 /* If we interrupt the Lua processing in yieldable state, we yield.
974 * If the state is not yieldable, trying yield causes an error.
975 */
976 if (lua_isyieldable(L))
977 WILL_LJMP(hlua_yieldk(L, 0, 0, NULL, TICK_ETERNITY, HLUA_CTRLYIELD));
978
Thierry FOURNIERa85cfb12015-03-13 14:50:06 +0100979 /* If we cannot yield, update the clock and check the timeout. */
980 tv_update_date(0, 1);
Thierry FOURNIER10770fa2015-09-29 01:59:42 +0200981 hlua->run_time += now_ms - hlua->start_time;
982 if (hlua->max_time && hlua->run_time >= hlua->max_time) {
Thierry FOURNIERcae49c92015-03-06 14:05:24 +0100983 lua_pushfstring(L, "execution timeout");
984 WILL_LJMP(lua_error(L));
985 }
986
Thierry FOURNIER10770fa2015-09-29 01:59:42 +0200987 /* Update the start time. */
988 hlua->start_time = now_ms;
989
Thierry FOURNIERcae49c92015-03-06 14:05:24 +0100990 /* Try to interrupt the process at the end of the current
991 * unyieldable function.
992 */
993 lua_sethook(hlua->T, hlua_hook, LUA_MASKRET|LUA_MASKCOUNT, hlua_nb_instruction);
Thierry FOURNIERee9f8022015-03-03 17:37:37 +0100994}
995
Thierry FOURNIER380d0932015-01-23 14:27:52 +0100996/* This function start or resumes the Lua stack execution. If the flag
997 * "yield_allowed" if no set and the LUA stack execution returns a yield
998 * The function return an error.
999 *
1000 * The function can returns 4 values:
1001 * - HLUA_E_OK : The execution is terminated without any errors.
1002 * - HLUA_E_AGAIN : The execution must continue at the next associated
1003 * task wakeup.
1004 * - HLUA_E_ERRMSG : An error has occured, an error message is set in
1005 * the top of the stack.
1006 * - HLUA_E_ERR : An error has occured without error message.
1007 *
1008 * If an error occured, the stack is renewed and it is ready to run new
1009 * LUA code.
1010 */
1011static enum hlua_exec hlua_ctx_resume(struct hlua *lua, int yield_allowed)
1012{
1013 int ret;
1014 const char *msg;
1015
Thierry FOURNIER10770fa2015-09-29 01:59:42 +02001016 /* Initialise run time counter. */
1017 if (!HLUA_IS_RUNNING(lua))
1018 lua->run_time = 0;
Thierry FOURNIERdc9ca962015-03-05 11:16:52 +01001019
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01001020resume_execution:
1021
1022 /* This hook interrupts the Lua processing each 'hlua_nb_instruction'
1023 * instructions. it is used for preventing infinite loops.
1024 */
1025 lua_sethook(lua->T, hlua_hook, LUA_MASKCOUNT, hlua_nb_instruction);
1026
Thierry FOURNIER1bfc09b2015-03-05 17:10:14 +01001027 /* Remove all flags except the running flags. */
Thierry FOURNIER2f3867f2015-09-28 01:02:01 +02001028 HLUA_SET_RUN(lua);
1029 HLUA_CLR_CTRLYIELD(lua);
1030 HLUA_CLR_WAKERESWR(lua);
1031 HLUA_CLR_WAKEREQWR(lua);
Thierry FOURNIER1bfc09b2015-03-05 17:10:14 +01001032
Thierry FOURNIER10770fa2015-09-29 01:59:42 +02001033 /* Update the start time. */
1034 lua->start_time = now_ms;
1035
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001036 /* Call the function. */
1037 ret = lua_resume(lua->T, gL.T, lua->nargs);
1038 switch (ret) {
1039
1040 case LUA_OK:
1041 ret = HLUA_E_OK;
1042 break;
1043
1044 case LUA_YIELD:
Thierry FOURNIERdc9ca962015-03-05 11:16:52 +01001045 /* Check if the execution timeout is expired. It it is the case, we
1046 * break the Lua execution.
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01001047 */
Thierry FOURNIER10770fa2015-09-29 01:59:42 +02001048 tv_update_date(0, 1);
1049 lua->run_time += now_ms - lua->start_time;
1050 if (lua->max_time && lua->run_time > lua->max_time) {
Thierry FOURNIERdc9ca962015-03-05 11:16:52 +01001051 lua_settop(lua->T, 0); /* Empty the stack. */
1052 if (!lua_checkstack(lua->T, 1)) {
1053 ret = HLUA_E_ERR;
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01001054 break;
1055 }
Thierry FOURNIERdc9ca962015-03-05 11:16:52 +01001056 lua_pushfstring(lua->T, "execution timeout");
1057 ret = HLUA_E_ERRMSG;
1058 break;
1059 }
1060 /* Process the forced yield. if the general yield is not allowed or
1061 * if no task were associated this the current Lua execution
1062 * coroutine, we resume the execution. Else we want to return in the
1063 * scheduler and we want to be waked up again, to continue the
1064 * current Lua execution. So we schedule our own task.
1065 */
1066 if (HLUA_IS_CTRLYIELDING(lua)) {
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01001067 if (!yield_allowed || !lua->task)
1068 goto resume_execution;
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01001069 task_wakeup(lua->task, TASK_WOKEN_MSG);
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01001070 }
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001071 if (!yield_allowed) {
1072 lua_settop(lua->T, 0); /* Empty the stack. */
1073 if (!lua_checkstack(lua->T, 1)) {
1074 ret = HLUA_E_ERR;
1075 break;
1076 }
1077 lua_pushfstring(lua->T, "yield not allowed");
1078 ret = HLUA_E_ERRMSG;
1079 break;
1080 }
1081 ret = HLUA_E_AGAIN;
1082 break;
1083
1084 case LUA_ERRRUN:
Thierry FOURNIER0a99b892015-08-26 00:14:17 +02001085
1086 /* Special exit case. The traditionnal exit is returned as an error
1087 * because the errors ares the only one mean to return immediately
1088 * from and lua execution.
1089 */
1090 if (lua->flags & HLUA_EXIT) {
1091 ret = HLUA_E_OK;
Thierry FOURNIERe1587b32015-08-28 09:54:13 +02001092 hlua_ctx_renew(lua, 0);
Thierry FOURNIER0a99b892015-08-26 00:14:17 +02001093 break;
1094 }
1095
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01001096 lua->wake_time = TICK_ETERNITY;
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001097 if (!lua_checkstack(lua->T, 1)) {
1098 ret = HLUA_E_ERR;
1099 break;
1100 }
1101 msg = lua_tostring(lua->T, -1);
1102 lua_settop(lua->T, 0); /* Empty the stack. */
1103 lua_pop(lua->T, 1);
1104 if (msg)
1105 lua_pushfstring(lua->T, "runtime error: %s", msg);
1106 else
1107 lua_pushfstring(lua->T, "unknown runtime error");
1108 ret = HLUA_E_ERRMSG;
1109 break;
1110
1111 case LUA_ERRMEM:
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01001112 lua->wake_time = TICK_ETERNITY;
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001113 lua_settop(lua->T, 0); /* Empty the stack. */
1114 if (!lua_checkstack(lua->T, 1)) {
1115 ret = HLUA_E_ERR;
1116 break;
1117 }
1118 lua_pushfstring(lua->T, "out of memory error");
1119 ret = HLUA_E_ERRMSG;
1120 break;
1121
1122 case LUA_ERRERR:
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01001123 lua->wake_time = TICK_ETERNITY;
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001124 if (!lua_checkstack(lua->T, 1)) {
1125 ret = HLUA_E_ERR;
1126 break;
1127 }
1128 msg = lua_tostring(lua->T, -1);
1129 lua_settop(lua->T, 0); /* Empty the stack. */
1130 lua_pop(lua->T, 1);
1131 if (msg)
1132 lua_pushfstring(lua->T, "message handler error: %s", msg);
1133 else
1134 lua_pushfstring(lua->T, "message handler error");
1135 ret = HLUA_E_ERRMSG;
1136 break;
1137
1138 default:
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01001139 lua->wake_time = TICK_ETERNITY;
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001140 lua_settop(lua->T, 0); /* Empty the stack. */
1141 if (!lua_checkstack(lua->T, 1)) {
1142 ret = HLUA_E_ERR;
1143 break;
1144 }
1145 lua_pushfstring(lua->T, "unknonwn error");
1146 ret = HLUA_E_ERRMSG;
1147 break;
1148 }
1149
Thierry FOURNIER6ab4d8e2015-09-27 22:17:19 +02001150 /* This GC permits to destroy some object when a Lua timeout strikes. */
Thierry FOURNIER7c39ab42015-09-27 22:53:33 +02001151 if (lua->flags & HLUA_MUST_GC &&
1152 ret != HLUA_E_AGAIN)
Thierry FOURNIER6ab4d8e2015-09-27 22:17:19 +02001153 lua_gc(lua->T, LUA_GCCOLLECT, 0);
1154
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001155 switch (ret) {
1156 case HLUA_E_AGAIN:
1157 break;
1158
1159 case HLUA_E_ERRMSG:
Thierry FOURNIER847ca662016-12-16 13:07:22 +01001160 hlua_com_purge(&lua->com);
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001161 hlua_ctx_renew(lua, 1);
Thierry FOURNIERa097fdf2015-03-03 15:17:35 +01001162 HLUA_CLR_RUN(lua);
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001163 break;
1164
1165 case HLUA_E_ERR:
Thierry FOURNIERa097fdf2015-03-03 15:17:35 +01001166 HLUA_CLR_RUN(lua);
Thierry FOURNIER847ca662016-12-16 13:07:22 +01001167 hlua_com_purge(&lua->com);
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001168 hlua_ctx_renew(lua, 0);
1169 break;
1170
1171 case HLUA_E_OK:
Thierry FOURNIERa097fdf2015-03-03 15:17:35 +01001172 HLUA_CLR_RUN(lua);
Thierry FOURNIER847ca662016-12-16 13:07:22 +01001173 hlua_com_purge(&lua->com);
Thierry FOURNIER380d0932015-01-23 14:27:52 +01001174 break;
1175 }
1176
1177 return ret;
1178}
1179
Thierry FOURNIER0a99b892015-08-26 00:14:17 +02001180/* This function exit the current code. */
1181__LJMP static int hlua_done(lua_State *L)
1182{
1183 struct hlua *hlua = hlua_gethlua(L);
1184
1185 hlua->flags |= HLUA_EXIT;
1186 WILL_LJMP(lua_error(L));
1187
1188 return 0;
1189}
1190
Thierry FOURNIER83758bb2015-02-04 13:21:04 +01001191/* This function is an LUA binding. It provides a function
1192 * for deleting ACL from a referenced ACL file.
1193 */
1194__LJMP static int hlua_del_acl(lua_State *L)
1195{
1196 const char *name;
1197 const char *key;
1198 struct pat_ref *ref;
1199
1200 MAY_LJMP(check_args(L, 2, "del_acl"));
1201
1202 name = MAY_LJMP(luaL_checkstring(L, 1));
1203 key = MAY_LJMP(luaL_checkstring(L, 2));
1204
1205 ref = pat_ref_lookup(name);
1206 if (!ref)
Vincent Bernata72db182015-10-06 16:05:59 +02001207 WILL_LJMP(luaL_error(L, "'del_acl': unknown acl file '%s'", name));
Thierry FOURNIER83758bb2015-02-04 13:21:04 +01001208
1209 pat_ref_delete(ref, key);
1210 return 0;
1211}
1212
1213/* This function is an LUA binding. It provides a function
1214 * for deleting map entry from a referenced map file.
1215 */
1216static int hlua_del_map(lua_State *L)
1217{
1218 const char *name;
1219 const char *key;
1220 struct pat_ref *ref;
1221
1222 MAY_LJMP(check_args(L, 2, "del_map"));
1223
1224 name = MAY_LJMP(luaL_checkstring(L, 1));
1225 key = MAY_LJMP(luaL_checkstring(L, 2));
1226
1227 ref = pat_ref_lookup(name);
1228 if (!ref)
Vincent Bernata72db182015-10-06 16:05:59 +02001229 WILL_LJMP(luaL_error(L, "'del_map': unknown acl file '%s'", name));
Thierry FOURNIER83758bb2015-02-04 13:21:04 +01001230
1231 pat_ref_delete(ref, key);
1232 return 0;
1233}
1234
1235/* This function is an LUA binding. It provides a function
1236 * for adding ACL pattern from a referenced ACL file.
1237 */
1238static int hlua_add_acl(lua_State *L)
1239{
1240 const char *name;
1241 const char *key;
1242 struct pat_ref *ref;
1243
1244 MAY_LJMP(check_args(L, 2, "add_acl"));
1245
1246 name = MAY_LJMP(luaL_checkstring(L, 1));
1247 key = MAY_LJMP(luaL_checkstring(L, 2));
1248
1249 ref = pat_ref_lookup(name);
1250 if (!ref)
Vincent Bernata72db182015-10-06 16:05:59 +02001251 WILL_LJMP(luaL_error(L, "'add_acl': unknown acl file '%s'", name));
Thierry FOURNIER83758bb2015-02-04 13:21:04 +01001252
1253 if (pat_ref_find_elt(ref, key) == NULL)
1254 pat_ref_add(ref, key, NULL, NULL);
1255 return 0;
1256}
1257
1258/* This function is an LUA binding. It provides a function
1259 * for setting map pattern and sample from a referenced map
1260 * file.
1261 */
1262static int hlua_set_map(lua_State *L)
1263{
1264 const char *name;
1265 const char *key;
1266 const char *value;
1267 struct pat_ref *ref;
1268
1269 MAY_LJMP(check_args(L, 3, "set_map"));
1270
1271 name = MAY_LJMP(luaL_checkstring(L, 1));
1272 key = MAY_LJMP(luaL_checkstring(L, 2));
1273 value = MAY_LJMP(luaL_checkstring(L, 3));
1274
1275 ref = pat_ref_lookup(name);
1276 if (!ref)
Vincent Bernata72db182015-10-06 16:05:59 +02001277 WILL_LJMP(luaL_error(L, "'set_map': unknown map file '%s'", name));
Thierry FOURNIER83758bb2015-02-04 13:21:04 +01001278
1279 if (pat_ref_find_elt(ref, key) != NULL)
1280 pat_ref_set(ref, key, value, NULL);
1281 else
1282 pat_ref_add(ref, key, value, NULL);
1283 return 0;
1284}
1285
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01001286/* A class is a lot of memory that contain data. This data can be a table,
1287 * an integer or user data. This data is associated with a metatable. This
1288 * metatable have an original version registred in the global context with
1289 * the name of the object (_G[<name>] = <metable> ).
1290 *
1291 * A metable is a table that modify the standard behavior of a standard
1292 * access to the associated data. The entries of this new metatable are
1293 * defined as is:
1294 *
1295 * http://lua-users.org/wiki/MetatableEvents
1296 *
1297 * __index
1298 *
1299 * we access an absent field in a table, the result is nil. This is
1300 * true, but it is not the whole truth. Actually, such access triggers
1301 * the interpreter to look for an __index metamethod: If there is no
1302 * such method, as usually happens, then the access results in nil;
1303 * otherwise, the metamethod will provide the result.
1304 *
1305 * Control 'prototype' inheritance. When accessing "myTable[key]" and
1306 * the key does not appear in the table, but the metatable has an __index
1307 * property:
1308 *
1309 * - if the value is a function, the function is called, passing in the
1310 * table and the key; the return value of that function is returned as
1311 * the result.
1312 *
1313 * - if the value is another table, the value of the key in that table is
1314 * asked for and returned (and if it doesn't exist in that table, but that
1315 * table's metatable has an __index property, then it continues on up)
1316 *
1317 * - Use "rawget(myTable,key)" to skip this metamethod.
1318 *
1319 * http://www.lua.org/pil/13.4.1.html
1320 *
1321 * __newindex
1322 *
1323 * Like __index, but control property assignment.
1324 *
1325 * __mode - Control weak references. A string value with one or both
1326 * of the characters 'k' and 'v' which specifies that the the
1327 * keys and/or values in the table are weak references.
1328 *
1329 * __call - Treat a table like a function. When a table is followed by
1330 * parenthesis such as "myTable( 'foo' )" and the metatable has
1331 * a __call key pointing to a function, that function is invoked
1332 * (passing any specified arguments) and the return value is
1333 * returned.
1334 *
1335 * __metatable - Hide the metatable. When "getmetatable( myTable )" is
1336 * called, if the metatable for myTable has a __metatable
1337 * key, the value of that key is returned instead of the
1338 * actual metatable.
1339 *
1340 * __tostring - Control string representation. When the builtin
1341 * "tostring( myTable )" function is called, if the metatable
1342 * for myTable has a __tostring property set to a function,
1343 * that function is invoked (passing myTable to it) and the
1344 * return value is used as the string representation.
1345 *
1346 * __len - Control table length. When the table length is requested using
1347 * the length operator ( '#' ), if the metatable for myTable has
1348 * a __len key pointing to a function, that function is invoked
1349 * (passing myTable to it) and the return value used as the value
1350 * of "#myTable".
1351 *
1352 * __gc - Userdata finalizer code. When userdata is set to be garbage
1353 * collected, if the metatable has a __gc field pointing to a
1354 * function, that function is first invoked, passing the userdata
1355 * to it. The __gc metamethod is not called for tables.
1356 * (See http://lua-users.org/lists/lua-l/2006-11/msg00508.html)
1357 *
1358 * Special metamethods for redefining standard operators:
1359 * http://www.lua.org/pil/13.1.html
1360 *
1361 * __add "+"
1362 * __sub "-"
1363 * __mul "*"
1364 * __div "/"
1365 * __unm "!"
1366 * __pow "^"
1367 * __concat ".."
1368 *
1369 * Special methods for redfining standar relations
1370 * http://www.lua.org/pil/13.2.html
1371 *
1372 * __eq "=="
1373 * __lt "<"
1374 * __le "<="
1375 */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001376
1377/*
1378 *
1379 *
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001380 * Class Map
1381 *
1382 *
1383 */
1384
1385/* Returns a struct hlua_map if the stack entry "ud" is
1386 * a class session, otherwise it throws an error.
1387 */
1388__LJMP static struct map_descriptor *hlua_checkmap(lua_State *L, int ud)
1389{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001390 return MAY_LJMP(hlua_checkudata(L, ud, class_map_ref));
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001391}
1392
1393/* This function is the map constructor. It don't need
1394 * the class Map object. It creates and return a new Map
1395 * object. It must be called only during "body" or "init"
1396 * context because it process some filesystem accesses.
1397 */
1398__LJMP static int hlua_map_new(struct lua_State *L)
1399{
1400 const char *fn;
1401 int match = PAT_MATCH_STR;
1402 struct sample_conv conv;
1403 const char *file = "";
1404 int line = 0;
1405 lua_Debug ar;
1406 char *err = NULL;
1407 struct arg args[2];
1408
1409 if (lua_gettop(L) < 1 || lua_gettop(L) > 2)
1410 WILL_LJMP(luaL_error(L, "'new' needs at least 1 argument."));
1411
1412 fn = MAY_LJMP(luaL_checkstring(L, 1));
1413
1414 if (lua_gettop(L) >= 2) {
1415 match = MAY_LJMP(luaL_checkinteger(L, 2));
1416 if (match < 0 || match >= PAT_MATCH_NUM)
1417 WILL_LJMP(luaL_error(L, "'new' needs a valid match method."));
1418 }
1419
1420 /* Get Lua filename and line number. */
1421 if (lua_getstack(L, 1, &ar)) { /* check function at level */
1422 lua_getinfo(L, "Sl", &ar); /* get info about it */
1423 if (ar.currentline > 0) { /* is there info? */
1424 file = ar.short_src;
1425 line = ar.currentline;
1426 }
1427 }
1428
1429 /* fill fake sample_conv struct. */
1430 conv.kw = ""; /* unused. */
1431 conv.process = NULL; /* unused. */
1432 conv.arg_mask = 0; /* unused. */
1433 conv.val_args = NULL; /* unused. */
1434 conv.out_type = SMP_T_STR;
1435 conv.private = (void *)(long)match;
1436 switch (match) {
1437 case PAT_MATCH_STR: conv.in_type = SMP_T_STR; break;
1438 case PAT_MATCH_BEG: conv.in_type = SMP_T_STR; break;
1439 case PAT_MATCH_SUB: conv.in_type = SMP_T_STR; break;
1440 case PAT_MATCH_DIR: conv.in_type = SMP_T_STR; break;
1441 case PAT_MATCH_DOM: conv.in_type = SMP_T_STR; break;
1442 case PAT_MATCH_END: conv.in_type = SMP_T_STR; break;
1443 case PAT_MATCH_REG: conv.in_type = SMP_T_STR; break;
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02001444 case PAT_MATCH_INT: conv.in_type = SMP_T_SINT; break;
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001445 case PAT_MATCH_IP: conv.in_type = SMP_T_ADDR; break;
1446 default:
1447 WILL_LJMP(luaL_error(L, "'new' doesn't support this match mode."));
1448 }
1449
1450 /* fill fake args. */
1451 args[0].type = ARGT_STR;
1452 args[0].data.str.str = (char *)fn;
1453 args[1].type = ARGT_STOP;
1454
1455 /* load the map. */
1456 if (!sample_load_map(args, &conv, file, line, &err)) {
1457 /* error case: we cant use luaL_error because we must
1458 * free the err variable.
1459 */
1460 luaL_where(L, 1);
1461 lua_pushfstring(L, "'new': %s.", err);
1462 lua_concat(L, 2);
1463 free(err);
1464 WILL_LJMP(lua_error(L));
1465 }
1466
1467 /* create the lua object. */
1468 lua_newtable(L);
1469 lua_pushlightuserdata(L, args[0].data.map);
1470 lua_rawseti(L, -2, 0);
1471
1472 /* Pop a class Map metatable and affect it to the userdata. */
1473 lua_rawgeti(L, LUA_REGISTRYINDEX, class_map_ref);
1474 lua_setmetatable(L, -2);
1475
1476
1477 return 1;
1478}
1479
1480__LJMP static inline int _hlua_map_lookup(struct lua_State *L, int str)
1481{
1482 struct map_descriptor *desc;
1483 struct pattern *pat;
1484 struct sample smp;
1485
1486 MAY_LJMP(check_args(L, 2, "lookup"));
1487 desc = MAY_LJMP(hlua_checkmap(L, 1));
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02001488 if (desc->pat.expect_type == SMP_T_SINT) {
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02001489 smp.data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02001490 smp.data.u.sint = MAY_LJMP(luaL_checkinteger(L, 2));
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001491 }
1492 else {
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02001493 smp.data.type = SMP_T_STR;
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001494 smp.flags = SMP_F_CONST;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02001495 smp.data.u.str.str = (char *)MAY_LJMP(luaL_checklstring(L, 2, (size_t *)&smp.data.u.str.len));
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001496 }
1497
1498 pat = pattern_exec_match(&desc->pat, &smp, 1);
Thierry FOURNIER503bb092015-08-19 08:35:43 +02001499 if (!pat || !pat->data) {
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001500 if (str)
1501 lua_pushstring(L, "");
1502 else
1503 lua_pushnil(L);
1504 return 1;
1505 }
1506
1507 /* The Lua pattern must return a string, so we can't check the returned type */
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02001508 lua_pushlstring(L, pat->data->u.str.str, pat->data->u.str.len);
Thierry FOURNIER3def3932015-04-07 11:27:54 +02001509 return 1;
1510}
1511
1512__LJMP static int hlua_map_lookup(struct lua_State *L)
1513{
1514 return _hlua_map_lookup(L, 0);
1515}
1516
1517__LJMP static int hlua_map_slookup(struct lua_State *L)
1518{
1519 return _hlua_map_lookup(L, 1);
1520}
1521
1522/*
1523 *
1524 *
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001525 * Class Socket
1526 *
1527 *
1528 */
1529
1530__LJMP static struct hlua_socket *hlua_checksocket(lua_State *L, int ud)
1531{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001532 return MAY_LJMP(hlua_checkudata(L, ud, class_socket_ref));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001533}
1534
1535/* This function is the handler called for each I/O on the established
1536 * connection. It is used for notify space avalaible to send or data
1537 * received.
1538 */
Willy Tarreau00a37f02015-04-13 12:05:19 +02001539static void hlua_socket_handler(struct appctx *appctx)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001540{
Willy Tarreau00a37f02015-04-13 12:05:19 +02001541 struct stream_interface *si = appctx->owner;
Willy Tarreau50fe03b2014-11-28 13:59:31 +01001542 struct connection *c = objt_conn(si_opposite(si)->end);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001543
Thierry FOURNIER6d695e62015-09-27 19:29:38 +02001544 /* If the connection object is not avalaible, close all the
1545 * streams and wakeup everithing waiting for.
1546 */
1547 if (!c) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001548 si_shutw(si);
1549 si_shutr(si);
Willy Tarreau2bb4a962014-11-28 11:11:05 +01001550 si_ic(si)->flags |= CF_READ_NULL;
Thierry FOURNIER18d09902016-12-16 09:25:38 +01001551 hlua_com_wake(&appctx->ctx.hlua_cosocket.wake_on_read);
1552 hlua_com_wake(&appctx->ctx.hlua_cosocket.wake_on_write);
Willy Tarreaud4da1962015-04-20 01:31:23 +02001553 return;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001554 }
1555
Thierry FOURNIER6d695e62015-09-27 19:29:38 +02001556 /* If we cant write, wakeup the pending write signals. */
1557 if (channel_output_closed(si_ic(si)))
Thierry FOURNIER18d09902016-12-16 09:25:38 +01001558 hlua_com_wake(&appctx->ctx.hlua_cosocket.wake_on_write);
Thierry FOURNIER6d695e62015-09-27 19:29:38 +02001559
1560 /* If we cant read, wakeup the pending read signals. */
1561 if (channel_input_closed(si_oc(si)))
Thierry FOURNIER18d09902016-12-16 09:25:38 +01001562 hlua_com_wake(&appctx->ctx.hlua_cosocket.wake_on_read);
Thierry FOURNIER6d695e62015-09-27 19:29:38 +02001563
Thierry FOURNIER316e3192015-09-04 18:25:53 +02001564 /* if the connection is not estabkished, inform the stream that we want
1565 * to be notified whenever the connection completes.
1566 */
1567 if (!(c->flags & CO_FL_CONNECTED)) {
1568 si_applet_cant_get(si);
1569 si_applet_cant_put(si);
Willy Tarreaud4da1962015-04-20 01:31:23 +02001570 return;
Thierry FOURNIER316e3192015-09-04 18:25:53 +02001571 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001572
1573 /* This function is called after the connect. */
Thierry FOURNIER18d09902016-12-16 09:25:38 +01001574 appctx->ctx.hlua_cosocket.connected = 1;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001575
1576 /* Wake the tasks which wants to write if the buffer have avalaible space. */
Thierry FOURNIEReba6f642015-09-26 22:01:07 +02001577 if (channel_may_recv(si_ic(si)))
Thierry FOURNIER18d09902016-12-16 09:25:38 +01001578 hlua_com_wake(&appctx->ctx.hlua_cosocket.wake_on_write);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001579
1580 /* Wake the tasks which wants to read if the buffer contains data. */
Thierry FOURNIEReba6f642015-09-26 22:01:07 +02001581 if (!channel_is_empty(si_oc(si)))
Thierry FOURNIER18d09902016-12-16 09:25:38 +01001582 hlua_com_wake(&appctx->ctx.hlua_cosocket.wake_on_read);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001583}
1584
Willy Tarreau87b09662015-04-03 00:22:06 +02001585/* This function is called when the "struct stream" is destroyed.
1586 * Remove the link from the object to this stream.
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001587 * Wake all the pending signals.
1588 */
Willy Tarreau00a37f02015-04-13 12:05:19 +02001589static void hlua_socket_release(struct appctx *appctx)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001590{
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001591 /* Remove my link in the original object. */
Thierry FOURNIER18d09902016-12-16 09:25:38 +01001592 if (appctx->ctx.hlua_cosocket.socket)
1593 appctx->ctx.hlua_cosocket.socket->s = NULL;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001594
1595 /* Wake all the task waiting for me. */
Thierry FOURNIER18d09902016-12-16 09:25:38 +01001596 hlua_com_wake(&appctx->ctx.hlua_cosocket.wake_on_read);
1597 hlua_com_wake(&appctx->ctx.hlua_cosocket.wake_on_write);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001598}
1599
1600/* If the garbage collectio of the object is launch, nobody
Willy Tarreau87b09662015-04-03 00:22:06 +02001601 * uses this object. If the stream does not exists, just quit.
1602 * Send the shutdown signal to the stream. In some cases,
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001603 * pending signal can rest in the read and write lists. destroy
1604 * it.
1605 */
1606__LJMP static int hlua_socket_gc(lua_State *L)
1607{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001608 struct hlua_socket *socket;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001609 struct appctx *appctx;
1610
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001611 MAY_LJMP(check_args(L, 1, "__gc"));
1612
1613 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001614 if (!socket->s)
1615 return 0;
1616
Willy Tarreau87b09662015-04-03 00:22:06 +02001617 /* Remove all reference between the Lua stack and the coroutine stream. */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001618 appctx = objt_appctx(socket->s->si[0].end);
Willy Tarreaue7dff022015-04-03 01:14:29 +02001619 stream_shutdown(socket->s, SF_ERR_KILLED);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001620 socket->s = NULL;
Thierry FOURNIER18d09902016-12-16 09:25:38 +01001621 appctx->ctx.hlua_cosocket.socket = NULL;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001622
1623 return 0;
1624}
1625
1626/* The close function send shutdown signal and break the
Willy Tarreau87b09662015-04-03 00:22:06 +02001627 * links between the stream and the object.
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001628 */
1629__LJMP static int hlua_socket_close(lua_State *L)
1630{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001631 struct hlua_socket *socket;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001632 struct appctx *appctx;
1633
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001634 MAY_LJMP(check_args(L, 1, "close"));
1635
1636 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001637 if (!socket->s)
1638 return 0;
1639
Willy Tarreau87b09662015-04-03 00:22:06 +02001640 /* Close the stream and remove the associated stop task. */
Willy Tarreaue7dff022015-04-03 01:14:29 +02001641 stream_shutdown(socket->s, SF_ERR_KILLED);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001642 appctx = objt_appctx(socket->s->si[0].end);
Thierry FOURNIER18d09902016-12-16 09:25:38 +01001643 appctx->ctx.hlua_cosocket.socket = NULL;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001644 socket->s = NULL;
1645
1646 return 0;
1647}
1648
1649/* This Lua function assumes that the stack contain three parameters.
1650 * 1 - USERDATA containing a struct socket
1651 * 2 - INTEGER with values of the macro defined below
1652 * If the integer is -1, we must read at most one line.
1653 * If the integer is -2, we ust read all the data until the
1654 * end of the stream.
1655 * If the integer is positive value, we must read a number of
1656 * bytes corresponding to this value.
1657 */
1658#define HLSR_READ_LINE (-1)
1659#define HLSR_READ_ALL (-2)
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01001660__LJMP static int hlua_socket_receive_yield(struct lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001661{
1662 struct hlua_socket *socket = MAY_LJMP(hlua_checksocket(L, 1));
1663 int wanted = lua_tointeger(L, 2);
1664 struct hlua *hlua = hlua_gethlua(L);
1665 struct appctx *appctx;
1666 int len;
1667 int nblk;
1668 char *blk1;
1669 int len1;
1670 char *blk2;
1671 int len2;
Thierry FOURNIER00543922015-03-09 18:35:06 +01001672 int skip_at_end = 0;
Willy Tarreau81389672015-03-10 12:03:52 +01001673 struct channel *oc;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001674
1675 /* Check if this lua stack is schedulable. */
1676 if (!hlua || !hlua->task)
1677 WILL_LJMP(luaL_error(L, "The 'receive' function is only allowed in "
1678 "'frontend', 'backend' or 'task'"));
1679
1680 /* check for connection closed. If some data where read, return it. */
1681 if (!socket->s)
1682 goto connection_closed;
1683
Willy Tarreau94aa6172015-03-13 14:19:06 +01001684 oc = &socket->s->res;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001685 if (wanted == HLSR_READ_LINE) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001686 /* Read line. */
Willy Tarreau81389672015-03-10 12:03:52 +01001687 nblk = bo_getline_nc(oc, &blk1, &len1, &blk2, &len2);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001688 if (nblk < 0) /* Connection close. */
1689 goto connection_closed;
1690 if (nblk == 0) /* No data avalaible. */
1691 goto connection_empty;
Thierry FOURNIER00543922015-03-09 18:35:06 +01001692
1693 /* remove final \r\n. */
1694 if (nblk == 1) {
1695 if (blk1[len1-1] == '\n') {
1696 len1--;
1697 skip_at_end++;
1698 if (blk1[len1-1] == '\r') {
1699 len1--;
1700 skip_at_end++;
1701 }
1702 }
1703 }
1704 else {
1705 if (blk2[len2-1] == '\n') {
1706 len2--;
1707 skip_at_end++;
1708 if (blk2[len2-1] == '\r') {
1709 len2--;
1710 skip_at_end++;
1711 }
1712 }
1713 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001714 }
1715
1716 else if (wanted == HLSR_READ_ALL) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001717 /* Read all the available data. */
Willy Tarreau81389672015-03-10 12:03:52 +01001718 nblk = bo_getblk_nc(oc, &blk1, &len1, &blk2, &len2);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001719 if (nblk < 0) /* Connection close. */
1720 goto connection_closed;
1721 if (nblk == 0) /* No data avalaible. */
1722 goto connection_empty;
1723 }
1724
1725 else {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001726 /* Read a block of data. */
Willy Tarreau81389672015-03-10 12:03:52 +01001727 nblk = bo_getblk_nc(oc, &blk1, &len1, &blk2, &len2);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001728 if (nblk < 0) /* Connection close. */
1729 goto connection_closed;
1730 if (nblk == 0) /* No data avalaible. */
1731 goto connection_empty;
1732
1733 if (len1 > wanted) {
1734 nblk = 1;
1735 len1 = wanted;
1736 } if (nblk == 2 && len1 + len2 > wanted)
1737 len2 = wanted - len1;
1738 }
1739
1740 len = len1;
1741
1742 luaL_addlstring(&socket->b, blk1, len1);
1743 if (nblk == 2) {
1744 len += len2;
1745 luaL_addlstring(&socket->b, blk2, len2);
1746 }
1747
1748 /* Consume data. */
Willy Tarreau81389672015-03-10 12:03:52 +01001749 bo_skip(oc, len + skip_at_end);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001750
1751 /* Don't wait anything. */
Willy Tarreaude70fa12015-09-26 11:25:05 +02001752 stream_int_notify(&socket->s->si[0]);
1753 stream_int_update_applet(&socket->s->si[0]);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001754
1755 /* If the pattern reclaim to read all the data
1756 * in the connection, got out.
1757 */
1758 if (wanted == HLSR_READ_ALL)
1759 goto connection_empty;
1760 else if (wanted >= 0 && len < wanted)
1761 goto connection_empty;
1762
1763 /* Return result. */
1764 luaL_pushresult(&socket->b);
1765 return 1;
1766
1767connection_closed:
1768
1769 /* If the buffer containds data. */
1770 if (socket->b.n > 0) {
1771 luaL_pushresult(&socket->b);
1772 return 1;
1773 }
1774 lua_pushnil(L);
1775 lua_pushstring(L, "connection closed.");
1776 return 2;
1777
1778connection_empty:
1779
1780 appctx = objt_appctx(socket->s->si[0].end);
Thierry FOURNIER847ca662016-12-16 13:07:22 +01001781 if (!hlua_com_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_read, hlua->task))
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001782 WILL_LJMP(luaL_error(L, "out of memory"));
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +01001783 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_receive_yield, TICK_ETERNITY, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001784 return 0;
1785}
1786
1787/* This Lus function gets two parameters. The first one can be string
1788 * or a number. If the string is "*l", the user require one line. If
1789 * the string is "*a", the user require all the content of the stream.
1790 * If the value is a number, the user require a number of bytes equal
1791 * to the value. The default value is "*l" (a line).
1792 *
1793 * This paraeter with a variable type is converted in integer. This
1794 * integer takes this values:
1795 * -1 : read a line
1796 * -2 : read all the stream
1797 * >0 : amount if bytes.
1798 *
1799 * The second parameter is optinal. It contains a string that must be
1800 * concatenated with the read data.
1801 */
1802__LJMP static int hlua_socket_receive(struct lua_State *L)
1803{
1804 int wanted = HLSR_READ_LINE;
1805 const char *pattern;
1806 int type;
1807 char *error;
1808 size_t len;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001809 struct hlua_socket *socket;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001810
1811 if (lua_gettop(L) < 1 || lua_gettop(L) > 3)
1812 WILL_LJMP(luaL_error(L, "The 'receive' function requires between 1 and 3 arguments."));
1813
Willy Tarreau80f5fae2015-02-27 16:38:20 +01001814 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001815
1816 /* check for pattern. */
1817 if (lua_gettop(L) >= 2) {
1818 type = lua_type(L, 2);
1819 if (type == LUA_TSTRING) {
1820 pattern = lua_tostring(L, 2);
1821 if (strcmp(pattern, "*a") == 0)
1822 wanted = HLSR_READ_ALL;
1823 else if (strcmp(pattern, "*l") == 0)
1824 wanted = HLSR_READ_LINE;
1825 else {
1826 wanted = strtoll(pattern, &error, 10);
1827 if (*error != '\0')
1828 WILL_LJMP(luaL_error(L, "Unsupported pattern."));
1829 }
1830 }
1831 else if (type == LUA_TNUMBER) {
1832 wanted = lua_tointeger(L, 2);
1833 if (wanted < 0)
1834 WILL_LJMP(luaL_error(L, "Unsupported size."));
1835 }
1836 }
1837
1838 /* Set pattern. */
1839 lua_pushinteger(L, wanted);
1840 lua_replace(L, 2);
1841
1842 /* init bufffer, and fiil it wih prefix. */
1843 luaL_buffinit(L, &socket->b);
1844
1845 /* Check prefix. */
1846 if (lua_gettop(L) >= 3) {
1847 if (lua_type(L, 3) != LUA_TSTRING)
1848 WILL_LJMP(luaL_error(L, "Expect a 'string' for the prefix"));
1849 pattern = lua_tolstring(L, 3, &len);
1850 luaL_addlstring(&socket->b, pattern, len);
1851 }
1852
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01001853 return __LJMP(hlua_socket_receive_yield(L, 0, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001854}
1855
1856/* Write the Lua input string in the output buffer.
1857 * This fucntion returns a yield if no space are available.
1858 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01001859static int hlua_socket_write_yield(struct lua_State *L,int status, lua_KContext ctx)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001860{
1861 struct hlua_socket *socket;
1862 struct hlua *hlua = hlua_gethlua(L);
1863 struct appctx *appctx;
1864 size_t buf_len;
1865 const char *buf;
1866 int len;
1867 int send_len;
1868 int sent;
1869
1870 /* Check if this lua stack is schedulable. */
1871 if (!hlua || !hlua->task)
1872 WILL_LJMP(luaL_error(L, "The 'write' function is only allowed in "
1873 "'frontend', 'backend' or 'task'"));
1874
1875 /* Get object */
1876 socket = MAY_LJMP(hlua_checksocket(L, 1));
1877 buf = MAY_LJMP(luaL_checklstring(L, 2, &buf_len));
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01001878 sent = MAY_LJMP(luaL_checkinteger(L, 3));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001879
1880 /* Check for connection close. */
Willy Tarreau22ec1ea2014-11-27 20:45:39 +01001881 if (!socket->s || channel_output_closed(&socket->s->req)) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001882 lua_pushinteger(L, -1);
1883 return 1;
1884 }
1885
1886 /* Update the input buffer data. */
1887 buf += sent;
1888 send_len = buf_len - sent;
1889
1890 /* All the data are sent. */
1891 if (sent >= buf_len)
1892 return 1; /* Implicitly return the length sent. */
1893
Thierry FOURNIER486d52a2015-03-09 17:51:43 +01001894 /* Check if the buffer is avalaible because HAProxy doesn't allocate
1895 * the request buffer if its not required.
1896 */
Willy Tarreau22ec1ea2014-11-27 20:45:39 +01001897 if (socket->s->req.buf->size == 0) {
Christopher Faulet33834b12016-12-19 09:29:06 +01001898 appctx = hlua->task->context;
1899 if (!channel_alloc_buffer(&socket->s->req, &appctx->buffer_wait))
1900 goto hlua_socket_write_yield_return;
Thierry FOURNIER486d52a2015-03-09 17:51:43 +01001901 }
1902
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001903 /* Check for avalaible space. */
Willy Tarreau94aa6172015-03-13 14:19:06 +01001904 len = buffer_total_space(socket->s->req.buf);
Christopher Faulet33834b12016-12-19 09:29:06 +01001905 if (len <= 0) {
1906 appctx = objt_appctx(socket->s->si[0].end);
1907 if (!hlua_com_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task))
1908 WILL_LJMP(luaL_error(L, "out of memory"));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001909 goto hlua_socket_write_yield_return;
Christopher Faulet33834b12016-12-19 09:29:06 +01001910 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001911
1912 /* send data */
1913 if (len < send_len)
1914 send_len = len;
Willy Tarreau94aa6172015-03-13 14:19:06 +01001915 len = bi_putblk(&socket->s->req, buf+sent, send_len);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001916
1917 /* "Not enough space" (-1), "Buffer too little to contain
1918 * the data" (-2) are not expected because the available length
1919 * is tested.
1920 * Other unknown error are also not expected.
1921 */
1922 if (len <= 0) {
Willy Tarreaubc18da12015-03-13 14:00:47 +01001923 if (len == -1)
Willy Tarreau94aa6172015-03-13 14:19:06 +01001924 socket->s->req.flags |= CF_WAKE_WRITE;
Willy Tarreaubc18da12015-03-13 14:00:47 +01001925
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001926 MAY_LJMP(hlua_socket_close(L));
1927 lua_pop(L, 1);
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01001928 lua_pushinteger(L, -1);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001929 return 1;
1930 }
1931
1932 /* update buffers. */
Willy Tarreaude70fa12015-09-26 11:25:05 +02001933 stream_int_notify(&socket->s->si[0]);
1934 stream_int_update_applet(&socket->s->si[0]);
1935
Willy Tarreau94aa6172015-03-13 14:19:06 +01001936 socket->s->req.rex = TICK_ETERNITY;
1937 socket->s->res.wex = TICK_ETERNITY;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001938
1939 /* Update length sent. */
1940 lua_pop(L, 1);
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01001941 lua_pushinteger(L, sent + len);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001942
1943 /* All the data buffer is sent ? */
1944 if (sent + len >= buf_len)
1945 return 1;
1946
1947hlua_socket_write_yield_return:
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +01001948 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_write_yield, TICK_ETERNITY, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01001949 return 0;
1950}
1951
1952/* This function initiate the send of data. It just check the input
1953 * parameters and push an integer in the Lua stack that contain the
1954 * amount of data writed in the buffer. This is used by the function
1955 * "hlua_socket_write_yield" that can yield.
1956 *
1957 * The Lua function gets between 3 and 4 parameters. The first one is
1958 * the associated object. The second is a string buffer. The third is
1959 * a facultative integer that represents where is the buffer position
1960 * of the start of the data that can send. The first byte is the
1961 * position "1". The default value is "1". The fourth argument is a
1962 * facultative integer that represents where is the buffer position
1963 * of the end of the data that can send. The default is the last byte.
1964 */
1965static int hlua_socket_send(struct lua_State *L)
1966{
1967 int i;
1968 int j;
1969 const char *buf;
1970 size_t buf_len;
1971
1972 /* Check number of arguments. */
1973 if (lua_gettop(L) < 2 || lua_gettop(L) > 4)
1974 WILL_LJMP(luaL_error(L, "'send' needs between 2 and 4 arguments"));
1975
1976 /* Get the string. */
1977 buf = MAY_LJMP(luaL_checklstring(L, 2, &buf_len));
1978
1979 /* Get and check j. */
1980 if (lua_gettop(L) == 4) {
1981 j = MAY_LJMP(luaL_checkinteger(L, 4));
1982 if (j < 0)
1983 j = buf_len + j + 1;
1984 if (j > buf_len)
1985 j = buf_len + 1;
1986 lua_pop(L, 1);
1987 }
1988 else
1989 j = buf_len;
1990
1991 /* Get and check i. */
1992 if (lua_gettop(L) == 3) {
1993 i = MAY_LJMP(luaL_checkinteger(L, 3));
1994 if (i < 0)
1995 i = buf_len + i + 1;
1996 if (i > buf_len)
1997 i = buf_len + 1;
1998 lua_pop(L, 1);
1999 } else
2000 i = 1;
2001
2002 /* Check bth i and j. */
2003 if (i > j) {
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002004 lua_pushinteger(L, 0);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002005 return 1;
2006 }
2007 if (i == 0 && j == 0) {
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002008 lua_pushinteger(L, 0);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002009 return 1;
2010 }
2011 if (i == 0)
2012 i = 1;
2013 if (j == 0)
2014 j = 1;
2015
2016 /* Pop the string. */
2017 lua_pop(L, 1);
2018
2019 /* Update the buffer length. */
2020 buf += i - 1;
2021 buf_len = j - i + 1;
2022 lua_pushlstring(L, buf, buf_len);
2023
2024 /* This unsigned is used to remember the amount of sent data. */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002025 lua_pushinteger(L, 0);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002026
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002027 return MAY_LJMP(hlua_socket_write_yield(L, 0, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002028}
2029
Willy Tarreau22b0a682015-06-17 19:43:49 +02002030#define SOCKET_INFO_MAX_LEN sizeof("[0000:0000:0000:0000:0000:0000:0000:0000]:12345")
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002031__LJMP static inline int hlua_socket_info(struct lua_State *L, struct sockaddr_storage *addr)
2032{
2033 static char buffer[SOCKET_INFO_MAX_LEN];
2034 int ret;
2035 int len;
2036 char *p;
2037
2038 ret = addr_to_str(addr, buffer+1, SOCKET_INFO_MAX_LEN-1);
2039 if (ret <= 0) {
2040 lua_pushnil(L);
2041 return 1;
2042 }
2043
2044 if (ret == AF_UNIX) {
2045 lua_pushstring(L, buffer+1);
2046 return 1;
2047 }
2048 else if (ret == AF_INET6) {
2049 buffer[0] = '[';
2050 len = strlen(buffer);
2051 buffer[len] = ']';
2052 len++;
2053 buffer[len] = ':';
2054 len++;
2055 p = buffer;
2056 }
2057 else if (ret == AF_INET) {
2058 p = buffer + 1;
2059 len = strlen(p);
2060 p[len] = ':';
2061 len++;
2062 }
2063 else {
2064 lua_pushnil(L);
2065 return 1;
2066 }
2067
2068 if (port_to_str(addr, p + len, SOCKET_INFO_MAX_LEN-1 - len) <= 0) {
2069 lua_pushnil(L);
2070 return 1;
2071 }
2072
2073 lua_pushstring(L, p);
2074 return 1;
2075}
2076
2077/* Returns information about the peer of the connection. */
2078__LJMP static int hlua_socket_getpeername(struct lua_State *L)
2079{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002080 struct hlua_socket *socket;
2081 struct connection *conn;
2082
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002083 MAY_LJMP(check_args(L, 1, "getpeername"));
2084
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002085 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002086
2087 /* Check if the tcp object is avalaible. */
2088 if (!socket->s) {
2089 lua_pushnil(L);
2090 return 1;
2091 }
2092
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002093 conn = objt_conn(socket->s->si[1].end);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002094 if (!conn) {
2095 lua_pushnil(L);
2096 return 1;
2097 }
2098
Willy Tarreaua71f6422016-11-16 17:00:14 +01002099 conn_get_to_addr(conn);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002100 if (!(conn->flags & CO_FL_ADDR_TO_SET)) {
Willy Tarreaua71f6422016-11-16 17:00:14 +01002101 lua_pushnil(L);
2102 return 1;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002103 }
2104
2105 return MAY_LJMP(hlua_socket_info(L, &conn->addr.to));
2106}
2107
2108/* Returns information about my connection side. */
2109static int hlua_socket_getsockname(struct lua_State *L)
2110{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002111 struct hlua_socket *socket;
2112 struct connection *conn;
2113
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002114 MAY_LJMP(check_args(L, 1, "getsockname"));
2115
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002116 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002117
2118 /* Check if the tcp object is avalaible. */
2119 if (!socket->s) {
2120 lua_pushnil(L);
2121 return 1;
2122 }
2123
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002124 conn = objt_conn(socket->s->si[1].end);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002125 if (!conn) {
2126 lua_pushnil(L);
2127 return 1;
2128 }
2129
Willy Tarreaua71f6422016-11-16 17:00:14 +01002130 conn_get_from_addr(conn);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002131 if (!(conn->flags & CO_FL_ADDR_FROM_SET)) {
Willy Tarreaua71f6422016-11-16 17:00:14 +01002132 lua_pushnil(L);
2133 return 1;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002134 }
2135
2136 return hlua_socket_info(L, &conn->addr.from);
2137}
2138
2139/* This struct define the applet. */
Willy Tarreau30576452015-04-13 13:50:30 +02002140static struct applet update_applet = {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002141 .obj_type = OBJ_TYPE_APPLET,
2142 .name = "<LUA_TCP>",
2143 .fct = hlua_socket_handler,
2144 .release = hlua_socket_release,
2145};
2146
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002147__LJMP static int hlua_socket_connect_yield(struct lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002148{
2149 struct hlua_socket *socket = MAY_LJMP(hlua_checksocket(L, 1));
2150 struct hlua *hlua = hlua_gethlua(L);
2151 struct appctx *appctx;
2152
2153 /* Check for connection close. */
Willy Tarreau22ec1ea2014-11-27 20:45:39 +01002154 if (!hlua || !socket->s || channel_output_closed(&socket->s->req)) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002155 lua_pushnil(L);
2156 lua_pushstring(L, "Can't connect");
2157 return 2;
2158 }
2159
2160 appctx = objt_appctx(socket->s->si[0].end);
2161
2162 /* Check for connection established. */
Thierry FOURNIER18d09902016-12-16 09:25:38 +01002163 if (appctx->ctx.hlua_cosocket.connected) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002164 lua_pushinteger(L, 1);
2165 return 1;
2166 }
2167
Thierry FOURNIER847ca662016-12-16 13:07:22 +01002168 if (!hlua_com_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task))
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002169 WILL_LJMP(luaL_error(L, "out of memory error"));
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +01002170 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_connect_yield, TICK_ETERNITY, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002171 return 0;
2172}
2173
2174/* This function fail or initite the connection. */
2175__LJMP static int hlua_socket_connect(struct lua_State *L)
2176{
2177 struct hlua_socket *socket;
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002178 int port = -1;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002179 const char *ip;
2180 struct connection *conn;
Thierry FOURNIER95ad96a2015-03-09 18:12:40 +01002181 struct hlua *hlua;
2182 struct appctx *appctx;
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002183 int low, high;
2184 struct sockaddr_storage *addr;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002185
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002186 if (lua_gettop(L) < 2)
2187 WILL_LJMP(luaL_error(L, "connect: need at least 2 arguments"));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002188
2189 /* Get args. */
2190 socket = MAY_LJMP(hlua_checksocket(L, 1));
2191 ip = MAY_LJMP(luaL_checkstring(L, 2));
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002192 if (lua_gettop(L) >= 3)
2193 port = MAY_LJMP(luaL_checkinteger(L, 3));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002194
Willy Tarreau973a5422015-08-05 21:47:23 +02002195 conn = si_alloc_conn(&socket->s->si[1]);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002196 if (!conn)
2197 WILL_LJMP(luaL_error(L, "connect: internal error"));
2198
Willy Tarreau3adac082015-09-26 17:51:09 +02002199 /* needed for the connection not to be closed */
2200 conn->target = socket->s->target;
2201
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002202 /* Parse ip address. */
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002203 addr = str2sa_range(ip, &low, &high, NULL, NULL, NULL, 0);
2204 if (!addr)
2205 WILL_LJMP(luaL_error(L, "connect: cannot parse destination address '%s'", ip));
2206 if (low != high)
2207 WILL_LJMP(luaL_error(L, "connect: port ranges not supported : address '%s'", ip));
2208 memcpy(&conn->addr.to, addr, sizeof(struct sockaddr_storage));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002209
2210 /* Set port. */
Thierry FOURNIERc2f56532015-09-26 20:23:30 +02002211 if (low == 0) {
2212 if (conn->addr.to.ss_family == AF_INET) {
2213 if (port == -1)
2214 WILL_LJMP(luaL_error(L, "connect: port missing"));
2215 ((struct sockaddr_in *)&conn->addr.to)->sin_port = htons(port);
2216 } else if (conn->addr.to.ss_family == AF_INET6) {
2217 if (port == -1)
2218 WILL_LJMP(luaL_error(L, "connect: port missing"));
2219 ((struct sockaddr_in6 *)&conn->addr.to)->sin6_port = htons(port);
2220 }
2221 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002222
Thierry FOURNIER95ad96a2015-03-09 18:12:40 +01002223 hlua = hlua_gethlua(L);
2224 appctx = objt_appctx(socket->s->si[0].end);
Willy Tarreaubdc97a82015-08-24 15:42:28 +02002225
2226 /* inform the stream that we want to be notified whenever the
2227 * connection completes.
2228 */
2229 si_applet_cant_get(&socket->s->si[0]);
2230 si_applet_cant_put(&socket->s->si[0]);
Thierry FOURNIER8c8fbbe2015-09-26 17:02:35 +02002231 appctx_wakeup(appctx);
Willy Tarreaubdc97a82015-08-24 15:42:28 +02002232
Thierry FOURNIER7c39ab42015-09-27 22:53:33 +02002233 hlua->flags |= HLUA_MUST_GC;
2234
Thierry FOURNIER847ca662016-12-16 13:07:22 +01002235 if (!hlua_com_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task))
Thierry FOURNIER95ad96a2015-03-09 18:12:40 +01002236 WILL_LJMP(luaL_error(L, "out of memory"));
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +01002237 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_connect_yield, TICK_ETERNITY, 0));
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002238
2239 return 0;
2240}
2241
Baptiste Assmann84bb4932015-03-02 21:40:06 +01002242#ifdef USE_OPENSSL
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002243__LJMP static int hlua_socket_connect_ssl(struct lua_State *L)
2244{
2245 struct hlua_socket *socket;
2246
2247 MAY_LJMP(check_args(L, 3, "connect_ssl"));
2248 socket = MAY_LJMP(hlua_checksocket(L, 1));
2249 socket->s->target = &socket_ssl.obj_type;
2250 return MAY_LJMP(hlua_socket_connect(L));
2251}
Baptiste Assmann84bb4932015-03-02 21:40:06 +01002252#endif
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002253
2254__LJMP static int hlua_socket_setoption(struct lua_State *L)
2255{
2256 return 0;
2257}
2258
2259__LJMP static int hlua_socket_settimeout(struct lua_State *L)
2260{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002261 struct hlua_socket *socket;
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002262 int tmout;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002263
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002264 MAY_LJMP(check_args(L, 2, "settimeout"));
2265
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002266 socket = MAY_LJMP(hlua_checksocket(L, 1));
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002267 tmout = MAY_LJMP(luaL_checkinteger(L, 2)) * 1000;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002268
Willy Tarreau22ec1ea2014-11-27 20:45:39 +01002269 socket->s->req.rto = tmout;
2270 socket->s->req.wto = tmout;
2271 socket->s->res.rto = tmout;
2272 socket->s->res.wto = tmout;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002273
2274 return 0;
2275}
2276
2277__LJMP static int hlua_socket_new(lua_State *L)
2278{
2279 struct hlua_socket *socket;
2280 struct appctx *appctx;
Willy Tarreau15b5e142015-04-04 14:38:25 +02002281 struct session *sess;
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002282 struct stream *strm;
Willy Tarreaud420a972015-04-06 00:39:18 +02002283 struct task *task;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002284
2285 /* Check stack size. */
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002286 if (!lua_checkstack(L, 3)) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002287 hlua_pusherror(L, "socket: full stack");
2288 goto out_fail_conf;
2289 }
2290
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002291 /* Create the object: obj[0] = userdata. */
2292 lua_newtable(L);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002293 socket = MAY_LJMP(lua_newuserdata(L, sizeof(*socket)));
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002294 lua_rawseti(L, -2, 0);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002295 memset(socket, 0, sizeof(*socket));
2296
Thierry FOURNIER4a6170c2015-03-09 17:07:10 +01002297 /* Check if the various memory pools are intialized. */
Willy Tarreau87b09662015-04-03 00:22:06 +02002298 if (!pool2_stream || !pool2_buffer) {
Thierry FOURNIER4a6170c2015-03-09 17:07:10 +01002299 hlua_pusherror(L, "socket: uninitialized pools.");
2300 goto out_fail_conf;
2301 }
2302
Willy Tarreau87b09662015-04-03 00:22:06 +02002303 /* Pop a class stream metatable and affect it to the userdata. */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002304 lua_rawgeti(L, LUA_REGISTRYINDEX, class_socket_ref);
2305 lua_setmetatable(L, -2);
2306
Willy Tarreaud420a972015-04-06 00:39:18 +02002307 /* Create the applet context */
2308 appctx = appctx_new(&update_applet);
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002309 if (!appctx) {
2310 hlua_pusherror(L, "socket: out of memory");
Willy Tarreaufeb76402015-04-03 14:10:06 +02002311 goto out_fail_conf;
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002312 }
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002313
Thierry FOURNIER18d09902016-12-16 09:25:38 +01002314 appctx->ctx.hlua_cosocket.socket = socket;
2315 appctx->ctx.hlua_cosocket.connected = 0;
2316 LIST_INIT(&appctx->ctx.hlua_cosocket.wake_on_write);
2317 LIST_INIT(&appctx->ctx.hlua_cosocket.wake_on_read);
Willy Tarreaub2bf8332015-04-04 15:58:58 +02002318
Willy Tarreaud420a972015-04-06 00:39:18 +02002319 /* Now create a session, task and stream for this applet */
2320 sess = session_new(&socket_proxy, NULL, &appctx->obj_type);
2321 if (!sess) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002322 hlua_pusherror(L, "socket: out of memory");
Willy Tarreaud420a972015-04-06 00:39:18 +02002323 goto out_fail_sess;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002324 }
2325
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002326 task = task_new();
2327 if (!task) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002328 hlua_pusherror(L, "socket: out of memory");
Willy Tarreaufeb76402015-04-03 14:10:06 +02002329 goto out_fail_task;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002330 }
Willy Tarreaud420a972015-04-06 00:39:18 +02002331 task->nice = 0;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002332
Willy Tarreau73b65ac2015-04-08 18:26:29 +02002333 strm = stream_new(sess, task, &appctx->obj_type);
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002334 if (!strm) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002335 hlua_pusherror(L, "socket: out of memory");
Willy Tarreaud420a972015-04-06 00:39:18 +02002336 goto out_fail_stream;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002337 }
2338
Willy Tarreaud420a972015-04-06 00:39:18 +02002339 /* Configure an empty Lua for the stream. */
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002340 socket->s = strm;
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01002341 strm->hlua = NULL;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002342
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002343 /* Configure "right" stream interface. this "si" is used to connect
2344 * and retrieve data from the server. The connection is initialized
2345 * with the "struct server".
2346 */
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002347 si_set_state(&strm->si[1], SI_ST_ASS);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002348
2349 /* Force destination server. */
Willy Tarreau61cf7c82015-04-06 00:48:33 +02002350 strm->flags |= SF_DIRECT | SF_ASSIGNED | SF_ADDR_SET | SF_BE_ASSIGNED;
2351 strm->target = &socket_tcp.obj_type;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002352
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002353 /* Update statistics counters. */
2354 socket_proxy.feconn++; /* beconn will be increased later */
2355 jobs++;
2356 totalconn++;
2357
2358 /* Return yield waiting for connection. */
2359 return 1;
2360
Willy Tarreaud420a972015-04-06 00:39:18 +02002361 out_fail_stream:
2362 task_free(task);
2363 out_fail_task:
Willy Tarreau11c36242015-04-04 15:54:03 +02002364 session_free(sess);
Willy Tarreaud420a972015-04-06 00:39:18 +02002365 out_fail_sess:
2366 appctx_free(appctx);
2367 out_fail_conf:
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01002368 WILL_LJMP(lua_error(L));
2369 return 0;
2370}
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01002371
2372/*
2373 *
2374 *
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002375 * Class Channel
2376 *
2377 *
2378 */
2379
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002380/* The state between the channel data and the HTTP parser state can be
2381 * unconsistent, so reset the parser and call it again. Warning, this
2382 * action not revalidate the request and not send a 400 if the modified
2383 * resuest is not valid.
2384 *
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01002385 * This function never fails. The direction is set using dir, which equals
2386 * either SMP_OPT_DIR_REQ or SMP_OPT_DIR_RES.
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002387 */
2388static void hlua_resynchonize_proto(struct stream *stream, int dir)
2389{
2390 /* Protocol HTTP. */
2391 if (stream->be->mode == PR_MODE_HTTP) {
2392
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01002393 if (dir == SMP_OPT_DIR_REQ)
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002394 http_txn_reset_req(stream->txn);
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01002395 else if (dir == SMP_OPT_DIR_RES)
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002396 http_txn_reset_res(stream->txn);
2397
2398 if (stream->txn->hdr_idx.v)
2399 hdr_idx_init(&stream->txn->hdr_idx);
2400
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01002401 if (dir == SMP_OPT_DIR_REQ)
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002402 http_msg_analyzer(&stream->txn->req, &stream->txn->hdr_idx);
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01002403 else if (dir == SMP_OPT_DIR_RES)
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002404 http_msg_analyzer(&stream->txn->rsp, &stream->txn->hdr_idx);
2405 }
2406}
2407
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01002408/* This function is called before the Lua execution. It stores
2409 * the differents parsers state before executing some Lua code.
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002410 */
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01002411static inline void consistency_set(struct stream *stream, int opt, struct hlua_consistency *c)
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002412{
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01002413 c->mode = stream->be->mode;
2414 switch (c->mode) {
2415 case PR_MODE_HTTP:
2416 c->data.http.dir = opt & SMP_OPT_DIR;
2417 if (c->data.http.dir == SMP_OPT_DIR_REQ)
2418 c->data.http.state = stream->txn->req.msg_state;
2419 else
2420 c->data.http.state = stream->txn->rsp.msg_state;
2421 break;
2422 default:
2423 break;
2424 }
2425}
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002426
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01002427/* This function is called after the Lua execution. it
2428 * returns true if the parser state is consistent, otherwise,
2429 * it return false.
2430 *
2431 * In HTTP mode, the parser state must be in the same state
2432 * or greater when we exit the function. Even if we do a
2433 * control yield. This prevent to break the HTTP message
2434 * from the Lua code.
2435 */
2436static inline int consistency_check(struct stream *stream, int opt, struct hlua_consistency *c)
2437{
2438 if (c->mode != stream->be->mode)
2439 return 0;
2440
2441 switch (c->mode) {
2442 case PR_MODE_HTTP:
2443 if (c->data.http.dir != (opt & SMP_OPT_DIR))
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002444 return 0;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01002445 if (c->data.http.dir == SMP_OPT_DIR_REQ)
2446 return stream->txn->req.msg_state >= c->data.http.state;
2447 else
2448 return stream->txn->rsp.msg_state >= c->data.http.state;
2449 default:
2450 return 1;
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002451 }
2452 return 1;
2453}
2454
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002455/* Returns the struct hlua_channel join to the class channel in the
2456 * stack entry "ud" or throws an argument error.
2457 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002458__LJMP static struct channel *hlua_checkchannel(lua_State *L, int ud)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002459{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002460 return MAY_LJMP(hlua_checkudata(L, ud, class_channel_ref));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002461}
2462
Willy Tarreau47860ed2015-03-10 14:07:50 +01002463/* Pushes the channel onto the top of the stack. If the stask does not have a
2464 * free slots, the function fails and returns 0;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002465 */
Willy Tarreau2a71af42015-03-10 13:51:50 +01002466static int hlua_channel_new(lua_State *L, struct channel *channel)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002467{
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002468 /* Check stack size. */
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002469 if (!lua_checkstack(L, 3))
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002470 return 0;
2471
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002472 lua_newtable(L);
Willy Tarreau47860ed2015-03-10 14:07:50 +01002473 lua_pushlightuserdata(L, channel);
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01002474 lua_rawseti(L, -2, 0);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002475
2476 /* Pop a class sesison metatable and affect it to the userdata. */
2477 lua_rawgeti(L, LUA_REGISTRYINDEX, class_channel_ref);
2478 lua_setmetatable(L, -2);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002479 return 1;
2480}
2481
2482/* Duplicate all the data present in the input channel and put it
2483 * in a string LUA variables. Returns -1 and push a nil value in
2484 * the stack if the channel is closed and all the data are consumed,
2485 * returns 0 if no data are available, otherwise it returns the length
2486 * of the builded string.
2487 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002488static inline int _hlua_channel_dup(struct channel *chn, lua_State *L)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002489{
2490 char *blk1;
2491 char *blk2;
2492 int len1;
2493 int len2;
2494 int ret;
2495 luaL_Buffer b;
2496
Willy Tarreau47860ed2015-03-10 14:07:50 +01002497 ret = bi_getblk_nc(chn, &blk1, &len1, &blk2, &len2);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002498 if (unlikely(ret == 0))
2499 return 0;
2500
2501 if (unlikely(ret < 0)) {
2502 lua_pushnil(L);
2503 return -1;
2504 }
2505
2506 luaL_buffinit(L, &b);
2507 luaL_addlstring(&b, blk1, len1);
2508 if (unlikely(ret == 2))
2509 luaL_addlstring(&b, blk2, len2);
2510 luaL_pushresult(&b);
2511
2512 if (unlikely(ret == 2))
2513 return len1 + len2;
2514 return len1;
2515}
2516
2517/* "_hlua_channel_dup" wrapper. If no data are available, it returns
2518 * a yield. This function keep the data in the buffer.
2519 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002520__LJMP static int hlua_channel_dup_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002521{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002522 struct channel *chn;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002523
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002524 chn = MAY_LJMP(hlua_checkchannel(L, 1));
2525
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002526 if (_hlua_channel_dup(chn, L) == 0)
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002527 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_dup_yield, TICK_ETERNITY, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002528 return 1;
2529}
2530
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002531/* Check arguments for the function "hlua_channel_dup_yield". */
2532__LJMP static int hlua_channel_dup(lua_State *L)
2533{
2534 MAY_LJMP(check_args(L, 1, "dup"));
2535 MAY_LJMP(hlua_checkchannel(L, 1));
2536 return MAY_LJMP(hlua_channel_dup_yield(L, 0, 0));
2537}
2538
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002539/* "_hlua_channel_dup" wrapper. If no data are available, it returns
2540 * a yield. This function consumes the data in the buffer. It returns
2541 * a string containing the data or a nil pointer if no data are available
2542 * and the channel is closed.
2543 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002544__LJMP static int hlua_channel_get_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002545{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002546 struct channel *chn;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002547 int ret;
2548
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002549 chn = MAY_LJMP(hlua_checkchannel(L, 1));
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002550
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002551 ret = _hlua_channel_dup(chn, L);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002552 if (unlikely(ret == 0))
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002553 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_get_yield, TICK_ETERNITY, 0));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002554
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002555 if (unlikely(ret == -1))
2556 return 1;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002557
Willy Tarreau47860ed2015-03-10 14:07:50 +01002558 chn->buf->i -= ret;
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002559 hlua_resynchonize_proto(chn_strm(chn), !!(chn->flags & CF_ISRESP));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002560 return 1;
2561}
2562
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002563/* Check arguments for the fucntion "hlua_channel_get_yield". */
2564__LJMP static int hlua_channel_get(lua_State *L)
2565{
2566 MAY_LJMP(check_args(L, 1, "get"));
2567 MAY_LJMP(hlua_checkchannel(L, 1));
2568 return MAY_LJMP(hlua_channel_get_yield(L, 0, 0));
2569}
2570
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002571/* This functions consumes and returns one line. If the channel is closed,
2572 * and the last data does not contains a final '\n', the data are returned
2573 * without the final '\n'. When no more data are avalaible, it returns nil
2574 * value.
2575 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002576__LJMP static int hlua_channel_getline_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002577{
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002578 char *blk1;
2579 char *blk2;
2580 int len1;
2581 int len2;
2582 int len;
Willy Tarreau47860ed2015-03-10 14:07:50 +01002583 struct channel *chn;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002584 int ret;
2585 luaL_Buffer b;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002586
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002587 chn = MAY_LJMP(hlua_checkchannel(L, 1));
2588
Willy Tarreau47860ed2015-03-10 14:07:50 +01002589 ret = bi_getline_nc(chn, &blk1, &len1, &blk2, &len2);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002590 if (ret == 0)
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002591 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_getline_yield, TICK_ETERNITY, 0));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002592
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002593 if (ret == -1) {
2594 lua_pushnil(L);
2595 return 1;
2596 }
2597
2598 luaL_buffinit(L, &b);
2599 luaL_addlstring(&b, blk1, len1);
2600 len = len1;
2601 if (unlikely(ret == 2)) {
2602 luaL_addlstring(&b, blk2, len2);
2603 len += len2;
2604 }
2605 luaL_pushresult(&b);
Willy Tarreau47860ed2015-03-10 14:07:50 +01002606 buffer_replace2(chn->buf, chn->buf->p, chn->buf->p + len, NULL, 0);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002607 hlua_resynchonize_proto(chn_strm(chn), !!(chn->flags & CF_ISRESP));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002608 return 1;
2609}
2610
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002611/* Check arguments for the fucntion "hlua_channel_getline_yield". */
2612__LJMP static int hlua_channel_getline(lua_State *L)
2613{
2614 MAY_LJMP(check_args(L, 1, "getline"));
2615 MAY_LJMP(hlua_checkchannel(L, 1));
2616 return MAY_LJMP(hlua_channel_getline_yield(L, 0, 0));
2617}
2618
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002619/* This function takes a string as input, and append it at the
2620 * input side of channel. If the data is too big, but a space
2621 * is probably available after sending some data, the function
2622 * yield. If the data is bigger than the buffer, or if the
2623 * channel is closed, it returns -1. otherwise, it returns the
2624 * amount of data writed.
2625 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002626__LJMP static int hlua_channel_append_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002627{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002628 struct channel *chn = MAY_LJMP(hlua_checkchannel(L, 1));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002629 size_t len;
2630 const char *str = MAY_LJMP(luaL_checklstring(L, 2, &len));
2631 int l = MAY_LJMP(luaL_checkinteger(L, 3));
2632 int ret;
2633 int max;
2634
Christopher Fauleta73e59b2016-12-09 17:30:18 +01002635 /* Check if the buffer is avalaible because HAProxy doesn't allocate
2636 * the request buffer if its not required.
2637 */
2638 if (chn->buf->size == 0) {
2639 si_applet_cant_put(chn_prod(chn));
2640 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_append_yield, TICK_ETERNITY, 0));
2641 }
2642
Willy Tarreau47860ed2015-03-10 14:07:50 +01002643 max = channel_recv_limit(chn) - buffer_len(chn->buf);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002644 if (max > len - l)
2645 max = len - l;
2646
Willy Tarreau47860ed2015-03-10 14:07:50 +01002647 ret = bi_putblk(chn, str + l, max);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002648 if (ret == -2 || ret == -3) {
2649 lua_pushinteger(L, -1);
2650 return 1;
2651 }
Willy Tarreaubc18da12015-03-13 14:00:47 +01002652 if (ret == -1) {
2653 chn->flags |= CF_WAKE_WRITE;
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002654 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_append_yield, TICK_ETERNITY, 0));
Willy Tarreaubc18da12015-03-13 14:00:47 +01002655 }
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002656 l += ret;
2657 lua_pop(L, 1);
2658 lua_pushinteger(L, l);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02002659 hlua_resynchonize_proto(chn_strm(chn), !!(chn->flags & CF_ISRESP));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002660
Willy Tarreau47860ed2015-03-10 14:07:50 +01002661 max = channel_recv_limit(chn) - buffer_len(chn->buf);
2662 if (max == 0 && chn->buf->o == 0) {
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002663 /* There are no space avalaible, and the output buffer is empty.
2664 * in this case, we cannot add more data, so we cannot yield,
2665 * we return the amount of copyied data.
2666 */
2667 return 1;
2668 }
2669 if (l < len)
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002670 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_append_yield, TICK_ETERNITY, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002671 return 1;
2672}
2673
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002674/* just a wrapper of "hlua_channel_append_yield". It returns the length
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002675 * of the writed string, or -1 if the channel is closed or if the
2676 * buffer size is too little for the data.
2677 */
2678__LJMP static int hlua_channel_append(lua_State *L)
2679{
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002680 size_t len;
2681
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002682 MAY_LJMP(check_args(L, 2, "append"));
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002683 MAY_LJMP(hlua_checkchannel(L, 1));
2684 MAY_LJMP(luaL_checklstring(L, 2, &len));
2685 MAY_LJMP(luaL_checkinteger(L, 3));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002686 lua_pushinteger(L, 0);
2687
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002688 return MAY_LJMP(hlua_channel_append_yield(L, 0, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002689}
2690
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002691/* just a wrapper of "hlua_channel_append_yield". This wrapper starts
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002692 * his process by cleaning the buffer. The result is a replacement
2693 * of the current data. It returns the length of the writed string,
2694 * or -1 if the channel is closed or if the buffer size is too
2695 * little for the data.
2696 */
2697__LJMP static int hlua_channel_set(lua_State *L)
2698{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002699 struct channel *chn;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002700
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002701 MAY_LJMP(check_args(L, 2, "set"));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002702 chn = MAY_LJMP(hlua_checkchannel(L, 1));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002703 lua_pushinteger(L, 0);
2704
Willy Tarreau47860ed2015-03-10 14:07:50 +01002705 chn->buf->i = 0;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002706
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002707 return MAY_LJMP(hlua_channel_append_yield(L, 0, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002708}
2709
2710/* Append data in the output side of the buffer. This data is immediatly
2711 * sent. The fcuntion returns the ammount of data writed. If the buffer
2712 * cannot contains the data, the function yield. The function returns -1
2713 * if the channel is closed.
2714 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002715__LJMP static int hlua_channel_send_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002716{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002717 struct channel *chn = MAY_LJMP(hlua_checkchannel(L, 1));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002718 size_t len;
2719 const char *str = MAY_LJMP(luaL_checklstring(L, 2, &len));
2720 int l = MAY_LJMP(luaL_checkinteger(L, 3));
2721 int max;
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01002722 struct hlua *hlua = hlua_gethlua(L);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002723
Willy Tarreau47860ed2015-03-10 14:07:50 +01002724 if (unlikely(channel_output_closed(chn))) {
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002725 lua_pushinteger(L, -1);
2726 return 1;
2727 }
2728
Thierry FOURNIER3e3a6082015-03-05 17:06:12 +01002729 /* Check if the buffer is avalaible because HAProxy doesn't allocate
2730 * the request buffer if its not required.
2731 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002732 if (chn->buf->size == 0) {
Christopher Fauleta73e59b2016-12-09 17:30:18 +01002733 si_applet_cant_put(chn_prod(chn));
2734 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_send_yield, TICK_ETERNITY, 0));
Thierry FOURNIER3e3a6082015-03-05 17:06:12 +01002735 }
2736
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002737 /* the writed data will be immediatly sent, so we can check
2738 * the avalaible space without taking in account the reserve.
2739 * The reserve is guaranted for the processing of incoming
2740 * data, because the buffer will be flushed.
2741 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002742 max = chn->buf->size - buffer_len(chn->buf);
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002743
2744 /* If there are no space avalaible, and the output buffer is empty.
2745 * in this case, we cannot add more data, so we cannot yield,
2746 * we return the amount of copyied data.
2747 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002748 if (max == 0 && chn->buf->o == 0)
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002749 return 1;
2750
2751 /* Adjust the real required length. */
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002752 if (max > len - l)
2753 max = len - l;
2754
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002755 /* The buffer avalaible size may be not contiguous. This test
2756 * detects a non contiguous buffer and realign it.
2757 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002758 if (bi_space_for_replace(chn->buf) < max)
2759 buffer_slow_realign(chn->buf);
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002760
2761 /* Copy input data in the buffer. */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002762 max = buffer_replace2(chn->buf, chn->buf->p, chn->buf->p, str + l, max);
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002763
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002764 /* buffer replace considers that the input part is filled.
2765 * so, I must forward these new data in the output part.
2766 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002767 b_adv(chn->buf, max);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002768
2769 l += max;
2770 lua_pop(L, 1);
2771 lua_pushinteger(L, l);
2772
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002773 /* If there are no space avalaible, and the output buffer is empty.
2774 * in this case, we cannot add more data, so we cannot yield,
2775 * we return the amount of copyied data.
2776 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002777 max = chn->buf->size - buffer_len(chn->buf);
2778 if (max == 0 && chn->buf->o == 0)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002779 return 1;
Thierry FOURNIERdeb5d732015-03-06 01:07:45 +01002780
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01002781 if (l < len) {
2782 /* If we are waiting for space in the response buffer, we
2783 * must set the flag WAKERESWR. This flag required the task
2784 * wake up if any activity is detected on the response buffer.
2785 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002786 if (chn->flags & CF_ISRESP)
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01002787 HLUA_SET_WAKERESWR(hlua);
Thierry FOURNIER53e08ec2015-03-06 00:35:53 +01002788 else
2789 HLUA_SET_WAKEREQWR(hlua);
2790 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_send_yield, TICK_ETERNITY, 0));
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01002791 }
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002792
2793 return 1;
2794}
2795
2796/* Just a wraper of "_hlua_channel_send". This wrapper permits
2797 * yield the LUA process, and resume it without checking the
2798 * input arguments.
2799 */
2800__LJMP static int hlua_channel_send(lua_State *L)
2801{
2802 MAY_LJMP(check_args(L, 2, "send"));
2803 lua_pushinteger(L, 0);
2804
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002805 return MAY_LJMP(hlua_channel_send_yield(L, 0, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002806}
2807
2808/* This function forward and amount of butes. The data pass from
2809 * the input side of the buffer to the output side, and can be
2810 * forwarded. This function never fails.
2811 *
2812 * The Lua function takes an amount of bytes to be forwarded in
2813 * imput. It returns the number of bytes forwarded.
2814 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002815__LJMP static int hlua_channel_forward_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002816{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002817 struct channel *chn;
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002818 int len;
2819 int l;
2820 int max;
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01002821 struct hlua *hlua = hlua_gethlua(L);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002822
2823 chn = MAY_LJMP(hlua_checkchannel(L, 1));
2824 len = MAY_LJMP(luaL_checkinteger(L, 2));
2825 l = MAY_LJMP(luaL_checkinteger(L, -1));
2826
2827 max = len - l;
Willy Tarreau47860ed2015-03-10 14:07:50 +01002828 if (max > chn->buf->i)
2829 max = chn->buf->i;
2830 channel_forward(chn, max);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002831 l += max;
2832
2833 lua_pop(L, 1);
2834 lua_pushinteger(L, l);
2835
2836 /* Check if it miss bytes to forward. */
2837 if (l < len) {
2838 /* The the input channel or the output channel are closed, we
2839 * must return the amount of data forwarded.
2840 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002841 if (channel_input_closed(chn) || channel_output_closed(chn))
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002842 return 1;
2843
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01002844 /* If we are waiting for space data in the response buffer, we
2845 * must set the flag WAKERESWR. This flag required the task
2846 * wake up if any activity is detected on the response buffer.
2847 */
Willy Tarreau47860ed2015-03-10 14:07:50 +01002848 if (chn->flags & CF_ISRESP)
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01002849 HLUA_SET_WAKERESWR(hlua);
Thierry FOURNIER53e08ec2015-03-06 00:35:53 +01002850 else
2851 HLUA_SET_WAKEREQWR(hlua);
Thierry FOURNIERef6a2112015-03-05 17:45:34 +01002852
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002853 /* Otherwise, we can yield waiting for new data in the inpout side. */
Thierry FOURNIER4abd3ae2015-03-03 17:29:06 +01002854 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_forward_yield, TICK_ETERNITY, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002855 }
2856
2857 return 1;
2858}
2859
2860/* Just check the input and prepare the stack for the previous
2861 * function "hlua_channel_forward_yield"
2862 */
2863__LJMP static int hlua_channel_forward(lua_State *L)
2864{
2865 MAY_LJMP(check_args(L, 2, "forward"));
2866 MAY_LJMP(hlua_checkchannel(L, 1));
2867 MAY_LJMP(luaL_checkinteger(L, 2));
2868
2869 lua_pushinteger(L, 0);
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01002870 return MAY_LJMP(hlua_channel_forward_yield(L, 0, 0));
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002871}
2872
2873/* Just returns the number of bytes available in the input
2874 * side of the buffer. This function never fails.
2875 */
2876__LJMP static int hlua_channel_get_in_len(lua_State *L)
2877{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002878 struct channel *chn;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002879
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002880 MAY_LJMP(check_args(L, 1, "get_in_len"));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002881 chn = MAY_LJMP(hlua_checkchannel(L, 1));
Willy Tarreau47860ed2015-03-10 14:07:50 +01002882 lua_pushinteger(L, chn->buf->i);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002883 return 1;
2884}
2885
Thierry FOURNIER / OZON.IO65192f32016-11-07 15:28:40 +01002886/* Returns true if the channel is full. */
2887__LJMP static int hlua_channel_is_full(lua_State *L)
2888{
2889 struct channel *chn;
2890 int rem;
2891
2892 MAY_LJMP(check_args(L, 1, "is_full"));
2893 chn = MAY_LJMP(hlua_checkchannel(L, 1));
2894
2895 rem = chn->buf->size;
2896 rem -= chn->buf->o; /* Output size */
2897 rem -= chn->buf->i; /* Input size */
2898 rem -= global.tune.maxrewrite; /* Rewrite reserved size */
2899
2900 lua_pushboolean(L, rem <= 0);
2901 return 1;
2902}
2903
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002904/* Just returns the number of bytes available in the output
2905 * side of the buffer. This function never fails.
2906 */
2907__LJMP static int hlua_channel_get_out_len(lua_State *L)
2908{
Willy Tarreau47860ed2015-03-10 14:07:50 +01002909 struct channel *chn;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002910
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002911 MAY_LJMP(check_args(L, 1, "get_out_len"));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01002912 chn = MAY_LJMP(hlua_checkchannel(L, 1));
Willy Tarreau47860ed2015-03-10 14:07:50 +01002913 lua_pushinteger(L, chn->buf->o);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01002914 return 1;
2915}
2916
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01002917/*
2918 *
2919 *
2920 * Class Fetches
2921 *
2922 *
2923 */
2924
2925/* Returns a struct hlua_session if the stack entry "ud" is
Willy Tarreau87b09662015-04-03 00:22:06 +02002926 * a class stream, otherwise it throws an error.
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01002927 */
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01002928__LJMP static struct hlua_smp *hlua_checkfetches(lua_State *L, int ud)
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01002929{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002930 return MAY_LJMP(hlua_checkudata(L, ud, class_fetches_ref));
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01002931}
2932
2933/* This function creates and push in the stack a fetch object according
2934 * with a current TXN.
2935 */
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01002936static int hlua_fetches_new(lua_State *L, struct hlua_txn *txn, unsigned int flags)
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01002937{
Willy Tarreau7073c472015-04-06 11:15:40 +02002938 struct hlua_smp *hsmp;
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01002939
2940 /* Check stack size. */
2941 if (!lua_checkstack(L, 3))
2942 return 0;
2943
2944 /* Create the object: obj[0] = userdata.
2945 * Note that the base of the Fetches object is the
2946 * transaction object.
2947 */
2948 lua_newtable(L);
Willy Tarreau7073c472015-04-06 11:15:40 +02002949 hsmp = lua_newuserdata(L, sizeof(*hsmp));
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01002950 lua_rawseti(L, -2, 0);
2951
Willy Tarreau7073c472015-04-06 11:15:40 +02002952 hsmp->s = txn->s;
2953 hsmp->p = txn->p;
Thierry FOURNIERc4eebc82015-11-02 10:01:59 +01002954 hsmp->dir = txn->dir;
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01002955 hsmp->flags = flags;
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01002956
2957 /* Pop a class sesison metatable and affect it to the userdata. */
2958 lua_rawgeti(L, LUA_REGISTRYINDEX, class_fetches_ref);
2959 lua_setmetatable(L, -2);
2960
2961 return 1;
2962}
2963
2964/* This function is an LUA binding. It is called with each sample-fetch.
2965 * It uses closure argument to store the associated sample-fetch. It
2966 * returns only one argument or throws an error. An error is thrown
2967 * only if an error is encountered during the argument parsing. If
2968 * the "sample-fetch" function fails, nil is returned.
2969 */
2970__LJMP static int hlua_run_sample_fetch(lua_State *L)
2971{
Willy Tarreaub2ccb562015-04-06 11:11:15 +02002972 struct hlua_smp *hsmp;
Willy Tarreau2ec22742015-03-10 14:27:20 +01002973 struct sample_fetch *f;
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01002974 struct arg args[ARGM_NBARGS + 1];
2975 int i;
2976 struct sample smp;
2977
2978 /* Get closure arguments. */
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002979 f = lua_touserdata(L, lua_upvalueindex(1));
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01002980
2981 /* Get traditionnal arguments. */
Willy Tarreaub2ccb562015-04-06 11:11:15 +02002982 hsmp = MAY_LJMP(hlua_checkfetches(L, 1));
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01002983
Thierry FOURNIERca988662015-12-20 18:43:03 +01002984 /* Check execution authorization. */
2985 if (f->use & SMP_USE_HTTP_ANY &&
2986 !(hsmp->flags & HLUA_F_MAY_USE_HTTP)) {
2987 lua_pushfstring(L, "the sample-fetch '%s' needs an HTTP parser which "
2988 "is not available in Lua services", f->kw);
2989 WILL_LJMP(lua_error(L));
2990 }
2991
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01002992 /* Get extra arguments. */
2993 for (i = 0; i < lua_gettop(L) - 1; i++) {
2994 if (i >= ARGM_NBARGS)
2995 break;
2996 hlua_lua2arg(L, i + 2, &args[i]);
2997 }
2998 args[i].type = ARGT_STOP;
David Carlierabdb00f2016-04-27 16:14:50 +01002999 args[i].data.str.str = NULL;
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003000
3001 /* Check arguments. */
Willy Tarreaub2ccb562015-04-06 11:11:15 +02003002 MAY_LJMP(hlua_lua2arg_check(L, 2, args, f->arg_mask, hsmp->p));
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003003
3004 /* Run the special args checker. */
Willy Tarreau2ec22742015-03-10 14:27:20 +01003005 if (f->val_args && !f->val_args(args, NULL)) {
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003006 lua_pushfstring(L, "error in arguments");
3007 WILL_LJMP(lua_error(L));
3008 }
3009
3010 /* Initialise the sample. */
3011 memset(&smp, 0, sizeof(smp));
3012
3013 /* Run the sample fetch process. */
Willy Tarreau1777ea62016-03-10 16:15:46 +01003014 smp_set_owner(&smp, hsmp->p, hsmp->s->sess, hsmp->s, hsmp->dir & SMP_OPT_DIR);
Thierry FOURNIER0786d052015-05-11 15:42:45 +02003015 if (!f->process(args, &smp, f->kw, f->private)) {
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003016 if (hsmp->flags & HLUA_F_AS_STRING)
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003017 lua_pushstring(L, "");
3018 else
3019 lua_pushnil(L);
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003020 return 1;
3021 }
3022
3023 /* Convert the returned sample in lua value. */
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003024 if (hsmp->flags & HLUA_F_AS_STRING)
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003025 hlua_smp2lua_str(L, &smp);
3026 else
3027 hlua_smp2lua(L, &smp);
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01003028 return 1;
3029}
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01003030
3031/*
3032 *
3033 *
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003034 * Class Converters
3035 *
3036 *
3037 */
3038
3039/* Returns a struct hlua_session if the stack entry "ud" is
Willy Tarreau87b09662015-04-03 00:22:06 +02003040 * a class stream, otherwise it throws an error.
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003041 */
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003042__LJMP static struct hlua_smp *hlua_checkconverters(lua_State *L, int ud)
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003043{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003044 return MAY_LJMP(hlua_checkudata(L, ud, class_converters_ref));
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003045}
3046
3047/* This function creates and push in the stack a Converters object
3048 * according with a current TXN.
3049 */
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003050static int hlua_converters_new(lua_State *L, struct hlua_txn *txn, unsigned int flags)
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003051{
Willy Tarreau7073c472015-04-06 11:15:40 +02003052 struct hlua_smp *hsmp;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003053
3054 /* Check stack size. */
3055 if (!lua_checkstack(L, 3))
3056 return 0;
3057
3058 /* Create the object: obj[0] = userdata.
3059 * Note that the base of the Converters object is the
3060 * same than the TXN object.
3061 */
3062 lua_newtable(L);
Willy Tarreau7073c472015-04-06 11:15:40 +02003063 hsmp = lua_newuserdata(L, sizeof(*hsmp));
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003064 lua_rawseti(L, -2, 0);
3065
Willy Tarreau7073c472015-04-06 11:15:40 +02003066 hsmp->s = txn->s;
3067 hsmp->p = txn->p;
Thierry FOURNIERc4eebc82015-11-02 10:01:59 +01003068 hsmp->dir = txn->dir;
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003069 hsmp->flags = flags;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003070
Willy Tarreau87b09662015-04-03 00:22:06 +02003071 /* Pop a class stream metatable and affect it to the table. */
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003072 lua_rawgeti(L, LUA_REGISTRYINDEX, class_converters_ref);
3073 lua_setmetatable(L, -2);
3074
3075 return 1;
3076}
3077
3078/* This function is an LUA binding. It is called with each converter.
3079 * It uses closure argument to store the associated converter. It
3080 * returns only one argument or throws an error. An error is thrown
3081 * only if an error is encountered during the argument parsing. If
3082 * the converter function function fails, nil is returned.
3083 */
3084__LJMP static int hlua_run_sample_conv(lua_State *L)
3085{
Willy Tarreauda5f1082015-04-06 11:17:13 +02003086 struct hlua_smp *hsmp;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003087 struct sample_conv *conv;
3088 struct arg args[ARGM_NBARGS + 1];
3089 int i;
3090 struct sample smp;
3091
3092 /* Get closure arguments. */
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003093 conv = lua_touserdata(L, lua_upvalueindex(1));
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003094
3095 /* Get traditionnal arguments. */
Willy Tarreauda5f1082015-04-06 11:17:13 +02003096 hsmp = MAY_LJMP(hlua_checkconverters(L, 1));
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003097
3098 /* Get extra arguments. */
3099 for (i = 0; i < lua_gettop(L) - 2; i++) {
3100 if (i >= ARGM_NBARGS)
3101 break;
3102 hlua_lua2arg(L, i + 3, &args[i]);
3103 }
3104 args[i].type = ARGT_STOP;
David Carlierabdb00f2016-04-27 16:14:50 +01003105 args[i].data.str.str = NULL;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003106
3107 /* Check arguments. */
Willy Tarreauda5f1082015-04-06 11:17:13 +02003108 MAY_LJMP(hlua_lua2arg_check(L, 3, args, conv->arg_mask, hsmp->p));
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003109
3110 /* Run the special args checker. */
3111 if (conv->val_args && !conv->val_args(args, conv, "", 0, NULL)) {
3112 hlua_pusherror(L, "error in arguments");
3113 WILL_LJMP(lua_error(L));
3114 }
3115
3116 /* Initialise the sample. */
3117 if (!hlua_lua2smp(L, 2, &smp)) {
3118 hlua_pusherror(L, "error in the input argument");
3119 WILL_LJMP(lua_error(L));
3120 }
3121
Willy Tarreau1777ea62016-03-10 16:15:46 +01003122 smp_set_owner(&smp, hsmp->p, hsmp->s->sess, hsmp->s, hsmp->dir & SMP_OPT_DIR);
3123
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003124 /* Apply expected cast. */
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02003125 if (!sample_casts[smp.data.type][conv->in_type]) {
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003126 hlua_pusherror(L, "invalid input argument: cannot cast '%s' to '%s'",
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02003127 smp_to_type[smp.data.type], smp_to_type[conv->in_type]);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003128 WILL_LJMP(lua_error(L));
3129 }
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02003130 if (sample_casts[smp.data.type][conv->in_type] != c_none &&
3131 !sample_casts[smp.data.type][conv->in_type](&smp)) {
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003132 hlua_pusherror(L, "error during the input argument casting");
3133 WILL_LJMP(lua_error(L));
3134 }
3135
3136 /* Run the sample conversion process. */
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02003137 if (!conv->process(args, &smp, conv->private)) {
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003138 if (hsmp->flags & HLUA_F_AS_STRING)
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003139 lua_pushstring(L, "");
3140 else
Willy Tarreaua678b432015-08-28 10:14:59 +02003141 lua_pushnil(L);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003142 return 1;
3143 }
3144
3145 /* Convert the returned sample in lua value. */
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003146 if (hsmp->flags & HLUA_F_AS_STRING)
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01003147 hlua_smp2lua_str(L, &smp);
3148 else
3149 hlua_smp2lua(L, &smp);
Willy Tarreaua678b432015-08-28 10:14:59 +02003150 return 1;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003151}
3152
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003153/*
3154 *
3155 *
3156 * Class AppletTCP
3157 *
3158 *
3159 */
3160
3161/* Returns a struct hlua_txn if the stack entry "ud" is
3162 * a class stream, otherwise it throws an error.
3163 */
3164__LJMP static struct hlua_appctx *hlua_checkapplet_tcp(lua_State *L, int ud)
3165{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003166 return MAY_LJMP(hlua_checkudata(L, ud, class_applet_tcp_ref));
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003167}
3168
3169/* This function creates and push in the stack an Applet object
3170 * according with a current TXN.
3171 */
3172static int hlua_applet_tcp_new(lua_State *L, struct appctx *ctx)
3173{
3174 struct hlua_appctx *appctx;
3175 struct stream_interface *si = ctx->owner;
3176 struct stream *s = si_strm(si);
3177 struct proxy *p = s->be;
3178
3179 /* Check stack size. */
3180 if (!lua_checkstack(L, 3))
3181 return 0;
3182
3183 /* Create the object: obj[0] = userdata.
3184 * Note that the base of the Converters object is the
3185 * same than the TXN object.
3186 */
3187 lua_newtable(L);
3188 appctx = lua_newuserdata(L, sizeof(*appctx));
3189 lua_rawseti(L, -2, 0);
3190 appctx->appctx = ctx;
3191 appctx->htxn.s = s;
3192 appctx->htxn.p = p;
3193
3194 /* Create the "f" field that contains a list of fetches. */
3195 lua_pushstring(L, "f");
3196 if (!hlua_fetches_new(L, &appctx->htxn, 0))
3197 return 0;
3198 lua_settable(L, -3);
3199
3200 /* Create the "sf" field that contains a list of stringsafe fetches. */
3201 lua_pushstring(L, "sf");
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003202 if (!hlua_fetches_new(L, &appctx->htxn, HLUA_F_AS_STRING))
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003203 return 0;
3204 lua_settable(L, -3);
3205
3206 /* Create the "c" field that contains a list of converters. */
3207 lua_pushstring(L, "c");
3208 if (!hlua_converters_new(L, &appctx->htxn, 0))
3209 return 0;
3210 lua_settable(L, -3);
3211
3212 /* Create the "sc" field that contains a list of stringsafe converters. */
3213 lua_pushstring(L, "sc");
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003214 if (!hlua_converters_new(L, &appctx->htxn, HLUA_F_AS_STRING))
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003215 return 0;
3216 lua_settable(L, -3);
3217
3218 /* Pop a class stream metatable and affect it to the table. */
3219 lua_rawgeti(L, LUA_REGISTRYINDEX, class_applet_tcp_ref);
3220 lua_setmetatable(L, -2);
3221
3222 return 1;
3223}
3224
Thierry FOURNIER / OZON.IO4394a2c2016-12-12 12:31:54 +01003225__LJMP static int hlua_applet_tcp_set_var(lua_State *L)
3226{
3227 struct hlua_appctx *appctx;
3228 struct stream *s;
3229 const char *name;
3230 size_t len;
3231 struct sample smp;
3232
3233 MAY_LJMP(check_args(L, 3, "set_var"));
3234
3235 /* It is useles to retrieve the stream, but this function
3236 * runs only in a stream context.
3237 */
3238 appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3239 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3240 s = appctx->htxn.s;
3241
3242 /* Converts the third argument in a sample. */
3243 hlua_lua2smp(L, 3, &smp);
3244
3245 /* Store the sample in a variable. */
3246 smp_set_owner(&smp, s->be, s->sess, s, 0);
3247 vars_set_by_name(name, len, &smp);
3248 return 0;
3249}
3250
3251__LJMP static int hlua_applet_tcp_unset_var(lua_State *L)
3252{
3253 struct hlua_appctx *appctx;
3254 struct stream *s;
3255 const char *name;
3256 size_t len;
3257 struct sample smp;
3258
3259 MAY_LJMP(check_args(L, 2, "unset_var"));
3260
3261 /* It is useles to retrieve the stream, but this function
3262 * runs only in a stream context.
3263 */
3264 appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3265 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3266 s = appctx->htxn.s;
3267
3268 /* Unset the variable. */
3269 smp_set_owner(&smp, s->be, s->sess, s, 0);
3270 vars_unset_by_name(name, len, &smp);
3271 return 0;
3272}
3273
3274__LJMP static int hlua_applet_tcp_get_var(lua_State *L)
3275{
3276 struct hlua_appctx *appctx;
3277 struct stream *s;
3278 const char *name;
3279 size_t len;
3280 struct sample smp;
3281
3282 MAY_LJMP(check_args(L, 2, "get_var"));
3283
3284 /* It is useles to retrieve the stream, but this function
3285 * runs only in a stream context.
3286 */
3287 appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3288 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3289 s = appctx->htxn.s;
3290
3291 smp_set_owner(&smp, s->be, s->sess, s, 0);
3292 if (!vars_get_by_name(name, len, &smp)) {
3293 lua_pushnil(L);
3294 return 1;
3295 }
3296
3297 return hlua_smp2lua(L, &smp);
3298}
3299
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003300__LJMP static int hlua_applet_tcp_set_priv(lua_State *L)
3301{
3302 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3303 struct stream *s = appctx->htxn.s;
Thierry FOURNIER3b0a6d42016-12-16 08:48:32 +01003304 struct hlua *hlua;
3305
3306 /* Note that this hlua struct is from the session and not from the applet. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01003307 if (!s->hlua)
3308 return 0;
3309 hlua = s->hlua;
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003310
3311 MAY_LJMP(check_args(L, 2, "set_priv"));
3312
3313 /* Remove previous value. */
3314 if (hlua->Mref != -1)
3315 luaL_unref(L, hlua->Mref, LUA_REGISTRYINDEX);
3316
3317 /* Get and store new value. */
3318 lua_pushvalue(L, 2); /* Copy the element 2 at the top of the stack. */
3319 hlua->Mref = luaL_ref(L, LUA_REGISTRYINDEX); /* pop the previously pushed value. */
3320
3321 return 0;
3322}
3323
3324__LJMP static int hlua_applet_tcp_get_priv(lua_State *L)
3325{
3326 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3327 struct stream *s = appctx->htxn.s;
Thierry FOURNIER3b0a6d42016-12-16 08:48:32 +01003328 struct hlua *hlua;
3329
3330 /* Note that this hlua struct is from the session and not from the applet. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01003331 if (!s->hlua) {
3332 lua_pushnil(L);
3333 return 1;
3334 }
3335 hlua = s->hlua;
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003336
3337 /* Push configuration index in the stack. */
3338 lua_rawgeti(L, LUA_REGISTRYINDEX, hlua->Mref);
3339
3340 return 1;
3341}
3342
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02003343/* If expected data not yet available, it returns a yield. This function
3344 * consumes the data in the buffer. It returns a string containing the
3345 * data. This string can be empty.
3346 */
3347__LJMP static int hlua_applet_tcp_getline_yield(lua_State *L, int status, lua_KContext ctx)
3348{
3349 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3350 struct stream_interface *si = appctx->appctx->owner;
3351 int ret;
3352 char *blk1;
3353 int len1;
3354 char *blk2;
3355 int len2;
3356
3357 /* Read the maximum amount of data avalaible. */
3358 ret = bo_getline_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
3359
3360 /* Data not yet avalaible. return yield. */
3361 if (ret == 0) {
3362 si_applet_cant_get(si);
3363 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_getline_yield, TICK_ETERNITY, 0));
3364 }
3365
3366 /* End of data: commit the total strings and return. */
3367 if (ret < 0) {
3368 luaL_pushresult(&appctx->b);
3369 return 1;
3370 }
3371
3372 /* Ensure that the block 2 length is usable. */
3373 if (ret == 1)
3374 len2 = 0;
3375
3376 /* dont check the max length read and dont check. */
3377 luaL_addlstring(&appctx->b, blk1, len1);
3378 luaL_addlstring(&appctx->b, blk2, len2);
3379
3380 /* Consume input channel output buffer data. */
3381 bo_skip(si_oc(si), len1 + len2);
3382 luaL_pushresult(&appctx->b);
3383 return 1;
3384}
3385
3386/* Check arguments for the fucntion "hlua_channel_get_yield". */
3387__LJMP static int hlua_applet_tcp_getline(lua_State *L)
3388{
3389 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3390
3391 /* Initialise the string catenation. */
3392 luaL_buffinit(L, &appctx->b);
3393
3394 return MAY_LJMP(hlua_applet_tcp_getline_yield(L, 0, 0));
3395}
3396
3397/* If expected data not yet available, it returns a yield. This function
3398 * consumes the data in the buffer. It returns a string containing the
3399 * data. This string can be empty.
3400 */
3401__LJMP static int hlua_applet_tcp_recv_yield(lua_State *L, int status, lua_KContext ctx)
3402{
3403 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3404 struct stream_interface *si = appctx->appctx->owner;
3405 int len = MAY_LJMP(luaL_checkinteger(L, 2));
3406 int ret;
3407 char *blk1;
3408 int len1;
3409 char *blk2;
3410 int len2;
3411
3412 /* Read the maximum amount of data avalaible. */
3413 ret = bo_getblk_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
3414
3415 /* Data not yet avalaible. return yield. */
3416 if (ret == 0) {
3417 si_applet_cant_get(si);
3418 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_recv_yield, TICK_ETERNITY, 0));
3419 }
3420
3421 /* End of data: commit the total strings and return. */
3422 if (ret < 0) {
3423 luaL_pushresult(&appctx->b);
3424 return 1;
3425 }
3426
3427 /* Ensure that the block 2 length is usable. */
3428 if (ret == 1)
3429 len2 = 0;
3430
3431 if (len == -1) {
3432
3433 /* If len == -1, catenate all the data avalaile and
3434 * yield because we want to get all the data until
3435 * the end of data stream.
3436 */
3437 luaL_addlstring(&appctx->b, blk1, len1);
3438 luaL_addlstring(&appctx->b, blk2, len2);
3439 bo_skip(si_oc(si), len1 + len2);
3440 si_applet_cant_get(si);
3441 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_recv_yield, TICK_ETERNITY, 0));
3442
3443 } else {
3444
3445 /* Copy the fisrt block caping to the length required. */
3446 if (len1 > len)
3447 len1 = len;
3448 luaL_addlstring(&appctx->b, blk1, len1);
3449 len -= len1;
3450
3451 /* Copy the second block. */
3452 if (len2 > len)
3453 len2 = len;
3454 luaL_addlstring(&appctx->b, blk2, len2);
3455 len -= len2;
3456
3457 /* Consume input channel output buffer data. */
3458 bo_skip(si_oc(si), len1 + len2);
3459
3460 /* If we are no other data avalaible, yield waiting for new data. */
3461 if (len > 0) {
3462 lua_pushinteger(L, len);
3463 lua_replace(L, 2);
3464 si_applet_cant_get(si);
3465 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_recv_yield, TICK_ETERNITY, 0));
3466 }
3467
3468 /* return the result. */
3469 luaL_pushresult(&appctx->b);
3470 return 1;
3471 }
3472
3473 /* we never executes this */
3474 hlua_pusherror(L, "Lua: internal error");
3475 WILL_LJMP(lua_error(L));
3476 return 0;
3477}
3478
3479/* Check arguments for the fucntion "hlua_channel_get_yield". */
3480__LJMP static int hlua_applet_tcp_recv(lua_State *L)
3481{
3482 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3483 int len = -1;
3484
3485 if (lua_gettop(L) > 2)
3486 WILL_LJMP(luaL_error(L, "The 'recv' function requires between 1 and 2 arguments."));
3487 if (lua_gettop(L) >= 2) {
3488 len = MAY_LJMP(luaL_checkinteger(L, 2));
3489 lua_pop(L, 1);
3490 }
3491
3492 /* Confirm or set the required length */
3493 lua_pushinteger(L, len);
3494
3495 /* Initialise the string catenation. */
3496 luaL_buffinit(L, &appctx->b);
3497
3498 return MAY_LJMP(hlua_applet_tcp_recv_yield(L, 0, 0));
3499}
3500
3501/* Append data in the output side of the buffer. This data is immediatly
3502 * sent. The fcuntion returns the ammount of data writed. If the buffer
3503 * cannot contains the data, the function yield. The function returns -1
3504 * if the channel is closed.
3505 */
3506__LJMP static int hlua_applet_tcp_send_yield(lua_State *L, int status, lua_KContext ctx)
3507{
3508 size_t len;
3509 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3510 const char *str = MAY_LJMP(luaL_checklstring(L, 2, &len));
3511 int l = MAY_LJMP(luaL_checkinteger(L, 3));
3512 struct stream_interface *si = appctx->appctx->owner;
3513 struct channel *chn = si_ic(si);
3514 int max;
3515
3516 /* Get the max amount of data which can write as input in the channel. */
3517 max = channel_recv_max(chn);
3518 if (max > (len - l))
3519 max = len - l;
3520
3521 /* Copy data. */
3522 bi_putblk(chn, str + l, max);
3523
3524 /* update counters. */
3525 l += max;
3526 lua_pop(L, 1);
3527 lua_pushinteger(L, l);
3528
3529 /* If some data is not send, declares the situation to the
3530 * applet, and returns a yield.
3531 */
3532 if (l < len) {
3533 si_applet_cant_put(si);
3534 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_send_yield, TICK_ETERNITY, 0));
3535 }
3536
3537 return 1;
3538}
3539
3540/* Just a wraper of "hlua_applet_tcp_send_yield". This wrapper permits
3541 * yield the LUA process, and resume it without checking the
3542 * input arguments.
3543 */
3544__LJMP static int hlua_applet_tcp_send(lua_State *L)
3545{
3546 MAY_LJMP(check_args(L, 2, "send"));
3547 lua_pushinteger(L, 0);
3548
3549 return MAY_LJMP(hlua_applet_tcp_send_yield(L, 0, 0));
3550}
3551
Thierry FOURNIER594afe72015-03-10 23:58:30 +01003552/*
3553 *
3554 *
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003555 * Class AppletHTTP
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003556 *
3557 *
3558 */
3559
3560/* Returns a struct hlua_txn if the stack entry "ud" is
Willy Tarreau87b09662015-04-03 00:22:06 +02003561 * a class stream, otherwise it throws an error.
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003562 */
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003563__LJMP static struct hlua_appctx *hlua_checkapplet_http(lua_State *L, int ud)
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003564{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003565 return MAY_LJMP(hlua_checkudata(L, ud, class_applet_http_ref));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003566}
3567
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003568/* This function creates and push in the stack an Applet object
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003569 * according with a current TXN.
3570 */
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003571static int hlua_applet_http_new(lua_State *L, struct appctx *ctx)
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003572{
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003573 struct hlua_appctx *appctx;
Thierry FOURNIER841475e2015-12-11 17:10:09 +01003574 struct hlua_txn htxn;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003575 struct stream_interface *si = ctx->owner;
3576 struct stream *s = si_strm(si);
3577 struct proxy *px = s->be;
3578 struct http_txn *txn = s->txn;
3579 const char *path;
3580 const char *end;
3581 const char *p;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003582
3583 /* Check stack size. */
3584 if (!lua_checkstack(L, 3))
3585 return 0;
3586
3587 /* Create the object: obj[0] = userdata.
3588 * Note that the base of the Converters object is the
3589 * same than the TXN object.
3590 */
3591 lua_newtable(L);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003592 appctx = lua_newuserdata(L, sizeof(*appctx));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003593 lua_rawseti(L, -2, 0);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003594 appctx->appctx = ctx;
3595 appctx->appctx->ctx.hlua_apphttp.status = 200; /* Default status code returned. */
3596 appctx->htxn.s = s;
3597 appctx->htxn.p = px;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003598
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003599 /* Create the "f" field that contains a list of fetches. */
3600 lua_pushstring(L, "f");
3601 if (!hlua_fetches_new(L, &appctx->htxn, 0))
3602 return 0;
3603 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003604
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003605 /* Create the "sf" field that contains a list of stringsafe fetches. */
3606 lua_pushstring(L, "sf");
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003607 if (!hlua_fetches_new(L, &appctx->htxn, HLUA_F_AS_STRING))
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003608 return 0;
3609 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003610
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003611 /* Create the "c" field that contains a list of converters. */
3612 lua_pushstring(L, "c");
3613 if (!hlua_converters_new(L, &appctx->htxn, 0))
3614 return 0;
3615 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003616
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003617 /* Create the "sc" field that contains a list of stringsafe converters. */
3618 lua_pushstring(L, "sc");
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01003619 if (!hlua_converters_new(L, &appctx->htxn, HLUA_F_AS_STRING))
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003620 return 0;
3621 lua_settable(L, -3);
Willy Tarreaueee5b512015-04-03 23:46:31 +02003622
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003623 /* Stores the request method. */
3624 lua_pushstring(L, "method");
3625 lua_pushlstring(L, txn->req.chn->buf->p, txn->req.sl.rq.m_l);
3626 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003627
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003628 /* Stores the http version. */
3629 lua_pushstring(L, "version");
3630 lua_pushlstring(L, txn->req.chn->buf->p + txn->req.sl.rq.v, txn->req.sl.rq.v_l);
3631 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003632
Thierry FOURNIER841475e2015-12-11 17:10:09 +01003633 /* creates an array of headers. hlua_http_get_headers() crates and push
3634 * the array on the top of the stack.
3635 */
3636 lua_pushstring(L, "headers");
3637 htxn.s = s;
3638 htxn.p = px;
3639 htxn.dir = SMP_OPT_DIR_REQ;
3640 if (!hlua_http_get_headers(L, &htxn, &htxn.s->txn->req))
3641 return 0;
3642 lua_settable(L, -3);
3643
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003644 /* Get path and qs */
3645 path = http_get_path(txn);
3646 end = txn->req.chn->buf->p + txn->req.sl.rq.u + txn->req.sl.rq.u_l;
3647 p = path;
3648 while (p < end && *p != '?')
3649 p++;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003650
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003651 /* Stores the request path. */
3652 lua_pushstring(L, "path");
3653 lua_pushlstring(L, path, p - path);
3654 lua_settable(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003655
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003656 /* Stores the query string. */
3657 lua_pushstring(L, "qs");
3658 if (*p == '?')
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003659 p++;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003660 lua_pushlstring(L, p, end - p);
3661 lua_settable(L, -3);
Thierry FOURNIER04c57b32015-03-18 13:43:10 +01003662
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003663 /* Stores the request path. */
3664 lua_pushstring(L, "length");
3665 lua_pushinteger(L, txn->req.body_len);
3666 lua_settable(L, -3);
Thierry FOURNIER04c57b32015-03-18 13:43:10 +01003667
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003668 /* Create an array of HTTP request headers. */
3669 lua_pushstring(L, "headers");
3670 MAY_LJMP(hlua_http_get_headers(L, &appctx->htxn, &appctx->htxn.s->txn->req));
3671 lua_settable(L, -3);
Thierry FOURNIER04c57b32015-03-18 13:43:10 +01003672
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003673 /* Create an empty array of HTTP request headers. */
3674 lua_pushstring(L, "response");
3675 lua_newtable(L);
3676 lua_settable(L, -3);
Thierry FOURNIER04c57b32015-03-18 13:43:10 +01003677
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003678 /* Pop a class stream metatable and affect it to the table. */
3679 lua_rawgeti(L, LUA_REGISTRYINDEX, class_applet_http_ref);
3680 lua_setmetatable(L, -2);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003681
3682 return 1;
3683}
3684
Thierry FOURNIER / OZON.IO4394a2c2016-12-12 12:31:54 +01003685__LJMP static int hlua_applet_http_set_var(lua_State *L)
3686{
3687 struct hlua_appctx *appctx;
3688 struct stream *s;
3689 const char *name;
3690 size_t len;
3691 struct sample smp;
3692
3693 MAY_LJMP(check_args(L, 3, "set_var"));
3694
3695 /* It is useles to retrieve the stream, but this function
3696 * runs only in a stream context.
3697 */
3698 appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
3699 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3700 s = appctx->htxn.s;
3701
3702 /* Converts the third argument in a sample. */
3703 hlua_lua2smp(L, 3, &smp);
3704
3705 /* Store the sample in a variable. */
3706 smp_set_owner(&smp, s->be, s->sess, s, 0);
3707 vars_set_by_name(name, len, &smp);
3708 return 0;
3709}
3710
3711__LJMP static int hlua_applet_http_unset_var(lua_State *L)
3712{
3713 struct hlua_appctx *appctx;
3714 struct stream *s;
3715 const char *name;
3716 size_t len;
3717 struct sample smp;
3718
3719 MAY_LJMP(check_args(L, 2, "unset_var"));
3720
3721 /* It is useles to retrieve the stream, but this function
3722 * runs only in a stream context.
3723 */
3724 appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
3725 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3726 s = appctx->htxn.s;
3727
3728 /* Unset the variable. */
3729 smp_set_owner(&smp, s->be, s->sess, s, 0);
3730 vars_unset_by_name(name, len, &smp);
3731 return 0;
3732}
3733
3734__LJMP static int hlua_applet_http_get_var(lua_State *L)
3735{
3736 struct hlua_appctx *appctx;
3737 struct stream *s;
3738 const char *name;
3739 size_t len;
3740 struct sample smp;
3741
3742 MAY_LJMP(check_args(L, 2, "get_var"));
3743
3744 /* It is useles to retrieve the stream, but this function
3745 * runs only in a stream context.
3746 */
3747 appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
3748 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3749 s = appctx->htxn.s;
3750
3751 smp_set_owner(&smp, s->be, s->sess, s, 0);
3752 if (!vars_get_by_name(name, len, &smp)) {
3753 lua_pushnil(L);
3754 return 1;
3755 }
3756
3757 return hlua_smp2lua(L, &smp);
3758}
3759
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003760__LJMP static int hlua_applet_http_set_priv(lua_State *L)
3761{
3762 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
3763 struct stream *s = appctx->htxn.s;
Thierry FOURNIER3b0a6d42016-12-16 08:48:32 +01003764 struct hlua *hlua;
3765
3766 /* Note that this hlua struct is from the session and not from the applet. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01003767 if (!s->hlua)
3768 return 0;
3769 hlua = s->hlua;
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003770
3771 MAY_LJMP(check_args(L, 2, "set_priv"));
3772
3773 /* Remove previous value. */
3774 if (hlua->Mref != -1)
3775 luaL_unref(L, hlua->Mref, LUA_REGISTRYINDEX);
3776
3777 /* Get and store new value. */
3778 lua_pushvalue(L, 2); /* Copy the element 2 at the top of the stack. */
3779 hlua->Mref = luaL_ref(L, LUA_REGISTRYINDEX); /* pop the previously pushed value. */
3780
3781 return 0;
3782}
3783
3784__LJMP static int hlua_applet_http_get_priv(lua_State *L)
3785{
3786 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
3787 struct stream *s = appctx->htxn.s;
Thierry FOURNIER3b0a6d42016-12-16 08:48:32 +01003788 struct hlua *hlua;
3789
3790 /* Note that this hlua struct is from the session and not from the applet. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01003791 if (!s->hlua) {
3792 lua_pushnil(L);
3793 return 1;
3794 }
3795 hlua = s->hlua;
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01003796
3797 /* Push configuration index in the stack. */
3798 lua_rawgeti(L, LUA_REGISTRYINDEX, hlua->Mref);
3799
3800 return 1;
3801}
3802
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003803/* If expected data not yet available, it returns a yield. This function
3804 * consumes the data in the buffer. It returns a string containing the
3805 * data. This string can be empty.
3806 */
3807__LJMP static int hlua_applet_http_getline_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003808{
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003809 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
3810 struct stream_interface *si = appctx->appctx->owner;
3811 struct channel *chn = si_ic(si);
3812 int ret;
3813 char *blk1;
3814 int len1;
3815 char *blk2;
3816 int len2;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003817
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003818 /* Maybe we cant send a 100-continue ? */
3819 if (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_100C) {
3820 ret = bi_putblk(chn, HTTP_100C, strlen(HTTP_100C));
3821 /* if ret == -2 or -3 the channel closed or the message si too
3822 * big for the buffers. We cant send anything. So, we ignoring
3823 * the error, considers that the 100-continue is sent, and try
3824 * to receive.
3825 * If ret is -1, we dont have room in the buffer, so we yield.
3826 */
3827 if (ret == -1) {
3828 si_applet_cant_put(si);
3829 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_getline_yield, TICK_ETERNITY, 0));
3830 }
3831 appctx->appctx->ctx.hlua_apphttp.flags &= ~APPLET_100C;
3832 }
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003833
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003834 /* Check for the end of the data. */
3835 if (appctx->appctx->ctx.hlua_apphttp.left_bytes <= 0) {
3836 luaL_pushresult(&appctx->b);
3837 return 1;
3838 }
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003839
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003840 /* Read the maximum amount of data avalaible. */
3841 ret = bo_getline_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003842
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003843 /* Data not yet avalaible. return yield. */
3844 if (ret == 0) {
3845 si_applet_cant_get(si);
3846 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_getline_yield, TICK_ETERNITY, 0));
3847 }
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003848
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003849 /* End of data: commit the total strings and return. */
3850 if (ret < 0) {
3851 luaL_pushresult(&appctx->b);
3852 return 1;
3853 }
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003854
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003855 /* Ensure that the block 2 length is usable. */
3856 if (ret == 1)
3857 len2 = 0;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003858
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003859 /* Copy the fisrt block caping to the length required. */
3860 if (len1 > appctx->appctx->ctx.hlua_apphttp.left_bytes)
3861 len1 = appctx->appctx->ctx.hlua_apphttp.left_bytes;
3862 luaL_addlstring(&appctx->b, blk1, len1);
3863 appctx->appctx->ctx.hlua_apphttp.left_bytes -= len1;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003864
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003865 /* Copy the second block. */
3866 if (len2 > appctx->appctx->ctx.hlua_apphttp.left_bytes)
3867 len2 = appctx->appctx->ctx.hlua_apphttp.left_bytes;
3868 luaL_addlstring(&appctx->b, blk2, len2);
3869 appctx->appctx->ctx.hlua_apphttp.left_bytes -= len2;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003870
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003871 /* Consume input channel output buffer data. */
3872 bo_skip(si_oc(si), len1 + len2);
3873 luaL_pushresult(&appctx->b);
3874 return 1;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003875}
3876
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003877/* Check arguments for the fucntion "hlua_channel_get_yield". */
3878__LJMP static int hlua_applet_http_getline(lua_State *L)
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003879{
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003880 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003881
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003882 /* Initialise the string catenation. */
3883 luaL_buffinit(L, &appctx->b);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003884
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003885 return MAY_LJMP(hlua_applet_http_getline_yield(L, 0, 0));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003886}
3887
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003888/* If expected data not yet available, it returns a yield. This function
3889 * consumes the data in the buffer. It returns a string containing the
3890 * data. This string can be empty.
3891 */
3892__LJMP static int hlua_applet_http_recv_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003893{
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003894 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
3895 struct stream_interface *si = appctx->appctx->owner;
3896 int len = MAY_LJMP(luaL_checkinteger(L, 2));
3897 struct channel *chn = si_ic(si);
3898 int ret;
3899 char *blk1;
3900 int len1;
3901 char *blk2;
3902 int len2;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003903
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003904 /* Maybe we cant send a 100-continue ? */
3905 if (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_100C) {
3906 ret = bi_putblk(chn, HTTP_100C, strlen(HTTP_100C));
3907 /* if ret == -2 or -3 the channel closed or the message si too
3908 * big for the buffers. We cant send anything. So, we ignoring
3909 * the error, considers that the 100-continue is sent, and try
3910 * to receive.
3911 * If ret is -1, we dont have room in the buffer, so we yield.
3912 */
3913 if (ret == -1) {
3914 si_applet_cant_put(si);
3915 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_recv_yield, TICK_ETERNITY, 0));
3916 }
3917 appctx->appctx->ctx.hlua_apphttp.flags &= ~APPLET_100C;
3918 }
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003919
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003920 /* Read the maximum amount of data avalaible. */
3921 ret = bo_getblk_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01003922
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02003923 /* Data not yet avalaible. return yield. */
3924 if (ret == 0) {
3925 si_applet_cant_get(si);
3926 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_recv_yield, TICK_ETERNITY, 0));
3927 }
3928
3929 /* End of data: commit the total strings and return. */
3930 if (ret < 0) {
3931 luaL_pushresult(&appctx->b);
3932 return 1;
3933 }
3934
3935 /* Ensure that the block 2 length is usable. */
3936 if (ret == 1)
3937 len2 = 0;
3938
3939 /* Copy the fisrt block caping to the length required. */
3940 if (len1 > len)
3941 len1 = len;
3942 luaL_addlstring(&appctx->b, blk1, len1);
3943 len -= len1;
3944
3945 /* Copy the second block. */
3946 if (len2 > len)
3947 len2 = len;
3948 luaL_addlstring(&appctx->b, blk2, len2);
3949 len -= len2;
3950
3951 /* Consume input channel output buffer data. */
3952 bo_skip(si_oc(si), len1 + len2);
3953 if (appctx->appctx->ctx.hlua_apphttp.left_bytes != -1)
3954 appctx->appctx->ctx.hlua_apphttp.left_bytes -= len;
3955
3956 /* If we are no other data avalaible, yield waiting for new data. */
3957 if (len > 0) {
3958 lua_pushinteger(L, len);
3959 lua_replace(L, 2);
3960 si_applet_cant_get(si);
3961 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_recv_yield, TICK_ETERNITY, 0));
3962 }
3963
3964 /* return the result. */
3965 luaL_pushresult(&appctx->b);
3966 return 1;
3967}
3968
3969/* Check arguments for the fucntion "hlua_channel_get_yield". */
3970__LJMP static int hlua_applet_http_recv(lua_State *L)
3971{
3972 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
3973 int len = -1;
3974
3975 /* Check arguments. */
3976 if (lua_gettop(L) > 2)
3977 WILL_LJMP(luaL_error(L, "The 'recv' function requires between 1 and 2 arguments."));
3978 if (lua_gettop(L) >= 2) {
3979 len = MAY_LJMP(luaL_checkinteger(L, 2));
3980 lua_pop(L, 1);
3981 }
3982
3983 /* Check the required length */
3984 if (len == -1 || len > appctx->appctx->ctx.hlua_apphttp.left_bytes)
3985 len = appctx->appctx->ctx.hlua_apphttp.left_bytes;
3986 lua_pushinteger(L, len);
3987
3988 /* Initialise the string catenation. */
3989 luaL_buffinit(L, &appctx->b);
3990
3991 return MAY_LJMP(hlua_applet_http_recv_yield(L, 0, 0));
3992}
3993
3994/* Append data in the output side of the buffer. This data is immediatly
3995 * sent. The fcuntion returns the ammount of data writed. If the buffer
3996 * cannot contains the data, the function yield. The function returns -1
3997 * if the channel is closed.
3998 */
3999__LJMP static int hlua_applet_http_send_yield(lua_State *L, int status, lua_KContext ctx)
4000{
4001 size_t len;
4002 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4003 const char *str = MAY_LJMP(luaL_checklstring(L, 2, &len));
4004 int l = MAY_LJMP(luaL_checkinteger(L, 3));
4005 struct stream_interface *si = appctx->appctx->owner;
4006 struct channel *chn = si_ic(si);
4007 int max;
4008
4009 /* Get the max amount of data which can write as input in the channel. */
4010 max = channel_recv_max(chn);
4011 if (max > (len - l))
4012 max = len - l;
4013
4014 /* Copy data. */
4015 bi_putblk(chn, str + l, max);
4016
4017 /* update counters. */
4018 l += max;
4019 lua_pop(L, 1);
4020 lua_pushinteger(L, l);
4021
4022 /* If some data is not send, declares the situation to the
4023 * applet, and returns a yield.
4024 */
4025 if (l < len) {
4026 si_applet_cant_put(si);
4027 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_send_yield, TICK_ETERNITY, 0));
4028 }
4029
4030 return 1;
4031}
4032
4033/* Just a wraper of "hlua_applet_send_yield". This wrapper permits
4034 * yield the LUA process, and resume it without checking the
4035 * input arguments.
4036 */
4037__LJMP static int hlua_applet_http_send(lua_State *L)
4038{
4039 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4040 size_t len;
4041 char hex[10];
4042
4043 MAY_LJMP(luaL_checklstring(L, 2, &len));
4044
4045 /* If transfer encoding chunked is selected, we surround the data
4046 * by chunk data.
4047 */
4048 if (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_CHUNKED) {
4049 snprintf(hex, 9, "%x", (unsigned int)len);
4050 lua_pushfstring(L, "%s\r\n", hex);
4051 lua_insert(L, 2); /* swap the last 2 entries. */
4052 lua_pushstring(L, "\r\n");
4053 lua_concat(L, 3);
4054 }
4055
4056 /* This interger is used for followinf the amount of data sent. */
4057 lua_pushinteger(L, 0);
4058
4059 /* We want to send some data. Headers must be sent. */
4060 if (!(appctx->appctx->ctx.hlua_apphttp.flags & APPLET_HDR_SENT)) {
4061 hlua_pusherror(L, "Lua: 'send' you must call start_response() before sending data.");
4062 WILL_LJMP(lua_error(L));
4063 }
4064
4065 return MAY_LJMP(hlua_applet_http_send_yield(L, 0, 0));
4066}
4067
4068__LJMP static int hlua_applet_http_addheader(lua_State *L)
4069{
4070 const char *name;
4071 int ret;
4072
4073 MAY_LJMP(hlua_checkapplet_http(L, 1));
4074 name = MAY_LJMP(luaL_checkstring(L, 2));
4075 MAY_LJMP(luaL_checkstring(L, 3));
4076
4077 /* Push in the stack the "response" entry. */
4078 ret = lua_getfield(L, 1, "response");
4079 if (ret != LUA_TTABLE) {
4080 hlua_pusherror(L, "Lua: 'add_header' internal error: AppletHTTP['response'] "
4081 "is expected as an array. %s found", lua_typename(L, ret));
4082 WILL_LJMP(lua_error(L));
4083 }
4084
4085 /* check if the header is already registered if it is not
4086 * the case, register it.
4087 */
4088 ret = lua_getfield(L, -1, name);
4089 if (ret == LUA_TNIL) {
4090
4091 /* Entry not found. */
4092 lua_pop(L, 1); /* remove the nil. The "response" table is the top of the stack. */
4093
4094 /* Insert the new header name in the array in the top of the stack.
4095 * It left the new array in the top of the stack.
4096 */
4097 lua_newtable(L);
4098 lua_pushvalue(L, 2);
4099 lua_pushvalue(L, -2);
4100 lua_settable(L, -4);
4101
4102 } else if (ret != LUA_TTABLE) {
4103
4104 /* corruption error. */
4105 hlua_pusherror(L, "Lua: 'add_header' internal error: AppletHTTP['response']['%s'] "
4106 "is expected as an array. %s found", name, lua_typename(L, ret));
4107 WILL_LJMP(lua_error(L));
4108 }
4109
4110 /* Now the top od thestack is an array of values. We push
4111 * the header value as new entry.
4112 */
4113 lua_pushvalue(L, 3);
4114 ret = lua_rawlen(L, -2);
4115 lua_rawseti(L, -2, ret + 1);
4116 lua_pushboolean(L, 1);
4117 return 1;
4118}
4119
4120__LJMP static int hlua_applet_http_status(lua_State *L)
4121{
4122 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4123 int status = MAY_LJMP(luaL_checkinteger(L, 2));
4124
4125 if (status < 100 || status > 599) {
4126 lua_pushboolean(L, 0);
4127 return 1;
4128 }
4129
4130 appctx->appctx->ctx.hlua_apphttp.status = status;
4131 lua_pushboolean(L, 1);
4132 return 1;
4133}
4134
4135/* We will build the status line and the headers of the HTTP response.
4136 * We will try send at once if its not possible, we give back the hand
4137 * waiting for more room.
4138 */
4139__LJMP static int hlua_applet_http_start_response_yield(lua_State *L, int status, lua_KContext ctx)
4140{
4141 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4142 struct stream_interface *si = appctx->appctx->owner;
4143 struct channel *chn = si_ic(si);
4144 int ret;
4145 size_t len;
4146 const char *msg;
4147
4148 /* Get the message as the first argument on the stack. */
4149 msg = MAY_LJMP(luaL_checklstring(L, 2, &len));
4150
4151 /* Send the message at once. */
4152 ret = bi_putblk(chn, msg, len);
4153
4154 /* if ret == -2 or -3 the channel closed or the message si too
4155 * big for the buffers.
4156 */
4157 if (ret == -2 || ret == -3) {
4158 hlua_pusherror(L, "Lua: 'start_response': response header block too big");
4159 WILL_LJMP(lua_error(L));
4160 }
4161
4162 /* If ret is -1, we dont have room in the buffer, so we yield. */
4163 if (ret == -1) {
4164 si_applet_cant_put(si);
4165 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_start_response_yield, TICK_ETERNITY, 0));
4166 }
4167
4168 /* Headers sent, set the flag. */
4169 appctx->appctx->ctx.hlua_apphttp.flags |= APPLET_HDR_SENT;
4170 return 0;
4171}
4172
4173__LJMP static int hlua_applet_http_start_response(lua_State *L)
4174{
4175 struct chunk *tmp = get_trash_chunk();
4176 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004177 const char *name;
4178 const char *value;
4179 int id;
4180 int hdr_connection = 0;
4181 int hdr_contentlength = -1;
4182 int hdr_chunked = 0;
4183
4184 /* Use the same http version than the request. */
4185 chunk_appendf(tmp, "HTTP/1.%c %d %s\r\n",
Thierry FOURNIERd93ea2b2015-12-20 19:14:52 +01004186 appctx->appctx->ctx.hlua_apphttp.flags & APPLET_HTTP11 ? '1' : '0',
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004187 appctx->appctx->ctx.hlua_apphttp.status,
4188 get_reason(appctx->appctx->ctx.hlua_apphttp.status));
4189
4190 /* Get the array associated to the field "response" in the object AppletHTTP. */
4191 lua_pushvalue(L, 0);
4192 if (lua_getfield(L, 1, "response") != LUA_TTABLE) {
4193 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response'] missing.\n",
4194 appctx->appctx->rule->arg.hlua_rule->fcn.name);
4195 WILL_LJMP(lua_error(L));
4196 }
4197
4198 /* Browse the list of headers. */
4199 lua_pushnil(L);
4200 while(lua_next(L, -2) != 0) {
4201
4202 /* We expect a string as -2. */
4203 if (lua_type(L, -2) != LUA_TSTRING) {
4204 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response'][] element must be a string. got %s.\n",
4205 appctx->appctx->rule->arg.hlua_rule->fcn.name,
4206 lua_typename(L, lua_type(L, -2)));
4207 WILL_LJMP(lua_error(L));
4208 }
4209 name = lua_tostring(L, -2);
4210
4211 /* We expect an array as -1. */
4212 if (lua_type(L, -1) != LUA_TTABLE) {
4213 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response']['%s'] element must be an table. got %s.\n",
4214 appctx->appctx->rule->arg.hlua_rule->fcn.name,
4215 name,
4216 lua_typename(L, lua_type(L, -1)));
4217 WILL_LJMP(lua_error(L));
4218 }
4219
4220 /* Browse the table who is on the top of the stack. */
4221 lua_pushnil(L);
4222 while(lua_next(L, -2) != 0) {
4223
4224 /* We expect a number as -2. */
4225 if (lua_type(L, -2) != LUA_TNUMBER) {
4226 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response']['%s'][] element must be a number. got %s.\n",
4227 appctx->appctx->rule->arg.hlua_rule->fcn.name,
4228 name,
4229 lua_typename(L, lua_type(L, -2)));
4230 WILL_LJMP(lua_error(L));
4231 }
4232 id = lua_tointeger(L, -2);
4233
4234 /* We expect a string as -2. */
4235 if (lua_type(L, -1) != LUA_TSTRING) {
4236 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response']['%s'][%d] element must be a string. got %s.\n",
4237 appctx->appctx->rule->arg.hlua_rule->fcn.name,
4238 name, id,
4239 lua_typename(L, lua_type(L, -1)));
4240 WILL_LJMP(lua_error(L));
4241 }
4242 value = lua_tostring(L, -1);
4243
4244 /* Catenate a new header. */
4245 chunk_appendf(tmp, "%s: %s\r\n", name, value);
4246
4247 /* Protocol checks. */
4248
4249 /* Check if the header conneciton is present. */
4250 if (strcasecmp("connection", name) == 0)
4251 hdr_connection = 1;
4252
4253 /* Copy the header content length. The length conversion
4254 * is done without control. If it contains a ad value, this
4255 * is not our problem.
4256 */
4257 if (strcasecmp("content-length", name) == 0)
4258 hdr_contentlength = atoi(value);
4259
4260 /* Check if the client annouces a transfer-encoding chunked it self. */
4261 if (strcasecmp("transfer-encoding", name) == 0 &&
4262 strcasecmp("chunked", value) == 0)
4263 hdr_chunked = 1;
4264
4265 /* Remove the array from the stack, and get next element with a remaining string. */
4266 lua_pop(L, 1);
4267 }
4268
4269 /* Remove the array from the stack, and get next element with a remaining string. */
4270 lua_pop(L, 1);
4271 }
4272
4273 /* If the http protocol version is 1.1, we expect an header "connection" set
4274 * to "close" to be HAProxy/keeplive compliant. Otherwise, we expect nothing.
4275 * If the header conneciton is present, don't change it, if it is not present,
4276 * we must set.
4277 *
4278 * we set a "connection: close" header for ensuring that the keepalive will be
4279 * respected by haproxy. HAProcy considers that the application cloe the connection
4280 * and it keep the connection from the client open.
4281 */
Thierry FOURNIERd93ea2b2015-12-20 19:14:52 +01004282 if (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_HTTP11 && !hdr_connection)
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004283 chunk_appendf(tmp, "Connection: close\r\n");
4284
4285 /* If we dont have a content-length set, we must announce a transfer enconding
4286 * chunked. This is required by haproxy for the keepalive compliance.
4287 * If the applet annouce a transfer-encoding chunked itslef, don't
4288 * do anything.
4289 */
4290 if (hdr_contentlength == -1 && hdr_chunked == 0) {
4291 chunk_appendf(tmp, "Transfer-encoding: chunked\r\n");
4292 appctx->appctx->ctx.hlua_apphttp.flags |= APPLET_CHUNKED;
4293 }
4294
4295 /* Finalize headers. */
4296 chunk_appendf(tmp, "\r\n");
4297
4298 /* Remove the last entry and the array of headers */
4299 lua_pop(L, 2);
4300
4301 /* Push the headers block. */
4302 lua_pushlstring(L, tmp->str, tmp->len);
4303
4304 return MAY_LJMP(hlua_applet_http_start_response_yield(L, 0, 0));
4305}
4306
4307/*
4308 *
4309 *
4310 * Class HTTP
4311 *
4312 *
4313 */
4314
4315/* Returns a struct hlua_txn if the stack entry "ud" is
4316 * a class stream, otherwise it throws an error.
4317 */
4318__LJMP static struct hlua_txn *hlua_checkhttp(lua_State *L, int ud)
4319{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004320 return MAY_LJMP(hlua_checkudata(L, ud, class_http_ref));
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004321}
4322
4323/* This function creates and push in the stack a HTTP object
4324 * according with a current TXN.
4325 */
4326static int hlua_http_new(lua_State *L, struct hlua_txn *txn)
4327{
4328 struct hlua_txn *htxn;
4329
4330 /* Check stack size. */
4331 if (!lua_checkstack(L, 3))
4332 return 0;
4333
4334 /* Create the object: obj[0] = userdata.
4335 * Note that the base of the Converters object is the
4336 * same than the TXN object.
4337 */
4338 lua_newtable(L);
4339 htxn = lua_newuserdata(L, sizeof(*htxn));
4340 lua_rawseti(L, -2, 0);
4341
4342 htxn->s = txn->s;
4343 htxn->p = txn->p;
4344
4345 /* Pop a class stream metatable and affect it to the table. */
4346 lua_rawgeti(L, LUA_REGISTRYINDEX, class_http_ref);
4347 lua_setmetatable(L, -2);
4348
4349 return 1;
4350}
4351
4352/* This function creates ans returns an array of HTTP headers.
4353 * This function does not fails. It is used as wrapper with the
4354 * 2 following functions.
4355 */
4356__LJMP static int hlua_http_get_headers(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg)
4357{
4358 const char *cur_ptr, *cur_next, *p;
4359 int old_idx, cur_idx;
4360 struct hdr_idx_elem *cur_hdr;
4361 const char *hn, *hv;
4362 int hnl, hvl;
4363 int type;
4364 const char *in;
4365 char *out;
4366 int len;
4367
4368 /* Create the table. */
4369 lua_newtable(L);
4370
4371 if (!htxn->s->txn)
4372 return 1;
4373
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004374 /* Check if a valid response is parsed */
4375 if (unlikely(msg->msg_state < HTTP_MSG_BODY))
4376 return 1;
4377
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004378 /* Build array of headers. */
4379 old_idx = 0;
4380 cur_next = msg->chn->buf->p + hdr_idx_first_pos(&htxn->s->txn->hdr_idx);
4381
4382 while (1) {
4383 cur_idx = htxn->s->txn->hdr_idx.v[old_idx].next;
4384 if (!cur_idx)
4385 break;
4386 old_idx = cur_idx;
4387
4388 cur_hdr = &htxn->s->txn->hdr_idx.v[cur_idx];
4389 cur_ptr = cur_next;
4390 cur_next = cur_ptr + cur_hdr->len + cur_hdr->cr + 1;
4391
4392 /* Now we have one full header at cur_ptr of len cur_hdr->len,
4393 * and the next header starts at cur_next. We'll check
4394 * this header in the list as well as against the default
4395 * rule.
4396 */
4397
4398 /* look for ': *'. */
4399 hn = cur_ptr;
4400 for (p = cur_ptr; p < cur_ptr + cur_hdr->len && *p != ':'; p++);
4401 if (p >= cur_ptr+cur_hdr->len)
4402 continue;
4403 hnl = p - hn;
4404 p++;
4405 while (p < cur_ptr+cur_hdr->len && ( *p == ' ' || *p == '\t' ))
4406 p++;
4407 if (p >= cur_ptr+cur_hdr->len)
4408 continue;
4409 hv = p;
4410 hvl = cur_ptr+cur_hdr->len-p;
4411
4412 /* Lowercase the key. Don't check the size of trash, it have
4413 * the size of one buffer and the input data contains in one
4414 * buffer.
4415 */
4416 out = trash.str;
4417 for (in=hn; in<hn+hnl; in++, out++)
4418 *out = tolower(*in);
4419 *out = '\0';
4420
4421 /* Check for existing entry:
4422 * assume that the table is on the top of the stack, and
4423 * push the key in the stack, the function lua_gettable()
4424 * perform the lookup.
4425 */
4426 lua_pushlstring(L, trash.str, hnl);
4427 lua_gettable(L, -2);
4428 type = lua_type(L, -1);
4429
4430 switch (type) {
4431 case LUA_TNIL:
4432 /* Table not found, create it. */
4433 lua_pop(L, 1); /* remove the nil value. */
4434 lua_pushlstring(L, trash.str, hnl); /* push the header name as key. */
4435 lua_newtable(L); /* create and push empty table. */
4436 lua_pushlstring(L, hv, hvl); /* push header value. */
4437 lua_rawseti(L, -2, 0); /* index header value (pop it). */
4438 lua_rawset(L, -3); /* index new table with header name (pop the values). */
4439 break;
4440
4441 case LUA_TTABLE:
4442 /* Entry found: push the value in the table. */
4443 len = lua_rawlen(L, -1);
4444 lua_pushlstring(L, hv, hvl); /* push header value. */
4445 lua_rawseti(L, -2, len+1); /* index header value (pop it). */
4446 lua_pop(L, 1); /* remove the table (it is stored in the main table). */
4447 break;
4448
4449 default:
4450 /* Other cases are errors. */
4451 hlua_pusherror(L, "internal error during the parsing of headers.");
4452 WILL_LJMP(lua_error(L));
4453 }
4454 }
4455
4456 return 1;
4457}
4458
4459__LJMP static int hlua_http_req_get_headers(lua_State *L)
4460{
4461 struct hlua_txn *htxn;
4462
4463 MAY_LJMP(check_args(L, 1, "req_get_headers"));
4464 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4465
4466 return hlua_http_get_headers(L, htxn, &htxn->s->txn->req);
4467}
4468
4469__LJMP static int hlua_http_res_get_headers(lua_State *L)
4470{
4471 struct hlua_txn *htxn;
4472
4473 MAY_LJMP(check_args(L, 1, "res_get_headers"));
4474 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4475
4476 return hlua_http_get_headers(L, htxn, &htxn->s->txn->rsp);
4477}
4478
4479/* This function replace full header, or just a value in
4480 * the request or in the response. It is a wrapper fir the
4481 * 4 following functions.
4482 */
4483__LJMP static inline int hlua_http_rep_hdr(lua_State *L, struct hlua_txn *htxn,
4484 struct http_msg *msg, int action)
4485{
4486 size_t name_len;
4487 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
4488 const char *reg = MAY_LJMP(luaL_checkstring(L, 3));
4489 const char *value = MAY_LJMP(luaL_checkstring(L, 4));
4490 struct my_regex re;
4491
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004492 /* Check if a valid response is parsed */
4493 if (unlikely(msg->msg_state < HTTP_MSG_BODY))
4494 return 0;
4495
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02004496 if (!regex_comp(reg, &re, 1, 1, NULL))
4497 WILL_LJMP(luaL_argerror(L, 3, "invalid regex"));
4498
4499 http_transform_header_str(htxn->s, msg, name, name_len, value, &re, action);
4500 regex_free(&re);
4501 return 0;
4502}
4503
4504__LJMP static int hlua_http_req_rep_hdr(lua_State *L)
4505{
4506 struct hlua_txn *htxn;
4507
4508 MAY_LJMP(check_args(L, 4, "req_rep_hdr"));
4509 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4510
4511 return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->req, ACT_HTTP_REPLACE_HDR));
4512}
4513
4514__LJMP static int hlua_http_res_rep_hdr(lua_State *L)
4515{
4516 struct hlua_txn *htxn;
4517
4518 MAY_LJMP(check_args(L, 4, "res_rep_hdr"));
4519 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4520
4521 return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->rsp, ACT_HTTP_REPLACE_HDR));
4522}
4523
4524__LJMP static int hlua_http_req_rep_val(lua_State *L)
4525{
4526 struct hlua_txn *htxn;
4527
4528 MAY_LJMP(check_args(L, 4, "req_rep_hdr"));
4529 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4530
4531 return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->req, ACT_HTTP_REPLACE_VAL));
4532}
4533
4534__LJMP static int hlua_http_res_rep_val(lua_State *L)
4535{
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004536 struct hlua_txn *htxn;
4537
4538 MAY_LJMP(check_args(L, 4, "res_rep_val"));
4539 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4540
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02004541 return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->rsp, ACT_HTTP_REPLACE_VAL));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004542}
4543
4544/* This function deletes all the occurences of an header.
4545 * It is a wrapper for the 2 following functions.
4546 */
4547__LJMP static inline int hlua_http_del_hdr(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg)
4548{
4549 size_t len;
4550 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &len));
4551 struct hdr_ctx ctx;
Willy Tarreaueee5b512015-04-03 23:46:31 +02004552 struct http_txn *txn = htxn->s->txn;
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004553
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004554 /* Check if a valid response is parsed */
4555 if (unlikely(msg->msg_state < HTTP_MSG_BODY))
4556 return 0;
4557
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004558 ctx.idx = 0;
4559 while (http_find_header2(name, len, msg->chn->buf->p, &txn->hdr_idx, &ctx))
4560 http_remove_header2(msg, &txn->hdr_idx, &ctx);
4561 return 0;
4562}
4563
4564__LJMP static int hlua_http_req_del_hdr(lua_State *L)
4565{
4566 struct hlua_txn *htxn;
4567
4568 MAY_LJMP(check_args(L, 2, "req_del_hdr"));
4569 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4570
Willy Tarreaueee5b512015-04-03 23:46:31 +02004571 return hlua_http_del_hdr(L, htxn, &htxn->s->txn->req);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004572}
4573
4574__LJMP static int hlua_http_res_del_hdr(lua_State *L)
4575{
4576 struct hlua_txn *htxn;
4577
4578 MAY_LJMP(check_args(L, 2, "req_del_hdr"));
4579 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4580
Willy Tarreaueee5b512015-04-03 23:46:31 +02004581 return hlua_http_del_hdr(L, htxn, &htxn->s->txn->rsp);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004582}
4583
4584/* This function adds an header. It is a wrapper used by
4585 * the 2 following functions.
4586 */
4587__LJMP static inline int hlua_http_add_hdr(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg)
4588{
4589 size_t name_len;
4590 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
4591 size_t value_len;
4592 const char *value = MAY_LJMP(luaL_checklstring(L, 3, &value_len));
4593 char *p;
4594
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004595 /* Check if a valid message is parsed */
4596 if (unlikely(msg->msg_state < HTTP_MSG_BODY))
4597 return 0;
4598
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004599 /* Check length. */
4600 trash.len = value_len + name_len + 2;
4601 if (trash.len > trash.size)
4602 return 0;
4603
4604 /* Creates the header string. */
4605 p = trash.str;
4606 memcpy(p, name, name_len);
4607 p += name_len;
4608 *p = ':';
4609 p++;
4610 *p = ' ';
4611 p++;
4612 memcpy(p, value, value_len);
4613
Willy Tarreaueee5b512015-04-03 23:46:31 +02004614 lua_pushboolean(L, http_header_add_tail2(msg, &htxn->s->txn->hdr_idx,
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004615 trash.str, trash.len) != 0);
4616
4617 return 0;
4618}
4619
4620__LJMP static int hlua_http_req_add_hdr(lua_State *L)
4621{
4622 struct hlua_txn *htxn;
4623
4624 MAY_LJMP(check_args(L, 3, "req_add_hdr"));
4625 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4626
Willy Tarreaueee5b512015-04-03 23:46:31 +02004627 return hlua_http_add_hdr(L, htxn, &htxn->s->txn->req);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004628}
4629
4630__LJMP static int hlua_http_res_add_hdr(lua_State *L)
4631{
4632 struct hlua_txn *htxn;
4633
4634 MAY_LJMP(check_args(L, 3, "res_add_hdr"));
4635 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4636
Willy Tarreaueee5b512015-04-03 23:46:31 +02004637 return hlua_http_add_hdr(L, htxn, &htxn->s->txn->rsp);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004638}
4639
4640static int hlua_http_req_set_hdr(lua_State *L)
4641{
4642 struct hlua_txn *htxn;
4643
4644 MAY_LJMP(check_args(L, 3, "req_set_hdr"));
4645 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4646
Willy Tarreaueee5b512015-04-03 23:46:31 +02004647 hlua_http_del_hdr(L, htxn, &htxn->s->txn->req);
4648 return hlua_http_add_hdr(L, htxn, &htxn->s->txn->req);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004649}
4650
4651static int hlua_http_res_set_hdr(lua_State *L)
4652{
4653 struct hlua_txn *htxn;
4654
4655 MAY_LJMP(check_args(L, 3, "res_set_hdr"));
4656 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4657
Willy Tarreaueee5b512015-04-03 23:46:31 +02004658 hlua_http_del_hdr(L, htxn, &htxn->s->txn->rsp);
4659 return hlua_http_add_hdr(L, htxn, &htxn->s->txn->rsp);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004660}
4661
4662/* This function set the method. */
4663static int hlua_http_req_set_meth(lua_State *L)
4664{
Willy Tarreaubcb39cc2015-04-06 11:21:44 +02004665 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004666 size_t name_len;
4667 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004668
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004669 /* Check if a valid request is parsed */
4670 if (unlikely(htxn->s->txn->req.msg_state < HTTP_MSG_BODY)) {
4671 lua_pushboolean(L, 0);
4672 return 1;
4673 }
4674
Willy Tarreau987e3fb2015-04-04 01:09:08 +02004675 lua_pushboolean(L, http_replace_req_line(0, name, name_len, htxn->p, htxn->s) != -1);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004676 return 1;
4677}
4678
4679/* This function set the method. */
4680static int hlua_http_req_set_path(lua_State *L)
4681{
Willy Tarreaubcb39cc2015-04-06 11:21:44 +02004682 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004683 size_t name_len;
4684 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004685
4686 /* Check if a valid request is parsed */
4687 if (unlikely(htxn->s->txn->req.msg_state < HTTP_MSG_BODY)) {
4688 lua_pushboolean(L, 0);
4689 return 1;
4690 }
4691
Willy Tarreau987e3fb2015-04-04 01:09:08 +02004692 lua_pushboolean(L, http_replace_req_line(1, name, name_len, htxn->p, htxn->s) != -1);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004693 return 1;
4694}
4695
4696/* This function set the query-string. */
4697static int hlua_http_req_set_query(lua_State *L)
4698{
Willy Tarreaubcb39cc2015-04-06 11:21:44 +02004699 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004700 size_t name_len;
4701 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004702
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004703 /* Check if a valid request is parsed */
4704 if (unlikely(htxn->s->txn->req.msg_state < HTTP_MSG_BODY)) {
4705 lua_pushboolean(L, 0);
4706 return 1;
4707 }
4708
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004709 /* Check length. */
4710 if (name_len > trash.size - 1) {
4711 lua_pushboolean(L, 0);
4712 return 1;
4713 }
4714
4715 /* Add the mark question as prefix. */
4716 chunk_reset(&trash);
4717 trash.str[trash.len++] = '?';
4718 memcpy(trash.str + trash.len, name, name_len);
4719 trash.len += name_len;
4720
Willy Tarreau987e3fb2015-04-04 01:09:08 +02004721 lua_pushboolean(L, http_replace_req_line(2, trash.str, trash.len, htxn->p, htxn->s) != -1);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004722 return 1;
4723}
4724
4725/* This function set the uri. */
4726static int hlua_http_req_set_uri(lua_State *L)
4727{
Willy Tarreaubcb39cc2015-04-06 11:21:44 +02004728 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004729 size_t name_len;
4730 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004731
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004732 /* Check if a valid request is parsed */
4733 if (unlikely(htxn->s->txn->req.msg_state < HTTP_MSG_BODY)) {
4734 lua_pushboolean(L, 0);
4735 return 1;
4736 }
4737
Willy Tarreau987e3fb2015-04-04 01:09:08 +02004738 lua_pushboolean(L, http_replace_req_line(3, name, name_len, htxn->p, htxn->s) != -1);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004739 return 1;
4740}
4741
Thierry FOURNIER35d70ef2015-08-26 16:21:56 +02004742/* This function set the response code. */
4743static int hlua_http_res_set_status(lua_State *L)
4744{
4745 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4746 unsigned int code = MAY_LJMP(luaL_checkinteger(L, 2));
4747
Thierry FOURNIER / OZON.IOb84ae922016-08-02 23:44:58 +02004748 /* Check if a valid response is parsed */
4749 if (unlikely(htxn->s->txn->rsp.msg_state < HTTP_MSG_BODY))
4750 return 0;
4751
Thierry FOURNIER35d70ef2015-08-26 16:21:56 +02004752 http_set_status(code, htxn->s);
4753 return 0;
4754}
4755
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004756/*
4757 *
4758 *
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01004759 * Class TXN
4760 *
4761 *
4762 */
4763
4764/* Returns a struct hlua_session if the stack entry "ud" is
Willy Tarreau87b09662015-04-03 00:22:06 +02004765 * a class stream, otherwise it throws an error.
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01004766 */
4767__LJMP static struct hlua_txn *hlua_checktxn(lua_State *L, int ud)
4768{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004769 return MAY_LJMP(hlua_checkudata(L, ud, class_txn_ref));
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01004770}
4771
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +02004772__LJMP static int hlua_set_var(lua_State *L)
4773{
4774 struct hlua_txn *htxn;
4775 const char *name;
4776 size_t len;
4777 struct sample smp;
4778
4779 MAY_LJMP(check_args(L, 3, "set_var"));
4780
4781 /* It is useles to retrieve the stream, but this function
4782 * runs only in a stream context.
4783 */
4784 htxn = MAY_LJMP(hlua_checktxn(L, 1));
4785 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
4786
4787 /* Converts the third argument in a sample. */
4788 hlua_lua2smp(L, 3, &smp);
4789
4790 /* Store the sample in a variable. */
Willy Tarreau7560dd42016-03-10 16:28:58 +01004791 smp_set_owner(&smp, htxn->p, htxn->s->sess, htxn->s, htxn->dir & SMP_OPT_DIR);
Willy Tarreau6204cd92016-03-10 16:33:04 +01004792 vars_set_by_name(name, len, &smp);
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +02004793 return 0;
4794}
4795
Christopher Faulet85d79c92016-11-09 16:54:56 +01004796__LJMP static int hlua_unset_var(lua_State *L)
4797{
4798 struct hlua_txn *htxn;
4799 const char *name;
4800 size_t len;
4801 struct sample smp;
4802
4803 MAY_LJMP(check_args(L, 2, "unset_var"));
4804
4805 /* It is useles to retrieve the stream, but this function
4806 * runs only in a stream context.
4807 */
4808 htxn = MAY_LJMP(hlua_checktxn(L, 1));
4809 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
4810
4811 /* Unset the variable. */
4812 smp_set_owner(&smp, htxn->p, htxn->s->sess, htxn->s, htxn->dir & SMP_OPT_DIR);
4813 vars_unset_by_name(name, len, &smp);
4814 return 0;
4815}
4816
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +02004817__LJMP static int hlua_get_var(lua_State *L)
4818{
4819 struct hlua_txn *htxn;
4820 const char *name;
4821 size_t len;
4822 struct sample smp;
4823
4824 MAY_LJMP(check_args(L, 2, "get_var"));
4825
4826 /* It is useles to retrieve the stream, but this function
4827 * runs only in a stream context.
4828 */
4829 htxn = MAY_LJMP(hlua_checktxn(L, 1));
4830 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
4831
Willy Tarreau7560dd42016-03-10 16:28:58 +01004832 smp_set_owner(&smp, htxn->p, htxn->s->sess, htxn->s, htxn->dir & SMP_OPT_DIR);
Willy Tarreau6204cd92016-03-10 16:33:04 +01004833 if (!vars_get_by_name(name, len, &smp)) {
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +02004834 lua_pushnil(L);
4835 return 1;
4836 }
4837
4838 return hlua_smp2lua(L, &smp);
4839}
4840
Willy Tarreau59551662015-03-10 14:23:13 +01004841__LJMP static int hlua_set_priv(lua_State *L)
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01004842{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01004843 struct hlua *hlua;
4844
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01004845 MAY_LJMP(check_args(L, 2, "set_priv"));
4846
Willy Tarreau87b09662015-04-03 00:22:06 +02004847 /* It is useles to retrieve the stream, but this function
4848 * runs only in a stream context.
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01004849 */
4850 MAY_LJMP(hlua_checktxn(L, 1));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01004851 hlua = hlua_gethlua(L);
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01004852
4853 /* Remove previous value. */
4854 if (hlua->Mref != -1)
4855 luaL_unref(L, hlua->Mref, LUA_REGISTRYINDEX);
4856
4857 /* Get and store new value. */
4858 lua_pushvalue(L, 2); /* Copy the element 2 at the top of the stack. */
4859 hlua->Mref = luaL_ref(L, LUA_REGISTRYINDEX); /* pop the previously pushed value. */
4860
4861 return 0;
4862}
4863
Willy Tarreau59551662015-03-10 14:23:13 +01004864__LJMP static int hlua_get_priv(lua_State *L)
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01004865{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01004866 struct hlua *hlua;
4867
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01004868 MAY_LJMP(check_args(L, 1, "get_priv"));
4869
Willy Tarreau87b09662015-04-03 00:22:06 +02004870 /* It is useles to retrieve the stream, but this function
4871 * runs only in a stream context.
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01004872 */
4873 MAY_LJMP(hlua_checktxn(L, 1));
Willy Tarreau80f5fae2015-02-27 16:38:20 +01004874 hlua = hlua_gethlua(L);
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01004875
4876 /* Push configuration index in the stack. */
4877 lua_rawgeti(L, LUA_REGISTRYINDEX, hlua->Mref);
4878
4879 return 1;
4880}
4881
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01004882/* Create stack entry containing a class TXN. This function
4883 * return 0 if the stack does not contains free slots,
4884 * otherwise it returns 1.
4885 */
Thierry FOURNIERab00df62016-07-14 11:42:37 +02004886static int hlua_txn_new(lua_State *L, struct stream *s, struct proxy *p, int dir, int flags)
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01004887{
Willy Tarreaude491382015-04-06 11:04:28 +02004888 struct hlua_txn *htxn;
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01004889
4890 /* Check stack size. */
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01004891 if (!lua_checkstack(L, 3))
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01004892 return 0;
4893
4894 /* NOTE: The allocation never fails. The failure
4895 * throw an error, and the function never returns.
4896 * if the throw is not avalaible, the process is aborted.
4897 */
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01004898 /* Create the object: obj[0] = userdata. */
4899 lua_newtable(L);
Willy Tarreaude491382015-04-06 11:04:28 +02004900 htxn = lua_newuserdata(L, sizeof(*htxn));
Thierry FOURNIER2297bc22015-03-11 17:43:33 +01004901 lua_rawseti(L, -2, 0);
4902
Willy Tarreaude491382015-04-06 11:04:28 +02004903 htxn->s = s;
4904 htxn->p = p;
Thierry FOURNIERc4eebc82015-11-02 10:01:59 +01004905 htxn->dir = dir;
Thierry FOURNIERab00df62016-07-14 11:42:37 +02004906 htxn->flags = flags;
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01004907
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01004908 /* Create the "f" field that contains a list of fetches. */
4909 lua_pushstring(L, "f");
Thierry FOURNIERca988662015-12-20 18:43:03 +01004910 if (!hlua_fetches_new(L, htxn, HLUA_F_MAY_USE_HTTP))
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01004911 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02004912 lua_rawset(L, -3);
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01004913
4914 /* Create the "sf" field that contains a list of stringsafe fetches. */
4915 lua_pushstring(L, "sf");
Thierry FOURNIERca988662015-12-20 18:43:03 +01004916 if (!hlua_fetches_new(L, htxn, HLUA_F_MAY_USE_HTTP | HLUA_F_AS_STRING))
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01004917 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02004918 lua_rawset(L, -3);
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01004919
Thierry FOURNIER594afe72015-03-10 23:58:30 +01004920 /* Create the "c" field that contains a list of converters. */
4921 lua_pushstring(L, "c");
Willy Tarreaude491382015-04-06 11:04:28 +02004922 if (!hlua_converters_new(L, htxn, 0))
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01004923 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02004924 lua_rawset(L, -3);
Thierry FOURNIER2694a1a2015-03-11 20:13:36 +01004925
4926 /* Create the "sc" field that contains a list of stringsafe converters. */
4927 lua_pushstring(L, "sc");
Thierry FOURNIER7fa05492015-12-20 18:42:25 +01004928 if (!hlua_converters_new(L, htxn, HLUA_F_AS_STRING))
Thierry FOURNIER594afe72015-03-10 23:58:30 +01004929 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02004930 lua_rawset(L, -3);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01004931
Thierry FOURNIER397826a2015-03-11 19:39:09 +01004932 /* Create the "req" field that contains the request channel object. */
4933 lua_pushstring(L, "req");
Willy Tarreau2a71af42015-03-10 13:51:50 +01004934 if (!hlua_channel_new(L, &s->req))
Thierry FOURNIER397826a2015-03-11 19:39:09 +01004935 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02004936 lua_rawset(L, -3);
Thierry FOURNIER397826a2015-03-11 19:39:09 +01004937
4938 /* Create the "res" field that contains the response channel object. */
4939 lua_pushstring(L, "res");
Willy Tarreau2a71af42015-03-10 13:51:50 +01004940 if (!hlua_channel_new(L, &s->res))
Thierry FOURNIER397826a2015-03-11 19:39:09 +01004941 return 0;
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02004942 lua_rawset(L, -3);
Thierry FOURNIER397826a2015-03-11 19:39:09 +01004943
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004944 /* Creates the HTTP object is the current proxy allows http. */
4945 lua_pushstring(L, "http");
4946 if (p->mode == PR_MODE_HTTP) {
Willy Tarreaude491382015-04-06 11:04:28 +02004947 if (!hlua_http_new(L, htxn))
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004948 return 0;
4949 }
4950 else
4951 lua_pushnil(L);
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02004952 lua_rawset(L, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01004953
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01004954 /* Pop a class sesison metatable and affect it to the userdata. */
4955 lua_rawgeti(L, LUA_REGISTRYINDEX, class_txn_ref);
4956 lua_setmetatable(L, -2);
4957
4958 return 1;
4959}
4960
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +01004961__LJMP static int hlua_txn_deflog(lua_State *L)
4962{
4963 const char *msg;
4964 struct hlua_txn *htxn;
4965
4966 MAY_LJMP(check_args(L, 2, "deflog"));
4967 htxn = MAY_LJMP(hlua_checktxn(L, 1));
4968 msg = MAY_LJMP(luaL_checkstring(L, 2));
4969
4970 hlua_sendlog(htxn->s->be, htxn->s->logs.level, msg);
4971 return 0;
4972}
4973
4974__LJMP static int hlua_txn_log(lua_State *L)
4975{
4976 int level;
4977 const char *msg;
4978 struct hlua_txn *htxn;
4979
4980 MAY_LJMP(check_args(L, 3, "log"));
4981 htxn = MAY_LJMP(hlua_checktxn(L, 1));
4982 level = MAY_LJMP(luaL_checkinteger(L, 2));
4983 msg = MAY_LJMP(luaL_checkstring(L, 3));
4984
4985 if (level < 0 || level >= NB_LOG_LEVELS)
4986 WILL_LJMP(luaL_argerror(L, 1, "Invalid loglevel."));
4987
4988 hlua_sendlog(htxn->s->be, level, msg);
4989 return 0;
4990}
4991
4992__LJMP static int hlua_txn_log_debug(lua_State *L)
4993{
4994 const char *msg;
4995 struct hlua_txn *htxn;
4996
4997 MAY_LJMP(check_args(L, 2, "Debug"));
4998 htxn = MAY_LJMP(hlua_checktxn(L, 1));
4999 msg = MAY_LJMP(luaL_checkstring(L, 2));
5000 hlua_sendlog(htxn->s->be, LOG_DEBUG, msg);
5001 return 0;
5002}
5003
5004__LJMP static int hlua_txn_log_info(lua_State *L)
5005{
5006 const char *msg;
5007 struct hlua_txn *htxn;
5008
5009 MAY_LJMP(check_args(L, 2, "Info"));
5010 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5011 msg = MAY_LJMP(luaL_checkstring(L, 2));
5012 hlua_sendlog(htxn->s->be, LOG_INFO, msg);
5013 return 0;
5014}
5015
5016__LJMP static int hlua_txn_log_warning(lua_State *L)
5017{
5018 const char *msg;
5019 struct hlua_txn *htxn;
5020
5021 MAY_LJMP(check_args(L, 2, "Warning"));
5022 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5023 msg = MAY_LJMP(luaL_checkstring(L, 2));
5024 hlua_sendlog(htxn->s->be, LOG_WARNING, msg);
5025 return 0;
5026}
5027
5028__LJMP static int hlua_txn_log_alert(lua_State *L)
5029{
5030 const char *msg;
5031 struct hlua_txn *htxn;
5032
5033 MAY_LJMP(check_args(L, 2, "Alert"));
5034 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5035 msg = MAY_LJMP(luaL_checkstring(L, 2));
5036 hlua_sendlog(htxn->s->be, LOG_ALERT, msg);
5037 return 0;
5038}
5039
Thierry FOURNIER2cce3532015-03-16 12:04:16 +01005040__LJMP static int hlua_txn_set_loglevel(lua_State *L)
5041{
5042 struct hlua_txn *htxn;
5043 int ll;
5044
5045 MAY_LJMP(check_args(L, 2, "set_loglevel"));
5046 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5047 ll = MAY_LJMP(luaL_checkinteger(L, 2));
5048
5049 if (ll < 0 || ll > 7)
5050 WILL_LJMP(luaL_argerror(L, 2, "Bad log level. It must be between 0 and 7"));
5051
5052 htxn->s->logs.level = ll;
5053 return 0;
5054}
5055
5056__LJMP static int hlua_txn_set_tos(lua_State *L)
5057{
5058 struct hlua_txn *htxn;
5059 struct connection *cli_conn;
5060 int tos;
5061
5062 MAY_LJMP(check_args(L, 2, "set_tos"));
5063 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5064 tos = MAY_LJMP(luaL_checkinteger(L, 2));
5065
Willy Tarreau9ad7bd42015-04-03 19:19:59 +02005066 if ((cli_conn = objt_conn(htxn->s->sess->origin)) && conn_ctrl_ready(cli_conn))
Vincent Bernat6e615892016-05-18 16:17:44 +02005067 inet_set_tos(cli_conn->t.sock.fd, &cli_conn->addr.from, tos);
Thierry FOURNIER2cce3532015-03-16 12:04:16 +01005068
5069 return 0;
5070}
5071
5072__LJMP static int hlua_txn_set_mark(lua_State *L)
5073{
5074#ifdef SO_MARK
5075 struct hlua_txn *htxn;
5076 struct connection *cli_conn;
5077 int mark;
5078
5079 MAY_LJMP(check_args(L, 2, "set_mark"));
5080 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5081 mark = MAY_LJMP(luaL_checkinteger(L, 2));
5082
Willy Tarreau9ad7bd42015-04-03 19:19:59 +02005083 if ((cli_conn = objt_conn(htxn->s->sess->origin)) && conn_ctrl_ready(cli_conn))
Willy Tarreau07081fe2015-04-06 10:59:20 +02005084 setsockopt(cli_conn->t.sock.fd, SOL_SOCKET, SO_MARK, &mark, sizeof(mark));
Thierry FOURNIER2cce3532015-03-16 12:04:16 +01005085#endif
5086 return 0;
5087}
5088
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005089/* This function is an Lua binding that send pending data
5090 * to the client, and close the stream interface.
5091 */
Thierry FOURNIER4bb375c2015-08-26 08:42:21 +02005092__LJMP static int hlua_txn_done(lua_State *L)
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005093{
Willy Tarreaub2ccb562015-04-06 11:11:15 +02005094 struct hlua_txn *htxn;
Thierry FOURNIER9bd52d42016-07-14 11:45:33 +02005095 struct hlua *hlua;
Willy Tarreau81389672015-03-10 12:03:52 +01005096 struct channel *ic, *oc;
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005097
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005098 MAY_LJMP(check_args(L, 1, "close"));
Willy Tarreaub2ccb562015-04-06 11:11:15 +02005099 htxn = MAY_LJMP(hlua_checktxn(L, 1));
Thierry FOURNIER9bd52d42016-07-14 11:45:33 +02005100 hlua = hlua_gethlua(L);
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005101
Thierry FOURNIERab00df62016-07-14 11:42:37 +02005102 /* If the flags NOTERM is set, we cannot terminate the http
5103 * session, so we just end the execution of the current
5104 * lua code.
5105 */
5106 if (htxn->flags & HLUA_TXN_NOTERM) {
5107 WILL_LJMP(hlua_done(L));
5108 return 0;
5109 }
5110
Willy Tarreaub2ccb562015-04-06 11:11:15 +02005111 ic = &htxn->s->req;
5112 oc = &htxn->s->res;
Willy Tarreau81389672015-03-10 12:03:52 +01005113
Willy Tarreau630ef452015-08-28 10:06:15 +02005114 if (htxn->s->txn) {
5115 /* HTTP mode, let's stay in sync with the stream */
5116 bi_fast_delete(ic->buf, htxn->s->txn->req.sov);
5117 htxn->s->txn->req.next -= htxn->s->txn->req.sov;
5118 htxn->s->txn->req.sov = 0;
5119 ic->analysers &= AN_REQ_HTTP_XFER_BODY;
5120 oc->analysers = AN_RES_HTTP_XFER_BODY;
5121 htxn->s->txn->req.msg_state = HTTP_MSG_CLOSED;
5122 htxn->s->txn->rsp.msg_state = HTTP_MSG_DONE;
5123
Willy Tarreau630ef452015-08-28 10:06:15 +02005124 /* Note that if we want to support keep-alive, we need
5125 * to bypass the close/shutr_now calls below, but that
5126 * may only be done if the HTTP request was already
5127 * processed and the connection header is known (ie
5128 * not during TCP rules).
5129 */
5130 }
5131
Thierry FOURNIER10ec2142015-08-24 17:23:45 +02005132 channel_auto_read(ic);
Willy Tarreau81389672015-03-10 12:03:52 +01005133 channel_abort(ic);
5134 channel_auto_close(ic);
5135 channel_erase(ic);
Thierry FOURNIER10ec2142015-08-24 17:23:45 +02005136
5137 oc->wex = tick_add_ifset(now_ms, oc->wto);
Willy Tarreau81389672015-03-10 12:03:52 +01005138 channel_auto_read(oc);
5139 channel_auto_close(oc);
5140 channel_shutr_now(oc);
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005141
Willy Tarreau0458b082015-08-28 09:40:04 +02005142 ic->analysers = 0;
Thierry FOURNIER4bb375c2015-08-26 08:42:21 +02005143
Thierry FOURNIER9bd52d42016-07-14 11:45:33 +02005144 hlua->flags |= HLUA_STOP;
Thierry FOURNIER4bb375c2015-08-26 08:42:21 +02005145 WILL_LJMP(hlua_done(L));
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +01005146 return 0;
5147}
5148
5149__LJMP static int hlua_log(lua_State *L)
5150{
5151 int level;
5152 const char *msg;
5153
5154 MAY_LJMP(check_args(L, 2, "log"));
5155 level = MAY_LJMP(luaL_checkinteger(L, 1));
5156 msg = MAY_LJMP(luaL_checkstring(L, 2));
5157
5158 if (level < 0 || level >= NB_LOG_LEVELS)
5159 WILL_LJMP(luaL_argerror(L, 1, "Invalid loglevel."));
5160
5161 hlua_sendlog(NULL, level, msg);
5162 return 0;
5163}
5164
5165__LJMP static int hlua_log_debug(lua_State *L)
5166{
5167 const char *msg;
5168
5169 MAY_LJMP(check_args(L, 1, "debug"));
5170 msg = MAY_LJMP(luaL_checkstring(L, 1));
5171 hlua_sendlog(NULL, LOG_DEBUG, msg);
5172 return 0;
5173}
5174
5175__LJMP static int hlua_log_info(lua_State *L)
5176{
5177 const char *msg;
5178
5179 MAY_LJMP(check_args(L, 1, "info"));
5180 msg = MAY_LJMP(luaL_checkstring(L, 1));
5181 hlua_sendlog(NULL, LOG_INFO, msg);
5182 return 0;
5183}
5184
5185__LJMP static int hlua_log_warning(lua_State *L)
5186{
5187 const char *msg;
5188
5189 MAY_LJMP(check_args(L, 1, "warning"));
5190 msg = MAY_LJMP(luaL_checkstring(L, 1));
5191 hlua_sendlog(NULL, LOG_WARNING, msg);
5192 return 0;
5193}
5194
5195__LJMP static int hlua_log_alert(lua_State *L)
5196{
5197 const char *msg;
5198
5199 MAY_LJMP(check_args(L, 1, "alert"));
5200 msg = MAY_LJMP(luaL_checkstring(L, 1));
5201 hlua_sendlog(NULL, LOG_ALERT, msg);
Thierry FOURNIER893bfa32015-02-17 18:42:34 +01005202 return 0;
5203}
5204
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01005205__LJMP static int hlua_sleep_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005206{
5207 int wakeup_ms = lua_tointeger(L, -1);
5208 if (now_ms < wakeup_ms)
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005209 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_sleep_yield, wakeup_ms, 0));
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005210 return 0;
5211}
5212
5213__LJMP static int hlua_sleep(lua_State *L)
5214{
5215 unsigned int delay;
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005216 unsigned int wakeup_ms;
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005217
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005218 MAY_LJMP(check_args(L, 1, "sleep"));
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005219
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01005220 delay = MAY_LJMP(luaL_checkinteger(L, 1)) * 1000;
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005221 wakeup_ms = tick_add(now_ms, delay);
5222 lua_pushinteger(L, wakeup_ms);
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005223
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005224 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_sleep_yield, wakeup_ms, 0));
5225 return 0;
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005226}
5227
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005228__LJMP static int hlua_msleep(lua_State *L)
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005229{
5230 unsigned int delay;
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005231 unsigned int wakeup_ms;
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005232
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005233 MAY_LJMP(check_args(L, 1, "msleep"));
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005234
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01005235 delay = MAY_LJMP(luaL_checkinteger(L, 1));
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005236 wakeup_ms = tick_add(now_ms, delay);
5237 lua_pushinteger(L, wakeup_ms);
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005238
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005239 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_sleep_yield, wakeup_ms, 0));
5240 return 0;
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01005241}
5242
Thierry FOURNIER13416fe2015-02-17 15:01:59 +01005243/* This functionis an LUA binding. it permits to give back
5244 * the hand at the HAProxy scheduler. It is used when the
5245 * LUA processing consumes a lot of time.
5246 */
Thierry FOURNIERf90838b2015-03-06 13:48:32 +01005247__LJMP static int hlua_yield_yield(lua_State *L, int status, lua_KContext ctx)
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005248{
5249 return 0;
5250}
5251
Thierry FOURNIER13416fe2015-02-17 15:01:59 +01005252__LJMP static int hlua_yield(lua_State *L)
5253{
Thierry FOURNIERd44731f2015-03-04 15:51:09 +01005254 WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_yield_yield, TICK_ETERNITY, HLUA_CTRLYIELD));
5255 return 0;
Thierry FOURNIER13416fe2015-02-17 15:01:59 +01005256}
5257
Thierry FOURNIER37196f42015-02-16 19:34:56 +01005258/* This function change the nice of the currently executed
5259 * task. It is used set low or high priority at the current
5260 * task.
5261 */
Willy Tarreau59551662015-03-10 14:23:13 +01005262__LJMP static int hlua_set_nice(lua_State *L)
Thierry FOURNIER37196f42015-02-16 19:34:56 +01005263{
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005264 struct hlua *hlua;
5265 int nice;
Thierry FOURNIER37196f42015-02-16 19:34:56 +01005266
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005267 MAY_LJMP(check_args(L, 1, "set_nice"));
5268 hlua = hlua_gethlua(L);
5269 nice = MAY_LJMP(luaL_checkinteger(L, 1));
Thierry FOURNIER37196f42015-02-16 19:34:56 +01005270
5271 /* If he task is not set, I'm in a start mode. */
5272 if (!hlua || !hlua->task)
5273 return 0;
5274
5275 if (nice < -1024)
5276 nice = -1024;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01005277 else if (nice > 1024)
Thierry FOURNIER37196f42015-02-16 19:34:56 +01005278 nice = 1024;
5279
5280 hlua->task->nice = nice;
5281 return 0;
5282}
5283
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005284/* This function is used as a calback of a task. It is called by the
5285 * HAProxy task subsystem when the task is awaked. The LUA runtime can
5286 * return an E_AGAIN signal, the emmiter of this signal must set a
5287 * signal to wake the task.
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005288 *
5289 * Task wrapper are longjmp safe because the only one Lua code
5290 * executed is the safe hlua_ctx_resume();
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005291 */
5292static struct task *hlua_process_task(struct task *task)
5293{
5294 struct hlua *hlua = task->context;
5295 enum hlua_exec status;
5296
5297 /* We need to remove the task from the wait queue before executing
5298 * the Lua code because we don't know if it needs to wait for
5299 * another timer or not in the case of E_AGAIN.
5300 */
5301 task_delete(task);
5302
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005303 /* If it is the first call to the task, we must initialize the
5304 * execution timeouts.
5305 */
5306 if (!HLUA_IS_RUNNING(hlua))
Thierry FOURNIER10770fa2015-09-29 01:59:42 +02005307 hlua->max_time = hlua_timeout_task;
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005308
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005309 /* Execute the Lua code. */
5310 status = hlua_ctx_resume(hlua, 1);
5311
5312 switch (status) {
5313 /* finished or yield */
5314 case HLUA_E_OK:
5315 hlua_ctx_destroy(hlua);
5316 task_delete(task);
5317 task_free(task);
5318 break;
5319
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01005320 case HLUA_E_AGAIN: /* co process or timeout wake me later. */
5321 if (hlua->wake_time != TICK_ETERNITY)
5322 task_schedule(task, hlua->wake_time);
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005323 break;
5324
5325 /* finished with error. */
5326 case HLUA_E_ERRMSG:
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005327 SEND_ERR(NULL, "Lua task: %s.\n", lua_tostring(hlua->T, -1));
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005328 hlua_ctx_destroy(hlua);
5329 task_delete(task);
5330 task_free(task);
5331 break;
5332
5333 case HLUA_E_ERR:
5334 default:
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005335 SEND_ERR(NULL, "Lua task: unknown error.\n");
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005336 hlua_ctx_destroy(hlua);
5337 task_delete(task);
5338 task_free(task);
5339 break;
5340 }
5341 return NULL;
5342}
5343
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01005344/* This function is an LUA binding that register LUA function to be
5345 * executed after the HAProxy configuration parsing and before the
5346 * HAProxy scheduler starts. This function expect only one LUA
5347 * argument that is a function. This function returns nothing, but
5348 * throws if an error is encountered.
5349 */
5350__LJMP static int hlua_register_init(lua_State *L)
5351{
5352 struct hlua_init_function *init;
5353 int ref;
5354
5355 MAY_LJMP(check_args(L, 1, "register_init"));
5356
5357 ref = MAY_LJMP(hlua_checkfunction(L, 1));
5358
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02005359 init = calloc(1, sizeof(*init));
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01005360 if (!init)
5361 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5362
5363 init->function_ref = ref;
5364 LIST_ADDQ(&hlua_init_functions, &init->l);
5365 return 0;
5366}
5367
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005368/* This functio is an LUA binding. It permits to register a task
5369 * executed in parallel of the main HAroxy activity. The task is
5370 * created and it is set in the HAProxy scheduler. It can be called
5371 * from the "init" section, "post init" or during the runtime.
5372 *
5373 * Lua prototype:
5374 *
5375 * <none> core.register_task(<function>)
5376 */
5377static int hlua_register_task(lua_State *L)
5378{
5379 struct hlua *hlua;
5380 struct task *task;
5381 int ref;
5382
5383 MAY_LJMP(check_args(L, 1, "register_task"));
5384
5385 ref = MAY_LJMP(hlua_checkfunction(L, 1));
5386
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005387 hlua = pool_alloc2(pool2_hlua);
Thierry FOURNIER24f33532015-01-23 12:13:00 +01005388 if (!hlua)
5389 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5390
5391 task = task_new();
5392 task->context = hlua;
5393 task->process = hlua_process_task;
5394
5395 if (!hlua_ctx_init(hlua, task))
5396 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5397
5398 /* Restore the function in the stack. */
5399 lua_rawgeti(hlua->T, LUA_REGISTRYINDEX, ref);
5400 hlua->nargs = 0;
5401
5402 /* Schedule task. */
5403 task_schedule(task, now_ms);
5404
5405 return 0;
5406}
5407
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005408/* Wrapper called by HAProxy to execute an LUA converter. This wrapper
5409 * doesn't allow "yield" functions because the HAProxy engine cannot
5410 * resume converters.
5411 */
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005412static int hlua_sample_conv_wrapper(const struct arg *arg_p, struct sample *smp, void *private)
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005413{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005414 struct hlua_function *fcn = private;
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005415 struct stream *stream = smp->strm;
Thierry Fournierfd107a22016-02-19 19:57:23 +01005416 const char *error;
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005417
Willy Tarreaube508f12016-03-10 11:47:01 +01005418 if (!stream)
5419 return 0;
5420
Willy Tarreau87b09662015-04-03 00:22:06 +02005421 /* In the execution wrappers linked with a stream, the
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01005422 * Lua context can be not initialized. This behavior
5423 * permits to save performances because a systematic
5424 * Lua initialization cause 5% performances loss.
5425 */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005426 if (!stream->hlua) {
5427 stream->hlua = pool_alloc2(pool2_hlua);
5428 if (!stream->hlua) {
5429 SEND_ERR(stream->be, "Lua converter '%s': can't initialize Lua context.\n", fcn->name);
5430 return 0;
5431 }
5432 if (!hlua_ctx_init(stream->hlua, stream->task)) {
5433 SEND_ERR(stream->be, "Lua converter '%s': can't initialize Lua context.\n", fcn->name);
5434 return 0;
5435 }
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01005436 }
5437
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005438 /* If it is the first run, initialize the data for the call. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005439 if (!HLUA_IS_RUNNING(stream->hlua)) {
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005440
5441 /* The following Lua calls can fail. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005442 if (!SET_SAFE_LJMP(stream->hlua->T)) {
5443 if (lua_type(stream->hlua->T, -1) == LUA_TSTRING)
5444 error = lua_tostring(stream->hlua->T, -1);
Thierry Fournierfd107a22016-02-19 19:57:23 +01005445 else
5446 error = "critical error";
5447 SEND_ERR(stream->be, "Lua converter '%s': %s.\n", fcn->name, error);
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005448 return 0;
5449 }
5450
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005451 /* Check stack available size. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005452 if (!lua_checkstack(stream->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005453 SEND_ERR(stream->be, "Lua converter '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005454 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005455 return 0;
5456 }
5457
5458 /* Restore the function in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005459 lua_rawgeti(stream->hlua->T, LUA_REGISTRYINDEX, fcn->function_ref);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005460
5461 /* convert input sample and pust-it in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005462 if (!lua_checkstack(stream->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005463 SEND_ERR(stream->be, "Lua converter '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005464 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005465 return 0;
5466 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005467 hlua_smp2lua(stream->hlua->T, smp);
5468 stream->hlua->nargs = 1;
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005469
5470 /* push keywords in the stack. */
5471 if (arg_p) {
5472 for (; arg_p->type != ARGT_STOP; arg_p++) {
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005473 if (!lua_checkstack(stream->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005474 SEND_ERR(stream->be, "Lua converter '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005475 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005476 return 0;
5477 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005478 hlua_arg2lua(stream->hlua->T, arg_p);
5479 stream->hlua->nargs++;
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005480 }
5481 }
5482
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005483 /* We must initialize the execution timeouts. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005484 stream->hlua->max_time = hlua_timeout_session;
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005485
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005486 /* At this point the execution is safe. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005487 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005488 }
5489
5490 /* Execute the function. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005491 switch (hlua_ctx_resume(stream->hlua, 0)) {
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005492 /* finished. */
5493 case HLUA_E_OK:
5494 /* Convert the returned value in sample. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005495 hlua_lua2smp(stream->hlua->T, -1, smp);
5496 lua_pop(stream->hlua->T, 1);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005497 return 1;
5498
5499 /* yield. */
5500 case HLUA_E_AGAIN:
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005501 SEND_ERR(stream->be, "Lua converter '%s': cannot use yielded functions.\n", fcn->name);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005502 return 0;
5503
5504 /* finished with error. */
5505 case HLUA_E_ERRMSG:
5506 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005507 SEND_ERR(stream->be, "Lua converter '%s': %s.\n",
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005508 fcn->name, lua_tostring(stream->hlua->T, -1));
5509 lua_pop(stream->hlua->T, 1);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005510 return 0;
5511
5512 case HLUA_E_ERR:
5513 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005514 SEND_ERR(stream->be, "Lua converter '%s' returns an unknown error.\n", fcn->name);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005515
5516 default:
5517 return 0;
5518 }
5519}
5520
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005521/* Wrapper called by HAProxy to execute a sample-fetch. this wrapper
5522 * doesn't allow "yield" functions because the HAProxy engine cannot
Willy Tarreaube508f12016-03-10 11:47:01 +01005523 * resume sample-fetches. This function will be called by the sample
5524 * fetch engine to call lua-based fetch operations.
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005525 */
Thierry FOURNIER0786d052015-05-11 15:42:45 +02005526static int hlua_sample_fetch_wrapper(const struct arg *arg_p, struct sample *smp,
5527 const char *kw, void *private)
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005528{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005529 struct hlua_function *fcn = private;
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02005530 struct stream *stream = smp->strm;
Thierry Fournierfd107a22016-02-19 19:57:23 +01005531 const char *error;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005532 const struct chunk msg = { .len = 0 };
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005533
Willy Tarreaube508f12016-03-10 11:47:01 +01005534 if (!stream)
5535 return 0;
5536
Willy Tarreau87b09662015-04-03 00:22:06 +02005537 /* In the execution wrappers linked with a stream, the
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01005538 * Lua context can be not initialized. This behavior
5539 * permits to save performances because a systematic
5540 * Lua initialization cause 5% performances loss.
5541 */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005542 if (!stream->hlua) {
5543 stream->hlua = pool_alloc2(pool2_hlua);
5544 if (!stream->hlua) {
5545 SEND_ERR(stream->be, "Lua sample-fetch '%s': can't initialize Lua context.\n", fcn->name);
5546 return 0;
5547 }
5548 if (!hlua_ctx_init(stream->hlua, stream->task)) {
5549 SEND_ERR(stream->be, "Lua sample-fetch '%s': can't initialize Lua context.\n", fcn->name);
5550 return 0;
5551 }
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01005552 }
5553
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005554 consistency_set(stream, smp->opt, &stream->hlua->cons);
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005555
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005556 /* If it is the first run, initialize the data for the call. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005557 if (!HLUA_IS_RUNNING(stream->hlua)) {
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005558
5559 /* The following Lua calls can fail. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005560 if (!SET_SAFE_LJMP(stream->hlua->T)) {
5561 if (lua_type(stream->hlua->T, -1) == LUA_TSTRING)
5562 error = lua_tostring(stream->hlua->T, -1);
Thierry Fournierfd107a22016-02-19 19:57:23 +01005563 else
5564 error = "critical error";
5565 SEND_ERR(smp->px, "Lua sample-fetch '%s': %s.\n", fcn->name, error);
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005566 return 0;
5567 }
5568
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005569 /* Check stack available size. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005570 if (!lua_checkstack(stream->hlua->T, 2)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005571 SEND_ERR(smp->px, "Lua sample-fetch '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005572 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005573 return 0;
5574 }
5575
5576 /* Restore the function in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005577 lua_rawgeti(stream->hlua->T, LUA_REGISTRYINDEX, fcn->function_ref);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005578
5579 /* push arguments in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005580 if (!hlua_txn_new(stream->hlua->T, stream, smp->px, smp->opt & SMP_OPT_DIR,
Thierry FOURNIERab00df62016-07-14 11:42:37 +02005581 HLUA_TXN_NOTERM)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005582 SEND_ERR(smp->px, "Lua sample-fetch '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005583 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005584 return 0;
5585 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005586 stream->hlua->nargs = 1;
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005587
5588 /* push keywords in the stack. */
5589 for (; arg_p && arg_p->type != ARGT_STOP; arg_p++) {
5590 /* Check stack available size. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005591 if (!lua_checkstack(stream->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005592 SEND_ERR(smp->px, "Lua sample-fetch '%s': full stack.\n", fcn->name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005593 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005594 return 0;
5595 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005596 hlua_arg2lua(stream->hlua->T, arg_p);
5597 stream->hlua->nargs++;
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005598 }
5599
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005600 /* We must initialize the execution timeouts. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005601 stream->hlua->max_time = hlua_timeout_session;
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005602
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005603 /* At this point the execution is safe. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005604 RESET_SAFE_LJMP(stream->hlua->T);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005605 }
5606
5607 /* Execute the function. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005608 switch (hlua_ctx_resume(stream->hlua, 0)) {
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005609 /* finished. */
5610 case HLUA_E_OK:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005611 if (!consistency_check(stream, smp->opt, &stream->hlua->cons)) {
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005612 stream_int_retnclose(&stream->si[0], &msg);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02005613 return 0;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005614 }
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005615 /* Convert the returned value in sample. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005616 hlua_lua2smp(stream->hlua->T, -1, smp);
5617 lua_pop(stream->hlua->T, 1);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005618
5619 /* Set the end of execution flag. */
5620 smp->flags &= ~SMP_F_MAY_CHANGE;
5621 return 1;
5622
5623 /* yield. */
5624 case HLUA_E_AGAIN:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005625 if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005626 stream_int_retnclose(&stream->si[0], &msg);
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005627 SEND_ERR(smp->px, "Lua sample-fetch '%s': cannot use yielded functions.\n", fcn->name);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005628 return 0;
5629
5630 /* finished with error. */
5631 case HLUA_E_ERRMSG:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005632 if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005633 stream_int_retnclose(&stream->si[0], &msg);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005634 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005635 SEND_ERR(smp->px, "Lua sample-fetch '%s': %s.\n",
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005636 fcn->name, lua_tostring(stream->hlua->T, -1));
5637 lua_pop(stream->hlua->T, 1);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005638 return 0;
5639
5640 case HLUA_E_ERR:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005641 if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005642 stream_int_retnclose(&stream->si[0], &msg);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005643 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005644 SEND_ERR(smp->px, "Lua sample-fetch '%s' returns an unknown error.\n", fcn->name);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005645
5646 default:
5647 return 0;
5648 }
5649}
5650
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005651/* This function is an LUA binding used for registering
5652 * "sample-conv" functions. It expects a converter name used
5653 * in the haproxy configuration file, and an LUA function.
5654 */
5655__LJMP static int hlua_register_converters(lua_State *L)
5656{
5657 struct sample_conv_kw_list *sck;
5658 const char *name;
5659 int ref;
5660 int len;
5661 struct hlua_function *fcn;
5662
5663 MAY_LJMP(check_args(L, 2, "register_converters"));
5664
5665 /* First argument : converter name. */
5666 name = MAY_LJMP(luaL_checkstring(L, 1));
5667
5668 /* Second argument : lua function. */
5669 ref = MAY_LJMP(hlua_checkfunction(L, 2));
5670
5671 /* Allocate and fill the sample fetch keyword struct. */
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02005672 sck = calloc(1, sizeof(*sck) + sizeof(struct sample_conv) * 2);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005673 if (!sck)
5674 WILL_LJMP(luaL_error(L, "lua out of memory error."));
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02005675 fcn = calloc(1, sizeof(*fcn));
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005676 if (!fcn)
5677 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5678
5679 /* Fill fcn. */
5680 fcn->name = strdup(name);
5681 if (!fcn->name)
5682 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5683 fcn->function_ref = ref;
5684
5685 /* List head */
5686 sck->list.n = sck->list.p = NULL;
5687
5688 /* converter keyword. */
5689 len = strlen("lua.") + strlen(name) + 1;
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02005690 sck->kw[0].kw = calloc(1, len);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005691 if (!sck->kw[0].kw)
5692 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5693
5694 snprintf((char *)sck->kw[0].kw, len, "lua.%s", name);
5695 sck->kw[0].process = hlua_sample_conv_wrapper;
David Carlier0c437f42016-04-27 16:21:56 +01005696 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 +01005697 sck->kw[0].val_args = NULL;
5698 sck->kw[0].in_type = SMP_T_STR;
5699 sck->kw[0].out_type = SMP_T_STR;
5700 sck->kw[0].private = fcn;
5701
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01005702 /* Register this new converter */
5703 sample_register_convs(sck);
5704
5705 return 0;
5706}
5707
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005708/* This fucntion is an LUA binding used for registering
5709 * "sample-fetch" functions. It expects a converter name used
5710 * in the haproxy configuration file, and an LUA function.
5711 */
5712__LJMP static int hlua_register_fetches(lua_State *L)
5713{
5714 const char *name;
5715 int ref;
5716 int len;
5717 struct sample_fetch_kw_list *sfk;
5718 struct hlua_function *fcn;
5719
5720 MAY_LJMP(check_args(L, 2, "register_fetches"));
5721
5722 /* First argument : sample-fetch name. */
5723 name = MAY_LJMP(luaL_checkstring(L, 1));
5724
5725 /* Second argument : lua function. */
5726 ref = MAY_LJMP(hlua_checkfunction(L, 2));
5727
5728 /* Allocate and fill the sample fetch keyword struct. */
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02005729 sfk = calloc(1, sizeof(*sfk) + sizeof(struct sample_fetch) * 2);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005730 if (!sfk)
5731 WILL_LJMP(luaL_error(L, "lua out of memory error."));
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02005732 fcn = calloc(1, sizeof(*fcn));
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005733 if (!fcn)
5734 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5735
5736 /* Fill fcn. */
5737 fcn->name = strdup(name);
5738 if (!fcn->name)
5739 WILL_LJMP(luaL_error(L, "lua out of memory error."));
5740 fcn->function_ref = ref;
5741
5742 /* List head */
5743 sfk->list.n = sfk->list.p = NULL;
5744
5745 /* sample-fetch keyword. */
5746 len = strlen("lua.") + strlen(name) + 1;
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02005747 sfk->kw[0].kw = calloc(1, len);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005748 if (!sfk->kw[0].kw)
5749 return luaL_error(L, "lua out of memory error.");
5750
5751 snprintf((char *)sfk->kw[0].kw, len, "lua.%s", name);
5752 sfk->kw[0].process = hlua_sample_fetch_wrapper;
David Carlier0c437f42016-04-27 16:21:56 +01005753 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 +01005754 sfk->kw[0].val_args = NULL;
5755 sfk->kw[0].out_type = SMP_T_STR;
5756 sfk->kw[0].use = SMP_USE_HTTP_ANY;
5757 sfk->kw[0].val = 0;
5758 sfk->kw[0].private = fcn;
5759
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01005760 /* Register this new fetch. */
5761 sample_register_fetches(sfk);
5762
5763 return 0;
5764}
5765
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005766/* This function is a wrapper to execute each LUA function declared
5767 * as an action wrapper during the initialisation period. This function
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005768 * return ACT_RET_CONT if the processing is finished (with or without
5769 * error) and return ACT_RET_YIELD if the function must be called again
5770 * because the LUA returns a yield.
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005771 */
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005772static enum act_return hlua_action(struct act_rule *rule, struct proxy *px,
Willy Tarreau658b85b2015-09-27 10:00:49 +02005773 struct session *sess, struct stream *s, int flags)
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005774{
5775 char **arg;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005776 unsigned int analyzer;
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02005777 int dir;
Thierry Fournierfd107a22016-02-19 19:57:23 +01005778 const char *error;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005779 const struct chunk msg = { .len = 0 };
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005780
5781 switch (rule->from) {
Thierry FOURNIER6e01f382015-11-02 09:52:54 +01005782 case ACT_F_TCP_REQ_CNT: analyzer = AN_REQ_INSPECT_FE ; dir = SMP_OPT_DIR_REQ; break;
5783 case ACT_F_TCP_RES_CNT: analyzer = AN_RES_INSPECT ; dir = SMP_OPT_DIR_RES; break;
5784 case ACT_F_HTTP_REQ: analyzer = AN_REQ_HTTP_PROCESS_FE; dir = SMP_OPT_DIR_REQ; break;
5785 case ACT_F_HTTP_RES: analyzer = AN_RES_HTTP_PROCESS_BE; dir = SMP_OPT_DIR_RES; break;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005786 default:
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005787 SEND_ERR(px, "Lua: internal error while execute action.\n");
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005788 return ACT_RET_CONT;
5789 }
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005790
Willy Tarreau87b09662015-04-03 00:22:06 +02005791 /* In the execution wrappers linked with a stream, the
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01005792 * Lua context can be not initialized. This behavior
5793 * permits to save performances because a systematic
5794 * Lua initialization cause 5% performances loss.
5795 */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005796 if (!s->hlua) {
5797 s->hlua = pool_alloc2(pool2_hlua);
5798 if (!s->hlua) {
5799 SEND_ERR(px, "Lua action '%s': can't initialize Lua context.\n",
5800 rule->arg.hlua_rule->fcn.name);
5801 return ACT_RET_CONT;
5802 }
5803 if (!hlua_ctx_init(s->hlua, s->task)) {
5804 SEND_ERR(px, "Lua action '%s': can't initialize Lua context.\n",
5805 rule->arg.hlua_rule->fcn.name);
5806 return ACT_RET_CONT;
5807 }
Thierry FOURNIER05ac4242015-02-27 18:37:27 +01005808 }
5809
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005810 consistency_set(s, dir, &s->hlua->cons);
5811
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005812 /* If it is the first run, initialize the data for the call. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005813 if (!HLUA_IS_RUNNING(s->hlua)) {
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005814
5815 /* The following Lua calls can fail. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005816 if (!SET_SAFE_LJMP(s->hlua->T)) {
5817 if (lua_type(s->hlua->T, -1) == LUA_TSTRING)
5818 error = lua_tostring(s->hlua->T, -1);
Thierry Fournierfd107a22016-02-19 19:57:23 +01005819 else
5820 error = "critical error";
5821 SEND_ERR(px, "Lua function '%s': %s.\n",
5822 rule->arg.hlua_rule->fcn.name, error);
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005823 return ACT_RET_CONT;
5824 }
5825
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005826 /* Check stack available size. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005827 if (!lua_checkstack(s->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005828 SEND_ERR(px, "Lua function '%s': full stack.\n",
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005829 rule->arg.hlua_rule->fcn.name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005830 RESET_SAFE_LJMP(s->hlua->T);
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02005831 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005832 }
5833
5834 /* Restore the function in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005835 lua_rawgeti(s->hlua->T, LUA_REGISTRYINDEX, rule->arg.hlua_rule->fcn.function_ref);
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005836
Willy Tarreau87b09662015-04-03 00:22:06 +02005837 /* Create and and push object stream in the stack. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005838 if (!hlua_txn_new(s->hlua->T, s, px, dir, 0)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005839 SEND_ERR(px, "Lua function '%s': full stack.\n",
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005840 rule->arg.hlua_rule->fcn.name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005841 RESET_SAFE_LJMP(s->hlua->T);
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02005842 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005843 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005844 s->hlua->nargs = 1;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005845
5846 /* push keywords in the stack. */
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005847 for (arg = rule->arg.hlua_rule->args; arg && *arg; arg++) {
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005848 if (!lua_checkstack(s->hlua->T, 1)) {
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005849 SEND_ERR(px, "Lua function '%s': full stack.\n",
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005850 rule->arg.hlua_rule->fcn.name);
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005851 RESET_SAFE_LJMP(s->hlua->T);
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02005852 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005853 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005854 lua_pushstring(s->hlua->T, *arg);
5855 s->hlua->nargs++;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005856 }
5857
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005858 /* Now the execution is safe. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005859 RESET_SAFE_LJMP(s->hlua->T);
Thierry FOURNIERbabae282015-09-17 11:36:37 +02005860
Thierry FOURNIERbd413492015-03-03 16:52:26 +01005861 /* We must initialize the execution timeouts. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005862 s->hlua->max_time = hlua_timeout_session;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005863 }
5864
5865 /* Execute the function. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005866 switch (hlua_ctx_resume(s->hlua, !(flags & ACT_FLAG_FINAL))) {
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005867 /* finished. */
5868 case HLUA_E_OK:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005869 if (!consistency_check(s, dir, &s->hlua->cons)) {
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005870 stream_int_retnclose(&s->si[0], &msg);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02005871 return ACT_RET_ERR;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005872 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005873 if (s->hlua->flags & HLUA_STOP)
Thierry FOURNIER9bd52d42016-07-14 11:45:33 +02005874 return ACT_RET_STOP;
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02005875 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005876
5877 /* yield. */
5878 case HLUA_E_AGAIN:
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01005879 /* Set timeout in the required channel. */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005880 if (s->hlua->wake_time != TICK_ETERNITY) {
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01005881 if (analyzer & (AN_REQ_INSPECT_FE|AN_REQ_HTTP_PROCESS_FE))
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005882 s->req.analyse_exp = s->hlua->wake_time;
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01005883 else if (analyzer & (AN_RES_INSPECT|AN_RES_HTTP_PROCESS_BE))
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005884 s->res.analyse_exp = s->hlua->wake_time;
Thierry FOURNIERc42c1ae2015-03-03 17:17:55 +01005885 }
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005886 /* Some actions can be wake up when a "write" event
5887 * is detected on a response channel. This is useful
5888 * only for actions targetted on the requests.
5889 */
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005890 if (HLUA_IS_WAKERESWR(s->hlua)) {
Willy Tarreau22ec1ea2014-11-27 20:45:39 +01005891 s->res.flags |= CF_WAKE_WRITE;
Willy Tarreau76bd97f2015-03-10 17:16:10 +01005892 if ((analyzer & (AN_REQ_INSPECT_FE|AN_REQ_HTTP_PROCESS_FE)))
Willy Tarreau22ec1ea2014-11-27 20:45:39 +01005893 s->res.analysers |= analyzer;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005894 }
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005895 if (HLUA_IS_WAKEREQWR(s->hlua))
Willy Tarreau22ec1ea2014-11-27 20:45:39 +01005896 s->req.flags |= CF_WAKE_WRITE;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005897 /* We can quit the fcuntion without consistency check
5898 * because HAProxy is not able to manipulate data, it
5899 * is only allowed to call me again. */
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02005900 return ACT_RET_YIELD;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005901
5902 /* finished with error. */
5903 case HLUA_E_ERRMSG:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005904 if (!consistency_check(s, dir, &s->hlua->cons)) {
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005905 stream_int_retnclose(&s->si[0], &msg);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02005906 return ACT_RET_ERR;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005907 }
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005908 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005909 SEND_ERR(px, "Lua function '%s': %s.\n",
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005910 rule->arg.hlua_rule->fcn.name, lua_tostring(s->hlua->T, -1));
5911 lua_pop(s->hlua->T, 1);
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02005912 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005913
5914 case HLUA_E_ERR:
Thierry FOURNIER2c8b54e2016-12-17 12:45:32 +01005915 if (!consistency_check(s, dir, &s->hlua->cons)) {
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005916 stream_int_retnclose(&s->si[0], &msg);
Thierry FOURNIERd75cb0f2015-09-25 19:22:44 +02005917 return ACT_RET_ERR;
Thierry FOURNIER11cfb3d2016-12-13 13:06:23 +01005918 }
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005919 /* Display log. */
Thierry FOURNIER23bc3752015-09-11 19:15:43 +02005920 SEND_ERR(px, "Lua function '%s' return an unknown error.\n",
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02005921 rule->arg.hlua_rule->fcn.name);
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005922
5923 default:
Thierry FOURNIER24ff6c62015-08-06 08:52:53 +02005924 return ACT_RET_CONT;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01005925 }
5926}
5927
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02005928struct task *hlua_applet_wakeup(struct task *t)
5929{
5930 struct appctx *ctx = t->context;
5931 struct stream_interface *si = ctx->owner;
5932
5933 /* If the applet is wake up without any expected work, the sheduler
5934 * remove it from the run queue. This flag indicate that the applet
5935 * is waiting for write. If the buffer is full, the main processing
5936 * will send some data and after call the applet, otherwise it call
5937 * the applet ASAP.
5938 */
5939 si_applet_cant_put(si);
5940 appctx_wakeup(ctx);
5941 return NULL;
5942}
5943
5944static int hlua_applet_tcp_init(struct appctx *ctx, struct proxy *px, struct stream *strm)
5945{
5946 struct stream_interface *si = ctx->owner;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01005947 struct hlua *hlua;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02005948 struct task *task;
5949 char **arg;
Thierry Fournierfd107a22016-02-19 19:57:23 +01005950 const char *error;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02005951
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01005952 hlua = pool_alloc2(pool2_hlua);
5953 if (!hlua) {
5954 SEND_ERR(px, "Lua applet tcp '%s': out of memory.\n",
5955 ctx->rule->arg.hlua_rule->fcn.name);
5956 return 0;
5957 }
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02005958 HLUA_INIT(hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01005959 ctx->ctx.hlua_apptcp.hlua = hlua;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02005960 ctx->ctx.hlua_apptcp.flags = 0;
5961
5962 /* Create task used by signal to wakeup applets. */
5963 task = task_new();
5964 if (!task) {
5965 SEND_ERR(px, "Lua applet tcp '%s': out of memory.\n",
5966 ctx->rule->arg.hlua_rule->fcn.name);
5967 return 0;
5968 }
5969 task->nice = 0;
5970 task->context = ctx;
5971 task->process = hlua_applet_wakeup;
5972 ctx->ctx.hlua_apptcp.task = task;
5973
5974 /* In the execution wrappers linked with a stream, the
5975 * Lua context can be not initialized. This behavior
5976 * permits to save performances because a systematic
5977 * Lua initialization cause 5% performances loss.
5978 */
5979 if (!hlua_ctx_init(hlua, task)) {
5980 SEND_ERR(px, "Lua applet tcp '%s': can't initialize Lua context.\n",
5981 ctx->rule->arg.hlua_rule->fcn.name);
5982 return 0;
5983 }
5984
5985 /* Set timeout according with the applet configuration. */
Thierry FOURNIER10770fa2015-09-29 01:59:42 +02005986 hlua->max_time = ctx->applet->timeout;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02005987
5988 /* The following Lua calls can fail. */
5989 if (!SET_SAFE_LJMP(hlua->T)) {
Thierry Fournierfd107a22016-02-19 19:57:23 +01005990 if (lua_type(hlua->T, -1) == LUA_TSTRING)
5991 error = lua_tostring(hlua->T, -1);
5992 else
5993 error = "critical error";
5994 SEND_ERR(px, "Lua applet tcp '%s': %s.\n",
5995 ctx->rule->arg.hlua_rule->fcn.name, error);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02005996 RESET_SAFE_LJMP(hlua->T);
5997 return 0;
5998 }
5999
6000 /* Check stack available size. */
6001 if (!lua_checkstack(hlua->T, 1)) {
6002 SEND_ERR(px, "Lua applet tcp '%s': full stack.\n",
6003 ctx->rule->arg.hlua_rule->fcn.name);
6004 RESET_SAFE_LJMP(hlua->T);
6005 return 0;
6006 }
6007
6008 /* Restore the function in the stack. */
6009 lua_rawgeti(hlua->T, LUA_REGISTRYINDEX, ctx->rule->arg.hlua_rule->fcn.function_ref);
6010
6011 /* Create and and push object stream in the stack. */
6012 if (!hlua_applet_tcp_new(hlua->T, ctx)) {
6013 SEND_ERR(px, "Lua applet tcp '%s': full stack.\n",
6014 ctx->rule->arg.hlua_rule->fcn.name);
6015 RESET_SAFE_LJMP(hlua->T);
6016 return 0;
6017 }
6018 hlua->nargs = 1;
6019
6020 /* push keywords in the stack. */
6021 for (arg = ctx->rule->arg.hlua_rule->args; arg && *arg; arg++) {
6022 if (!lua_checkstack(hlua->T, 1)) {
6023 SEND_ERR(px, "Lua applet tcp '%s': full stack.\n",
6024 ctx->rule->arg.hlua_rule->fcn.name);
6025 RESET_SAFE_LJMP(hlua->T);
6026 return 0;
6027 }
6028 lua_pushstring(hlua->T, *arg);
6029 hlua->nargs++;
6030 }
6031
6032 RESET_SAFE_LJMP(hlua->T);
6033
6034 /* Wakeup the applet ASAP. */
6035 si_applet_cant_get(si);
6036 si_applet_cant_put(si);
6037
6038 return 1;
6039}
6040
6041static void hlua_applet_tcp_fct(struct appctx *ctx)
6042{
6043 struct stream_interface *si = ctx->owner;
6044 struct stream *strm = si_strm(si);
6045 struct channel *res = si_ic(si);
6046 struct act_rule *rule = ctx->rule;
6047 struct proxy *px = strm->be;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006048 struct hlua *hlua = ctx->ctx.hlua_apptcp.hlua;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006049
6050 /* The applet execution is already done. */
6051 if (ctx->ctx.hlua_apptcp.flags & APPLET_DONE)
6052 return;
6053
6054 /* If the stream is disconnect or closed, ldo nothing. */
6055 if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO))
6056 return;
6057
6058 /* Execute the function. */
6059 switch (hlua_ctx_resume(hlua, 1)) {
6060 /* finished. */
6061 case HLUA_E_OK:
6062 ctx->ctx.hlua_apptcp.flags |= APPLET_DONE;
6063
6064 /* log time */
6065 strm->logs.tv_request = now;
6066
6067 /* eat the whole request */
6068 bo_skip(si_oc(si), si_ob(si)->o);
6069 res->flags |= CF_READ_NULL;
6070 si_shutr(si);
6071 return;
6072
6073 /* yield. */
6074 case HLUA_E_AGAIN:
Thierry Fournier0164f202016-02-20 17:47:43 +01006075 if (hlua->wake_time != TICK_ETERNITY)
6076 task_schedule(ctx->ctx.hlua_apptcp.task, hlua->wake_time);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006077 return;
6078
6079 /* finished with error. */
6080 case HLUA_E_ERRMSG:
6081 /* Display log. */
6082 SEND_ERR(px, "Lua applet tcp '%s': %s.\n",
6083 rule->arg.hlua_rule->fcn.name, lua_tostring(hlua->T, -1));
6084 lua_pop(hlua->T, 1);
6085 goto error;
6086
6087 case HLUA_E_ERR:
6088 /* Display log. */
6089 SEND_ERR(px, "Lua applet tcp '%s' return an unknown error.\n",
6090 rule->arg.hlua_rule->fcn.name);
6091 goto error;
6092
6093 default:
6094 goto error;
6095 }
6096
6097error:
6098
6099 /* For all other cases, just close the stream. */
6100 si_shutw(si);
6101 si_shutr(si);
6102 ctx->ctx.hlua_apptcp.flags |= APPLET_DONE;
6103}
6104
6105static void hlua_applet_tcp_release(struct appctx *ctx)
6106{
6107 task_free(ctx->ctx.hlua_apptcp.task);
6108 ctx->ctx.hlua_apptcp.task = NULL;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006109 hlua_ctx_destroy(ctx->ctx.hlua_apptcp.hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006110 ctx->ctx.hlua_apptcp.hlua = NULL;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006111}
6112
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006113/* The function returns 1 if the initialisation is complete, 0 if
6114 * an errors occurs and -1 if more data are required for initializing
6115 * the applet.
6116 */
6117static int hlua_applet_http_init(struct appctx *ctx, struct proxy *px, struct stream *strm)
6118{
6119 struct stream_interface *si = ctx->owner;
6120 struct channel *req = si_oc(si);
6121 struct http_msg *msg;
6122 struct http_txn *txn;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006123 struct hlua *hlua;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006124 char **arg;
6125 struct hdr_ctx hdr;
6126 struct task *task;
6127 struct sample smp; /* just used for a valid call to smp_prefetch_http. */
Thierry Fournierfd107a22016-02-19 19:57:23 +01006128 const char *error;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006129
6130 /* Wait for a full HTTP request. */
6131 if (!smp_prefetch_http(px, strm, 0, NULL, &smp, 0)) {
6132 if (smp.flags & SMP_F_MAY_CHANGE)
6133 return -1;
6134 return 0;
6135 }
6136 txn = strm->txn;
6137 msg = &txn->req;
6138
Willy Tarreau0078bfc2015-10-07 20:20:28 +02006139 /* We want two things in HTTP mode :
6140 * - enforce server-close mode if we were in keep-alive, so that the
6141 * applet is released after each response ;
6142 * - enable request body transfer to the applet in order to resync
6143 * with the response body.
6144 */
6145 if ((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL)
6146 txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | TX_CON_WANT_SCL;
Willy Tarreau0078bfc2015-10-07 20:20:28 +02006147
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006148 hlua = pool_alloc2(pool2_hlua);
6149 if (!hlua) {
6150 SEND_ERR(px, "Lua applet http '%s': out of memory.\n",
6151 ctx->rule->arg.hlua_rule->fcn.name);
6152 return 0;
6153 }
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006154 HLUA_INIT(hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006155 ctx->ctx.hlua_apphttp.hlua = hlua;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006156 ctx->ctx.hlua_apphttp.left_bytes = -1;
6157 ctx->ctx.hlua_apphttp.flags = 0;
6158
Thierry FOURNIERd93ea2b2015-12-20 19:14:52 +01006159 if (txn->req.flags & HTTP_MSGF_VER_11)
6160 ctx->ctx.hlua_apphttp.flags |= APPLET_HTTP11;
6161
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006162 /* Create task used by signal to wakeup applets. */
6163 task = task_new();
6164 if (!task) {
6165 SEND_ERR(px, "Lua applet http '%s': out of memory.\n",
6166 ctx->rule->arg.hlua_rule->fcn.name);
6167 return 0;
6168 }
6169 task->nice = 0;
6170 task->context = ctx;
6171 task->process = hlua_applet_wakeup;
6172 ctx->ctx.hlua_apphttp.task = task;
6173
6174 /* In the execution wrappers linked with a stream, the
6175 * Lua context can be not initialized. This behavior
6176 * permits to save performances because a systematic
6177 * Lua initialization cause 5% performances loss.
6178 */
6179 if (!hlua_ctx_init(hlua, task)) {
6180 SEND_ERR(px, "Lua applet http '%s': can't initialize Lua context.\n",
6181 ctx->rule->arg.hlua_rule->fcn.name);
6182 return 0;
6183 }
6184
6185 /* Set timeout according with the applet configuration. */
Thierry FOURNIER10770fa2015-09-29 01:59:42 +02006186 hlua->max_time = ctx->applet->timeout;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006187
6188 /* The following Lua calls can fail. */
6189 if (!SET_SAFE_LJMP(hlua->T)) {
Thierry Fournierfd107a22016-02-19 19:57:23 +01006190 if (lua_type(hlua->T, -1) == LUA_TSTRING)
6191 error = lua_tostring(hlua->T, -1);
6192 else
6193 error = "critical error";
6194 SEND_ERR(px, "Lua applet http '%s': %s.\n",
6195 ctx->rule->arg.hlua_rule->fcn.name, error);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006196 return 0;
6197 }
6198
6199 /* Check stack available size. */
6200 if (!lua_checkstack(hlua->T, 1)) {
6201 SEND_ERR(px, "Lua applet http '%s': full stack.\n",
6202 ctx->rule->arg.hlua_rule->fcn.name);
6203 RESET_SAFE_LJMP(hlua->T);
6204 return 0;
6205 }
6206
6207 /* Restore the function in the stack. */
6208 lua_rawgeti(hlua->T, LUA_REGISTRYINDEX, ctx->rule->arg.hlua_rule->fcn.function_ref);
6209
6210 /* Create and and push object stream in the stack. */
6211 if (!hlua_applet_http_new(hlua->T, ctx)) {
6212 SEND_ERR(px, "Lua applet http '%s': full stack.\n",
6213 ctx->rule->arg.hlua_rule->fcn.name);
6214 RESET_SAFE_LJMP(hlua->T);
6215 return 0;
6216 }
6217 hlua->nargs = 1;
6218
6219 /* Look for a 100-continue expected. */
6220 if (msg->flags & HTTP_MSGF_VER_11) {
6221 hdr.idx = 0;
6222 if (http_find_header2("Expect", 6, req->buf->p, &txn->hdr_idx, &hdr) &&
6223 unlikely(hdr.vlen == 12 && strncasecmp(hdr.line+hdr.val, "100-continue", 12) == 0))
6224 ctx->ctx.hlua_apphttp.flags |= APPLET_100C;
6225 }
6226
6227 /* push keywords in the stack. */
6228 for (arg = ctx->rule->arg.hlua_rule->args; arg && *arg; arg++) {
6229 if (!lua_checkstack(hlua->T, 1)) {
6230 SEND_ERR(px, "Lua applet http '%s': full stack.\n",
6231 ctx->rule->arg.hlua_rule->fcn.name);
6232 RESET_SAFE_LJMP(hlua->T);
6233 return 0;
6234 }
6235 lua_pushstring(hlua->T, *arg);
6236 hlua->nargs++;
6237 }
6238
6239 RESET_SAFE_LJMP(hlua->T);
6240
6241 /* Wakeup the applet when data is ready for read. */
6242 si_applet_cant_get(si);
6243
6244 return 1;
6245}
6246
6247static void hlua_applet_http_fct(struct appctx *ctx)
6248{
6249 struct stream_interface *si = ctx->owner;
6250 struct stream *strm = si_strm(si);
6251 struct channel *res = si_ic(si);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006252 struct act_rule *rule = ctx->rule;
6253 struct proxy *px = strm->be;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006254 struct hlua *hlua = ctx->ctx.hlua_apphttp.hlua;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006255 char *blk1;
6256 int len1;
6257 char *blk2;
6258 int len2;
6259 int ret;
6260
6261 /* If the stream is disconnect or closed, ldo nothing. */
6262 if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO))
6263 return;
6264
6265 /* Set the currently running flag. */
6266 if (!HLUA_IS_RUNNING(hlua) &&
6267 !(ctx->ctx.hlua_apphttp.flags & APPLET_DONE)) {
6268
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006269 /* Wait for full HTTP analysys. */
6270 if (unlikely(strm->txn->req.msg_state < HTTP_MSG_BODY)) {
6271 si_applet_cant_get(si);
6272 return;
6273 }
6274
6275 /* Store the max amount of bytes that we can read. */
6276 ctx->ctx.hlua_apphttp.left_bytes = strm->txn->req.body_len;
6277
6278 /* We need to flush the request header. This left the body
6279 * for the Lua.
6280 */
6281
6282 /* Read the maximum amount of data avalaible. */
6283 ret = bo_getblk_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
6284 if (ret == -1)
6285 return;
6286
6287 /* No data available, ask for more data. */
6288 if (ret == 1)
6289 len2 = 0;
6290 if (ret == 0)
6291 len1 = 0;
6292 if (len1 + len2 < strm->txn->req.eoh + 2) {
6293 si_applet_cant_get(si);
6294 return;
6295 }
6296
6297 /* skip the requests bytes. */
6298 bo_skip(si_oc(si), strm->txn->req.eoh + 2);
6299 }
6300
6301 /* Executes The applet if it is not done. */
6302 if (!(ctx->ctx.hlua_apphttp.flags & APPLET_DONE)) {
6303
6304 /* Execute the function. */
6305 switch (hlua_ctx_resume(hlua, 1)) {
6306 /* finished. */
6307 case HLUA_E_OK:
6308 ctx->ctx.hlua_apphttp.flags |= APPLET_DONE;
6309 break;
6310
6311 /* yield. */
6312 case HLUA_E_AGAIN:
Thierry Fournier0164f202016-02-20 17:47:43 +01006313 if (hlua->wake_time != TICK_ETERNITY)
6314 task_schedule(ctx->ctx.hlua_apphttp.task, hlua->wake_time);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006315 return;
6316
6317 /* finished with error. */
6318 case HLUA_E_ERRMSG:
6319 /* Display log. */
6320 SEND_ERR(px, "Lua applet http '%s': %s.\n",
6321 rule->arg.hlua_rule->fcn.name, lua_tostring(hlua->T, -1));
6322 lua_pop(hlua->T, 1);
6323 goto error;
6324
6325 case HLUA_E_ERR:
6326 /* Display log. */
6327 SEND_ERR(px, "Lua applet http '%s' return an unknown error.\n",
6328 rule->arg.hlua_rule->fcn.name);
6329 goto error;
6330
6331 default:
6332 goto error;
6333 }
6334 }
6335
6336 if (ctx->ctx.hlua_apphttp.flags & APPLET_DONE) {
6337
6338 /* We must send the final chunk. */
6339 if (ctx->ctx.hlua_apphttp.flags & APPLET_CHUNKED &&
6340 !(ctx->ctx.hlua_apphttp.flags & APPLET_LAST_CHK)) {
6341
6342 /* sent last chunk at once. */
6343 ret = bi_putblk(res, "0\r\n\r\n", 5);
6344
6345 /* critical error. */
6346 if (ret == -2 || ret == -3) {
6347 SEND_ERR(px, "Lua applet http '%s'cannont send last chunk.\n",
6348 rule->arg.hlua_rule->fcn.name);
6349 goto error;
6350 }
6351
6352 /* no enough space error. */
6353 if (ret == -1) {
6354 si_applet_cant_put(si);
6355 return;
6356 }
6357
6358 /* set the last chunk sent. */
6359 ctx->ctx.hlua_apphttp.flags |= APPLET_LAST_CHK;
6360 }
6361
6362 /* close the connection. */
6363
6364 /* status / log */
6365 strm->txn->status = ctx->ctx.hlua_apphttp.status;
6366 strm->logs.tv_request = now;
6367
6368 /* eat the whole request */
6369 bo_skip(si_oc(si), si_ob(si)->o);
6370 res->flags |= CF_READ_NULL;
6371 si_shutr(si);
6372
6373 return;
6374 }
6375
6376error:
6377
6378 /* If we are in HTTP mode, and we are not send any
6379 * data, return a 500 server error in best effort:
6380 * if there are no room avalaible in the buffer,
6381 * just close the connection.
6382 */
6383 bi_putblk(res, error_500, strlen(error_500));
6384 if (!(strm->flags & SF_ERR_MASK))
6385 strm->flags |= SF_ERR_RESOURCE;
6386 si_shutw(si);
6387 si_shutr(si);
6388 ctx->ctx.hlua_apphttp.flags |= APPLET_DONE;
6389}
6390
6391static void hlua_applet_http_release(struct appctx *ctx)
6392{
6393 task_free(ctx->ctx.hlua_apphttp.task);
6394 ctx->ctx.hlua_apphttp.task = NULL;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006395 hlua_ctx_destroy(ctx->ctx.hlua_apphttp.hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006396 ctx->ctx.hlua_apphttp.hlua = NULL;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006397}
6398
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006399/* global {tcp|http}-request parser. Return ACT_RET_PRS_OK in
6400 * succes case, else return ACT_RET_PRS_ERR.
Thierry FOURNIERbabae282015-09-17 11:36:37 +02006401 *
6402 * This function can fail with an abort() due to an Lua critical error.
6403 * We are in the configuration parsing process of HAProxy, this abort() is
6404 * tolerated.
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006405 */
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006406static enum act_parse_ret action_register_lua(const char **args, int *cur_arg, struct proxy *px,
6407 struct act_rule *rule, char **err)
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006408{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02006409 struct hlua_function *fcn = rule->kw->private;
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006410 int i;
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006411
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006412 /* Memory for the rule. */
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02006413 rule->arg.hlua_rule = calloc(1, sizeof(*rule->arg.hlua_rule));
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006414 if (!rule->arg.hlua_rule) {
6415 memprintf(err, "out of memory error");
Thierry FOURNIERafa80492015-08-19 09:04:15 +02006416 return ACT_RET_PRS_ERR;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006417 }
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006418
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006419 /* Memory for arguments. */
6420 rule->arg.hlua_rule->args = calloc(fcn->nargs + 1, sizeof(char *));
6421 if (!rule->arg.hlua_rule->args) {
6422 memprintf(err, "out of memory error");
6423 return ACT_RET_PRS_ERR;
6424 }
6425
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006426 /* Reference the Lua function and store the reference. */
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006427 rule->arg.hlua_rule->fcn = *fcn;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006428
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006429 /* Expect some arguments */
6430 for (i = 0; i < fcn->nargs; i++) {
6431 if (*args[i+1] == '\0') {
6432 memprintf(err, "expect %d arguments", fcn->nargs);
6433 return ACT_RET_PRS_ERR;
6434 }
6435 rule->arg.hlua_rule->args[i] = strdup(args[i + 1]);
6436 if (!rule->arg.hlua_rule->args[i]) {
6437 memprintf(err, "out of memory error");
6438 return ACT_RET_PRS_ERR;
6439 }
6440 (*cur_arg)++;
6441 }
6442 rule->arg.hlua_rule->args[i] = NULL;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006443
Thierry FOURNIER42148732015-09-02 17:17:33 +02006444 rule->action = ACT_CUSTOM;
Thierry FOURNIER4dc15d12015-08-06 18:25:56 +02006445 rule->action_ptr = hlua_action;
Thierry FOURNIERafa80492015-08-19 09:04:15 +02006446 return ACT_RET_PRS_OK;
Thierry FOURNIER258d8aa2015-02-16 20:23:40 +01006447}
6448
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006449static enum act_parse_ret action_register_service_http(const char **args, int *cur_arg, struct proxy *px,
6450 struct act_rule *rule, char **err)
6451{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02006452 struct hlua_function *fcn = rule->kw->private;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006453
Thierry FOURNIER718e2a72015-12-20 20:13:14 +01006454 /* HTTP applets are forbidden in tcp-request rules.
6455 * HTTP applet request requires everything initilized by
6456 * "http_process_request" (analyzer flag AN_REQ_HTTP_INNER).
6457 * The applet will be immediately initilized, but its before
6458 * the call of this analyzer.
6459 */
6460 if (rule->from != ACT_F_HTTP_REQ) {
6461 memprintf(err, "HTTP applets are forbidden from 'tcp-request' rulesets");
6462 return ACT_RET_PRS_ERR;
6463 }
6464
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006465 /* Memory for the rule. */
6466 rule->arg.hlua_rule = calloc(1, sizeof(*rule->arg.hlua_rule));
6467 if (!rule->arg.hlua_rule) {
6468 memprintf(err, "out of memory error");
6469 return ACT_RET_PRS_ERR;
6470 }
6471
6472 /* Reference the Lua function and store the reference. */
6473 rule->arg.hlua_rule->fcn = *fcn;
6474
6475 /* TODO: later accept arguments. */
6476 rule->arg.hlua_rule->args = NULL;
6477
6478 /* Add applet pointer in the rule. */
6479 rule->applet.obj_type = OBJ_TYPE_APPLET;
6480 rule->applet.name = fcn->name;
6481 rule->applet.init = hlua_applet_http_init;
6482 rule->applet.fct = hlua_applet_http_fct;
6483 rule->applet.release = hlua_applet_http_release;
6484 rule->applet.timeout = hlua_timeout_applet;
6485
6486 return ACT_RET_PRS_OK;
6487}
6488
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006489/* This function is an LUA binding used for registering
6490 * "sample-conv" functions. It expects a converter name used
6491 * in the haproxy configuration file, and an LUA function.
6492 */
6493__LJMP static int hlua_register_action(lua_State *L)
6494{
6495 struct action_kw_list *akl;
6496 const char *name;
6497 int ref;
6498 int len;
6499 struct hlua_function *fcn;
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006500 int nargs;
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006501
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006502 /* Initialise the number of expected arguments at 0. */
6503 nargs = 0;
6504
6505 if (lua_gettop(L) < 3 || lua_gettop(L) > 4)
6506 WILL_LJMP(luaL_error(L, "'register_action' needs between 3 and 4 arguments"));
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006507
6508 /* First argument : converter name. */
6509 name = MAY_LJMP(luaL_checkstring(L, 1));
6510
6511 /* Second argument : environment. */
6512 if (lua_type(L, 2) != LUA_TTABLE)
6513 WILL_LJMP(luaL_error(L, "register_action: second argument must be a table of strings"));
6514
6515 /* Third argument : lua function. */
6516 ref = MAY_LJMP(hlua_checkfunction(L, 3));
6517
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006518 /* Fouth argument : number of mandatories arguments expected on the configuration line. */
6519 if (lua_gettop(L) >= 4)
6520 nargs = MAY_LJMP(luaL_checkinteger(L, 4));
6521
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006522 /* browse the second argulent as an array. */
6523 lua_pushnil(L);
6524 while (lua_next(L, 2) != 0) {
6525 if (lua_type(L, -1) != LUA_TSTRING)
6526 WILL_LJMP(luaL_error(L, "register_action: second argument must be a table of strings"));
6527
6528 /* Check required environment. Only accepted "http" or "tcp". */
6529 /* Allocate and fill the sample fetch keyword struct. */
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02006530 akl = calloc(1, sizeof(*akl) + sizeof(struct action_kw) * 2);
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006531 if (!akl)
6532 WILL_LJMP(luaL_error(L, "lua out of memory error."));
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02006533 fcn = calloc(1, sizeof(*fcn));
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006534 if (!fcn)
6535 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6536
6537 /* Fill fcn. */
6538 fcn->name = strdup(name);
6539 if (!fcn->name)
6540 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6541 fcn->function_ref = ref;
6542
Thierry FOURNIER / OZON.IO4b123be2016-12-09 18:03:31 +01006543 /* Set the expected number od arguments. */
6544 fcn->nargs = nargs;
6545
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006546 /* List head */
6547 akl->list.n = akl->list.p = NULL;
6548
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006549 /* action keyword. */
6550 len = strlen("lua.") + strlen(name) + 1;
Thierry FOURNIER3c7a77c2015-09-26 00:51:16 +02006551 akl->kw[0].kw = calloc(1, len);
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006552 if (!akl->kw[0].kw)
6553 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6554
6555 snprintf((char *)akl->kw[0].kw, len, "lua.%s", name);
6556
6557 akl->kw[0].match_pfx = 0;
6558 akl->kw[0].private = fcn;
6559 akl->kw[0].parse = action_register_lua;
6560
6561 /* select the action registering point. */
6562 if (strcmp(lua_tostring(L, -1), "tcp-req") == 0)
6563 tcp_req_cont_keywords_register(akl);
6564 else if (strcmp(lua_tostring(L, -1), "tcp-res") == 0)
6565 tcp_res_cont_keywords_register(akl);
6566 else if (strcmp(lua_tostring(L, -1), "http-req") == 0)
6567 http_req_keywords_register(akl);
6568 else if (strcmp(lua_tostring(L, -1), "http-res") == 0)
6569 http_res_keywords_register(akl);
6570 else
6571 WILL_LJMP(luaL_error(L, "lua action environment '%s' is unknown. "
6572 "'tcp-req', 'tcp-res', 'http-req' or 'http-res' "
6573 "are expected.", lua_tostring(L, -1)));
6574
6575 /* pop the environment string. */
6576 lua_pop(L, 1);
6577 }
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006578 return ACT_RET_PRS_OK;
6579}
6580
6581static enum act_parse_ret action_register_service_tcp(const char **args, int *cur_arg, struct proxy *px,
6582 struct act_rule *rule, char **err)
6583{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02006584 struct hlua_function *fcn = rule->kw->private;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006585
6586 /* Memory for the rule. */
6587 rule->arg.hlua_rule = calloc(1, sizeof(*rule->arg.hlua_rule));
6588 if (!rule->arg.hlua_rule) {
6589 memprintf(err, "out of memory error");
6590 return ACT_RET_PRS_ERR;
6591 }
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006592
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006593 /* Reference the Lua function and store the reference. */
6594 rule->arg.hlua_rule->fcn = *fcn;
6595
6596 /* TODO: later accept arguments. */
6597 rule->arg.hlua_rule->args = NULL;
6598
6599 /* Add applet pointer in the rule. */
6600 rule->applet.obj_type = OBJ_TYPE_APPLET;
6601 rule->applet.name = fcn->name;
6602 rule->applet.init = hlua_applet_tcp_init;
6603 rule->applet.fct = hlua_applet_tcp_fct;
6604 rule->applet.release = hlua_applet_tcp_release;
6605 rule->applet.timeout = hlua_timeout_applet;
6606
6607 return 0;
6608}
6609
6610/* This function is an LUA binding used for registering
6611 * "sample-conv" functions. It expects a converter name used
6612 * in the haproxy configuration file, and an LUA function.
6613 */
6614__LJMP static int hlua_register_service(lua_State *L)
6615{
6616 struct action_kw_list *akl;
6617 const char *name;
6618 const char *env;
6619 int ref;
6620 int len;
6621 struct hlua_function *fcn;
6622
6623 MAY_LJMP(check_args(L, 3, "register_service"));
6624
6625 /* First argument : converter name. */
6626 name = MAY_LJMP(luaL_checkstring(L, 1));
6627
6628 /* Second argument : environment. */
6629 env = MAY_LJMP(luaL_checkstring(L, 2));
6630
6631 /* Third argument : lua function. */
6632 ref = MAY_LJMP(hlua_checkfunction(L, 3));
6633
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006634 /* Allocate and fill the sample fetch keyword struct. */
6635 akl = calloc(1, sizeof(*akl) + sizeof(struct action_kw) * 2);
6636 if (!akl)
6637 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6638 fcn = calloc(1, sizeof(*fcn));
6639 if (!fcn)
6640 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6641
6642 /* Fill fcn. */
6643 len = strlen("<lua.>") + strlen(name) + 1;
6644 fcn->name = calloc(1, len);
6645 if (!fcn->name)
6646 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6647 snprintf((char *)fcn->name, len, "<lua.%s>", name);
6648 fcn->function_ref = ref;
6649
6650 /* List head */
6651 akl->list.n = akl->list.p = NULL;
6652
6653 /* converter keyword. */
6654 len = strlen("lua.") + strlen(name) + 1;
6655 akl->kw[0].kw = calloc(1, len);
6656 if (!akl->kw[0].kw)
6657 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6658
6659 snprintf((char *)akl->kw[0].kw, len, "lua.%s", name);
6660
Thierry FOURNIER / OZON.IO02564fd2016-11-12 11:07:05 +01006661 /* Check required environment. Only accepted "http" or "tcp". */
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006662 if (strcmp(env, "tcp") == 0)
6663 akl->kw[0].parse = action_register_service_tcp;
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006664 else if (strcmp(env, "http") == 0)
6665 akl->kw[0].parse = action_register_service_http;
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006666 else
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02006667 WILL_LJMP(luaL_error(L, "lua service environment '%s' is unknown. "
6668 "'tcp' or 'http' are expected."));
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006669
6670 akl->kw[0].match_pfx = 0;
6671 akl->kw[0].private = fcn;
6672
6673 /* End of array. */
6674 memset(&akl->kw[1], 0, sizeof(*akl->kw));
6675
6676 /* Register this new converter */
6677 service_keywords_register(akl);
6678
Thierry FOURNIER8255a752015-09-23 21:03:35 +02006679 return 0;
6680}
6681
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006682/* This function initialises Lua cli handler. It copies the
6683 * arguments in the Lua stack and create channel IO objects.
6684 */
6685static int hlua_cli_parse_fct(char **args, struct appctx *appctx, void *private)
6686{
6687 struct hlua *hlua;
6688 struct hlua_function *fcn;
6689 int i;
6690 const char *error;
6691
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006692 fcn = private;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006693 appctx->ctx.hlua_cli.fcn = private;
6694
6695 hlua = pool_alloc2(pool2_hlua);
6696 if (!hlua) {
6697 SEND_ERR(NULL, "Lua cli '%s': out of memory.\n", fcn->name);
Thierry FOURNIER1be34152016-12-17 12:09:51 +01006698 return 1;
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006699 }
6700 HLUA_INIT(hlua);
6701 appctx->ctx.hlua_cli.hlua = hlua;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006702
6703 /* Create task used by signal to wakeup applets.
6704 * We use the same wakeup fonction than the Lua applet_tcp and
6705 * applet_http. It is absolutely compatible.
6706 */
6707 appctx->ctx.hlua_cli.task = task_new();
6708 if (!appctx->ctx.hlua_cli.task) {
Thierry FOURNIERffbf5692016-12-16 11:14:06 +01006709 SEND_ERR(NULL, "Lua cli '%s': out of memory.\n", fcn->name);
Thierry FOURNIER1be34152016-12-17 12:09:51 +01006710 goto error;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006711 }
6712 appctx->ctx.hlua_cli.task->nice = 0;
6713 appctx->ctx.hlua_cli.task->context = appctx;
6714 appctx->ctx.hlua_cli.task->process = hlua_applet_wakeup;
6715
6716 /* Initialises the Lua context */
6717 if (!hlua_ctx_init(hlua, appctx->ctx.hlua_cli.task)) {
6718 SEND_ERR(NULL, "Lua cli '%s': can't initialize Lua context.\n", fcn->name);
Thierry FOURNIER1be34152016-12-17 12:09:51 +01006719 goto error;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006720 }
6721
6722 /* The following Lua calls can fail. */
6723 if (!SET_SAFE_LJMP(hlua->T)) {
6724 if (lua_type(hlua->T, -1) == LUA_TSTRING)
6725 error = lua_tostring(hlua->T, -1);
6726 else
6727 error = "critical error";
6728 SEND_ERR(NULL, "Lua cli '%s': %s.\n", fcn->name, error);
6729 goto error;
6730 }
6731
6732 /* Check stack available size. */
6733 if (!lua_checkstack(hlua->T, 2)) {
6734 SEND_ERR(NULL, "Lua cli '%s': full stack.\n", fcn->name);
6735 goto error;
6736 }
6737
6738 /* Restore the function in the stack. */
6739 lua_rawgeti(hlua->T, LUA_REGISTRYINDEX, fcn->function_ref);
6740
6741 /* Once the arguments parsed, the CLI is like an AppletTCP,
6742 * so push AppletTCP in the stack.
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006743 */
6744 if (!hlua_applet_tcp_new(hlua->T, appctx)) {
6745 SEND_ERR(NULL, "Lua cli '%s': full stack.\n", fcn->name);
6746 goto error;
6747 }
6748 hlua->nargs = 1;
6749
6750 /* push keywords in the stack. */
6751 for (i = 0; *args[i]; i++) {
6752 /* Check stack available size. */
6753 if (!lua_checkstack(hlua->T, 1)) {
6754 SEND_ERR(NULL, "Lua cli '%s': full stack.\n", fcn->name);
6755 goto error;
6756 }
6757 lua_pushstring(hlua->T, args[i]);
6758 hlua->nargs++;
6759 }
6760
6761 /* We must initialize the execution timeouts. */
6762 hlua->max_time = hlua_timeout_session;
6763
6764 /* At this point the execution is safe. */
6765 RESET_SAFE_LJMP(hlua->T);
6766
6767 /* It's ok */
6768 return 0;
6769
6770 /* It's not ok. */
6771error:
6772 RESET_SAFE_LJMP(hlua->T);
6773 hlua_ctx_destroy(hlua);
Thierry FOURNIER1be34152016-12-17 12:09:51 +01006774 appctx->ctx.hlua_cli.hlua = NULL;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006775 return 1;
6776}
6777
6778static int hlua_cli_io_handler_fct(struct appctx *appctx)
6779{
6780 struct hlua *hlua;
6781 struct stream_interface *si;
6782 struct hlua_function *fcn;
6783
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006784 hlua = appctx->ctx.hlua_cli.hlua;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006785 si = appctx->owner;
Willy Tarreau8ae4f752016-12-14 15:41:45 +01006786 fcn = appctx->ctx.hlua_cli.fcn;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006787
6788 /* If the stream is disconnect or closed, ldo nothing. */
6789 if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO))
6790 return 1;
6791
6792 /* Execute the function. */
6793 switch (hlua_ctx_resume(hlua, 1)) {
6794
6795 /* finished. */
6796 case HLUA_E_OK:
6797 return 1;
6798
6799 /* yield. */
6800 case HLUA_E_AGAIN:
6801 /* We want write. */
6802 if (HLUA_IS_WAKERESWR(hlua))
6803 si_applet_cant_put(si);
6804 /* Set the timeout. */
6805 if (hlua->wake_time != TICK_ETERNITY)
6806 task_schedule(hlua->task, hlua->wake_time);
6807 return 0;
6808
6809 /* finished with error. */
6810 case HLUA_E_ERRMSG:
6811 /* Display log. */
6812 SEND_ERR(NULL, "Lua cli '%s': %s.\n",
6813 fcn->name, lua_tostring(hlua->T, -1));
6814 lua_pop(hlua->T, 1);
6815 return 1;
6816
6817 case HLUA_E_ERR:
6818 /* Display log. */
6819 SEND_ERR(NULL, "Lua cli '%s' return an unknown error.\n",
6820 fcn->name);
6821 return 1;
6822
6823 default:
6824 return 1;
6825 }
6826
6827 return 1;
6828}
6829
6830static void hlua_cli_io_release_fct(struct appctx *appctx)
6831{
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006832 hlua_ctx_destroy(appctx->ctx.hlua_cli.hlua);
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01006833 appctx->ctx.hlua_cli.hlua = NULL;
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01006834}
6835
6836/* This function is an LUA binding used for registering
6837 * new keywords in the cli. It expects a list of keywords
6838 * which are the "path". It is limited to 5 keywords. A
6839 * description of the command, a function to be executed
6840 * for the parsing and a function for io handlers.
6841 */
6842__LJMP static int hlua_register_cli(lua_State *L)
6843{
6844 struct cli_kw_list *cli_kws;
6845 const char *message;
6846 int ref_io;
6847 int len;
6848 struct hlua_function *fcn;
6849 int index;
6850 int i;
6851
6852 MAY_LJMP(check_args(L, 3, "register_cli"));
6853
6854 /* First argument : an array of maximum 5 keywords. */
6855 if (!lua_istable(L, 1))
6856 WILL_LJMP(luaL_argerror(L, 1, "1st argument must be a table"));
6857
6858 /* Second argument : string with contextual message. */
6859 message = MAY_LJMP(luaL_checkstring(L, 2));
6860
6861 /* Third and fourth argument : lua function. */
6862 ref_io = MAY_LJMP(hlua_checkfunction(L, 3));
6863
6864 /* Allocate and fill the sample fetch keyword struct. */
6865 cli_kws = calloc(1, sizeof(*cli_kws) + sizeof(struct cli_kw) * 2);
6866 if (!cli_kws)
6867 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6868 fcn = calloc(1, sizeof(*fcn));
6869 if (!fcn)
6870 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6871
6872 /* Fill path. */
6873 index = 0;
6874 lua_pushnil(L);
6875 while(lua_next(L, 1) != 0) {
6876 if (index >= 5)
6877 WILL_LJMP(luaL_argerror(L, 1, "1st argument must be a table with a maximum of 5 entries"));
6878 if (lua_type(L, -1) != LUA_TSTRING)
6879 WILL_LJMP(luaL_argerror(L, 1, "1st argument must be a table filled with strings"));
6880 cli_kws->kw[0].str_kw[index] = strdup(lua_tostring(L, -1));
6881 if (!cli_kws->kw[0].str_kw[index])
6882 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6883 index++;
6884 lua_pop(L, 1);
6885 }
6886
6887 /* Copy help message. */
6888 cli_kws->kw[0].usage = strdup(message);
6889 if (!cli_kws->kw[0].usage)
6890 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6891
6892 /* Fill fcn io handler. */
6893 len = strlen("<lua.cli>") + 1;
6894 for (i = 0; i < index; i++)
6895 len += strlen(cli_kws->kw[0].str_kw[i]) + 1;
6896 fcn->name = calloc(1, len);
6897 if (!fcn->name)
6898 WILL_LJMP(luaL_error(L, "lua out of memory error."));
6899 strncat((char *)fcn->name, "<lua.cli", len);
6900 for (i = 0; i < index; i++) {
6901 strncat((char *)fcn->name, ".", len);
6902 strncat((char *)fcn->name, cli_kws->kw[0].str_kw[i], len);
6903 }
6904 strncat((char *)fcn->name, ">", len);
6905 fcn->function_ref = ref_io;
6906
6907 /* Fill last entries. */
6908 cli_kws->kw[0].private = fcn;
6909 cli_kws->kw[0].parse = hlua_cli_parse_fct;
6910 cli_kws->kw[0].io_handler = hlua_cli_io_handler_fct;
6911 cli_kws->kw[0].io_release = hlua_cli_io_release_fct;
6912
6913 /* Register this new converter */
6914 cli_register_kw(cli_kws);
6915
6916 return 0;
6917}
6918
Thierry FOURNIERbd413492015-03-03 16:52:26 +01006919static int hlua_read_timeout(char **args, int section_type, struct proxy *curpx,
6920 struct proxy *defpx, const char *file, int line,
6921 char **err, unsigned int *timeout)
6922{
6923 const char *error;
6924
6925 error = parse_time_err(args[1], timeout, TIME_UNIT_MS);
6926 if (error && *error != '\0') {
6927 memprintf(err, "%s: invalid timeout", args[0]);
6928 return -1;
6929 }
6930 return 0;
6931}
6932
6933static int hlua_session_timeout(char **args, int section_type, struct proxy *curpx,
6934 struct proxy *defpx, const char *file, int line,
6935 char **err)
6936{
6937 return hlua_read_timeout(args, section_type, curpx, defpx,
6938 file, line, err, &hlua_timeout_session);
6939}
6940
6941static int hlua_task_timeout(char **args, int section_type, struct proxy *curpx,
6942 struct proxy *defpx, const char *file, int line,
6943 char **err)
6944{
6945 return hlua_read_timeout(args, section_type, curpx, defpx,
6946 file, line, err, &hlua_timeout_task);
6947}
6948
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02006949static int hlua_applet_timeout(char **args, int section_type, struct proxy *curpx,
6950 struct proxy *defpx, const char *file, int line,
6951 char **err)
6952{
6953 return hlua_read_timeout(args, section_type, curpx, defpx,
6954 file, line, err, &hlua_timeout_applet);
6955}
6956
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01006957static int hlua_forced_yield(char **args, int section_type, struct proxy *curpx,
6958 struct proxy *defpx, const char *file, int line,
6959 char **err)
6960{
6961 char *error;
6962
6963 hlua_nb_instruction = strtoll(args[1], &error, 10);
6964 if (*error != '\0') {
6965 memprintf(err, "%s: invalid number", args[0]);
6966 return -1;
6967 }
6968 return 0;
6969}
6970
Willy Tarreau32f61e22015-03-18 17:54:59 +01006971static int hlua_parse_maxmem(char **args, int section_type, struct proxy *curpx,
6972 struct proxy *defpx, const char *file, int line,
6973 char **err)
6974{
6975 char *error;
6976
6977 if (*(args[1]) == 0) {
6978 memprintf(err, "'%s' expects an integer argument (Lua memory size in MB).\n", args[0]);
6979 return -1;
6980 }
6981 hlua_global_allocator.limit = strtoll(args[1], &error, 10) * 1024L * 1024L;
6982 if (*error != '\0') {
6983 memprintf(err, "%s: invalid number %s (error at '%c')", args[0], args[1], *error);
6984 return -1;
6985 }
6986 return 0;
6987}
6988
6989
Thierry FOURNIER6c9b52c2015-01-23 15:57:06 +01006990/* This function is called by the main configuration key "lua-load". It loads and
6991 * execute an lua file during the parsing of the HAProxy configuration file. It is
6992 * the main lua entry point.
6993 *
6994 * This funtion runs with the HAProxy keywords API. It returns -1 if an error is
6995 * occured, otherwise it returns 0.
6996 *
6997 * In some error case, LUA set an error message in top of the stack. This function
6998 * returns this error message in the HAProxy logs and pop it from the stack.
Thierry FOURNIERbabae282015-09-17 11:36:37 +02006999 *
7000 * This function can fail with an abort() due to an Lua critical error.
7001 * We are in the configuration parsing process of HAProxy, this abort() is
7002 * tolerated.
Thierry FOURNIER6c9b52c2015-01-23 15:57:06 +01007003 */
7004static int hlua_load(char **args, int section_type, struct proxy *curpx,
7005 struct proxy *defpx, const char *file, int line,
7006 char **err)
7007{
7008 int error;
7009
7010 /* Just load and compile the file. */
7011 error = luaL_loadfile(gL.T, args[1]);
7012 if (error) {
7013 memprintf(err, "error in lua file '%s': %s", args[1], lua_tostring(gL.T, -1));
7014 lua_pop(gL.T, 1);
7015 return -1;
7016 }
7017
7018 /* If no syntax error where detected, execute the code. */
7019 error = lua_pcall(gL.T, 0, LUA_MULTRET, 0);
7020 switch (error) {
7021 case LUA_OK:
7022 break;
7023 case LUA_ERRRUN:
7024 memprintf(err, "lua runtime error: %s\n", lua_tostring(gL.T, -1));
7025 lua_pop(gL.T, 1);
7026 return -1;
7027 case LUA_ERRMEM:
7028 memprintf(err, "lua out of memory error\n");
7029 return -1;
7030 case LUA_ERRERR:
7031 memprintf(err, "lua message handler error: %s\n", lua_tostring(gL.T, -1));
7032 lua_pop(gL.T, 1);
7033 return -1;
7034 case LUA_ERRGCMM:
7035 memprintf(err, "lua garbage collector error: %s\n", lua_tostring(gL.T, -1));
7036 lua_pop(gL.T, 1);
7037 return -1;
7038 default:
7039 memprintf(err, "lua unknonwn error: %s\n", lua_tostring(gL.T, -1));
7040 lua_pop(gL.T, 1);
7041 return -1;
7042 }
7043
7044 return 0;
7045}
7046
7047/* configuration keywords declaration */
7048static struct cfg_kw_list cfg_kws = {{ },{
Thierry FOURNIERbd413492015-03-03 16:52:26 +01007049 { CFG_GLOBAL, "lua-load", hlua_load },
7050 { CFG_GLOBAL, "tune.lua.session-timeout", hlua_session_timeout },
7051 { CFG_GLOBAL, "tune.lua.task-timeout", hlua_task_timeout },
Thierry FOURNIER56da1012015-10-01 08:42:31 +02007052 { CFG_GLOBAL, "tune.lua.service-timeout", hlua_applet_timeout },
Thierry FOURNIERee9f8022015-03-03 17:37:37 +01007053 { CFG_GLOBAL, "tune.lua.forced-yield", hlua_forced_yield },
Willy Tarreau32f61e22015-03-18 17:54:59 +01007054 { CFG_GLOBAL, "tune.lua.maxmem", hlua_parse_maxmem },
Thierry FOURNIER6c9b52c2015-01-23 15:57:06 +01007055 { 0, NULL, NULL },
7056}};
7057
Thierry FOURNIERbabae282015-09-17 11:36:37 +02007058/* This function can fail with an abort() due to an Lua critical error.
7059 * We are in the initialisation process of HAProxy, this abort() is
7060 * tolerated.
7061 */
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007062int hlua_post_init()
7063{
7064 struct hlua_init_function *init;
7065 const char *msg;
7066 enum hlua_exec ret;
Thierry Fournierfd107a22016-02-19 19:57:23 +01007067 const char *error;
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007068
Thierry Fournier3d4a6752016-02-19 20:53:30 +01007069 /* Call post initialisation function in safe environement. */
7070 if (!SET_SAFE_LJMP(gL.T)) {
7071 if (lua_type(gL.T, -1) == LUA_TSTRING)
7072 error = lua_tostring(gL.T, -1);
7073 else
7074 error = "critical error";
7075 fprintf(stderr, "Lua post-init: %s.\n", error);
7076 exit(1);
7077 }
7078 hlua_fcn_post_init(gL.T);
7079 RESET_SAFE_LJMP(gL.T);
7080
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007081 list_for_each_entry(init, &hlua_init_functions, l) {
7082 lua_rawgeti(gL.T, LUA_REGISTRYINDEX, init->function_ref);
7083 ret = hlua_ctx_resume(&gL, 0);
7084 switch (ret) {
7085 case HLUA_E_OK:
7086 lua_pop(gL.T, -1);
7087 return 1;
7088 case HLUA_E_AGAIN:
7089 Alert("lua init: yield not allowed.\n");
7090 return 0;
7091 case HLUA_E_ERRMSG:
7092 msg = lua_tostring(gL.T, -1);
7093 Alert("lua init: %s.\n", msg);
7094 return 0;
7095 case HLUA_E_ERR:
7096 default:
7097 Alert("lua init: unknown runtime error.\n");
7098 return 0;
7099 }
7100 }
7101 return 1;
7102}
7103
Willy Tarreau32f61e22015-03-18 17:54:59 +01007104/* The memory allocator used by the Lua stack. <ud> is a pointer to the
7105 * allocator's context. <ptr> is the pointer to alloc/free/realloc. <osize>
7106 * is the previously allocated size or the kind of object in case of a new
7107 * allocation. <nsize> is the requested new size.
7108 */
7109static void *hlua_alloc(void *ud, void *ptr, size_t osize, size_t nsize)
7110{
7111 struct hlua_mem_allocator *zone = ud;
7112
7113 if (nsize == 0) {
7114 /* it's a free */
7115 if (ptr)
7116 zone->allocated -= osize;
7117 free(ptr);
7118 return NULL;
7119 }
7120
7121 if (!ptr) {
7122 /* it's a new allocation */
7123 if (zone->limit && zone->allocated + nsize > zone->limit)
7124 return NULL;
7125
7126 ptr = malloc(nsize);
7127 if (ptr)
7128 zone->allocated += nsize;
7129 return ptr;
7130 }
7131
7132 /* it's a realloc */
7133 if (zone->limit && zone->allocated + nsize - osize > zone->limit)
7134 return NULL;
7135
7136 ptr = realloc(ptr, nsize);
7137 if (ptr)
7138 zone->allocated += nsize - osize;
7139 return ptr;
7140}
7141
Thierry FOURNIERbabae282015-09-17 11:36:37 +02007142/* Ithis function can fail with an abort() due to an Lua critical error.
7143 * We are in the initialisation process of HAProxy, this abort() is
7144 * tolerated.
7145 */
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01007146void hlua_init(void)
7147{
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007148 int i;
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +01007149 int idx;
7150 struct sample_fetch *sf;
Thierry FOURNIER594afe72015-03-10 23:58:30 +01007151 struct sample_conv *sc;
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +01007152 char *p;
Thierry Fournierfd107a22016-02-19 19:57:23 +01007153 const char *error_msg;
Willy Tarreau80f5fae2015-02-27 16:38:20 +01007154#ifdef USE_OPENSSL
Willy Tarreau80f5fae2015-02-27 16:38:20 +01007155 struct srv_kw *kw;
7156 int tmp_error;
7157 char *error;
Thierry FOURNIER36d13742015-03-17 16:48:53 +01007158 char *args[] = { /* SSL client configuration. */
7159 "ssl",
7160 "verify",
7161 "none",
Thierry FOURNIER36d13742015-03-17 16:48:53 +01007162 NULL
7163 };
Willy Tarreau80f5fae2015-02-27 16:38:20 +01007164#endif
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007165
Thierry FOURNIERebed6e92016-12-16 11:54:07 +01007166 /* Initialise struct hlua and com signals pool */
7167 pool2_hlua = create_pool("hlua", sizeof(struct hlua), MEM_F_SHARED);
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +01007168 pool2_hlua_com = create_pool("hlua_com", sizeof(struct hlua_com), MEM_F_SHARED);
7169
Thierry FOURNIER6c9b52c2015-01-23 15:57:06 +01007170 /* Register configuration keywords. */
7171 cfg_register_keywords(&cfg_kws);
7172
Thierry FOURNIER380d0932015-01-23 14:27:52 +01007173 /* Init main lua stack. */
7174 gL.Mref = LUA_REFNIL;
Thierry FOURNIERa097fdf2015-03-03 15:17:35 +01007175 gL.flags = 0;
Thierry FOURNIER9ff7e6e2015-01-23 11:08:20 +01007176 LIST_INIT(&gL.com);
Thierry FOURNIER380d0932015-01-23 14:27:52 +01007177 gL.T = luaL_newstate();
7178 hlua_sethlua(&gL);
7179 gL.Tref = LUA_REFNIL;
7180 gL.task = NULL;
7181
Thierry FOURNIERbabae282015-09-17 11:36:37 +02007182 /* From this point, until the end of the initialisation fucntion,
7183 * the Lua function can fail with an abort. We are in the initialisation
7184 * process of HAProxy, this abort() is tolerated.
7185 */
7186
Willy Tarreau32f61e22015-03-18 17:54:59 +01007187 /* change the memory allocators to track memory usage */
7188 lua_setallocf(gL.T, hlua_alloc, &hlua_global_allocator);
7189
Thierry FOURNIER380d0932015-01-23 14:27:52 +01007190 /* Initialise lua. */
7191 luaL_openlibs(gL.T);
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007192
Thierry Fournier75933d42016-01-21 09:30:18 +01007193 /* Set safe environment for the initialisation. */
7194 if (!SET_SAFE_LJMP(gL.T)) {
Thierry Fournierfd107a22016-02-19 19:57:23 +01007195 if (lua_type(gL.T, -1) == LUA_TSTRING)
7196 error_msg = lua_tostring(gL.T, -1);
7197 else
7198 error_msg = "critical error";
7199 fprintf(stderr, "Lua init: %s.\n", error_msg);
Thierry Fournier75933d42016-01-21 09:30:18 +01007200 exit(1);
7201 }
7202
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007203 /*
7204 *
7205 * Create "core" object.
7206 *
7207 */
7208
Thierry FOURNIERa2d8c652015-03-11 17:29:39 +01007209 /* This table entry is the object "core" base. */
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007210 lua_newtable(gL.T);
7211
7212 /* Push the loglevel constants. */
Willy Tarreau80f5fae2015-02-27 16:38:20 +01007213 for (i = 0; i < NB_LOG_LEVELS; i++)
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007214 hlua_class_const_int(gL.T, log_levels[i], i);
7215
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007216 /* Register special functions. */
7217 hlua_class_function(gL.T, "register_init", hlua_register_init);
Thierry FOURNIER24f33532015-01-23 12:13:00 +01007218 hlua_class_function(gL.T, "register_task", hlua_register_task);
Thierry FOURNIERfa0e5dd2015-02-16 20:19:18 +01007219 hlua_class_function(gL.T, "register_fetches", hlua_register_fetches);
Thierry FOURNIER9be813f2015-02-16 20:21:12 +01007220 hlua_class_function(gL.T, "register_converters", hlua_register_converters);
Thierry FOURNIER8255a752015-09-23 21:03:35 +02007221 hlua_class_function(gL.T, "register_action", hlua_register_action);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007222 hlua_class_function(gL.T, "register_service", hlua_register_service);
Thierry FOURNIER / OZON.IOa44fdd92016-11-13 13:19:20 +01007223 hlua_class_function(gL.T, "register_cli", hlua_register_cli);
Thierry FOURNIER13416fe2015-02-17 15:01:59 +01007224 hlua_class_function(gL.T, "yield", hlua_yield);
Willy Tarreau59551662015-03-10 14:23:13 +01007225 hlua_class_function(gL.T, "set_nice", hlua_set_nice);
Thierry FOURNIER5b8608f2015-02-16 19:43:25 +01007226 hlua_class_function(gL.T, "sleep", hlua_sleep);
7227 hlua_class_function(gL.T, "msleep", hlua_msleep);
Thierry FOURNIER83758bb2015-02-04 13:21:04 +01007228 hlua_class_function(gL.T, "add_acl", hlua_add_acl);
7229 hlua_class_function(gL.T, "del_acl", hlua_del_acl);
7230 hlua_class_function(gL.T, "set_map", hlua_set_map);
7231 hlua_class_function(gL.T, "del_map", hlua_del_map);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007232 hlua_class_function(gL.T, "tcp", hlua_socket_new);
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +01007233 hlua_class_function(gL.T, "log", hlua_log);
7234 hlua_class_function(gL.T, "Debug", hlua_log_debug);
7235 hlua_class_function(gL.T, "Info", hlua_log_info);
7236 hlua_class_function(gL.T, "Warning", hlua_log_warning);
7237 hlua_class_function(gL.T, "Alert", hlua_log_alert);
Thierry FOURNIER0a99b892015-08-26 00:14:17 +02007238 hlua_class_function(gL.T, "done", hlua_done);
Thierry Fournierfb0b5462016-01-21 09:28:58 +01007239 hlua_fcn_reg_core_fcn(gL.T);
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01007240
Thierry FOURNIER2ba18a22015-01-23 14:07:08 +01007241 lua_setglobal(gL.T, "core");
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01007242
7243 /*
7244 *
Thierry FOURNIER3def3932015-04-07 11:27:54 +02007245 * Register class Map
7246 *
7247 */
7248
7249 /* This table entry is the object "Map" base. */
7250 lua_newtable(gL.T);
7251
7252 /* register pattern types. */
7253 for (i=0; i<PAT_MATCH_NUM; i++)
7254 hlua_class_const_int(gL.T, pat_match_names[i], i);
7255
7256 /* register constructor. */
7257 hlua_class_function(gL.T, "new", hlua_map_new);
7258
7259 /* Create and fill the metatable. */
7260 lua_newtable(gL.T);
7261
7262 /* Create and fille the __index entry. */
7263 lua_pushstring(gL.T, "__index");
7264 lua_newtable(gL.T);
7265
7266 /* Register . */
7267 hlua_class_function(gL.T, "lookup", hlua_map_lookup);
7268 hlua_class_function(gL.T, "slookup", hlua_map_slookup);
7269
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007270 lua_rawset(gL.T, -3);
Thierry FOURNIER3def3932015-04-07 11:27:54 +02007271
Thierry Fournier45e78d72016-02-19 18:34:46 +01007272 /* Register previous table in the registry with reference and named entry.
7273 * The function hlua_register_metatable() pops the stack, so we
7274 * previously create a copy of the table.
7275 */
Thierry FOURNIER3def3932015-04-07 11:27:54 +02007276 lua_pushvalue(gL.T, -1); /* Copy the -1 entry and push it on the stack. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007277 class_map_ref = hlua_register_metatable(gL.T, CLASS_MAP);
Thierry FOURNIER3def3932015-04-07 11:27:54 +02007278
7279 /* Assign the metatable to the mai Map object. */
7280 lua_setmetatable(gL.T, -2);
7281
7282 /* Set a name to the table. */
7283 lua_setglobal(gL.T, "Map");
7284
7285 /*
7286 *
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01007287 * Register class Channel
7288 *
7289 */
7290
7291 /* Create and fill the metatable. */
7292 lua_newtable(gL.T);
7293
7294 /* Create and fille the __index entry. */
7295 lua_pushstring(gL.T, "__index");
7296 lua_newtable(gL.T);
7297
7298 /* Register . */
7299 hlua_class_function(gL.T, "get", hlua_channel_get);
7300 hlua_class_function(gL.T, "dup", hlua_channel_dup);
7301 hlua_class_function(gL.T, "getline", hlua_channel_getline);
7302 hlua_class_function(gL.T, "set", hlua_channel_set);
7303 hlua_class_function(gL.T, "append", hlua_channel_append);
7304 hlua_class_function(gL.T, "send", hlua_channel_send);
7305 hlua_class_function(gL.T, "forward", hlua_channel_forward);
7306 hlua_class_function(gL.T, "get_in_len", hlua_channel_get_in_len);
7307 hlua_class_function(gL.T, "get_out_len", hlua_channel_get_out_len);
Thierry FOURNIER / OZON.IO65192f32016-11-07 15:28:40 +01007308 hlua_class_function(gL.T, "is_full", hlua_channel_is_full);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01007309
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007310 lua_rawset(gL.T, -3);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01007311
7312 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007313 class_channel_ref = hlua_register_metatable(gL.T, CLASS_CHANNEL);
Thierry FOURNIER5a6d3fd2015-02-09 16:38:34 +01007314
7315 /*
7316 *
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01007317 * Register class Fetches
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01007318 *
7319 */
7320
7321 /* Create and fill the metatable. */
7322 lua_newtable(gL.T);
7323
7324 /* Create and fille the __index entry. */
7325 lua_pushstring(gL.T, "__index");
7326 lua_newtable(gL.T);
7327
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +01007328 /* Browse existing fetches and create the associated
7329 * object method.
7330 */
7331 sf = NULL;
7332 while ((sf = sample_fetch_getnext(sf, &idx)) != NULL) {
7333
7334 /* Dont register the keywork if the arguments check function are
7335 * not safe during the runtime.
7336 */
7337 if ((sf->val_args != NULL) &&
7338 (sf->val_args != val_payload_lv) &&
7339 (sf->val_args != val_hdr))
7340 continue;
7341
7342 /* gL.Tua doesn't support '.' and '-' in the function names, replace it
7343 * by an underscore.
7344 */
7345 strncpy(trash.str, sf->kw, trash.size);
7346 trash.str[trash.size - 1] = '\0';
7347 for (p = trash.str; *p; p++)
7348 if (*p == '.' || *p == '-' || *p == '+')
7349 *p = '_';
7350
7351 /* Register the function. */
7352 lua_pushstring(gL.T, trash.str);
Willy Tarreau2ec22742015-03-10 14:27:20 +01007353 lua_pushlightuserdata(gL.T, sf);
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +01007354 lua_pushcclosure(gL.T, hlua_run_sample_fetch, 1);
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007355 lua_rawset(gL.T, -3);
Thierry FOURNIERd0fa5382015-02-16 20:14:51 +01007356 }
7357
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007358 lua_rawset(gL.T, -3);
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01007359
7360 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007361 class_fetches_ref = hlua_register_metatable(gL.T, CLASS_FETCHES);
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01007362
7363 /*
7364 *
Thierry FOURNIER594afe72015-03-10 23:58:30 +01007365 * Register class Converters
7366 *
7367 */
7368
7369 /* Create and fill the metatable. */
7370 lua_newtable(gL.T);
7371
7372 /* Create and fill the __index entry. */
7373 lua_pushstring(gL.T, "__index");
7374 lua_newtable(gL.T);
7375
7376 /* Browse existing converters and create the associated
7377 * object method.
7378 */
7379 sc = NULL;
7380 while ((sc = sample_conv_getnext(sc, &idx)) != NULL) {
7381 /* Dont register the keywork if the arguments check function are
7382 * not safe during the runtime.
7383 */
7384 if (sc->val_args != NULL)
7385 continue;
7386
7387 /* gL.Tua doesn't support '.' and '-' in the function names, replace it
7388 * by an underscore.
7389 */
7390 strncpy(trash.str, sc->kw, trash.size);
7391 trash.str[trash.size - 1] = '\0';
7392 for (p = trash.str; *p; p++)
7393 if (*p == '.' || *p == '-' || *p == '+')
7394 *p = '_';
7395
7396 /* Register the function. */
7397 lua_pushstring(gL.T, trash.str);
7398 lua_pushlightuserdata(gL.T, sc);
7399 lua_pushcclosure(gL.T, hlua_run_sample_conv, 1);
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007400 lua_rawset(gL.T, -3);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01007401 }
7402
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007403 lua_rawset(gL.T, -3);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01007404
7405 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007406 class_converters_ref = hlua_register_metatable(gL.T, CLASS_CONVERTERS);
Thierry FOURNIER594afe72015-03-10 23:58:30 +01007407
7408 /*
7409 *
Thierry FOURNIER08504f42015-03-16 14:17:08 +01007410 * Register class HTTP
7411 *
7412 */
7413
7414 /* Create and fill the metatable. */
7415 lua_newtable(gL.T);
7416
7417 /* Create and fille the __index entry. */
7418 lua_pushstring(gL.T, "__index");
7419 lua_newtable(gL.T);
7420
7421 /* Register Lua functions. */
7422 hlua_class_function(gL.T, "req_get_headers",hlua_http_req_get_headers);
7423 hlua_class_function(gL.T, "req_del_header", hlua_http_req_del_hdr);
7424 hlua_class_function(gL.T, "req_rep_header", hlua_http_req_rep_hdr);
7425 hlua_class_function(gL.T, "req_rep_value", hlua_http_req_rep_val);
7426 hlua_class_function(gL.T, "req_add_header", hlua_http_req_add_hdr);
7427 hlua_class_function(gL.T, "req_set_header", hlua_http_req_set_hdr);
7428 hlua_class_function(gL.T, "req_set_method", hlua_http_req_set_meth);
7429 hlua_class_function(gL.T, "req_set_path", hlua_http_req_set_path);
7430 hlua_class_function(gL.T, "req_set_query", hlua_http_req_set_query);
7431 hlua_class_function(gL.T, "req_set_uri", hlua_http_req_set_uri);
7432
7433 hlua_class_function(gL.T, "res_get_headers",hlua_http_res_get_headers);
7434 hlua_class_function(gL.T, "res_del_header", hlua_http_res_del_hdr);
7435 hlua_class_function(gL.T, "res_rep_header", hlua_http_res_rep_hdr);
7436 hlua_class_function(gL.T, "res_rep_value", hlua_http_res_rep_val);
7437 hlua_class_function(gL.T, "res_add_header", hlua_http_res_add_hdr);
7438 hlua_class_function(gL.T, "res_set_header", hlua_http_res_set_hdr);
Thierry FOURNIER35d70ef2015-08-26 16:21:56 +02007439 hlua_class_function(gL.T, "res_set_status", hlua_http_res_set_status);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01007440
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007441 lua_rawset(gL.T, -3);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01007442
7443 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007444 class_http_ref = hlua_register_metatable(gL.T, CLASS_HTTP);
Thierry FOURNIER08504f42015-03-16 14:17:08 +01007445
7446 /*
7447 *
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007448 * Register class AppletTCP
7449 *
7450 */
7451
7452 /* Create and fill the metatable. */
7453 lua_newtable(gL.T);
7454
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007455 /* Create and fille the __index entry. */
7456 lua_pushstring(gL.T, "__index");
7457 lua_newtable(gL.T);
7458
7459 /* Register Lua functions. */
Thierry FOURNIER / OZON.IO3e1d7912016-12-12 12:29:34 +01007460 hlua_class_function(gL.T, "getline", hlua_applet_tcp_getline);
7461 hlua_class_function(gL.T, "receive", hlua_applet_tcp_recv);
7462 hlua_class_function(gL.T, "send", hlua_applet_tcp_send);
7463 hlua_class_function(gL.T, "set_priv", hlua_applet_tcp_set_priv);
7464 hlua_class_function(gL.T, "get_priv", hlua_applet_tcp_get_priv);
Thierry FOURNIER / OZON.IO4394a2c2016-12-12 12:31:54 +01007465 hlua_class_function(gL.T, "set_var", hlua_applet_tcp_set_var);
7466 hlua_class_function(gL.T, "unset_var", hlua_applet_tcp_unset_var);
7467 hlua_class_function(gL.T, "get_var", hlua_applet_tcp_get_var);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007468
7469 lua_settable(gL.T, -3);
7470
7471 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007472 class_applet_tcp_ref = hlua_register_metatable(gL.T, CLASS_APPLET_TCP);
Thierry FOURNIERf0a64b62015-09-19 12:36:17 +02007473
7474 /*
7475 *
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02007476 * Register class AppletHTTP
7477 *
7478 */
7479
7480 /* Create and fill the metatable. */
7481 lua_newtable(gL.T);
7482
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02007483 /* Create and fille the __index entry. */
7484 lua_pushstring(gL.T, "__index");
7485 lua_newtable(gL.T);
7486
7487 /* Register Lua functions. */
Thierry FOURNIER8db004c2015-12-25 01:33:18 +01007488 hlua_class_function(gL.T, "set_priv", hlua_applet_http_set_priv);
7489 hlua_class_function(gL.T, "get_priv", hlua_applet_http_get_priv);
Thierry FOURNIER / OZON.IO4394a2c2016-12-12 12:31:54 +01007490 hlua_class_function(gL.T, "set_var", hlua_applet_http_set_var);
7491 hlua_class_function(gL.T, "unset_var", hlua_applet_http_unset_var);
7492 hlua_class_function(gL.T, "get_var", hlua_applet_http_get_var);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02007493 hlua_class_function(gL.T, "getline", hlua_applet_http_getline);
7494 hlua_class_function(gL.T, "receive", hlua_applet_http_recv);
7495 hlua_class_function(gL.T, "send", hlua_applet_http_send);
7496 hlua_class_function(gL.T, "add_header", hlua_applet_http_addheader);
7497 hlua_class_function(gL.T, "set_status", hlua_applet_http_status);
7498 hlua_class_function(gL.T, "start_response", hlua_applet_http_start_response);
7499
7500 lua_settable(gL.T, -3);
7501
7502 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007503 class_applet_http_ref = hlua_register_metatable(gL.T, CLASS_APPLET_HTTP);
Thierry FOURNIERa30b5db2015-09-18 09:04:27 +02007504
7505 /*
7506 *
Thierry FOURNIERbb53c7b2015-03-11 18:28:02 +01007507 * Register class TXN
7508 *
7509 */
7510
7511 /* Create and fill the metatable. */
7512 lua_newtable(gL.T);
7513
7514 /* Create and fille the __index entry. */
7515 lua_pushstring(gL.T, "__index");
7516 lua_newtable(gL.T);
7517
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01007518 /* Register Lua functions. */
Willy Tarreau59551662015-03-10 14:23:13 +01007519 hlua_class_function(gL.T, "set_priv", hlua_set_priv);
7520 hlua_class_function(gL.T, "get_priv", hlua_get_priv);
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +02007521 hlua_class_function(gL.T, "set_var", hlua_set_var);
Christopher Faulet85d79c92016-11-09 16:54:56 +01007522 hlua_class_function(gL.T, "unset_var", hlua_unset_var);
Thierry FOURNIER053ba8ad2015-06-08 13:05:33 +02007523 hlua_class_function(gL.T, "get_var", hlua_get_var);
Thierry FOURNIER4bb375c2015-08-26 08:42:21 +02007524 hlua_class_function(gL.T, "done", hlua_txn_done);
Thierry FOURNIER2cce3532015-03-16 12:04:16 +01007525 hlua_class_function(gL.T, "set_loglevel",hlua_txn_set_loglevel);
7526 hlua_class_function(gL.T, "set_tos", hlua_txn_set_tos);
7527 hlua_class_function(gL.T, "set_mark", hlua_txn_set_mark);
Thierry FOURNIERc798b5d2015-03-17 01:09:57 +01007528 hlua_class_function(gL.T, "deflog", hlua_txn_deflog);
7529 hlua_class_function(gL.T, "log", hlua_txn_log);
7530 hlua_class_function(gL.T, "Debug", hlua_txn_log_debug);
7531 hlua_class_function(gL.T, "Info", hlua_txn_log_info);
7532 hlua_class_function(gL.T, "Warning", hlua_txn_log_warning);
7533 hlua_class_function(gL.T, "Alert", hlua_txn_log_alert);
Thierry FOURNIER05c0b8a2015-02-25 11:43:21 +01007534
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007535 lua_rawset(gL.T, -3);
Thierry FOURNIER65f34c62015-02-16 20:11:43 +01007536
7537 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007538 class_txn_ref = hlua_register_metatable(gL.T, CLASS_TXN);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007539
7540 /*
7541 *
7542 * Register class Socket
7543 *
7544 */
7545
7546 /* Create and fill the metatable. */
7547 lua_newtable(gL.T);
7548
7549 /* Create and fille the __index entry. */
7550 lua_pushstring(gL.T, "__index");
7551 lua_newtable(gL.T);
7552
Baptiste Assmann84bb4932015-03-02 21:40:06 +01007553#ifdef USE_OPENSSL
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007554 hlua_class_function(gL.T, "connect_ssl", hlua_socket_connect_ssl);
Baptiste Assmann84bb4932015-03-02 21:40:06 +01007555#endif
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007556 hlua_class_function(gL.T, "connect", hlua_socket_connect);
7557 hlua_class_function(gL.T, "send", hlua_socket_send);
7558 hlua_class_function(gL.T, "receive", hlua_socket_receive);
7559 hlua_class_function(gL.T, "close", hlua_socket_close);
7560 hlua_class_function(gL.T, "getpeername", hlua_socket_getpeername);
7561 hlua_class_function(gL.T, "getsockname", hlua_socket_getsockname);
7562 hlua_class_function(gL.T, "setoption", hlua_socket_setoption);
7563 hlua_class_function(gL.T, "settimeout", hlua_socket_settimeout);
7564
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007565 lua_rawset(gL.T, -3); /* Push the last 2 entries in the table at index -3 */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007566
7567 /* Register the garbage collector entry. */
7568 lua_pushstring(gL.T, "__gc");
7569 lua_pushcclosure(gL.T, hlua_socket_gc, 0);
Thierry FOURNIER84e73c82015-09-25 22:13:32 +02007570 lua_rawset(gL.T, -3); /* Push the last 2 entries in the table at index -3 */
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007571
7572 /* Register previous table in the registry with reference and named entry. */
Thierry Fournier45e78d72016-02-19 18:34:46 +01007573 class_socket_ref = hlua_register_metatable(gL.T, CLASS_SOCKET);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007574
7575 /* Proxy and server configuration initialisation. */
7576 memset(&socket_proxy, 0, sizeof(socket_proxy));
7577 init_new_proxy(&socket_proxy);
7578 socket_proxy.parent = NULL;
7579 socket_proxy.last_change = now.tv_sec;
7580 socket_proxy.id = "LUA-SOCKET";
7581 socket_proxy.cap = PR_CAP_FE | PR_CAP_BE;
7582 socket_proxy.maxconn = 0;
7583 socket_proxy.accept = NULL;
7584 socket_proxy.options2 |= PR_O2_INDEPSTR;
7585 socket_proxy.srv = NULL;
7586 socket_proxy.conn_retries = 0;
7587 socket_proxy.timeout.connect = 5000; /* By default the timeout connection is 5s. */
7588
7589 /* Init TCP server: unchanged parameters */
7590 memset(&socket_tcp, 0, sizeof(socket_tcp));
7591 socket_tcp.next = NULL;
7592 socket_tcp.proxy = &socket_proxy;
7593 socket_tcp.obj_type = OBJ_TYPE_SERVER;
7594 LIST_INIT(&socket_tcp.actconns);
7595 LIST_INIT(&socket_tcp.pendconns);
Willy Tarreau600802a2015-08-04 17:19:06 +02007596 LIST_INIT(&socket_tcp.priv_conns);
Willy Tarreau173a1c62015-08-05 10:31:57 +02007597 LIST_INIT(&socket_tcp.idle_conns);
Willy Tarreau7017cb02015-08-05 16:35:23 +02007598 LIST_INIT(&socket_tcp.safe_conns);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007599 socket_tcp.state = SRV_ST_RUNNING; /* early server setup */
7600 socket_tcp.last_change = 0;
7601 socket_tcp.id = "LUA-TCP-CONN";
7602 socket_tcp.check.state &= ~CHK_ST_ENABLED; /* Disable health checks. */
7603 socket_tcp.agent.state &= ~CHK_ST_ENABLED; /* Disable health checks. */
7604 socket_tcp.pp_opts = 0; /* Remove proxy protocol. */
7605
7606 /* XXX: Copy default parameter from default server,
7607 * but the default server is not initialized.
7608 */
7609 socket_tcp.maxqueue = socket_proxy.defsrv.maxqueue;
7610 socket_tcp.minconn = socket_proxy.defsrv.minconn;
7611 socket_tcp.maxconn = socket_proxy.defsrv.maxconn;
7612 socket_tcp.slowstart = socket_proxy.defsrv.slowstart;
7613 socket_tcp.onerror = socket_proxy.defsrv.onerror;
7614 socket_tcp.onmarkeddown = socket_proxy.defsrv.onmarkeddown;
7615 socket_tcp.onmarkedup = socket_proxy.defsrv.onmarkedup;
7616 socket_tcp.consecutive_errors_limit = socket_proxy.defsrv.consecutive_errors_limit;
7617 socket_tcp.uweight = socket_proxy.defsrv.iweight;
7618 socket_tcp.iweight = socket_proxy.defsrv.iweight;
7619
7620 socket_tcp.check.status = HCHK_STATUS_INI;
7621 socket_tcp.check.rise = socket_proxy.defsrv.check.rise;
7622 socket_tcp.check.fall = socket_proxy.defsrv.check.fall;
7623 socket_tcp.check.health = socket_tcp.check.rise; /* socket, but will fall down at first failure */
7624 socket_tcp.check.server = &socket_tcp;
7625
7626 socket_tcp.agent.status = HCHK_STATUS_INI;
7627 socket_tcp.agent.rise = socket_proxy.defsrv.agent.rise;
7628 socket_tcp.agent.fall = socket_proxy.defsrv.agent.fall;
7629 socket_tcp.agent.health = socket_tcp.agent.rise; /* socket, but will fall down at first failure */
7630 socket_tcp.agent.server = &socket_tcp;
7631
7632 socket_tcp.xprt = &raw_sock;
7633
7634#ifdef USE_OPENSSL
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007635 /* Init TCP server: unchanged parameters */
7636 memset(&socket_ssl, 0, sizeof(socket_ssl));
7637 socket_ssl.next = NULL;
7638 socket_ssl.proxy = &socket_proxy;
7639 socket_ssl.obj_type = OBJ_TYPE_SERVER;
7640 LIST_INIT(&socket_ssl.actconns);
7641 LIST_INIT(&socket_ssl.pendconns);
Willy Tarreau600802a2015-08-04 17:19:06 +02007642 LIST_INIT(&socket_ssl.priv_conns);
Willy Tarreau173a1c62015-08-05 10:31:57 +02007643 LIST_INIT(&socket_ssl.idle_conns);
Willy Tarreau7017cb02015-08-05 16:35:23 +02007644 LIST_INIT(&socket_ssl.safe_conns);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007645 socket_ssl.state = SRV_ST_RUNNING; /* early server setup */
7646 socket_ssl.last_change = 0;
7647 socket_ssl.id = "LUA-SSL-CONN";
7648 socket_ssl.check.state &= ~CHK_ST_ENABLED; /* Disable health checks. */
7649 socket_ssl.agent.state &= ~CHK_ST_ENABLED; /* Disable health checks. */
7650 socket_ssl.pp_opts = 0; /* Remove proxy protocol. */
7651
7652 /* XXX: Copy default parameter from default server,
7653 * but the default server is not initialized.
7654 */
7655 socket_ssl.maxqueue = socket_proxy.defsrv.maxqueue;
7656 socket_ssl.minconn = socket_proxy.defsrv.minconn;
7657 socket_ssl.maxconn = socket_proxy.defsrv.maxconn;
7658 socket_ssl.slowstart = socket_proxy.defsrv.slowstart;
7659 socket_ssl.onerror = socket_proxy.defsrv.onerror;
7660 socket_ssl.onmarkeddown = socket_proxy.defsrv.onmarkeddown;
7661 socket_ssl.onmarkedup = socket_proxy.defsrv.onmarkedup;
7662 socket_ssl.consecutive_errors_limit = socket_proxy.defsrv.consecutive_errors_limit;
7663 socket_ssl.uweight = socket_proxy.defsrv.iweight;
7664 socket_ssl.iweight = socket_proxy.defsrv.iweight;
7665
7666 socket_ssl.check.status = HCHK_STATUS_INI;
7667 socket_ssl.check.rise = socket_proxy.defsrv.check.rise;
7668 socket_ssl.check.fall = socket_proxy.defsrv.check.fall;
7669 socket_ssl.check.health = socket_ssl.check.rise; /* socket, but will fall down at first failure */
7670 socket_ssl.check.server = &socket_ssl;
7671
7672 socket_ssl.agent.status = HCHK_STATUS_INI;
7673 socket_ssl.agent.rise = socket_proxy.defsrv.agent.rise;
7674 socket_ssl.agent.fall = socket_proxy.defsrv.agent.fall;
7675 socket_ssl.agent.health = socket_ssl.agent.rise; /* socket, but will fall down at first failure */
7676 socket_ssl.agent.server = &socket_ssl;
7677
Thierry FOURNIER36d13742015-03-17 16:48:53 +01007678 socket_ssl.use_ssl = 1;
7679 socket_ssl.xprt = &ssl_sock;
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007680
Thierry FOURNIER36d13742015-03-17 16:48:53 +01007681 for (idx = 0; args[idx] != NULL; idx++) {
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007682 if ((kw = srv_find_kw(args[idx])) != NULL) { /* Maybe it's registered server keyword */
7683 /*
7684 *
7685 * If the keyword is not known, we can search in the registered
7686 * server keywords. This is usefull to configure special SSL
7687 * features like client certificates and ssl_verify.
7688 *
7689 */
7690 tmp_error = kw->parse(args, &idx, &socket_proxy, &socket_ssl, &error);
7691 if (tmp_error != 0) {
7692 fprintf(stderr, "INTERNAL ERROR: %s\n", error);
7693 abort(); /* This must be never arrives because the command line
7694 not editable by the user. */
7695 }
7696 idx += kw->skip;
7697 }
7698 }
7699
7700 /* Initialize SSL server. */
Thierry FOURNIER36d13742015-03-17 16:48:53 +01007701 ssl_sock_prepare_srv_ctx(&socket_ssl, &socket_proxy);
Thierry FOURNIER7e7ac322015-02-16 19:27:16 +01007702#endif
Thierry Fournier75933d42016-01-21 09:30:18 +01007703
7704 RESET_SAFE_LJMP(gL.T);
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01007705}
Willy Tarreaubb57d942016-12-21 19:04:56 +01007706
7707__attribute__((constructor))
7708static void __hlua_init(void)
7709{
7710 char *ptr = NULL;
7711 memprintf(&ptr, "Built with Lua version : %s", LUA_RELEASE);
7712 hap_register_build_opts(ptr, 1);
7713}