1 /*
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
13 #define _GNU_SOURCE
14
15 #include <ctype.h>
16 #include <limits.h>
17 #include <setjmp.h>
18
19 #include <lauxlib.h>
20 #include <lua.h>
21 #include <lualib.h>
22
23 #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 503
24 #error "Requires Lua 5.3 or later."
25 #endif
26
27 #include <ebpttree.h>
28
29 #include <common/cfgparse.h>
30 #include <common/compiler.h>
31 #include <common/hathreads.h>
32 #include <common/initcall.h>
33 #include <common/xref.h>
34 #include <common/h1.h>
35
36 #include <types/cli.h>
37 #include <types/hlua.h>
38 #include <types/proxy.h>
39 #include <types/stats.h>
40
41 #include <proto/arg.h>
42 #include <proto/applet.h>
43 #include <proto/channel.h>
44 #include <proto/cli.h>
45 #include <proto/connection.h>
46 #include <proto/stats.h>
47 #include <proto/hlua.h>
48 #include <proto/hlua_fcn.h>
49 #include <proto/http_fetch.h>
50 #include <proto/http_htx.h>
51 #include <proto/http_rules.h>
52 #include <proto/map.h>
53 #include <proto/obj_type.h>
54 #include <proto/queue.h>
55 #include <proto/pattern.h>
56 #include <proto/payload.h>
57 #include <proto/http_ana.h>
58 #include <proto/sample.h>
59 #include <proto/server.h>
60 #include <proto/session.h>
61 #include <proto/stream.h>
62 #include <proto/stream_interface.h>
63 #include <proto/task.h>
64 #include <proto/tcp_rules.h>
65 #include <proto/vars.h>
66
67 /* Lua uses longjmp to perform yield or throwing errors. This
68 * macro is used only for identifying the function that can
69 * not return because a longjmp is executed.
70 * __LJMP marks a prototype of hlua file that can use longjmp.
71 * WILL_LJMP() marks an lua function that will use longjmp.
72 * MAY_LJMP() marks an lua function that may use longjmp.
73 */
74 #define __LJMP
75 #define WILL_LJMP(func) do { func; my_unreachable(); } while(0)
76 #define MAY_LJMP(func) func
77
78 /* This couple of function executes securely some Lua calls outside of
79 * the lua runtime environment. Each Lua call can return a longjmp
80 * if it encounter a memory error.
81 *
82 * Lua documentation extract:
83 *
84 * If an error happens outside any protected environment, Lua calls
85 * a panic function (see lua_atpanic) and then calls abort, thus
86 * exiting the host application. Your panic function can avoid this
87 * exit by never returning (e.g., doing a long jump to your own
88 * recovery point outside Lua).
89 *
90 * The panic function runs as if it were a message handler (see
91 * §2.3); in particular, the error message is at the top of the
92 * stack. However, there is no guarantee about stack space. To push
93 * anything on the stack, the panic function must first check the
94 * available space (see §4.2).
95 *
96 * We must check all the Lua entry point. This includes:
97 * - The include/proto/hlua.h exported functions
98 * - the task wrapper function
99 * - The action wrapper function
100 * - The converters wrapper function
101 * - The sample-fetch wrapper functions
102 *
103 * It is tolerated that the initilisation function returns an abort.
104 * Before each Lua abort, an error message is written on stderr.
105 *
106 * The macro SET_SAFE_LJMP initialise the longjmp. The Macro
107 * RESET_SAFE_LJMP reset the longjmp. These function must be macro
108 * because they must be exists in the program stack when the longjmp
109 * is called.
110 *
111 * Note that the Lua processing is not really thread safe. It provides
112 * heavy system which consists to add our own lock function in the Lua
113 * code and recompile the library. This system will probably not accepted
114 * by maintainers of various distribs.
115 *
116 * Our main excution point of the Lua is the function lua_resume(). A
117 * quick looking on the Lua sources displays a lua_lock() a the start
118 * of function and a lua_unlock() at the end of the function. So I
119 * conclude that the Lua thread safe mode just perform a mutex around
120 * all execution. So I prefer to do this in the HAProxy code, it will be
121 * easier for distro maintainers.
122 *
123 * Note that the HAProxy lua functions rounded by the macro SET_SAFE_LJMP
124 * and RESET_SAFE_LJMP manipulates the Lua stack, so it will be careful
125 * to set mutex around these functions.
126 */
127 __decl_spinlock(hlua_global_lock);
128 THREAD_LOCAL jmp_buf safe_ljmp_env;
hlua_panic_safe(lua_State * L)129 static int hlua_panic_safe(lua_State *L) { return 0; }
hlua_panic_ljmp(lua_State * L)130 static int hlua_panic_ljmp(lua_State *L) { longjmp(safe_ljmp_env, 1); }
131
132 #define SET_SAFE_LJMP(__L) \
133 ({ \
134 int ret; \
135 HA_SPIN_LOCK(LUA_LOCK, &hlua_global_lock); \
136 if (setjmp(safe_ljmp_env) != 0) { \
137 lua_atpanic(__L, hlua_panic_safe); \
138 ret = 0; \
139 HA_SPIN_UNLOCK(LUA_LOCK, &hlua_global_lock); \
140 } else { \
141 lua_atpanic(__L, hlua_panic_ljmp); \
142 ret = 1; \
143 } \
144 ret; \
145 })
146
147 /* If we are the last function catching Lua errors, we
148 * must reset the panic function.
149 */
150 #define RESET_SAFE_LJMP(__L) \
151 do { \
152 lua_atpanic(__L, hlua_panic_safe); \
153 HA_SPIN_UNLOCK(LUA_LOCK, &hlua_global_lock); \
154 } while(0)
155
156 /* Applet status flags */
157 #define APPLET_DONE 0x01 /* applet processing is done. */
158 /* unused: 0x02 */
159 #define APPLET_HDR_SENT 0x04 /* Response header sent. */
160 /* unused: 0x08, 0x10 */
161 #define APPLET_HTTP11 0x20 /* Last chunk sent. */
162 #define APPLET_RSP_SENT 0x40 /* The response was fully sent */
163
164 /* The main Lua execution context. */
165 struct hlua gL;
166
167 /* This is the memory pool containing struct lua for applets
168 * (including cli).
169 */
170 DECLARE_STATIC_POOL(pool_head_hlua, "hlua", sizeof(struct hlua));
171
172 /* Used for Socket connection. */
173 static struct proxy socket_proxy;
174 static struct server socket_tcp;
175 #ifdef USE_OPENSSL
176 static struct server socket_ssl;
177 #endif
178
179 /* List head of the function called at the initialisation time. */
180 struct list hlua_init_functions = LIST_HEAD_INIT(hlua_init_functions);
181
182 /* The following variables contains the reference of the different
183 * Lua classes. These references are useful for identify metadata
184 * associated with an object.
185 */
186 static int class_txn_ref;
187 static int class_socket_ref;
188 static int class_channel_ref;
189 static int class_fetches_ref;
190 static int class_converters_ref;
191 static int class_http_ref;
192 static int class_map_ref;
193 static int class_applet_tcp_ref;
194 static int class_applet_http_ref;
195
196 /* Global Lua execution timeout. By default Lua, execution linked
197 * with stream (actions, sample-fetches and converters) have a
198 * short timeout. Lua linked with tasks doesn't have a timeout
199 * because a task may remain alive during all the haproxy execution.
200 */
201 static unsigned int hlua_timeout_session = 4000; /* session timeout. */
202 static unsigned int hlua_timeout_task = TICK_ETERNITY; /* task timeout. */
203 static unsigned int hlua_timeout_applet = 4000; /* applet timeout. */
204
205 /* Interrupts the Lua processing each "hlua_nb_instruction" instructions.
206 * it is used for preventing infinite loops.
207 *
208 * I test the scheer with an infinite loop containing one incrementation
209 * and one test. I run this loop between 10 seconds, I raise a ceil of
210 * 710M loops from one interrupt each 9000 instructions, so I fix the value
211 * to one interrupt each 10 000 instructions.
212 *
213 * configured | Number of
214 * instructions | loops executed
215 * between two | in milions
216 * forced yields |
217 * ---------------+---------------
218 * 10 | 160
219 * 500 | 670
220 * 1000 | 680
221 * 5000 | 700
222 * 7000 | 700
223 * 8000 | 700
224 * 9000 | 710 <- ceil
225 * 10000 | 710
226 * 100000 | 710
227 * 1000000 | 710
228 *
229 */
230 static unsigned int hlua_nb_instruction = 10000;
231
232 /* Descriptor for the memory allocation state. If limit is not null, it will
233 * be enforced on any memory allocation.
234 */
235 struct hlua_mem_allocator {
236 size_t allocated;
237 size_t limit;
238 };
239
240 static struct hlua_mem_allocator hlua_global_allocator;
241
242 /* These functions converts types between HAProxy internal args or
243 * sample and LUA types. Another function permits to check if the
244 * LUA stack contains arguments according with an required ARG_T
245 * format.
246 */
247 static int hlua_arg2lua(lua_State *L, const struct arg *arg);
248 static int hlua_lua2arg(lua_State *L, int ud, struct arg *arg);
249 __LJMP static int hlua_lua2arg_check(lua_State *L, int first, struct arg *argp,
250 uint64_t mask, struct proxy *p);
251 static int hlua_smp2lua(lua_State *L, struct sample *smp);
252 static int hlua_smp2lua_str(lua_State *L, struct sample *smp);
253 static int hlua_lua2smp(lua_State *L, int ud, struct sample *smp);
254
255 __LJMP static int hlua_http_get_headers(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg);
256
257 #define SEND_ERR(__be, __fmt, __args...) \
258 do { \
259 send_log(__be, LOG_ERR, __fmt, ## __args); \
260 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) \
261 ha_alert(__fmt, ## __args); \
262 } while (0)
263
264 /* Used to check an Lua function type in the stack. It creates and
265 * returns a reference of the function. This function throws an
266 * error if the rgument is not a "function".
267 */
hlua_checkfunction(lua_State * L,int argno)268 __LJMP unsigned int hlua_checkfunction(lua_State *L, int argno)
269 {
270 if (!lua_isfunction(L, argno)) {
271 const char *msg = lua_pushfstring(L, "function expected, got %s", luaL_typename(L, argno));
272 WILL_LJMP(luaL_argerror(L, argno, msg));
273 }
274 lua_pushvalue(L, argno);
275 return luaL_ref(L, LUA_REGISTRYINDEX);
276 }
277
278 /* Return the string that is of the top of the stack. */
hlua_get_top_error_string(lua_State * L)279 const char *hlua_get_top_error_string(lua_State *L)
280 {
281 if (lua_gettop(L) < 1)
282 return "unknown error";
283 if (lua_type(L, -1) != LUA_TSTRING)
284 return "unknown error";
285 return lua_tostring(L, -1);
286 }
287
hlua_traceback(lua_State * L)288 __LJMP static const char *hlua_traceback(lua_State *L)
289 {
290 lua_Debug ar;
291 int level = 0;
292 struct buffer *msg = get_trash_chunk();
293 int filled = 0;
294
295 while (lua_getstack(L, level++, &ar)) {
296
297 /* Add separator */
298 if (filled)
299 chunk_appendf(msg, ", ");
300 filled = 1;
301
302 /* Fill fields:
303 * 'S': fills in the fields source, short_src, linedefined, lastlinedefined, and what;
304 * 'l': fills in the field currentline;
305 * 'n': fills in the field name and namewhat;
306 * 't': fills in the field istailcall;
307 */
308 lua_getinfo(L, "Slnt", &ar);
309
310 /* Append code localisation */
311 if (ar.currentline > 0)
312 chunk_appendf(msg, "%s:%d ", ar.short_src, ar.currentline);
313 else
314 chunk_appendf(msg, "%s ", ar.short_src);
315
316 /*
317 * Get function name
318 *
319 * if namewhat is no empty, name is defined.
320 * what contains "Lua" for Lua function, "C" for C function,
321 * or "main" for main code.
322 */
323 if (*ar.namewhat != '\0' && ar.name != NULL) /* is there a name from code? */
324 chunk_appendf(msg, "%s '%s'", ar.namewhat, ar.name); /* use it */
325
326 else if (*ar.what == 'm') /* "main", the code is not executed in a function */
327 chunk_appendf(msg, "main chunk");
328
329 else if (*ar.what != 'C') /* for Lua functions, use <file:line> */
330 chunk_appendf(msg, "C function line %d", ar.linedefined);
331
332 else /* nothing left... */
333 chunk_appendf(msg, "?");
334
335
336 /* Display tailed call */
337 if (ar.istailcall)
338 chunk_appendf(msg, " ...");
339 }
340
341 return msg->area;
342 }
343
344
345 /* This function check the number of arguments available in the
346 * stack. If the number of arguments available is not the same
347 * then <nb> an error is throwed.
348 */
check_args(lua_State * L,int nb,char * fcn)349 __LJMP static inline void check_args(lua_State *L, int nb, char *fcn)
350 {
351 if (lua_gettop(L) == nb)
352 return;
353 WILL_LJMP(luaL_error(L, "'%s' needs %d arguments", fcn, nb));
354 }
355
356 /* This function pushes an error string prefixed by the file name
357 * and the line number where the error is encountered.
358 */
hlua_pusherror(lua_State * L,const char * fmt,...)359 static int hlua_pusherror(lua_State *L, const char *fmt, ...)
360 {
361 va_list argp;
362 va_start(argp, fmt);
363 luaL_where(L, 1);
364 lua_pushvfstring(L, fmt, argp);
365 va_end(argp);
366 lua_concat(L, 2);
367 return 1;
368 }
369
370 /* This functions is used with sample fetch and converters. It
371 * converts the HAProxy configuration argument in a lua stack
372 * values.
373 *
374 * It takes an array of "arg", and each entry of the array is
375 * converted and pushed in the LUA stack.
376 */
hlua_arg2lua(lua_State * L,const struct arg * arg)377 static int hlua_arg2lua(lua_State *L, const struct arg *arg)
378 {
379 switch (arg->type) {
380 case ARGT_SINT:
381 case ARGT_TIME:
382 case ARGT_SIZE:
383 lua_pushinteger(L, arg->data.sint);
384 break;
385
386 case ARGT_STR:
387 lua_pushlstring(L, arg->data.str.area, arg->data.str.data);
388 break;
389
390 case ARGT_IPV4:
391 case ARGT_IPV6:
392 case ARGT_MSK4:
393 case ARGT_MSK6:
394 case ARGT_FE:
395 case ARGT_BE:
396 case ARGT_TAB:
397 case ARGT_SRV:
398 case ARGT_USR:
399 case ARGT_MAP:
400 default:
401 lua_pushnil(L);
402 break;
403 }
404 return 1;
405 }
406
407 /* This function take one entrie in an LUA stack at the index "ud",
408 * and try to convert it in an HAProxy argument entry. This is useful
409 * with sample fetch wrappers. The input arguments are gived to the
410 * lua wrapper and converted as arg list by thi function.
411 */
hlua_lua2arg(lua_State * L,int ud,struct arg * arg)412 static int hlua_lua2arg(lua_State *L, int ud, struct arg *arg)
413 {
414 switch (lua_type(L, ud)) {
415
416 case LUA_TNUMBER:
417 case LUA_TBOOLEAN:
418 arg->type = ARGT_SINT;
419 arg->data.sint = lua_tointeger(L, ud);
420 break;
421
422 case LUA_TSTRING:
423 arg->type = ARGT_STR;
424 arg->data.str.area = (char *)lua_tolstring(L, ud, &arg->data.str.data);
425 /* We don't know the actual size of the underlying allocation, so be conservative. */
426 arg->data.str.size = arg->data.str.data+1; /* count the terminating null byte */
427 arg->data.str.head = 0;
428 break;
429
430 case LUA_TUSERDATA:
431 case LUA_TNIL:
432 case LUA_TTABLE:
433 case LUA_TFUNCTION:
434 case LUA_TTHREAD:
435 case LUA_TLIGHTUSERDATA:
436 arg->type = ARGT_SINT;
437 arg->data.sint = 0;
438 break;
439 }
440 return 1;
441 }
442
443 /* the following functions are used to convert a struct sample
444 * in Lua type. This useful to convert the return of the
445 * fetchs or converters.
446 */
hlua_smp2lua(lua_State * L,struct sample * smp)447 static int hlua_smp2lua(lua_State *L, struct sample *smp)
448 {
449 switch (smp->data.type) {
450 case SMP_T_SINT:
451 case SMP_T_BOOL:
452 lua_pushinteger(L, smp->data.u.sint);
453 break;
454
455 case SMP_T_BIN:
456 case SMP_T_STR:
457 lua_pushlstring(L, smp->data.u.str.area, smp->data.u.str.data);
458 break;
459
460 case SMP_T_METH:
461 switch (smp->data.u.meth.meth) {
462 case HTTP_METH_OPTIONS: lua_pushstring(L, "OPTIONS"); break;
463 case HTTP_METH_GET: lua_pushstring(L, "GET"); break;
464 case HTTP_METH_HEAD: lua_pushstring(L, "HEAD"); break;
465 case HTTP_METH_POST: lua_pushstring(L, "POST"); break;
466 case HTTP_METH_PUT: lua_pushstring(L, "PUT"); break;
467 case HTTP_METH_DELETE: lua_pushstring(L, "DELETE"); break;
468 case HTTP_METH_TRACE: lua_pushstring(L, "TRACE"); break;
469 case HTTP_METH_CONNECT: lua_pushstring(L, "CONNECT"); break;
470 case HTTP_METH_OTHER:
471 lua_pushlstring(L, smp->data.u.meth.str.area, smp->data.u.meth.str.data);
472 break;
473 default:
474 lua_pushnil(L);
475 break;
476 }
477 break;
478
479 case SMP_T_IPV4:
480 case SMP_T_IPV6:
481 case SMP_T_ADDR: /* This type is never used to qualify a sample. */
482 if (sample_casts[smp->data.type][SMP_T_STR] &&
483 sample_casts[smp->data.type][SMP_T_STR](smp))
484 lua_pushlstring(L, smp->data.u.str.area, smp->data.u.str.data);
485 else
486 lua_pushnil(L);
487 break;
488 default:
489 lua_pushnil(L);
490 break;
491 }
492 return 1;
493 }
494
495 /* the following functions are used to convert a struct sample
496 * in Lua strings. This is useful to convert the return of the
497 * fetchs or converters.
498 */
hlua_smp2lua_str(lua_State * L,struct sample * smp)499 static int hlua_smp2lua_str(lua_State *L, struct sample *smp)
500 {
501 switch (smp->data.type) {
502
503 case SMP_T_BIN:
504 case SMP_T_STR:
505 lua_pushlstring(L, smp->data.u.str.area, smp->data.u.str.data);
506 break;
507
508 case SMP_T_METH:
509 switch (smp->data.u.meth.meth) {
510 case HTTP_METH_OPTIONS: lua_pushstring(L, "OPTIONS"); break;
511 case HTTP_METH_GET: lua_pushstring(L, "GET"); break;
512 case HTTP_METH_HEAD: lua_pushstring(L, "HEAD"); break;
513 case HTTP_METH_POST: lua_pushstring(L, "POST"); break;
514 case HTTP_METH_PUT: lua_pushstring(L, "PUT"); break;
515 case HTTP_METH_DELETE: lua_pushstring(L, "DELETE"); break;
516 case HTTP_METH_TRACE: lua_pushstring(L, "TRACE"); break;
517 case HTTP_METH_CONNECT: lua_pushstring(L, "CONNECT"); break;
518 case HTTP_METH_OTHER:
519 lua_pushlstring(L, smp->data.u.meth.str.area, smp->data.u.meth.str.data);
520 break;
521 default:
522 lua_pushstring(L, "");
523 break;
524 }
525 break;
526
527 case SMP_T_SINT:
528 case SMP_T_BOOL:
529 case SMP_T_IPV4:
530 case SMP_T_IPV6:
531 case SMP_T_ADDR: /* This type is never used to qualify a sample. */
532 if (sample_casts[smp->data.type][SMP_T_STR] &&
533 sample_casts[smp->data.type][SMP_T_STR](smp))
534 lua_pushlstring(L, smp->data.u.str.area, smp->data.u.str.data);
535 else
536 lua_pushstring(L, "");
537 break;
538 default:
539 lua_pushstring(L, "");
540 break;
541 }
542 return 1;
543 }
544
545 /* the following functions are used to convert an Lua type in a
546 * struct sample. This is useful to provide data from a converter
547 * to the LUA code.
548 */
hlua_lua2smp(lua_State * L,int ud,struct sample * smp)549 static int hlua_lua2smp(lua_State *L, int ud, struct sample *smp)
550 {
551 switch (lua_type(L, ud)) {
552
553 case LUA_TNUMBER:
554 smp->data.type = SMP_T_SINT;
555 smp->data.u.sint = lua_tointeger(L, ud);
556 break;
557
558
559 case LUA_TBOOLEAN:
560 smp->data.type = SMP_T_BOOL;
561 smp->data.u.sint = lua_toboolean(L, ud);
562 break;
563
564 case LUA_TSTRING:
565 smp->data.type = SMP_T_STR;
566 smp->flags |= SMP_F_CONST;
567 smp->data.u.str.area = (char *)lua_tolstring(L, ud, &smp->data.u.str.data);
568 /* We don't know the actual size of the underlying allocation, so be conservative. */
569 smp->data.u.str.size = smp->data.u.str.data+1; /* count the terminating null byte */
570 smp->data.u.str.head = 0;
571 break;
572
573 case LUA_TUSERDATA:
574 case LUA_TNIL:
575 case LUA_TTABLE:
576 case LUA_TFUNCTION:
577 case LUA_TTHREAD:
578 case LUA_TLIGHTUSERDATA:
579 case LUA_TNONE:
580 default:
581 smp->data.type = SMP_T_BOOL;
582 smp->data.u.sint = 0;
583 break;
584 }
585 return 1;
586 }
587
588 /* This function check the "argp" builded by another conversion function
589 * is in accord with the expected argp defined by the "mask". The function
590 * returns true or false. It can be adjust the types if there compatibles.
591 *
592 * This function assumes thant the argp argument contains ARGM_NBARGS + 1
593 * entries.
594 */
hlua_lua2arg_check(lua_State * L,int first,struct arg * argp,uint64_t mask,struct proxy * p)595 __LJMP int hlua_lua2arg_check(lua_State *L, int first, struct arg *argp,
596 uint64_t mask, struct proxy *p)
597 {
598 int min_arg;
599 int i, idx;
600 struct proxy *px;
601 const char *msg = NULL;
602 char *sname, *pname;
603
604 idx = 0;
605 min_arg = ARGM(mask);
606 mask >>= ARGM_BITS;
607
608 while (1) {
609 struct buffer tmp = BUF_NULL;
610
611 /* Check oversize. */
612 if (idx >= ARGM_NBARGS && argp[idx].type != ARGT_STOP) {
613 msg = "Malformed argument mask";
614 goto error;
615 }
616
617 /* Check for mandatory arguments. */
618 if (argp[idx].type == ARGT_STOP) {
619 if (idx < min_arg) {
620
621 /* If miss other argument than the first one, we return an error. */
622 if (idx > 0) {
623 msg = "Mandatory argument expected";
624 goto error;
625 }
626
627 /* If first argument have a certain type, some default values
628 * may be used. See the function smp_resolve_args().
629 */
630 switch (mask & ARGT_MASK) {
631
632 case ARGT_FE:
633 if (!(p->cap & PR_CAP_FE)) {
634 msg = "Mandatory argument expected";
635 goto error;
636 }
637 argp[idx].data.prx = p;
638 argp[idx].type = ARGT_FE;
639 argp[idx+1].type = ARGT_STOP;
640 break;
641
642 case ARGT_BE:
643 if (!(p->cap & PR_CAP_BE)) {
644 msg = "Mandatory argument expected";
645 goto error;
646 }
647 argp[idx].data.prx = p;
648 argp[idx].type = ARGT_BE;
649 argp[idx+1].type = ARGT_STOP;
650 break;
651
652 case ARGT_TAB:
653 argp[idx].data.prx = p;
654 argp[idx].type = ARGT_TAB;
655 argp[idx+1].type = ARGT_STOP;
656 break;
657
658 default:
659 msg = "Mandatory argument expected";
660 goto error;
661 break;
662 }
663 }
664 break;
665 }
666
667 /* Check for exceed the number of requiered argument. */
668 if ((mask & ARGT_MASK) == ARGT_STOP &&
669 argp[idx].type != ARGT_STOP) {
670 msg = "Last argument expected";
671 goto error;
672 }
673
674 if ((mask & ARGT_MASK) == ARGT_STOP &&
675 argp[idx].type == ARGT_STOP) {
676 break;
677 }
678
679 /* Convert some argument types. All string in argp[] are for not
680 * duplicated yet.
681 */
682 switch (mask & ARGT_MASK) {
683 case ARGT_SINT:
684 if (argp[idx].type != ARGT_SINT) {
685 msg = "integer expected";
686 goto error;
687 }
688 argp[idx].type = ARGT_SINT;
689 break;
690
691 case ARGT_TIME:
692 if (argp[idx].type != ARGT_SINT) {
693 msg = "integer expected";
694 goto error;
695 }
696 argp[idx].type = ARGT_TIME;
697 break;
698
699 case ARGT_SIZE:
700 if (argp[idx].type != ARGT_SINT) {
701 msg = "integer expected";
702 goto error;
703 }
704 argp[idx].type = ARGT_SIZE;
705 break;
706
707 case ARGT_FE:
708 if (argp[idx].type != ARGT_STR) {
709 msg = "string expected";
710 goto error;
711 }
712 argp[idx].data.prx = proxy_fe_by_name(argp[idx].data.str.area);
713 if (!argp[idx].data.prx) {
714 msg = "frontend doesn't exist";
715 goto error;
716 }
717 argp[idx].type = ARGT_FE;
718 break;
719
720 case ARGT_BE:
721 if (argp[idx].type != ARGT_STR) {
722 msg = "string expected";
723 goto error;
724 }
725 argp[idx].data.prx = proxy_be_by_name(argp[idx].data.str.area);
726 if (!argp[idx].data.prx) {
727 msg = "backend doesn't exist";
728 goto error;
729 }
730 argp[idx].type = ARGT_BE;
731 break;
732
733 case ARGT_TAB:
734 if (argp[idx].type != ARGT_STR) {
735 msg = "string expected";
736 goto error;
737 }
738 argp[idx].data.t = stktable_find_by_name(argp[idx].data.str.area);
739 if (!argp[idx].data.t) {
740 msg = "table doesn't exist";
741 goto error;
742 }
743 argp[idx].type = ARGT_TAB;
744 break;
745
746 case ARGT_SRV:
747 if (argp[idx].type != ARGT_STR) {
748 msg = "string expected";
749 goto error;
750 }
751 sname = strrchr(argp[idx].data.str.area, '/');
752 if (sname) {
753 *sname++ = '\0';
754 pname = argp[idx].data.str.area;
755 px = proxy_be_by_name(pname);
756 if (!px) {
757 msg = "backend doesn't exist";
758 goto error;
759 }
760 }
761 else {
762 sname = argp[idx].data.str.area;
763 px = p;
764 }
765 argp[idx].data.srv = findserver(px, sname);
766 if (!argp[idx].data.srv) {
767 msg = "server doesn't exist";
768 goto error;
769 }
770 argp[idx].type = ARGT_SRV;
771 break;
772
773 case ARGT_IPV4:
774 if (argp[idx].type != ARGT_STR) {
775 msg = "string expected";
776 goto error;
777 }
778 if (inet_pton(AF_INET, argp[idx].data.str.area, &argp[idx].data.ipv4)) {
779 msg = "invalid IPv4 address";
780 goto error;
781 }
782 argp[idx].type = ARGT_IPV4;
783 break;
784
785 case ARGT_MSK4:
786 if (argp[idx].type == ARGT_SINT)
787 len2mask4(argp[idx].data.sint, &argp[idx].data.ipv4);
788 else if (argp[idx].type == ARGT_STR) {
789 if (!str2mask(argp[idx].data.str.area, &argp[idx].data.ipv4)) {
790 msg = "invalid IPv4 mask";
791 goto error;
792 }
793 }
794 else {
795 msg = "integer or string expected";
796 goto error;
797 }
798 argp[idx].type = ARGT_MSK4;
799 break;
800
801 case ARGT_IPV6:
802 if (argp[idx].type != ARGT_STR) {
803 msg = "string expected";
804 goto error;
805 }
806 if (inet_pton(AF_INET6, argp[idx].data.str.area, &argp[idx].data.ipv6)) {
807 msg = "invalid IPv6 address";
808 goto error;
809 }
810 argp[idx].type = ARGT_IPV6;
811 break;
812
813 case ARGT_MSK6:
814 if (argp[idx].type == ARGT_SINT)
815 len2mask6(argp[idx].data.sint, &argp[idx].data.ipv6);
816 else if (argp[idx].type == ARGT_STR) {
817 if (!str2mask6(argp[idx].data.str.area, &argp[idx].data.ipv6)) {
818 msg = "invalid IPv6 mask";
819 goto error;
820 }
821 }
822 else {
823 msg = "integer or string expected";
824 goto error;
825 }
826 argp[idx].type = ARGT_MSK6;
827 break;
828
829 case ARGT_MAP:
830 case ARGT_REG:
831 case ARGT_USR:
832 msg = "type not yet supported";
833 goto error;
834 break;
835
836 case ARGT_STR:
837 if (!chunk_dup(&tmp, &argp[idx].data.str)) {
838 msg = "unable to duplicate string arg";
839 goto error;
840 }
841 argp[idx].data.str = tmp;
842 break;
843
844 }
845
846 /* Check for type of argument. */
847 if ((mask & ARGT_MASK) != argp[idx].type) {
848 msg = lua_pushfstring(L, "'%s' expected, got '%s'",
849 arg_type_names[(mask & ARGT_MASK)],
850 arg_type_names[argp[idx].type & ARGT_MASK]);
851 goto error;
852 }
853
854 /* Next argument. */
855 mask >>= ARGT_BITS;
856 idx++;
857 }
858 return 0;
859
860 error:
861 for (i = 0; i < idx; i++) {
862 if (argp[i].type == ARGT_STR)
863 chunk_destroy(&argp[i].data.str);
864 }
865 WILL_LJMP(luaL_argerror(L, first + idx, msg));
866 return 0; /* Never reached */
867 }
868
869 /*
870 * The following functions are used to make correspondance between the the
871 * executed lua pointer and the "struct hlua *" that contain the context.
872 *
873 * - hlua_gethlua : return the hlua context associated with an lua_State.
874 * - hlua_sethlua : create the association between hlua context and lua_state.
875 */
hlua_gethlua(lua_State * L)876 static inline struct hlua *hlua_gethlua(lua_State *L)
877 {
878 struct hlua **hlua = lua_getextraspace(L);
879 return *hlua;
880 }
hlua_sethlua(struct hlua * hlua)881 static inline void hlua_sethlua(struct hlua *hlua)
882 {
883 struct hlua **hlua_store = lua_getextraspace(hlua->T);
884 *hlua_store = hlua;
885 }
886
887 /* This function is used to send logs. It try to send on screen (stderr)
888 * and on the default syslog server.
889 */
hlua_sendlog(struct proxy * px,int level,const char * msg)890 static inline void hlua_sendlog(struct proxy *px, int level, const char *msg)
891 {
892 struct tm tm;
893 char *p;
894
895 /* Cleanup the log message. */
896 p = trash.area;
897 for (; *msg != '\0'; msg++, p++) {
898 if (p >= trash.area + trash.size - 1) {
899 /* Break the message if exceed the buffer size. */
900 *(p-4) = ' ';
901 *(p-3) = '.';
902 *(p-2) = '.';
903 *(p-1) = '.';
904 break;
905 }
906 if (isprint(*msg))
907 *p = *msg;
908 else
909 *p = '.';
910 }
911 *p = '\0';
912
913 send_log(px, level, "%s\n", trash.area);
914 if (!(global.mode & MODE_QUIET) || (global.mode & (MODE_VERBOSE | MODE_STARTING))) {
915 if (level == LOG_DEBUG && !(global.mode & MODE_DEBUG))
916 return;
917
918 get_localtime(date.tv_sec, &tm);
919 fprintf(stderr, "[%s] %03d/%02d%02d%02d (%d) : %s\n",
920 log_levels[level], tm.tm_yday, tm.tm_hour, tm.tm_min, tm.tm_sec,
921 (int)getpid(), trash.area);
922 fflush(stderr);
923 }
924 }
925
926 /* This function just ensure that the yield will be always
927 * returned with a timeout and permit to set some flags
928 */
hlua_yieldk(lua_State * L,int nresults,int ctx,lua_KFunction k,int timeout,unsigned int flags)929 __LJMP void hlua_yieldk(lua_State *L, int nresults, int ctx,
930 lua_KFunction k, int timeout, unsigned int flags)
931 {
932 struct hlua *hlua = hlua_gethlua(L);
933
934 /* Set the wake timeout. If timeout is required, we set
935 * the expiration time.
936 */
937 hlua->wake_time = timeout;
938
939 hlua->flags |= flags;
940
941 /* Process the yield. */
942 MAY_LJMP(lua_yieldk(L, nresults, ctx, k));
943 }
944
945 /* This function initialises the Lua environment stored in the stream.
946 * It must be called at the start of the stream. This function creates
947 * an LUA coroutine. It can not be use to crete the main LUA context.
948 *
949 * This function is particular. it initialises a new Lua thread. If the
950 * initialisation fails (example: out of memory error), the lua function
951 * throws an error (longjmp).
952 *
953 * In some case (at least one), this function can be called from safe
954 * environement, so we must not initialise it. While the support of
955 * threads appear, the safe environment set a lock to ensure only one
956 * Lua execution at a time. If we initialize safe environment in another
957 * safe environmenet, we have a dead lock.
958 *
959 * set "already_safe" true if the context is initialized form safe
960 * Lua fonction.
961 *
962 * This function manipulates two Lua stacks: the main and the thread. Only
963 * the main stack can fail. The thread is not manipulated. This function
964 * MUST NOT manipulate the created thread stack state, because it is not
965 * proctected against errors thrown by the thread stack.
966 */
hlua_ctx_init(struct hlua * lua,struct task * task,int already_safe)967 int hlua_ctx_init(struct hlua *lua, struct task *task, int already_safe)
968 {
969 if (!already_safe) {
970 if (!SET_SAFE_LJMP(gL.T)) {
971 lua->Tref = LUA_REFNIL;
972 return 0;
973 }
974 }
975 lua->Mref = LUA_REFNIL;
976 lua->flags = 0;
977 LIST_INIT(&lua->com);
978 lua->T = lua_newthread(gL.T);
979 if (!lua->T) {
980 lua->Tref = LUA_REFNIL;
981 if (!already_safe)
982 RESET_SAFE_LJMP(gL.T);
983 return 0;
984 }
985 hlua_sethlua(lua);
986 lua->Tref = luaL_ref(gL.T, LUA_REGISTRYINDEX);
987 lua->task = task;
988 if (!already_safe)
989 RESET_SAFE_LJMP(gL.T);
990 return 1;
991 }
992
993 /* Used to destroy the Lua coroutine when the attached stream or task
994 * is destroyed. The destroy also the memory context. The struct "lua"
995 * is not freed.
996 */
hlua_ctx_destroy(struct hlua * lua)997 void hlua_ctx_destroy(struct hlua *lua)
998 {
999 if (!lua)
1000 return;
1001
1002 if (!lua->T)
1003 goto end;
1004
1005 /* Purge all the pending signals. */
1006 notification_purge(&lua->com);
1007
1008 if (!SET_SAFE_LJMP(lua->T))
1009 return;
1010 luaL_unref(lua->T, LUA_REGISTRYINDEX, lua->Mref);
1011 RESET_SAFE_LJMP(lua->T);
1012
1013 if (!SET_SAFE_LJMP(gL.T))
1014 return;
1015 luaL_unref(gL.T, LUA_REGISTRYINDEX, lua->Tref);
1016 RESET_SAFE_LJMP(gL.T);
1017 /* Forces a garbage collecting process. If the Lua program is finished
1018 * without error, we run the GC on the thread pointer. Its freed all
1019 * the unused memory.
1020 * If the thread is finnish with an error or is currently yielded,
1021 * it seems that the GC applied on the thread doesn't clean anything,
1022 * so e run the GC on the main thread.
1023 * NOTE: maybe this action locks all the Lua threads untiml the en of
1024 * the garbage collection.
1025 */
1026 if (lua->flags & HLUA_MUST_GC) {
1027 if (!SET_SAFE_LJMP(gL.T))
1028 return;
1029 lua_gc(gL.T, LUA_GCCOLLECT, 0);
1030 RESET_SAFE_LJMP(gL.T);
1031 }
1032
1033 lua->T = NULL;
1034
1035 end:
1036 pool_free(pool_head_hlua, lua);
1037 }
1038
1039 /* This function is used to restore the Lua context when a coroutine
1040 * fails. This function copy the common memory between old coroutine
1041 * and the new coroutine. The old coroutine is destroyed, and its
1042 * replaced by the new coroutine.
1043 * If the flag "keep_msg" is set, the last entry of the old is assumed
1044 * as string error message and it is copied in the new stack.
1045 */
hlua_ctx_renew(struct hlua * lua,int keep_msg)1046 static int hlua_ctx_renew(struct hlua *lua, int keep_msg)
1047 {
1048 lua_State *T;
1049 int new_ref;
1050
1051 /* Renew the main LUA stack doesn't have sense. */
1052 if (lua == &gL)
1053 return 0;
1054
1055 /* New Lua coroutine. */
1056 T = lua_newthread(gL.T);
1057 if (!T)
1058 return 0;
1059
1060 /* Copy last error message. */
1061 if (keep_msg)
1062 lua_xmove(lua->T, T, 1);
1063
1064 /* Copy data between the coroutines. */
1065 lua_rawgeti(lua->T, LUA_REGISTRYINDEX, lua->Mref);
1066 lua_xmove(lua->T, T, 1);
1067 new_ref = luaL_ref(T, LUA_REGISTRYINDEX); /* Valur poped. */
1068
1069 /* Destroy old data. */
1070 luaL_unref(lua->T, LUA_REGISTRYINDEX, lua->Mref);
1071
1072 /* The thread is garbage collected by Lua. */
1073 luaL_unref(gL.T, LUA_REGISTRYINDEX, lua->Tref);
1074
1075 /* Fill the struct with the new coroutine values. */
1076 lua->Mref = new_ref;
1077 lua->T = T;
1078 lua->Tref = luaL_ref(gL.T, LUA_REGISTRYINDEX);
1079
1080 /* Set context. */
1081 hlua_sethlua(lua);
1082
1083 return 1;
1084 }
1085
hlua_hook(lua_State * L,lua_Debug * ar)1086 void hlua_hook(lua_State *L, lua_Debug *ar)
1087 {
1088 struct hlua *hlua = hlua_gethlua(L);
1089
1090 /* Lua cannot yield when its returning from a function,
1091 * so, we can fix the interrupt hook to 1 instruction,
1092 * expecting that the function is finnished.
1093 */
1094 if (lua_gethookmask(L) & LUA_MASKRET) {
1095 lua_sethook(hlua->T, hlua_hook, LUA_MASKCOUNT, 1);
1096 return;
1097 }
1098
1099 /* restore the interrupt condition. */
1100 lua_sethook(hlua->T, hlua_hook, LUA_MASKCOUNT, hlua_nb_instruction);
1101
1102 /* If we interrupt the Lua processing in yieldable state, we yield.
1103 * If the state is not yieldable, trying yield causes an error.
1104 */
1105 if (lua_isyieldable(L))
1106 MAY_LJMP(hlua_yieldk(L, 0, 0, NULL, TICK_ETERNITY, HLUA_CTRLYIELD));
1107
1108 /* If we cannot yield, update the clock and check the timeout. */
1109 tv_update_date(0, 1);
1110 hlua->run_time += now_ms - hlua->start_time;
1111 if (hlua->max_time && hlua->run_time >= hlua->max_time) {
1112 lua_pushfstring(L, "execution timeout");
1113 WILL_LJMP(lua_error(L));
1114 }
1115
1116 /* Update the start time. */
1117 hlua->start_time = now_ms;
1118
1119 /* Try to interrupt the process at the end of the current
1120 * unyieldable function.
1121 */
1122 lua_sethook(hlua->T, hlua_hook, LUA_MASKRET|LUA_MASKCOUNT, hlua_nb_instruction);
1123 }
1124
1125 /* This function start or resumes the Lua stack execution. If the flag
1126 * "yield_allowed" if no set and the LUA stack execution returns a yield
1127 * The function return an error.
1128 *
1129 * The function can returns 4 values:
1130 * - HLUA_E_OK : The execution is terminated without any errors.
1131 * - HLUA_E_AGAIN : The execution must continue at the next associated
1132 * task wakeup.
1133 * - HLUA_E_ERRMSG : An error has occurred, an error message is set in
1134 * the top of the stack.
1135 * - HLUA_E_ERR : An error has occurred without error message.
1136 *
1137 * If an error occurred, the stack is renewed and it is ready to run new
1138 * LUA code.
1139 */
hlua_ctx_resume(struct hlua * lua,int yield_allowed)1140 static enum hlua_exec hlua_ctx_resume(struct hlua *lua, int yield_allowed)
1141 {
1142 #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 504
1143 int nres;
1144 #endif
1145 int ret;
1146 const char *msg;
1147 const char *trace;
1148
1149 /* Initialise run time counter. */
1150 if (!HLUA_IS_RUNNING(lua))
1151 lua->run_time = 0;
1152
1153 /* Lock the whole Lua execution. This lock must be before the
1154 * label "resume_execution".
1155 */
1156 HA_SPIN_LOCK(LUA_LOCK, &hlua_global_lock);
1157
1158 resume_execution:
1159
1160 /* This hook interrupts the Lua processing each 'hlua_nb_instruction'
1161 * instructions. it is used for preventing infinite loops.
1162 */
1163 lua_sethook(lua->T, hlua_hook, LUA_MASKCOUNT, hlua_nb_instruction);
1164
1165 /* Remove all flags except the running flags. */
1166 HLUA_SET_RUN(lua);
1167 HLUA_CLR_CTRLYIELD(lua);
1168 HLUA_CLR_WAKERESWR(lua);
1169 HLUA_CLR_WAKEREQWR(lua);
1170
1171 /* Update the start time. */
1172 lua->start_time = now_ms;
1173
1174 /* Call the function. */
1175 #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 504
1176 ret = lua_resume(lua->T, gL.T, lua->nargs, &nres);
1177 #else
1178 ret = lua_resume(lua->T, gL.T, lua->nargs);
1179 #endif
1180 switch (ret) {
1181
1182 case LUA_OK:
1183 ret = HLUA_E_OK;
1184 break;
1185
1186 case LUA_YIELD:
1187 /* Check if the execution timeout is expired. It it is the case, we
1188 * break the Lua execution.
1189 */
1190 tv_update_date(0, 1);
1191 lua->run_time += now_ms - lua->start_time;
1192 if (lua->max_time && lua->run_time > lua->max_time) {
1193 lua_settop(lua->T, 0); /* Empty the stack. */
1194 ret = HLUA_E_ETMOUT;
1195 break;
1196 }
1197 /* Process the forced yield. if the general yield is not allowed or
1198 * if no task were associated this the current Lua execution
1199 * coroutine, we resume the execution. Else we want to return in the
1200 * scheduler and we want to be waked up again, to continue the
1201 * current Lua execution. So we schedule our own task.
1202 */
1203 if (HLUA_IS_CTRLYIELDING(lua)) {
1204 if (!yield_allowed || !lua->task)
1205 goto resume_execution;
1206 task_wakeup(lua->task, TASK_WOKEN_MSG);
1207 }
1208 if (!yield_allowed) {
1209 lua_settop(lua->T, 0); /* Empty the stack. */
1210 ret = HLUA_E_YIELD;
1211 break;
1212 }
1213 ret = HLUA_E_AGAIN;
1214 break;
1215
1216 case LUA_ERRRUN:
1217
1218 /* Special exit case. The traditional exit is returned as an error
1219 * because the errors ares the only one mean to return immediately
1220 * from and lua execution.
1221 */
1222 if (lua->flags & HLUA_EXIT) {
1223 ret = HLUA_E_OK;
1224 hlua_ctx_renew(lua, 0);
1225 break;
1226 }
1227
1228 lua->wake_time = TICK_ETERNITY;
1229 if (!lua_checkstack(lua->T, 1)) {
1230 ret = HLUA_E_ERR;
1231 break;
1232 }
1233 msg = lua_tostring(lua->T, -1);
1234 lua_settop(lua->T, 0); /* Empty the stack. */
1235 lua_pop(lua->T, 1);
1236 trace = hlua_traceback(lua->T);
1237 if (msg)
1238 lua_pushfstring(lua->T, "runtime error: %s from %s", msg, trace);
1239 else
1240 lua_pushfstring(lua->T, "unknown runtime error from %s", trace);
1241 ret = HLUA_E_ERRMSG;
1242 break;
1243
1244 case LUA_ERRMEM:
1245 lua->wake_time = TICK_ETERNITY;
1246 lua_settop(lua->T, 0); /* Empty the stack. */
1247 ret = HLUA_E_NOMEM;
1248 break;
1249
1250 case LUA_ERRERR:
1251 lua->wake_time = TICK_ETERNITY;
1252 if (!lua_checkstack(lua->T, 1)) {
1253 ret = HLUA_E_ERR;
1254 break;
1255 }
1256 msg = lua_tostring(lua->T, -1);
1257 lua_settop(lua->T, 0); /* Empty the stack. */
1258 lua_pop(lua->T, 1);
1259 if (msg)
1260 lua_pushfstring(lua->T, "message handler error: %s", msg);
1261 else
1262 lua_pushfstring(lua->T, "message handler error");
1263 ret = HLUA_E_ERRMSG;
1264 break;
1265
1266 default:
1267 lua->wake_time = TICK_ETERNITY;
1268 lua_settop(lua->T, 0); /* Empty the stack. */
1269 ret = HLUA_E_ERR;
1270 break;
1271 }
1272
1273 /* This GC permits to destroy some object when a Lua timeout strikes. */
1274 if (lua->flags & HLUA_MUST_GC &&
1275 ret != HLUA_E_AGAIN)
1276 lua_gc(lua->T, LUA_GCCOLLECT, 0);
1277
1278 switch (ret) {
1279 case HLUA_E_AGAIN:
1280 break;
1281
1282 case HLUA_E_ERRMSG:
1283 notification_purge(&lua->com);
1284 hlua_ctx_renew(lua, 1);
1285 HLUA_CLR_RUN(lua);
1286 break;
1287
1288 case HLUA_E_ETMOUT:
1289 case HLUA_E_NOMEM:
1290 case HLUA_E_YIELD:
1291 case HLUA_E_ERR:
1292 HLUA_CLR_RUN(lua);
1293 notification_purge(&lua->com);
1294 hlua_ctx_renew(lua, 0);
1295 break;
1296
1297 case HLUA_E_OK:
1298 HLUA_CLR_RUN(lua);
1299 notification_purge(&lua->com);
1300 break;
1301 }
1302
1303 /* This is the main exit point, remove the Lua lock. */
1304 HA_SPIN_UNLOCK(LUA_LOCK, &hlua_global_lock);
1305
1306 return ret;
1307 }
1308
1309 /* This function exit the current code. */
hlua_done(lua_State * L)1310 __LJMP static int hlua_done(lua_State *L)
1311 {
1312 struct hlua *hlua = hlua_gethlua(L);
1313
1314 hlua->flags |= HLUA_EXIT;
1315 WILL_LJMP(lua_error(L));
1316
1317 return 0;
1318 }
1319
1320 /* This function is an LUA binding. It provides a function
1321 * for deleting ACL from a referenced ACL file.
1322 */
hlua_del_acl(lua_State * L)1323 __LJMP static int hlua_del_acl(lua_State *L)
1324 {
1325 const char *name;
1326 const char *key;
1327 struct pat_ref *ref;
1328
1329 MAY_LJMP(check_args(L, 2, "del_acl"));
1330
1331 name = MAY_LJMP(luaL_checkstring(L, 1));
1332 key = MAY_LJMP(luaL_checkstring(L, 2));
1333
1334 ref = pat_ref_lookup(name);
1335 if (!ref)
1336 WILL_LJMP(luaL_error(L, "'del_acl': unknown acl file '%s'", name));
1337
1338 HA_SPIN_LOCK(PATREF_LOCK, &ref->lock);
1339 pat_ref_delete(ref, key);
1340 HA_SPIN_UNLOCK(PATREF_LOCK, &ref->lock);
1341 return 0;
1342 }
1343
1344 /* This function is an LUA binding. It provides a function
1345 * for deleting map entry from a referenced map file.
1346 */
hlua_del_map(lua_State * L)1347 static int hlua_del_map(lua_State *L)
1348 {
1349 const char *name;
1350 const char *key;
1351 struct pat_ref *ref;
1352
1353 MAY_LJMP(check_args(L, 2, "del_map"));
1354
1355 name = MAY_LJMP(luaL_checkstring(L, 1));
1356 key = MAY_LJMP(luaL_checkstring(L, 2));
1357
1358 ref = pat_ref_lookup(name);
1359 if (!ref)
1360 WILL_LJMP(luaL_error(L, "'del_map': unknown acl file '%s'", name));
1361
1362 HA_SPIN_LOCK(PATREF_LOCK, &ref->lock);
1363 pat_ref_delete(ref, key);
1364 HA_SPIN_UNLOCK(PATREF_LOCK, &ref->lock);
1365 return 0;
1366 }
1367
1368 /* This function is an LUA binding. It provides a function
1369 * for adding ACL pattern from a referenced ACL file.
1370 */
hlua_add_acl(lua_State * L)1371 static int hlua_add_acl(lua_State *L)
1372 {
1373 const char *name;
1374 const char *key;
1375 struct pat_ref *ref;
1376
1377 MAY_LJMP(check_args(L, 2, "add_acl"));
1378
1379 name = MAY_LJMP(luaL_checkstring(L, 1));
1380 key = MAY_LJMP(luaL_checkstring(L, 2));
1381
1382 ref = pat_ref_lookup(name);
1383 if (!ref)
1384 WILL_LJMP(luaL_error(L, "'add_acl': unknown acl file '%s'", name));
1385
1386 HA_SPIN_LOCK(PATREF_LOCK, &ref->lock);
1387 if (pat_ref_find_elt(ref, key) == NULL)
1388 pat_ref_add(ref, key, NULL, NULL);
1389 HA_SPIN_UNLOCK(PATREF_LOCK, &ref->lock);
1390 return 0;
1391 }
1392
1393 /* This function is an LUA binding. It provides a function
1394 * for setting map pattern and sample from a referenced map
1395 * file.
1396 */
hlua_set_map(lua_State * L)1397 static int hlua_set_map(lua_State *L)
1398 {
1399 const char *name;
1400 const char *key;
1401 const char *value;
1402 struct pat_ref *ref;
1403
1404 MAY_LJMP(check_args(L, 3, "set_map"));
1405
1406 name = MAY_LJMP(luaL_checkstring(L, 1));
1407 key = MAY_LJMP(luaL_checkstring(L, 2));
1408 value = MAY_LJMP(luaL_checkstring(L, 3));
1409
1410 ref = pat_ref_lookup(name);
1411 if (!ref)
1412 WILL_LJMP(luaL_error(L, "'set_map': unknown map file '%s'", name));
1413
1414 HA_SPIN_LOCK(PATREF_LOCK, &ref->lock);
1415 if (pat_ref_find_elt(ref, key) != NULL)
1416 pat_ref_set(ref, key, value, NULL);
1417 else
1418 pat_ref_add(ref, key, value, NULL);
1419 HA_SPIN_UNLOCK(PATREF_LOCK, &ref->lock);
1420 return 0;
1421 }
1422
1423 /* A class is a lot of memory that contain data. This data can be a table,
1424 * an integer or user data. This data is associated with a metatable. This
1425 * metatable have an original version registred in the global context with
1426 * the name of the object (_G[<name>] = <metable> ).
1427 *
1428 * A metable is a table that modify the standard behavior of a standard
1429 * access to the associated data. The entries of this new metatable are
1430 * defined as is:
1431 *
1432 * http://lua-users.org/wiki/MetatableEvents
1433 *
1434 * __index
1435 *
1436 * we access an absent field in a table, the result is nil. This is
1437 * true, but it is not the whole truth. Actually, such access triggers
1438 * the interpreter to look for an __index metamethod: If there is no
1439 * such method, as usually happens, then the access results in nil;
1440 * otherwise, the metamethod will provide the result.
1441 *
1442 * Control 'prototype' inheritance. When accessing "myTable[key]" and
1443 * the key does not appear in the table, but the metatable has an __index
1444 * property:
1445 *
1446 * - if the value is a function, the function is called, passing in the
1447 * table and the key; the return value of that function is returned as
1448 * the result.
1449 *
1450 * - if the value is another table, the value of the key in that table is
1451 * asked for and returned (and if it doesn't exist in that table, but that
1452 * table's metatable has an __index property, then it continues on up)
1453 *
1454 * - Use "rawget(myTable,key)" to skip this metamethod.
1455 *
1456 * http://www.lua.org/pil/13.4.1.html
1457 *
1458 * __newindex
1459 *
1460 * Like __index, but control property assignment.
1461 *
1462 * __mode - Control weak references. A string value with one or both
1463 * of the characters 'k' and 'v' which specifies that the the
1464 * keys and/or values in the table are weak references.
1465 *
1466 * __call - Treat a table like a function. When a table is followed by
1467 * parenthesis such as "myTable( 'foo' )" and the metatable has
1468 * a __call key pointing to a function, that function is invoked
1469 * (passing any specified arguments) and the return value is
1470 * returned.
1471 *
1472 * __metatable - Hide the metatable. When "getmetatable( myTable )" is
1473 * called, if the metatable for myTable has a __metatable
1474 * key, the value of that key is returned instead of the
1475 * actual metatable.
1476 *
1477 * __tostring - Control string representation. When the builtin
1478 * "tostring( myTable )" function is called, if the metatable
1479 * for myTable has a __tostring property set to a function,
1480 * that function is invoked (passing myTable to it) and the
1481 * return value is used as the string representation.
1482 *
1483 * __len - Control table length. When the table length is requested using
1484 * the length operator ( '#' ), if the metatable for myTable has
1485 * a __len key pointing to a function, that function is invoked
1486 * (passing myTable to it) and the return value used as the value
1487 * of "#myTable".
1488 *
1489 * __gc - Userdata finalizer code. When userdata is set to be garbage
1490 * collected, if the metatable has a __gc field pointing to a
1491 * function, that function is first invoked, passing the userdata
1492 * to it. The __gc metamethod is not called for tables.
1493 * (See http://lua-users.org/lists/lua-l/2006-11/msg00508.html)
1494 *
1495 * Special metamethods for redefining standard operators:
1496 * http://www.lua.org/pil/13.1.html
1497 *
1498 * __add "+"
1499 * __sub "-"
1500 * __mul "*"
1501 * __div "/"
1502 * __unm "!"
1503 * __pow "^"
1504 * __concat ".."
1505 *
1506 * Special methods for redfining standar relations
1507 * http://www.lua.org/pil/13.2.html
1508 *
1509 * __eq "=="
1510 * __lt "<"
1511 * __le "<="
1512 */
1513
1514 /*
1515 *
1516 *
1517 * Class Map
1518 *
1519 *
1520 */
1521
1522 /* Returns a struct hlua_map if the stack entry "ud" is
1523 * a class session, otherwise it throws an error.
1524 */
hlua_checkmap(lua_State * L,int ud)1525 __LJMP static struct map_descriptor *hlua_checkmap(lua_State *L, int ud)
1526 {
1527 return MAY_LJMP(hlua_checkudata(L, ud, class_map_ref));
1528 }
1529
1530 /* This function is the map constructor. It don't need
1531 * the class Map object. It creates and return a new Map
1532 * object. It must be called only during "body" or "init"
1533 * context because it process some filesystem accesses.
1534 */
hlua_map_new(struct lua_State * L)1535 __LJMP static int hlua_map_new(struct lua_State *L)
1536 {
1537 const char *fn;
1538 int match = PAT_MATCH_STR;
1539 struct sample_conv conv;
1540 const char *file = "";
1541 int line = 0;
1542 lua_Debug ar;
1543 char *err = NULL;
1544 struct arg args[2];
1545
1546 if (lua_gettop(L) < 1 || lua_gettop(L) > 2)
1547 WILL_LJMP(luaL_error(L, "'new' needs at least 1 argument."));
1548
1549 fn = MAY_LJMP(luaL_checkstring(L, 1));
1550
1551 if (lua_gettop(L) >= 2) {
1552 match = MAY_LJMP(luaL_checkinteger(L, 2));
1553 if (match < 0 || match >= PAT_MATCH_NUM)
1554 WILL_LJMP(luaL_error(L, "'new' needs a valid match method."));
1555 }
1556
1557 /* Get Lua filename and line number. */
1558 if (lua_getstack(L, 1, &ar)) { /* check function at level */
1559 lua_getinfo(L, "Sl", &ar); /* get info about it */
1560 if (ar.currentline > 0) { /* is there info? */
1561 file = ar.short_src;
1562 line = ar.currentline;
1563 }
1564 }
1565
1566 /* fill fake sample_conv struct. */
1567 conv.kw = ""; /* unused. */
1568 conv.process = NULL; /* unused. */
1569 conv.arg_mask = 0; /* unused. */
1570 conv.val_args = NULL; /* unused. */
1571 conv.out_type = SMP_T_STR;
1572 conv.private = (void *)(long)match;
1573 switch (match) {
1574 case PAT_MATCH_STR: conv.in_type = SMP_T_STR; break;
1575 case PAT_MATCH_BEG: conv.in_type = SMP_T_STR; break;
1576 case PAT_MATCH_SUB: conv.in_type = SMP_T_STR; break;
1577 case PAT_MATCH_DIR: conv.in_type = SMP_T_STR; break;
1578 case PAT_MATCH_DOM: conv.in_type = SMP_T_STR; break;
1579 case PAT_MATCH_END: conv.in_type = SMP_T_STR; break;
1580 case PAT_MATCH_REG: conv.in_type = SMP_T_STR; break;
1581 case PAT_MATCH_INT: conv.in_type = SMP_T_SINT; break;
1582 case PAT_MATCH_IP: conv.in_type = SMP_T_ADDR; break;
1583 default:
1584 WILL_LJMP(luaL_error(L, "'new' doesn't support this match mode."));
1585 }
1586
1587 /* fill fake args. */
1588 args[0].type = ARGT_STR;
1589 args[0].data.str.area = strdup(fn);
1590 args[0].data.str.data = strlen(fn);
1591 args[0].data.str.size = args[0].data.str.data+1;
1592 args[1].type = ARGT_STOP;
1593
1594 /* load the map. */
1595 if (!sample_load_map(args, &conv, file, line, &err)) {
1596 /* error case: we cant use luaL_error because we must
1597 * free the err variable.
1598 */
1599 luaL_where(L, 1);
1600 lua_pushfstring(L, "'new': %s.", err);
1601 lua_concat(L, 2);
1602 free(err);
1603 chunk_destroy(&args[0].data.str);
1604 WILL_LJMP(lua_error(L));
1605 }
1606
1607 /* create the lua object. */
1608 lua_newtable(L);
1609 lua_pushlightuserdata(L, args[0].data.map);
1610 lua_rawseti(L, -2, 0);
1611
1612 /* Pop a class Map metatable and affect it to the userdata. */
1613 lua_rawgeti(L, LUA_REGISTRYINDEX, class_map_ref);
1614 lua_setmetatable(L, -2);
1615
1616
1617 return 1;
1618 }
1619
_hlua_map_lookup(struct lua_State * L,int str)1620 __LJMP static inline int _hlua_map_lookup(struct lua_State *L, int str)
1621 {
1622 struct map_descriptor *desc;
1623 struct pattern *pat;
1624 struct sample smp;
1625
1626 MAY_LJMP(check_args(L, 2, "lookup"));
1627 desc = MAY_LJMP(hlua_checkmap(L, 1));
1628 if (desc->pat.expect_type == SMP_T_SINT) {
1629 smp.data.type = SMP_T_SINT;
1630 smp.data.u.sint = MAY_LJMP(luaL_checkinteger(L, 2));
1631 }
1632 else {
1633 smp.data.type = SMP_T_STR;
1634 smp.flags = SMP_F_CONST;
1635 smp.data.u.str.area = (char *)MAY_LJMP(luaL_checklstring(L, 2, (size_t *)&smp.data.u.str.data));
1636 smp.data.u.str.size = smp.data.u.str.data + 1;
1637 }
1638
1639 pat = pattern_exec_match(&desc->pat, &smp, 1);
1640 if (!pat || !pat->data) {
1641 if (str)
1642 lua_pushstring(L, "");
1643 else
1644 lua_pushnil(L);
1645 return 1;
1646 }
1647
1648 /* The Lua pattern must return a string, so we can't check the returned type */
1649 lua_pushlstring(L, pat->data->u.str.area, pat->data->u.str.data);
1650 return 1;
1651 }
1652
hlua_map_lookup(struct lua_State * L)1653 __LJMP static int hlua_map_lookup(struct lua_State *L)
1654 {
1655 return _hlua_map_lookup(L, 0);
1656 }
1657
hlua_map_slookup(struct lua_State * L)1658 __LJMP static int hlua_map_slookup(struct lua_State *L)
1659 {
1660 return _hlua_map_lookup(L, 1);
1661 }
1662
1663 /*
1664 *
1665 *
1666 * Class Socket
1667 *
1668 *
1669 */
1670
hlua_checksocket(lua_State * L,int ud)1671 __LJMP static struct hlua_socket *hlua_checksocket(lua_State *L, int ud)
1672 {
1673 return MAY_LJMP(hlua_checkudata(L, ud, class_socket_ref));
1674 }
1675
1676 /* This function is the handler called for each I/O on the established
1677 * connection. It is used for notify space available to send or data
1678 * received.
1679 */
hlua_socket_handler(struct appctx * appctx)1680 static void hlua_socket_handler(struct appctx *appctx)
1681 {
1682 struct stream_interface *si = appctx->owner;
1683
1684 if (appctx->ctx.hlua_cosocket.die) {
1685 si_shutw(si);
1686 si_shutr(si);
1687 si_ic(si)->flags |= CF_READ_NULL;
1688 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_read);
1689 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_write);
1690 stream_shutdown(si_strm(si), SF_ERR_KILLED);
1691 }
1692
1693 /* If we cant write, wakeup the pending write signals. */
1694 if (channel_output_closed(si_ic(si)))
1695 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_write);
1696
1697 /* If we cant read, wakeup the pending read signals. */
1698 if (channel_input_closed(si_oc(si)))
1699 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_read);
1700
1701 /* if the connection is not established, inform the stream that we want
1702 * to be notified whenever the connection completes.
1703 */
1704 if (si_opposite(si)->state < SI_ST_EST) {
1705 si_cant_get(si);
1706 si_rx_conn_blk(si);
1707 si_rx_endp_more(si);
1708 return;
1709 }
1710
1711 /* This function is called after the connect. */
1712 appctx->ctx.hlua_cosocket.connected = 1;
1713
1714 /* Wake the tasks which wants to write if the buffer have available space. */
1715 if (channel_may_recv(si_ic(si)))
1716 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_write);
1717
1718 /* Wake the tasks which wants to read if the buffer contains data. */
1719 if (!channel_is_empty(si_oc(si)))
1720 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_read);
1721
1722 /* Some data were injected in the buffer, notify the stream
1723 * interface.
1724 */
1725 if (!channel_is_empty(si_ic(si)))
1726 si_update(si);
1727
1728 /* If write notifications are registered, we considers we want
1729 * to write, so we clear the blocking flag.
1730 */
1731 if (notification_registered(&appctx->ctx.hlua_cosocket.wake_on_write))
1732 si_rx_endp_more(si);
1733 }
1734
1735 /* This function is called when the "struct stream" is destroyed.
1736 * Remove the link from the object to this stream.
1737 * Wake all the pending signals.
1738 */
hlua_socket_release(struct appctx * appctx)1739 static void hlua_socket_release(struct appctx *appctx)
1740 {
1741 struct xref *peer;
1742
1743 /* Remove my link in the original object. */
1744 peer = xref_get_peer_and_lock(&appctx->ctx.hlua_cosocket.xref);
1745 if (peer)
1746 xref_disconnect(&appctx->ctx.hlua_cosocket.xref, peer);
1747
1748 /* Wake all the task waiting for me. */
1749 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_read);
1750 notification_wake(&appctx->ctx.hlua_cosocket.wake_on_write);
1751 }
1752
1753 /* If the garbage collectio of the object is launch, nobody
1754 * uses this object. If the stream does not exists, just quit.
1755 * Send the shutdown signal to the stream. In some cases,
1756 * pending signal can rest in the read and write lists. destroy
1757 * it.
1758 */
hlua_socket_gc(lua_State * L)1759 __LJMP static int hlua_socket_gc(lua_State *L)
1760 {
1761 struct hlua_socket *socket;
1762 struct appctx *appctx;
1763 struct xref *peer;
1764
1765 MAY_LJMP(check_args(L, 1, "__gc"));
1766
1767 socket = MAY_LJMP(hlua_checksocket(L, 1));
1768 peer = xref_get_peer_and_lock(&socket->xref);
1769 if (!peer)
1770 return 0;
1771 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
1772
1773 /* Set the flag which destroy the session. */
1774 appctx->ctx.hlua_cosocket.die = 1;
1775 appctx_wakeup(appctx);
1776
1777 /* Remove all reference between the Lua stack and the coroutine stream. */
1778 xref_disconnect(&socket->xref, peer);
1779 return 0;
1780 }
1781
1782 /* The close function send shutdown signal and break the
1783 * links between the stream and the object.
1784 */
hlua_socket_close_helper(lua_State * L)1785 __LJMP static int hlua_socket_close_helper(lua_State *L)
1786 {
1787 struct hlua_socket *socket;
1788 struct appctx *appctx;
1789 struct xref *peer;
1790
1791 socket = MAY_LJMP(hlua_checksocket(L, 1));
1792
1793 /* Check if we run on the same thread than the xreator thread.
1794 * We cannot access to the socket if the thread is different.
1795 */
1796 if (socket->tid != tid)
1797 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
1798
1799 peer = xref_get_peer_and_lock(&socket->xref);
1800 if (!peer)
1801 return 0;
1802 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
1803
1804 /* Set the flag which destroy the session. */
1805 appctx->ctx.hlua_cosocket.die = 1;
1806 appctx_wakeup(appctx);
1807
1808 /* Remove all reference between the Lua stack and the coroutine stream. */
1809 xref_disconnect(&socket->xref, peer);
1810 return 0;
1811 }
1812
1813 /* The close function calls close_helper.
1814 */
hlua_socket_close(lua_State * L)1815 __LJMP static int hlua_socket_close(lua_State *L)
1816 {
1817 MAY_LJMP(check_args(L, 1, "close"));
1818 return hlua_socket_close_helper(L);
1819 }
1820
1821 /* This Lua function assumes that the stack contain three parameters.
1822 * 1 - USERDATA containing a struct socket
1823 * 2 - INTEGER with values of the macro defined below
1824 * If the integer is -1, we must read at most one line.
1825 * If the integer is -2, we ust read all the data until the
1826 * end of the stream.
1827 * If the integer is positive value, we must read a number of
1828 * bytes corresponding to this value.
1829 */
1830 #define HLSR_READ_LINE (-1)
1831 #define HLSR_READ_ALL (-2)
hlua_socket_receive_yield(struct lua_State * L,int status,lua_KContext ctx)1832 __LJMP static int hlua_socket_receive_yield(struct lua_State *L, int status, lua_KContext ctx)
1833 {
1834 struct hlua_socket *socket = MAY_LJMP(hlua_checksocket(L, 1));
1835 int wanted = lua_tointeger(L, 2);
1836 struct hlua *hlua = hlua_gethlua(L);
1837 struct appctx *appctx;
1838 size_t len;
1839 int nblk;
1840 const char *blk1;
1841 size_t len1;
1842 const char *blk2;
1843 size_t len2;
1844 int skip_at_end = 0;
1845 struct channel *oc;
1846 struct stream_interface *si;
1847 struct stream *s;
1848 struct xref *peer;
1849 int missing_bytes;
1850
1851 /* Check if this lua stack is schedulable. */
1852 if (!hlua || !hlua->task)
1853 WILL_LJMP(luaL_error(L, "The 'receive' function is only allowed in "
1854 "'frontend', 'backend' or 'task'"));
1855
1856 /* Check if we run on the same thread than the xreator thread.
1857 * We cannot access to the socket if the thread is different.
1858 */
1859 if (socket->tid != tid)
1860 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
1861
1862 /* check for connection break. If some data where read, return it. */
1863 peer = xref_get_peer_and_lock(&socket->xref);
1864 if (!peer)
1865 goto no_peer;
1866 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
1867 si = appctx->owner;
1868 s = si_strm(si);
1869
1870 oc = &s->res;
1871 if (wanted == HLSR_READ_LINE) {
1872 /* Read line. */
1873 nblk = co_getline_nc(oc, &blk1, &len1, &blk2, &len2);
1874 if (nblk < 0) /* Connection close. */
1875 goto connection_closed;
1876 if (nblk == 0) /* No data available. */
1877 goto connection_empty;
1878
1879 /* remove final \r\n. */
1880 if (nblk == 1) {
1881 if (blk1[len1-1] == '\n') {
1882 len1--;
1883 skip_at_end++;
1884 if (blk1[len1-1] == '\r') {
1885 len1--;
1886 skip_at_end++;
1887 }
1888 }
1889 }
1890 else {
1891 if (blk2[len2-1] == '\n') {
1892 len2--;
1893 skip_at_end++;
1894 if (blk2[len2-1] == '\r') {
1895 len2--;
1896 skip_at_end++;
1897 }
1898 }
1899 }
1900 }
1901
1902 else if (wanted == HLSR_READ_ALL) {
1903 /* Read all the available data. */
1904 nblk = co_getblk_nc(oc, &blk1, &len1, &blk2, &len2);
1905 if (nblk < 0) /* Connection close. */
1906 goto connection_closed;
1907 if (nblk == 0) /* No data available. */
1908 goto connection_empty;
1909 }
1910
1911 else {
1912 /* Read a block of data. */
1913 nblk = co_getblk_nc(oc, &blk1, &len1, &blk2, &len2);
1914 if (nblk < 0) /* Connection close. */
1915 goto connection_closed;
1916 if (nblk == 0) /* No data available. */
1917 goto connection_empty;
1918
1919 missing_bytes = wanted - socket->b.n;
1920 if (len1 > missing_bytes) {
1921 nblk = 1;
1922 len1 = missing_bytes;
1923 } if (nblk == 2 && len1 + len2 > missing_bytes)
1924 len2 = missing_bytes - len1;
1925 }
1926
1927 len = len1;
1928
1929 luaL_addlstring(&socket->b, blk1, len1);
1930 if (nblk == 2) {
1931 len += len2;
1932 luaL_addlstring(&socket->b, blk2, len2);
1933 }
1934
1935 /* Consume data. */
1936 co_skip(oc, len + skip_at_end);
1937
1938 /* Don't wait anything. */
1939 appctx_wakeup(appctx);
1940
1941 /* If the pattern reclaim to read all the data
1942 * in the connection, got out.
1943 */
1944 if (wanted == HLSR_READ_ALL)
1945 goto connection_empty;
1946 else if (wanted >= 0 && socket->b.n < wanted)
1947 goto connection_empty;
1948
1949 /* Return result. */
1950 luaL_pushresult(&socket->b);
1951 xref_unlock(&socket->xref, peer);
1952 return 1;
1953
1954 connection_closed:
1955
1956 xref_unlock(&socket->xref, peer);
1957
1958 no_peer:
1959
1960 /* If the buffer containds data. */
1961 if (socket->b.n > 0) {
1962 luaL_pushresult(&socket->b);
1963 return 1;
1964 }
1965 lua_pushnil(L);
1966 lua_pushstring(L, "connection closed.");
1967 return 2;
1968
1969 connection_empty:
1970
1971 if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_read, hlua->task)) {
1972 xref_unlock(&socket->xref, peer);
1973 WILL_LJMP(luaL_error(L, "out of memory"));
1974 }
1975 xref_unlock(&socket->xref, peer);
1976 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_receive_yield, TICK_ETERNITY, 0));
1977 return 0;
1978 }
1979
1980 /* This Lua function gets two parameters. The first one can be string
1981 * or a number. If the string is "*l", the user requires one line. If
1982 * the string is "*a", the user requires all the contents of the stream.
1983 * If the value is a number, the user require a number of bytes equal
1984 * to the value. The default value is "*l" (a line).
1985 *
1986 * This parameter with a variable type is converted in integer. This
1987 * integer takes this values:
1988 * -1 : read a line
1989 * -2 : read all the stream
1990 * >0 : amount of bytes.
1991 *
1992 * The second parameter is optional. It contains a string that must be
1993 * concatenated with the read data.
1994 */
hlua_socket_receive(struct lua_State * L)1995 __LJMP static int hlua_socket_receive(struct lua_State *L)
1996 {
1997 int wanted = HLSR_READ_LINE;
1998 const char *pattern;
1999 int type;
2000 char *error;
2001 size_t len;
2002 struct hlua_socket *socket;
2003
2004 if (lua_gettop(L) < 1 || lua_gettop(L) > 3)
2005 WILL_LJMP(luaL_error(L, "The 'receive' function requires between 1 and 3 arguments."));
2006
2007 socket = MAY_LJMP(hlua_checksocket(L, 1));
2008
2009 /* Check if we run on the same thread than the xreator thread.
2010 * We cannot access to the socket if the thread is different.
2011 */
2012 if (socket->tid != tid)
2013 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
2014
2015 /* check for pattern. */
2016 if (lua_gettop(L) >= 2) {
2017 type = lua_type(L, 2);
2018 if (type == LUA_TSTRING) {
2019 pattern = lua_tostring(L, 2);
2020 if (strcmp(pattern, "*a") == 0)
2021 wanted = HLSR_READ_ALL;
2022 else if (strcmp(pattern, "*l") == 0)
2023 wanted = HLSR_READ_LINE;
2024 else {
2025 wanted = strtoll(pattern, &error, 10);
2026 if (*error != '\0')
2027 WILL_LJMP(luaL_error(L, "Unsupported pattern."));
2028 }
2029 }
2030 else if (type == LUA_TNUMBER) {
2031 wanted = lua_tointeger(L, 2);
2032 if (wanted < 0)
2033 WILL_LJMP(luaL_error(L, "Unsupported size."));
2034 }
2035 }
2036
2037 /* Set pattern. */
2038 lua_pushinteger(L, wanted);
2039
2040 /* Check if we would replace the top by itself. */
2041 if (lua_gettop(L) != 2)
2042 lua_replace(L, 2);
2043
2044 /* init buffer, and fill it with prefix. */
2045 luaL_buffinit(L, &socket->b);
2046
2047 /* Check prefix. */
2048 if (lua_gettop(L) >= 3) {
2049 if (lua_type(L, 3) != LUA_TSTRING)
2050 WILL_LJMP(luaL_error(L, "Expect a 'string' for the prefix"));
2051 pattern = lua_tolstring(L, 3, &len);
2052 luaL_addlstring(&socket->b, pattern, len);
2053 }
2054
2055 return __LJMP(hlua_socket_receive_yield(L, 0, 0));
2056 }
2057
2058 /* Write the Lua input string in the output buffer.
2059 * This function returns a yield if no space is available.
2060 */
hlua_socket_write_yield(struct lua_State * L,int status,lua_KContext ctx)2061 static int hlua_socket_write_yield(struct lua_State *L,int status, lua_KContext ctx)
2062 {
2063 struct hlua_socket *socket;
2064 struct hlua *hlua = hlua_gethlua(L);
2065 struct appctx *appctx;
2066 size_t buf_len;
2067 const char *buf;
2068 int len;
2069 int send_len;
2070 int sent;
2071 struct xref *peer;
2072 struct stream_interface *si;
2073 struct stream *s;
2074
2075 /* Check if this lua stack is schedulable. */
2076 if (!hlua || !hlua->task)
2077 WILL_LJMP(luaL_error(L, "The 'write' function is only allowed in "
2078 "'frontend', 'backend' or 'task'"));
2079
2080 /* Get object */
2081 socket = MAY_LJMP(hlua_checksocket(L, 1));
2082 buf = MAY_LJMP(luaL_checklstring(L, 2, &buf_len));
2083 sent = MAY_LJMP(luaL_checkinteger(L, 3));
2084
2085 /* Check if we run on the same thread than the xreator thread.
2086 * We cannot access to the socket if the thread is different.
2087 */
2088 if (socket->tid != tid)
2089 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
2090
2091 /* check for connection break. If some data where read, return it. */
2092 peer = xref_get_peer_and_lock(&socket->xref);
2093 if (!peer) {
2094 lua_pushinteger(L, -1);
2095 return 1;
2096 }
2097 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2098 si = appctx->owner;
2099 s = si_strm(si);
2100
2101 /* Check for connection close. */
2102 if (channel_output_closed(&s->req)) {
2103 xref_unlock(&socket->xref, peer);
2104 lua_pushinteger(L, -1);
2105 return 1;
2106 }
2107
2108 /* Update the input buffer data. */
2109 buf += sent;
2110 send_len = buf_len - sent;
2111
2112 /* All the data are sent. */
2113 if (sent >= buf_len) {
2114 xref_unlock(&socket->xref, peer);
2115 return 1; /* Implicitly return the length sent. */
2116 }
2117
2118 /* Check if the buffer is available because HAProxy doesn't allocate
2119 * the request buffer if its not required.
2120 */
2121 if (s->req.buf.size == 0) {
2122 if (!si_alloc_ibuf(si, &appctx->buffer_wait))
2123 goto hlua_socket_write_yield_return;
2124 }
2125
2126 /* Check for available space. */
2127 len = b_room(&s->req.buf);
2128 if (len <= 0) {
2129 goto hlua_socket_write_yield_return;
2130 }
2131
2132 /* send data */
2133 if (len < send_len)
2134 send_len = len;
2135 len = ci_putblk(&s->req, buf, send_len);
2136
2137 /* "Not enough space" (-1), "Buffer too little to contain
2138 * the data" (-2) are not expected because the available length
2139 * is tested.
2140 * Other unknown error are also not expected.
2141 */
2142 if (len <= 0) {
2143 if (len == -1)
2144 s->req.flags |= CF_WAKE_WRITE;
2145
2146 MAY_LJMP(hlua_socket_close_helper(L));
2147 lua_pop(L, 1);
2148 lua_pushinteger(L, -1);
2149 xref_unlock(&socket->xref, peer);
2150 return 1;
2151 }
2152
2153 /* update buffers. */
2154 appctx_wakeup(appctx);
2155
2156 s->req.rex = TICK_ETERNITY;
2157 s->res.wex = TICK_ETERNITY;
2158
2159 /* Update length sent. */
2160 lua_pop(L, 1);
2161 lua_pushinteger(L, sent + len);
2162
2163 /* All the data buffer is sent ? */
2164 if (sent + len >= buf_len) {
2165 xref_unlock(&socket->xref, peer);
2166 return 1;
2167 }
2168
2169 hlua_socket_write_yield_return:
2170 if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task)) {
2171 xref_unlock(&socket->xref, peer);
2172 WILL_LJMP(luaL_error(L, "out of memory"));
2173 }
2174 xref_unlock(&socket->xref, peer);
2175 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_write_yield, TICK_ETERNITY, 0));
2176 return 0;
2177 }
2178
2179 /* This function initiate the send of data. It just check the input
2180 * parameters and push an integer in the Lua stack that contain the
2181 * amount of data written to the buffer. This is used by the function
2182 * "hlua_socket_write_yield" that can yield.
2183 *
2184 * The Lua function gets between 3 and 4 parameters. The first one is
2185 * the associated object. The second is a string buffer. The third is
2186 * a facultative integer that represents where is the buffer position
2187 * of the start of the data that can send. The first byte is the
2188 * position "1". The default value is "1". The fourth argument is a
2189 * facultative integer that represents where is the buffer position
2190 * of the end of the data that can send. The default is the last byte.
2191 */
hlua_socket_send(struct lua_State * L)2192 static int hlua_socket_send(struct lua_State *L)
2193 {
2194 int i;
2195 int j;
2196 const char *buf;
2197 size_t buf_len;
2198
2199 /* Check number of arguments. */
2200 if (lua_gettop(L) < 2 || lua_gettop(L) > 4)
2201 WILL_LJMP(luaL_error(L, "'send' needs between 2 and 4 arguments"));
2202
2203 /* Get the string. */
2204 buf = MAY_LJMP(luaL_checklstring(L, 2, &buf_len));
2205
2206 /* Get and check j. */
2207 if (lua_gettop(L) == 4) {
2208 j = MAY_LJMP(luaL_checkinteger(L, 4));
2209 if (j < 0)
2210 j = buf_len + j + 1;
2211 if (j > buf_len)
2212 j = buf_len + 1;
2213 lua_pop(L, 1);
2214 }
2215 else
2216 j = buf_len;
2217
2218 /* Get and check i. */
2219 if (lua_gettop(L) == 3) {
2220 i = MAY_LJMP(luaL_checkinteger(L, 3));
2221 if (i < 0)
2222 i = buf_len + i + 1;
2223 if (i > buf_len)
2224 i = buf_len + 1;
2225 lua_pop(L, 1);
2226 } else
2227 i = 1;
2228
2229 /* Check bth i and j. */
2230 if (i > j) {
2231 lua_pushinteger(L, 0);
2232 return 1;
2233 }
2234 if (i == 0 && j == 0) {
2235 lua_pushinteger(L, 0);
2236 return 1;
2237 }
2238 if (i == 0)
2239 i = 1;
2240 if (j == 0)
2241 j = 1;
2242
2243 /* Pop the string. */
2244 lua_pop(L, 1);
2245
2246 /* Update the buffer length. */
2247 buf += i - 1;
2248 buf_len = j - i + 1;
2249 lua_pushlstring(L, buf, buf_len);
2250
2251 /* This unsigned is used to remember the amount of sent data. */
2252 lua_pushinteger(L, 0);
2253
2254 return MAY_LJMP(hlua_socket_write_yield(L, 0, 0));
2255 }
2256
2257 #define SOCKET_INFO_MAX_LEN sizeof("[0000:0000:0000:0000:0000:0000:0000:0000]:12345")
hlua_socket_info(struct lua_State * L,struct sockaddr_storage * addr)2258 __LJMP static inline int hlua_socket_info(struct lua_State *L, struct sockaddr_storage *addr)
2259 {
2260 static char buffer[SOCKET_INFO_MAX_LEN];
2261 int ret;
2262 int len;
2263 char *p;
2264
2265 ret = addr_to_str(addr, buffer+1, SOCKET_INFO_MAX_LEN-1);
2266 if (ret <= 0) {
2267 lua_pushnil(L);
2268 return 1;
2269 }
2270
2271 if (ret == AF_UNIX) {
2272 lua_pushstring(L, buffer+1);
2273 return 1;
2274 }
2275 else if (ret == AF_INET6) {
2276 buffer[0] = '[';
2277 len = strlen(buffer);
2278 buffer[len] = ']';
2279 len++;
2280 buffer[len] = ':';
2281 len++;
2282 p = buffer;
2283 }
2284 else if (ret == AF_INET) {
2285 p = buffer + 1;
2286 len = strlen(p);
2287 p[len] = ':';
2288 len++;
2289 }
2290 else {
2291 lua_pushnil(L);
2292 return 1;
2293 }
2294
2295 if (port_to_str(addr, p + len, SOCKET_INFO_MAX_LEN-1 - len) <= 0) {
2296 lua_pushnil(L);
2297 return 1;
2298 }
2299
2300 lua_pushstring(L, p);
2301 return 1;
2302 }
2303
2304 /* Returns information about the peer of the connection. */
hlua_socket_getpeername(struct lua_State * L)2305 __LJMP static int hlua_socket_getpeername(struct lua_State *L)
2306 {
2307 struct hlua_socket *socket;
2308 struct xref *peer;
2309 struct appctx *appctx;
2310 struct stream_interface *si;
2311 struct stream *s;
2312 int ret;
2313
2314 MAY_LJMP(check_args(L, 1, "getpeername"));
2315
2316 socket = MAY_LJMP(hlua_checksocket(L, 1));
2317
2318 /* Check if we run on the same thread than the xreator thread.
2319 * We cannot access to the socket if the thread is different.
2320 */
2321 if (socket->tid != tid)
2322 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
2323
2324 /* check for connection break. If some data where read, return it. */
2325 peer = xref_get_peer_and_lock(&socket->xref);
2326 if (!peer) {
2327 lua_pushnil(L);
2328 return 1;
2329 }
2330 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2331 si = appctx->owner;
2332 s = si_strm(si);
2333
2334 if (!s->target_addr) {
2335 xref_unlock(&socket->xref, peer);
2336 lua_pushnil(L);
2337 return 1;
2338 }
2339
2340 ret = MAY_LJMP(hlua_socket_info(L, s->target_addr));
2341 xref_unlock(&socket->xref, peer);
2342 return ret;
2343 }
2344
2345 /* Returns information about my connection side. */
hlua_socket_getsockname(struct lua_State * L)2346 static int hlua_socket_getsockname(struct lua_State *L)
2347 {
2348 struct hlua_socket *socket;
2349 struct connection *conn;
2350 struct appctx *appctx;
2351 struct xref *peer;
2352 struct stream_interface *si;
2353 struct stream *s;
2354 int ret;
2355
2356 MAY_LJMP(check_args(L, 1, "getsockname"));
2357
2358 socket = MAY_LJMP(hlua_checksocket(L, 1));
2359
2360 /* Check if we run on the same thread than the xreator thread.
2361 * We cannot access to the socket if the thread is different.
2362 */
2363 if (socket->tid != tid)
2364 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
2365
2366 /* check for connection break. If some data where read, return it. */
2367 peer = xref_get_peer_and_lock(&socket->xref);
2368 if (!peer) {
2369 lua_pushnil(L);
2370 return 1;
2371 }
2372 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2373 si = appctx->owner;
2374 s = si_strm(si);
2375
2376 conn = cs_conn(objt_cs(s->si[1].end));
2377 if (!conn || !conn_get_src(conn)) {
2378 xref_unlock(&socket->xref, peer);
2379 lua_pushnil(L);
2380 return 1;
2381 }
2382
2383 ret = hlua_socket_info(L, conn->src);
2384 xref_unlock(&socket->xref, peer);
2385 return ret;
2386 }
2387
2388 /* This struct define the applet. */
2389 static struct applet update_applet = {
2390 .obj_type = OBJ_TYPE_APPLET,
2391 .name = "<LUA_TCP>",
2392 .fct = hlua_socket_handler,
2393 .release = hlua_socket_release,
2394 };
2395
hlua_socket_connect_yield(struct lua_State * L,int status,lua_KContext ctx)2396 __LJMP static int hlua_socket_connect_yield(struct lua_State *L, int status, lua_KContext ctx)
2397 {
2398 struct hlua_socket *socket = MAY_LJMP(hlua_checksocket(L, 1));
2399 struct hlua *hlua = hlua_gethlua(L);
2400 struct xref *peer;
2401 struct appctx *appctx;
2402 struct stream_interface *si;
2403 struct stream *s;
2404
2405 /* Check if we run on the same thread than the xreator thread.
2406 * We cannot access to the socket if the thread is different.
2407 */
2408 if (socket->tid != tid)
2409 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
2410
2411 /* check for connection break. If some data where read, return it. */
2412 peer = xref_get_peer_and_lock(&socket->xref);
2413 if (!peer) {
2414 lua_pushnil(L);
2415 lua_pushstring(L, "Can't connect");
2416 return 2;
2417 }
2418 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2419 si = appctx->owner;
2420 s = si_strm(si);
2421
2422 /* Check if we run on the same thread than the xreator thread.
2423 * We cannot access to the socket if the thread is different.
2424 */
2425 if (socket->tid != tid) {
2426 xref_unlock(&socket->xref, peer);
2427 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
2428 }
2429
2430 /* Check for connection close. */
2431 if (!hlua || channel_output_closed(&s->req)) {
2432 xref_unlock(&socket->xref, peer);
2433 lua_pushnil(L);
2434 lua_pushstring(L, "Can't connect");
2435 return 2;
2436 }
2437
2438 appctx = __objt_appctx(s->si[0].end);
2439
2440 /* Check for connection established. */
2441 if (appctx->ctx.hlua_cosocket.connected) {
2442 xref_unlock(&socket->xref, peer);
2443 lua_pushinteger(L, 1);
2444 return 1;
2445 }
2446
2447 if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task)) {
2448 xref_unlock(&socket->xref, peer);
2449 WILL_LJMP(luaL_error(L, "out of memory error"));
2450 }
2451 xref_unlock(&socket->xref, peer);
2452 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_connect_yield, TICK_ETERNITY, 0));
2453 return 0;
2454 }
2455
2456 /* This function fail or initite the connection. */
hlua_socket_connect(struct lua_State * L)2457 __LJMP static int hlua_socket_connect(struct lua_State *L)
2458 {
2459 struct hlua_socket *socket;
2460 int port = -1;
2461 const char *ip;
2462 struct hlua *hlua;
2463 struct appctx *appctx;
2464 int low, high;
2465 struct sockaddr_storage *addr;
2466 struct xref *peer;
2467 struct stream_interface *si;
2468 struct stream *s;
2469
2470 if (lua_gettop(L) < 2)
2471 WILL_LJMP(luaL_error(L, "connect: need at least 2 arguments"));
2472
2473 /* Get args. */
2474 socket = MAY_LJMP(hlua_checksocket(L, 1));
2475
2476 /* Check if we run on the same thread than the xreator thread.
2477 * We cannot access to the socket if the thread is different.
2478 */
2479 if (socket->tid != tid)
2480 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
2481
2482 ip = MAY_LJMP(luaL_checkstring(L, 2));
2483 if (lua_gettop(L) >= 3) {
2484 luaL_Buffer b;
2485 port = MAY_LJMP(luaL_checkinteger(L, 3));
2486
2487 /* Force the ip to end with a colon, to support IPv6 addresses
2488 * that are not enclosed within square brackets.
2489 */
2490 if (port > 0) {
2491 luaL_buffinit(L, &b);
2492 luaL_addstring(&b, ip);
2493 luaL_addchar(&b, ':');
2494 luaL_pushresult(&b);
2495 ip = lua_tolstring(L, lua_gettop(L), NULL);
2496 }
2497 }
2498
2499 /* check for connection break. If some data where read, return it. */
2500 peer = xref_get_peer_and_lock(&socket->xref);
2501 if (!peer) {
2502 lua_pushnil(L);
2503 return 1;
2504 }
2505
2506 /* Parse ip address. */
2507 addr = str2sa_range(ip, NULL, &low, &high, NULL, NULL, NULL, 0);
2508 if (!addr) {
2509 xref_unlock(&socket->xref, peer);
2510 WILL_LJMP(luaL_error(L, "connect: cannot parse destination address '%s'", ip));
2511 }
2512 if (low != high) {
2513 xref_unlock(&socket->xref, peer);
2514 WILL_LJMP(luaL_error(L, "connect: port ranges not supported : address '%s'", ip));
2515 }
2516
2517 /* Set port. */
2518 if (low == 0) {
2519 if (addr->ss_family == AF_INET) {
2520 if (port == -1) {
2521 xref_unlock(&socket->xref, peer);
2522 WILL_LJMP(luaL_error(L, "connect: port missing"));
2523 }
2524 ((struct sockaddr_in *)addr)->sin_port = htons(port);
2525 } else if (addr->ss_family == AF_INET6) {
2526 if (port == -1) {
2527 xref_unlock(&socket->xref, peer);
2528 WILL_LJMP(luaL_error(L, "connect: port missing"));
2529 }
2530 ((struct sockaddr_in6 *)addr)->sin6_port = htons(port);
2531 }
2532 }
2533
2534 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2535 si = appctx->owner;
2536 s = si_strm(si);
2537
2538 if (!sockaddr_alloc(&s->target_addr)) {
2539 xref_unlock(&socket->xref, peer);
2540 WILL_LJMP(luaL_error(L, "connect: internal error"));
2541 }
2542 *s->target_addr = *addr;
2543 s->flags |= SF_ADDR_SET;
2544
2545 hlua = hlua_gethlua(L);
2546
2547 /* inform the stream that we want to be notified whenever the
2548 * connection completes.
2549 */
2550 si_cant_get(&s->si[0]);
2551 si_rx_endp_more(&s->si[0]);
2552 appctx_wakeup(appctx);
2553
2554 hlua->flags |= HLUA_MUST_GC;
2555
2556 if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task)) {
2557 xref_unlock(&socket->xref, peer);
2558 WILL_LJMP(luaL_error(L, "out of memory"));
2559 }
2560 xref_unlock(&socket->xref, peer);
2561
2562 task_wakeup(s->task, TASK_WOKEN_INIT);
2563 /* Return yield waiting for connection. */
2564
2565 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_connect_yield, TICK_ETERNITY, 0));
2566
2567 return 0;
2568 }
2569
2570 #ifdef USE_OPENSSL
hlua_socket_connect_ssl(struct lua_State * L)2571 __LJMP static int hlua_socket_connect_ssl(struct lua_State *L)
2572 {
2573 struct hlua_socket *socket;
2574 struct xref *peer;
2575 struct appctx *appctx;
2576 struct stream_interface *si;
2577 struct stream *s;
2578
2579 MAY_LJMP(check_args(L, 3, "connect_ssl"));
2580 socket = MAY_LJMP(hlua_checksocket(L, 1));
2581
2582 /* check for connection break. If some data where read, return it. */
2583 peer = xref_get_peer_and_lock(&socket->xref);
2584 if (!peer) {
2585 lua_pushnil(L);
2586 return 1;
2587 }
2588 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2589 si = appctx->owner;
2590 s = si_strm(si);
2591
2592 s->target = &socket_ssl.obj_type;
2593 xref_unlock(&socket->xref, peer);
2594 return MAY_LJMP(hlua_socket_connect(L));
2595 }
2596 #endif
2597
hlua_socket_setoption(struct lua_State * L)2598 __LJMP static int hlua_socket_setoption(struct lua_State *L)
2599 {
2600 return 0;
2601 }
2602
hlua_socket_settimeout(struct lua_State * L)2603 __LJMP static int hlua_socket_settimeout(struct lua_State *L)
2604 {
2605 struct hlua_socket *socket;
2606 int tmout;
2607 double dtmout;
2608 struct xref *peer;
2609 struct appctx *appctx;
2610 struct stream_interface *si;
2611 struct stream *s;
2612
2613 MAY_LJMP(check_args(L, 2, "settimeout"));
2614
2615 socket = MAY_LJMP(hlua_checksocket(L, 1));
2616
2617 /* convert the timeout to millis */
2618 dtmout = MAY_LJMP(luaL_checknumber(L, 2)) * 1000;
2619
2620 /* Check for negative values */
2621 if (dtmout < 0)
2622 WILL_LJMP(luaL_error(L, "settimeout: cannot set negatives values"));
2623
2624 if (dtmout > INT_MAX) /* overflow check */
2625 WILL_LJMP(luaL_error(L, "settimeout: cannot set values larger than %d ms", INT_MAX));
2626
2627 tmout = MS_TO_TICKS((int)dtmout);
2628 if (tmout == 0)
2629 tmout++; /* very small timeouts are adjusted to a minium of 1ms */
2630
2631 /* Check if we run on the same thread than the xreator thread.
2632 * We cannot access to the socket if the thread is different.
2633 */
2634 if (socket->tid != tid)
2635 WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
2636
2637 /* check for connection break. If some data were read, return it. */
2638 peer = xref_get_peer_and_lock(&socket->xref);
2639 if (!peer) {
2640 hlua_pusherror(L, "socket: not yet initialised, you can't set timeouts.");
2641 WILL_LJMP(lua_error(L));
2642 return 0;
2643 }
2644 appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
2645 si = appctx->owner;
2646 s = si_strm(si);
2647
2648 s->sess->fe->timeout.connect = tmout;
2649 s->req.rto = tmout;
2650 s->req.wto = tmout;
2651 s->res.rto = tmout;
2652 s->res.wto = tmout;
2653 s->req.rex = tick_add_ifset(now_ms, tmout);
2654 s->req.wex = tick_add_ifset(now_ms, tmout);
2655 s->res.rex = tick_add_ifset(now_ms, tmout);
2656 s->res.wex = tick_add_ifset(now_ms, tmout);
2657
2658 s->task->expire = tick_add_ifset(now_ms, tmout);
2659 task_queue(s->task);
2660
2661 xref_unlock(&socket->xref, peer);
2662
2663 lua_pushinteger(L, 1);
2664 return 1;
2665 }
2666
hlua_socket_new(lua_State * L)2667 __LJMP static int hlua_socket_new(lua_State *L)
2668 {
2669 struct hlua_socket *socket;
2670 struct appctx *appctx;
2671 struct session *sess;
2672 struct stream *strm;
2673
2674 /* Check stack size. */
2675 if (!lua_checkstack(L, 3)) {
2676 hlua_pusherror(L, "socket: full stack");
2677 goto out_fail_conf;
2678 }
2679
2680 /* Create the object: obj[0] = userdata. */
2681 lua_newtable(L);
2682 socket = MAY_LJMP(lua_newuserdata(L, sizeof(*socket)));
2683 lua_rawseti(L, -2, 0);
2684 memset(socket, 0, sizeof(*socket));
2685 socket->tid = tid;
2686
2687 /* Check if the various memory pools are intialized. */
2688 if (!pool_head_stream || !pool_head_buffer) {
2689 hlua_pusherror(L, "socket: uninitialized pools.");
2690 goto out_fail_conf;
2691 }
2692
2693 /* Pop a class stream metatable and affect it to the userdata. */
2694 lua_rawgeti(L, LUA_REGISTRYINDEX, class_socket_ref);
2695 lua_setmetatable(L, -2);
2696
2697 /* Create the applet context */
2698 appctx = appctx_new(&update_applet, tid_bit);
2699 if (!appctx) {
2700 hlua_pusherror(L, "socket: out of memory");
2701 goto out_fail_conf;
2702 }
2703
2704 appctx->ctx.hlua_cosocket.connected = 0;
2705 appctx->ctx.hlua_cosocket.die = 0;
2706 LIST_INIT(&appctx->ctx.hlua_cosocket.wake_on_write);
2707 LIST_INIT(&appctx->ctx.hlua_cosocket.wake_on_read);
2708
2709 /* Now create a session, task and stream for this applet */
2710 sess = session_new(&socket_proxy, NULL, &appctx->obj_type);
2711 if (!sess) {
2712 hlua_pusherror(L, "socket: out of memory");
2713 goto out_fail_sess;
2714 }
2715
2716 strm = stream_new(sess, &appctx->obj_type);
2717 if (!strm) {
2718 hlua_pusherror(L, "socket: out of memory");
2719 goto out_fail_stream;
2720 }
2721
2722 /* Initialise cross reference between stream and Lua socket object. */
2723 xref_create(&socket->xref, &appctx->ctx.hlua_cosocket.xref);
2724
2725 /* Configure "right" stream interface. this "si" is used to connect
2726 * and retrieve data from the server. The connection is initialized
2727 * with the "struct server".
2728 */
2729 si_set_state(&strm->si[1], SI_ST_ASS);
2730
2731 /* Force destination server. */
2732 strm->flags |= SF_DIRECT | SF_ASSIGNED | SF_BE_ASSIGNED;
2733 strm->target = &socket_tcp.obj_type;
2734
2735 return 1;
2736
2737 out_fail_stream:
2738 session_free(sess);
2739 out_fail_sess:
2740 appctx_free(appctx);
2741 out_fail_conf:
2742 WILL_LJMP(lua_error(L));
2743 return 0;
2744 }
2745
2746 /*
2747 *
2748 *
2749 * Class Channel
2750 *
2751 *
2752 */
2753
2754 /* This function is called before the Lua execution. It stores
2755 * the differents parsers state before executing some Lua code.
2756 */
consistency_set(struct stream * stream,int opt,struct hlua_consistency * c)2757 static inline void consistency_set(struct stream *stream, int opt, struct hlua_consistency *c)
2758 {
2759 c->mode = stream->be->mode;
2760 switch (c->mode) {
2761 case PR_MODE_HTTP:
2762 c->data.http.dir = opt & SMP_OPT_DIR;
2763 if (c->data.http.dir == SMP_OPT_DIR_REQ)
2764 c->data.http.state = stream->txn->req.msg_state;
2765 else
2766 c->data.http.state = stream->txn->rsp.msg_state;
2767 break;
2768 default:
2769 break;
2770 }
2771 }
2772
2773 /* This function is called after the Lua execution. it
2774 * returns true if the parser state is consistent, otherwise,
2775 * it return false.
2776 *
2777 * In HTTP mode, the parser state must be in the same state
2778 * or greater when we exit the function. Even if we do a
2779 * control yield. This prevent to break the HTTP message
2780 * from the Lua code.
2781 */
consistency_check(struct stream * stream,int opt,struct hlua_consistency * c)2782 static inline int consistency_check(struct stream *stream, int opt, struct hlua_consistency *c)
2783 {
2784 if (c->mode != stream->be->mode)
2785 return 0;
2786
2787 switch (c->mode) {
2788 case PR_MODE_HTTP:
2789 if (c->data.http.dir != (opt & SMP_OPT_DIR))
2790 return 0;
2791 if (c->data.http.dir == SMP_OPT_DIR_REQ)
2792 return stream->txn->req.msg_state >= c->data.http.state;
2793 else
2794 return stream->txn->rsp.msg_state >= c->data.http.state;
2795 default:
2796 return 1;
2797 }
2798 return 1;
2799 }
2800
2801 /* Returns the struct hlua_channel join to the class channel in the
2802 * stack entry "ud" or throws an argument error.
2803 */
hlua_checkchannel(lua_State * L,int ud)2804 __LJMP static struct channel *hlua_checkchannel(lua_State *L, int ud)
2805 {
2806 return MAY_LJMP(hlua_checkudata(L, ud, class_channel_ref));
2807 }
2808
2809 /* Pushes the channel onto the top of the stack. If the stask does not have a
2810 * free slots, the function fails and returns 0;
2811 */
hlua_channel_new(lua_State * L,struct channel * channel)2812 static int hlua_channel_new(lua_State *L, struct channel *channel)
2813 {
2814 /* Check stack size. */
2815 if (!lua_checkstack(L, 3))
2816 return 0;
2817
2818 lua_newtable(L);
2819 lua_pushlightuserdata(L, channel);
2820 lua_rawseti(L, -2, 0);
2821
2822 /* Pop a class sesison metatable and affect it to the userdata. */
2823 lua_rawgeti(L, LUA_REGISTRYINDEX, class_channel_ref);
2824 lua_setmetatable(L, -2);
2825 return 1;
2826 }
2827
2828 /* Duplicate all the data present in the input channel and put it
2829 * in a string LUA variables. Returns -1 and push a nil value in
2830 * the stack if the channel is closed and all the data are consumed,
2831 * returns 0 if no data are available, otherwise it returns the length
2832 * of the builded string.
2833 */
_hlua_channel_dup(struct channel * chn,lua_State * L)2834 static inline int _hlua_channel_dup(struct channel *chn, lua_State *L)
2835 {
2836 char *blk1;
2837 char *blk2;
2838 size_t len1;
2839 size_t len2;
2840 int ret;
2841 luaL_Buffer b;
2842
2843 ret = ci_getblk_nc(chn, &blk1, &len1, &blk2, &len2);
2844 if (unlikely(ret == 0))
2845 return 0;
2846
2847 if (unlikely(ret < 0)) {
2848 lua_pushnil(L);
2849 return -1;
2850 }
2851
2852 luaL_buffinit(L, &b);
2853 luaL_addlstring(&b, blk1, len1);
2854 if (unlikely(ret == 2))
2855 luaL_addlstring(&b, blk2, len2);
2856 luaL_pushresult(&b);
2857
2858 if (unlikely(ret == 2))
2859 return len1 + len2;
2860 return len1;
2861 }
2862
2863 /* "_hlua_channel_dup" wrapper. If no data are available, it returns
2864 * a yield. This function keep the data in the buffer.
2865 */
hlua_channel_dup_yield(lua_State * L,int status,lua_KContext ctx)2866 __LJMP static int hlua_channel_dup_yield(lua_State *L, int status, lua_KContext ctx)
2867 {
2868 struct channel *chn;
2869
2870 chn = MAY_LJMP(hlua_checkchannel(L, 1));
2871
2872 if (chn_strm(chn)->be->mode == PR_MODE_HTTP)
2873 WILL_LJMP(lua_error(L));
2874
2875 if (_hlua_channel_dup(chn, L) == 0)
2876 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_dup_yield, TICK_ETERNITY, 0));
2877 return 1;
2878 }
2879
2880 /* Check arguments for the function "hlua_channel_dup_yield". */
hlua_channel_dup(lua_State * L)2881 __LJMP static int hlua_channel_dup(lua_State *L)
2882 {
2883 MAY_LJMP(check_args(L, 1, "dup"));
2884 MAY_LJMP(hlua_checkchannel(L, 1));
2885 return MAY_LJMP(hlua_channel_dup_yield(L, 0, 0));
2886 }
2887
2888 /* "_hlua_channel_dup" wrapper. If no data are available, it returns
2889 * a yield. This function consumes the data in the buffer. It returns
2890 * a string containing the data or a nil pointer if no data are available
2891 * and the channel is closed.
2892 */
hlua_channel_get_yield(lua_State * L,int status,lua_KContext ctx)2893 __LJMP static int hlua_channel_get_yield(lua_State *L, int status, lua_KContext ctx)
2894 {
2895 struct channel *chn;
2896 int ret;
2897
2898 chn = MAY_LJMP(hlua_checkchannel(L, 1));
2899
2900 if (chn_strm(chn)->be->mode == PR_MODE_HTTP)
2901 WILL_LJMP(lua_error(L));
2902
2903 ret = _hlua_channel_dup(chn, L);
2904 if (unlikely(ret == 0))
2905 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_get_yield, TICK_ETERNITY, 0));
2906
2907 if (unlikely(ret == -1))
2908 return 1;
2909
2910 b_sub(&chn->buf, ret);
2911 return 1;
2912 }
2913
2914 /* Check arguments for the function "hlua_channel_get_yield". */
hlua_channel_get(lua_State * L)2915 __LJMP static int hlua_channel_get(lua_State *L)
2916 {
2917 MAY_LJMP(check_args(L, 1, "get"));
2918 MAY_LJMP(hlua_checkchannel(L, 1));
2919 return MAY_LJMP(hlua_channel_get_yield(L, 0, 0));
2920 }
2921
2922 /* This functions consumes and returns one line. If the channel is closed,
2923 * and the last data does not contains a final '\n', the data are returned
2924 * without the final '\n'. When no more data are available, it returns nil
2925 * value.
2926 */
hlua_channel_getline_yield(lua_State * L,int status,lua_KContext ctx)2927 __LJMP static int hlua_channel_getline_yield(lua_State *L, int status, lua_KContext ctx)
2928 {
2929 char *blk1;
2930 char *blk2;
2931 size_t len1;
2932 size_t len2;
2933 size_t len;
2934 struct channel *chn;
2935 int ret;
2936 luaL_Buffer b;
2937
2938 chn = MAY_LJMP(hlua_checkchannel(L, 1));
2939
2940 if (chn_strm(chn)->be->mode == PR_MODE_HTTP)
2941 WILL_LJMP(lua_error(L));
2942
2943 ret = ci_getline_nc(chn, &blk1, &len1, &blk2, &len2);
2944 if (ret == 0)
2945 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_getline_yield, TICK_ETERNITY, 0));
2946
2947 if (ret == -1) {
2948 lua_pushnil(L);
2949 return 1;
2950 }
2951
2952 luaL_buffinit(L, &b);
2953 luaL_addlstring(&b, blk1, len1);
2954 len = len1;
2955 if (unlikely(ret == 2)) {
2956 luaL_addlstring(&b, blk2, len2);
2957 len += len2;
2958 }
2959 luaL_pushresult(&b);
2960 b_rep_blk(&chn->buf, ci_head(chn), ci_head(chn) + len, NULL, 0);
2961 return 1;
2962 }
2963
2964 /* Check arguments for the function "hlua_channel_getline_yield". */
hlua_channel_getline(lua_State * L)2965 __LJMP static int hlua_channel_getline(lua_State *L)
2966 {
2967 MAY_LJMP(check_args(L, 1, "getline"));
2968 MAY_LJMP(hlua_checkchannel(L, 1));
2969 return MAY_LJMP(hlua_channel_getline_yield(L, 0, 0));
2970 }
2971
2972 /* This function takes a string as input, and append it at the
2973 * input side of channel. If the data is too big, but a space
2974 * is probably available after sending some data, the function
2975 * yields. If the data is bigger than the buffer, or if the
2976 * channel is closed, it returns -1. Otherwise, it returns the
2977 * amount of data written.
2978 */
hlua_channel_append_yield(lua_State * L,int status,lua_KContext ctx)2979 __LJMP static int hlua_channel_append_yield(lua_State *L, int status, lua_KContext ctx)
2980 {
2981 struct channel *chn = MAY_LJMP(hlua_checkchannel(L, 1));
2982 size_t len;
2983 const char *str = MAY_LJMP(luaL_checklstring(L, 2, &len));
2984 int l = MAY_LJMP(luaL_checkinteger(L, 3));
2985 int ret;
2986 int max;
2987
2988 if (chn_strm(chn)->be->mode == PR_MODE_HTTP)
2989 WILL_LJMP(lua_error(L));
2990
2991 /* Check if the buffer is available because HAProxy doesn't allocate
2992 * the request buffer if its not required.
2993 */
2994 if (chn->buf.size == 0) {
2995 si_rx_buff_blk(chn_prod(chn));
2996 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_append_yield, TICK_ETERNITY, 0));
2997 }
2998
2999 max = channel_recv_limit(chn) - b_data(&chn->buf);
3000 if (max > len - l)
3001 max = len - l;
3002
3003 ret = ci_putblk(chn, str + l, max);
3004 if (ret == -2 || ret == -3) {
3005 lua_pushinteger(L, -1);
3006 return 1;
3007 }
3008 if (ret == -1) {
3009 chn->flags |= CF_WAKE_WRITE;
3010 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_append_yield, TICK_ETERNITY, 0));
3011 }
3012 l += ret;
3013 lua_pop(L, 1);
3014 lua_pushinteger(L, l);
3015
3016 max = channel_recv_limit(chn) - b_data(&chn->buf);
3017 if (max == 0 && co_data(chn) == 0) {
3018 /* There are no space available, and the output buffer is empty.
3019 * in this case, we cannot add more data, so we cannot yield,
3020 * we return the amount of copyied data.
3021 */
3022 return 1;
3023 }
3024 if (l < len)
3025 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_append_yield, TICK_ETERNITY, 0));
3026 return 1;
3027 }
3028
3029 /* Just a wrapper of "hlua_channel_append_yield". It returns the length
3030 * of the written string, or -1 if the channel is closed or if the
3031 * buffer size is too little for the data.
3032 */
hlua_channel_append(lua_State * L)3033 __LJMP static int hlua_channel_append(lua_State *L)
3034 {
3035 size_t len;
3036
3037 MAY_LJMP(check_args(L, 2, "append"));
3038 MAY_LJMP(hlua_checkchannel(L, 1));
3039 MAY_LJMP(luaL_checklstring(L, 2, &len));
3040 MAY_LJMP(luaL_checkinteger(L, 3));
3041 lua_pushinteger(L, 0);
3042
3043 return MAY_LJMP(hlua_channel_append_yield(L, 0, 0));
3044 }
3045
3046 /* Just a wrapper of "hlua_channel_append_yield". This wrapper starts
3047 * his process by cleaning the buffer. The result is a replacement
3048 * of the current data. It returns the length of the written string,
3049 * or -1 if the channel is closed or if the buffer size is too
3050 * little for the data.
3051 */
hlua_channel_set(lua_State * L)3052 __LJMP static int hlua_channel_set(lua_State *L)
3053 {
3054 struct channel *chn;
3055
3056 MAY_LJMP(check_args(L, 2, "set"));
3057 chn = MAY_LJMP(hlua_checkchannel(L, 1));
3058 lua_pushinteger(L, 0);
3059
3060 if (chn_strm(chn)->be->mode == PR_MODE_HTTP)
3061 WILL_LJMP(lua_error(L));
3062
3063 b_set_data(&chn->buf, co_data(chn));
3064
3065 return MAY_LJMP(hlua_channel_append_yield(L, 0, 0));
3066 }
3067
3068 /* Append data in the output side of the buffer. This data is immediately
3069 * sent. The function returns the amount of data written. If the buffer
3070 * cannot contain the data, the function yields. The function returns -1
3071 * if the channel is closed.
3072 */
hlua_channel_send_yield(lua_State * L,int status,lua_KContext ctx)3073 __LJMP static int hlua_channel_send_yield(lua_State *L, int status, lua_KContext ctx)
3074 {
3075 struct channel *chn = MAY_LJMP(hlua_checkchannel(L, 1));
3076 size_t len;
3077 const char *str = MAY_LJMP(luaL_checklstring(L, 2, &len));
3078 int l = MAY_LJMP(luaL_checkinteger(L, 3));
3079 int max;
3080 struct hlua *hlua = hlua_gethlua(L);
3081
3082 if (chn_strm(chn)->be->mode == PR_MODE_HTTP)
3083 WILL_LJMP(lua_error(L));
3084
3085 if (unlikely(channel_output_closed(chn))) {
3086 lua_pushinteger(L, -1);
3087 return 1;
3088 }
3089
3090 /* Check if the buffer is available because HAProxy doesn't allocate
3091 * the request buffer if its not required.
3092 */
3093 if (chn->buf.size == 0) {
3094 si_rx_buff_blk(chn_prod(chn));
3095 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_send_yield, TICK_ETERNITY, 0));
3096 }
3097
3098 /* The written data will be immediately sent, so we can check
3099 * the available space without taking in account the reserve.
3100 * The reserve is guaranteed for the processing of incoming
3101 * data, because the buffer will be flushed.
3102 */
3103 max = b_room(&chn->buf);
3104
3105 /* If there is no space available, and the output buffer is empty.
3106 * in this case, we cannot add more data, so we cannot yield,
3107 * we return the amount of copyied data.
3108 */
3109 if (max == 0 && co_data(chn) == 0)
3110 return 1;
3111
3112 /* Adjust the real required length. */
3113 if (max > len - l)
3114 max = len - l;
3115
3116 /* The buffer available size may be not contiguous. This test
3117 * detects a non contiguous buffer and realign it.
3118 */
3119 if (ci_space_for_replace(chn) < max)
3120 channel_slow_realign(chn, trash.area);
3121
3122 /* Copy input data in the buffer. */
3123 max = b_rep_blk(&chn->buf, ci_head(chn), ci_head(chn), str + l, max);
3124
3125 /* buffer replace considers that the input part is filled.
3126 * so, I must forward these new data in the output part.
3127 */
3128 c_adv(chn, max);
3129
3130 l += max;
3131 lua_pop(L, 1);
3132 lua_pushinteger(L, l);
3133
3134 /* If there is no space available, and the output buffer is empty.
3135 * in this case, we cannot add more data, so we cannot yield,
3136 * we return the amount of copyied data.
3137 */
3138 max = b_room(&chn->buf);
3139 if (max == 0 && co_data(chn) == 0)
3140 return 1;
3141
3142 if (l < len) {
3143 /* If we are waiting for space in the response buffer, we
3144 * must set the flag WAKERESWR. This flag required the task
3145 * wake up if any activity is detected on the response buffer.
3146 */
3147 if (chn->flags & CF_ISRESP)
3148 HLUA_SET_WAKERESWR(hlua);
3149 else
3150 HLUA_SET_WAKEREQWR(hlua);
3151 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_send_yield, TICK_ETERNITY, 0));
3152 }
3153
3154 return 1;
3155 }
3156
3157 /* Just a wraper of "_hlua_channel_send". This wrapper permits
3158 * yield the LUA process, and resume it without checking the
3159 * input arguments.
3160 */
hlua_channel_send(lua_State * L)3161 __LJMP static int hlua_channel_send(lua_State *L)
3162 {
3163 MAY_LJMP(check_args(L, 2, "send"));
3164 lua_pushinteger(L, 0);
3165
3166 return MAY_LJMP(hlua_channel_send_yield(L, 0, 0));
3167 }
3168
3169 /* This function forward and amount of butes. The data pass from
3170 * the input side of the buffer to the output side, and can be
3171 * forwarded. This function never fails.
3172 *
3173 * The Lua function takes an amount of bytes to be forwarded in
3174 * imput. It returns the number of bytes forwarded.
3175 */
hlua_channel_forward_yield(lua_State * L,int status,lua_KContext ctx)3176 __LJMP static int hlua_channel_forward_yield(lua_State *L, int status, lua_KContext ctx)
3177 {
3178 struct channel *chn;
3179 int len;
3180 int l;
3181 int max;
3182 struct hlua *hlua = hlua_gethlua(L);
3183
3184 chn = MAY_LJMP(hlua_checkchannel(L, 1));
3185
3186 if (chn_strm(chn)->be->mode == PR_MODE_HTTP)
3187 WILL_LJMP(lua_error(L));
3188
3189 len = MAY_LJMP(luaL_checkinteger(L, 2));
3190 l = MAY_LJMP(luaL_checkinteger(L, -1));
3191
3192 max = len - l;
3193 if (max > ci_data(chn))
3194 max = ci_data(chn);
3195 channel_forward(chn, max);
3196 l += max;
3197
3198 lua_pop(L, 1);
3199 lua_pushinteger(L, l);
3200
3201 /* Check if it miss bytes to forward. */
3202 if (l < len) {
3203 /* The the input channel or the output channel are closed, we
3204 * must return the amount of data forwarded.
3205 */
3206 if (channel_input_closed(chn) || channel_output_closed(chn))
3207 return 1;
3208
3209 /* If we are waiting for space data in the response buffer, we
3210 * must set the flag WAKERESWR. This flag required the task
3211 * wake up if any activity is detected on the response buffer.
3212 */
3213 if (chn->flags & CF_ISRESP)
3214 HLUA_SET_WAKERESWR(hlua);
3215 else
3216 HLUA_SET_WAKEREQWR(hlua);
3217
3218 /* Otherwise, we can yield waiting for new data in the inpout side. */
3219 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_forward_yield, TICK_ETERNITY, 0));
3220 }
3221
3222 return 1;
3223 }
3224
3225 /* Just check the input and prepare the stack for the previous
3226 * function "hlua_channel_forward_yield"
3227 */
hlua_channel_forward(lua_State * L)3228 __LJMP static int hlua_channel_forward(lua_State *L)
3229 {
3230 MAY_LJMP(check_args(L, 2, "forward"));
3231 MAY_LJMP(hlua_checkchannel(L, 1));
3232 MAY_LJMP(luaL_checkinteger(L, 2));
3233
3234 lua_pushinteger(L, 0);
3235 return MAY_LJMP(hlua_channel_forward_yield(L, 0, 0));
3236 }
3237
3238 /* Just returns the number of bytes available in the input
3239 * side of the buffer. This function never fails.
3240 */
hlua_channel_get_in_len(lua_State * L)3241 __LJMP static int hlua_channel_get_in_len(lua_State *L)
3242 {
3243 struct channel *chn;
3244
3245 MAY_LJMP(check_args(L, 1, "get_in_len"));
3246 chn = MAY_LJMP(hlua_checkchannel(L, 1));
3247 if (IS_HTX_STRM(chn_strm(chn))) {
3248 struct htx *htx = htxbuf(&chn->buf);
3249 lua_pushinteger(L, htx->data - co_data(chn));
3250 }
3251 else
3252 lua_pushinteger(L, ci_data(chn));
3253 return 1;
3254 }
3255
3256 /* Returns true if the channel is full. */
hlua_channel_is_full(lua_State * L)3257 __LJMP static int hlua_channel_is_full(lua_State *L)
3258 {
3259 struct channel *chn;
3260
3261 MAY_LJMP(check_args(L, 1, "is_full"));
3262 chn = MAY_LJMP(hlua_checkchannel(L, 1));
3263 /* ignore the reserve, we are not on a producer side (ie in an
3264 * applet).
3265 */
3266 lua_pushboolean(L, channel_full(chn, 0));
3267 return 1;
3268 }
3269
3270 /* Just returns the number of bytes available in the output
3271 * side of the buffer. This function never fails.
3272 */
hlua_channel_get_out_len(lua_State * L)3273 __LJMP static int hlua_channel_get_out_len(lua_State *L)
3274 {
3275 struct channel *chn;
3276
3277 MAY_LJMP(check_args(L, 1, "get_out_len"));
3278 chn = MAY_LJMP(hlua_checkchannel(L, 1));
3279 lua_pushinteger(L, co_data(chn));
3280 return 1;
3281 }
3282
3283 /*
3284 *
3285 *
3286 * Class Fetches
3287 *
3288 *
3289 */
3290
3291 /* Returns a struct hlua_session if the stack entry "ud" is
3292 * a class stream, otherwise it throws an error.
3293 */
hlua_checkfetches(lua_State * L,int ud)3294 __LJMP static struct hlua_smp *hlua_checkfetches(lua_State *L, int ud)
3295 {
3296 return MAY_LJMP(hlua_checkudata(L, ud, class_fetches_ref));
3297 }
3298
3299 /* This function creates and push in the stack a fetch object according
3300 * with a current TXN.
3301 */
hlua_fetches_new(lua_State * L,struct hlua_txn * txn,unsigned int flags)3302 static int hlua_fetches_new(lua_State *L, struct hlua_txn *txn, unsigned int flags)
3303 {
3304 struct hlua_smp *hsmp;
3305
3306 /* Check stack size. */
3307 if (!lua_checkstack(L, 3))
3308 return 0;
3309
3310 /* Create the object: obj[0] = userdata.
3311 * Note that the base of the Fetches object is the
3312 * transaction object.
3313 */
3314 lua_newtable(L);
3315 hsmp = lua_newuserdata(L, sizeof(*hsmp));
3316 lua_rawseti(L, -2, 0);
3317
3318 hsmp->s = txn->s;
3319 hsmp->p = txn->p;
3320 hsmp->dir = txn->dir;
3321 hsmp->flags = flags;
3322
3323 /* Pop a class sesison metatable and affect it to the userdata. */
3324 lua_rawgeti(L, LUA_REGISTRYINDEX, class_fetches_ref);
3325 lua_setmetatable(L, -2);
3326
3327 return 1;
3328 }
3329
3330 /* This function is an LUA binding. It is called with each sample-fetch.
3331 * It uses closure argument to store the associated sample-fetch. It
3332 * returns only one argument or throws an error. An error is thrown
3333 * only if an error is encountered during the argument parsing. If
3334 * the "sample-fetch" function fails, nil is returned.
3335 */
hlua_run_sample_fetch(lua_State * L)3336 __LJMP static int hlua_run_sample_fetch(lua_State *L)
3337 {
3338 struct hlua_smp *hsmp;
3339 struct sample_fetch *f;
3340 struct arg args[ARGM_NBARGS + 1] = {{0}};
3341 int i;
3342 struct sample smp;
3343
3344 /* Get closure arguments. */
3345 f = lua_touserdata(L, lua_upvalueindex(1));
3346
3347 /* Get traditional arguments. */
3348 hsmp = MAY_LJMP(hlua_checkfetches(L, 1));
3349
3350 /* Check execution authorization. */
3351 if (f->use & SMP_USE_HTTP_ANY &&
3352 !(hsmp->flags & HLUA_F_MAY_USE_HTTP)) {
3353 lua_pushfstring(L, "the sample-fetch '%s' needs an HTTP parser which "
3354 "is not available in Lua services", f->kw);
3355 WILL_LJMP(lua_error(L));
3356 }
3357
3358 /* Get extra arguments. */
3359 for (i = 0; i < lua_gettop(L) - 1; i++) {
3360 if (i >= ARGM_NBARGS)
3361 break;
3362 hlua_lua2arg(L, i + 2, &args[i]);
3363 }
3364 args[i].type = ARGT_STOP;
3365 args[i].data.str.area = NULL;
3366
3367 /* Check arguments. */
3368 MAY_LJMP(hlua_lua2arg_check(L, 2, args, f->arg_mask, hsmp->p));
3369
3370 /* Run the special args checker. */
3371 if (f->val_args && !f->val_args(args, NULL)) {
3372 lua_pushfstring(L, "error in arguments");
3373 goto error;
3374 }
3375
3376 /* Initialise the sample. */
3377 memset(&smp, 0, sizeof(smp));
3378
3379 /* Run the sample fetch process. */
3380 smp_set_owner(&smp, hsmp->p, hsmp->s->sess, hsmp->s, hsmp->dir & SMP_OPT_DIR);
3381 if (!f->process(args, &smp, f->kw, f->private)) {
3382 if (hsmp->flags & HLUA_F_AS_STRING)
3383 lua_pushstring(L, "");
3384 else
3385 lua_pushnil(L);
3386 goto end;
3387 }
3388
3389 /* Convert the returned sample in lua value. */
3390 if (hsmp->flags & HLUA_F_AS_STRING)
3391 hlua_smp2lua_str(L, &smp);
3392 else
3393 hlua_smp2lua(L, &smp);
3394
3395 end:
3396 for (i = 0; args[i].type != ARGT_STOP; i++) {
3397 if (args[i].type == ARGT_STR)
3398 chunk_destroy(&args[i].data.str);
3399 }
3400 return 1;
3401
3402 error:
3403 for (i = 0; args[i].type != ARGT_STOP; i++) {
3404 if (args[i].type == ARGT_STR)
3405 chunk_destroy(&args[i].data.str);
3406 }
3407 WILL_LJMP(lua_error(L));
3408 return 0; /* Never reached */
3409 }
3410
3411 /*
3412 *
3413 *
3414 * Class Converters
3415 *
3416 *
3417 */
3418
3419 /* Returns a struct hlua_session if the stack entry "ud" is
3420 * a class stream, otherwise it throws an error.
3421 */
hlua_checkconverters(lua_State * L,int ud)3422 __LJMP static struct hlua_smp *hlua_checkconverters(lua_State *L, int ud)
3423 {
3424 return MAY_LJMP(hlua_checkudata(L, ud, class_converters_ref));
3425 }
3426
3427 /* This function creates and push in the stack a Converters object
3428 * according with a current TXN.
3429 */
hlua_converters_new(lua_State * L,struct hlua_txn * txn,unsigned int flags)3430 static int hlua_converters_new(lua_State *L, struct hlua_txn *txn, unsigned int flags)
3431 {
3432 struct hlua_smp *hsmp;
3433
3434 /* Check stack size. */
3435 if (!lua_checkstack(L, 3))
3436 return 0;
3437
3438 /* Create the object: obj[0] = userdata.
3439 * Note that the base of the Converters object is the
3440 * same than the TXN object.
3441 */
3442 lua_newtable(L);
3443 hsmp = lua_newuserdata(L, sizeof(*hsmp));
3444 lua_rawseti(L, -2, 0);
3445
3446 hsmp->s = txn->s;
3447 hsmp->p = txn->p;
3448 hsmp->dir = txn->dir;
3449 hsmp->flags = flags;
3450
3451 /* Pop a class stream metatable and affect it to the table. */
3452 lua_rawgeti(L, LUA_REGISTRYINDEX, class_converters_ref);
3453 lua_setmetatable(L, -2);
3454
3455 return 1;
3456 }
3457
3458 /* This function is an LUA binding. It is called with each converter.
3459 * It uses closure argument to store the associated converter. It
3460 * returns only one argument or throws an error. An error is thrown
3461 * only if an error is encountered during the argument parsing. If
3462 * the converter function function fails, nil is returned.
3463 */
hlua_run_sample_conv(lua_State * L)3464 __LJMP static int hlua_run_sample_conv(lua_State *L)
3465 {
3466 struct hlua_smp *hsmp;
3467 struct sample_conv *conv;
3468 struct arg args[ARGM_NBARGS + 1] = {{0}};
3469 int i;
3470 struct sample smp;
3471
3472 /* Get closure arguments. */
3473 conv = lua_touserdata(L, lua_upvalueindex(1));
3474
3475 /* Get traditional arguments. */
3476 hsmp = MAY_LJMP(hlua_checkconverters(L, 1));
3477
3478 /* Get extra arguments. */
3479 for (i = 0; i < lua_gettop(L) - 2; i++) {
3480 if (i >= ARGM_NBARGS)
3481 break;
3482 hlua_lua2arg(L, i + 3, &args[i]);
3483 }
3484 args[i].type = ARGT_STOP;
3485 args[i].data.str.area = NULL;
3486
3487 /* Check arguments. */
3488 MAY_LJMP(hlua_lua2arg_check(L, 3, args, conv->arg_mask, hsmp->p));
3489
3490 /* Run the special args checker. */
3491 if (conv->val_args && !conv->val_args(args, conv, "", 0, NULL)) {
3492 hlua_pusherror(L, "error in arguments");
3493 goto error;
3494 }
3495
3496 /* Initialise the sample. */
3497 memset(&smp, 0, sizeof(smp));
3498 if (!hlua_lua2smp(L, 2, &smp)) {
3499 hlua_pusherror(L, "error in the input argument");
3500 goto error;
3501 }
3502
3503 smp_set_owner(&smp, hsmp->p, hsmp->s->sess, hsmp->s, hsmp->dir & SMP_OPT_DIR);
3504
3505 /* Apply expected cast. */
3506 if (!sample_casts[smp.data.type][conv->in_type]) {
3507 hlua_pusherror(L, "invalid input argument: cannot cast '%s' to '%s'",
3508 smp_to_type[smp.data.type], smp_to_type[conv->in_type]);
3509 goto error;
3510 }
3511 if (sample_casts[smp.data.type][conv->in_type] != c_none &&
3512 !sample_casts[smp.data.type][conv->in_type](&smp)) {
3513 hlua_pusherror(L, "error during the input argument casting");
3514 goto error;
3515 }
3516
3517 /* Run the sample conversion process. */
3518 if (!conv->process(args, &smp, conv->private)) {
3519 if (hsmp->flags & HLUA_F_AS_STRING)
3520 lua_pushstring(L, "");
3521 else
3522 lua_pushnil(L);
3523 goto end;
3524 }
3525
3526 /* Convert the returned sample in lua value. */
3527 if (hsmp->flags & HLUA_F_AS_STRING)
3528 hlua_smp2lua_str(L, &smp);
3529 else
3530 hlua_smp2lua(L, &smp);
3531 end:
3532 for (i = 0; args[i].type != ARGT_STOP; i++) {
3533 if (args[i].type == ARGT_STR)
3534 chunk_destroy(&args[i].data.str);
3535 }
3536 return 1;
3537
3538 error:
3539 for (i = 0; args[i].type != ARGT_STOP; i++) {
3540 if (args[i].type == ARGT_STR)
3541 chunk_destroy(&args[i].data.str);
3542 }
3543 WILL_LJMP(lua_error(L));
3544 return 0; /* Never reached */
3545 }
3546
3547 /*
3548 *
3549 *
3550 * Class AppletTCP
3551 *
3552 *
3553 */
3554
3555 /* Returns a struct hlua_txn if the stack entry "ud" is
3556 * a class stream, otherwise it throws an error.
3557 */
hlua_checkapplet_tcp(lua_State * L,int ud)3558 __LJMP static struct hlua_appctx *hlua_checkapplet_tcp(lua_State *L, int ud)
3559 {
3560 return MAY_LJMP(hlua_checkudata(L, ud, class_applet_tcp_ref));
3561 }
3562
3563 /* This function creates and push in the stack an Applet object
3564 * according with a current TXN.
3565 */
hlua_applet_tcp_new(lua_State * L,struct appctx * ctx)3566 static int hlua_applet_tcp_new(lua_State *L, struct appctx *ctx)
3567 {
3568 struct hlua_appctx *appctx;
3569 struct stream_interface *si = ctx->owner;
3570 struct stream *s = si_strm(si);
3571 struct proxy *p = s->be;
3572
3573 /* Check stack size. */
3574 if (!lua_checkstack(L, 3))
3575 return 0;
3576
3577 /* Create the object: obj[0] = userdata.
3578 * Note that the base of the Converters object is the
3579 * same than the TXN object.
3580 */
3581 lua_newtable(L);
3582 appctx = lua_newuserdata(L, sizeof(*appctx));
3583 lua_rawseti(L, -2, 0);
3584 appctx->appctx = ctx;
3585 appctx->htxn.s = s;
3586 appctx->htxn.p = p;
3587
3588 /* Create the "f" field that contains a list of fetches. */
3589 lua_pushstring(L, "f");
3590 if (!hlua_fetches_new(L, &appctx->htxn, 0))
3591 return 0;
3592 lua_settable(L, -3);
3593
3594 /* Create the "sf" field that contains a list of stringsafe fetches. */
3595 lua_pushstring(L, "sf");
3596 if (!hlua_fetches_new(L, &appctx->htxn, HLUA_F_AS_STRING))
3597 return 0;
3598 lua_settable(L, -3);
3599
3600 /* Create the "c" field that contains a list of converters. */
3601 lua_pushstring(L, "c");
3602 if (!hlua_converters_new(L, &appctx->htxn, 0))
3603 return 0;
3604 lua_settable(L, -3);
3605
3606 /* Create the "sc" field that contains a list of stringsafe converters. */
3607 lua_pushstring(L, "sc");
3608 if (!hlua_converters_new(L, &appctx->htxn, HLUA_F_AS_STRING))
3609 return 0;
3610 lua_settable(L, -3);
3611
3612 /* Pop a class stream metatable and affect it to the table. */
3613 lua_rawgeti(L, LUA_REGISTRYINDEX, class_applet_tcp_ref);
3614 lua_setmetatable(L, -2);
3615
3616 return 1;
3617 }
3618
hlua_applet_tcp_set_var(lua_State * L)3619 __LJMP static int hlua_applet_tcp_set_var(lua_State *L)
3620 {
3621 struct hlua_appctx *appctx;
3622 struct stream *s;
3623 const char *name;
3624 size_t len;
3625 struct sample smp;
3626
3627 MAY_LJMP(check_args(L, 3, "set_var"));
3628
3629 /* It is useles to retrieve the stream, but this function
3630 * runs only in a stream context.
3631 */
3632 appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3633 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3634 s = appctx->htxn.s;
3635
3636 /* Converts the third argument in a sample. */
3637 memset(&smp, 0, sizeof(smp));
3638 hlua_lua2smp(L, 3, &smp);
3639
3640 /* Store the sample in a variable. */
3641 smp_set_owner(&smp, s->be, s->sess, s, 0);
3642 vars_set_by_name(name, len, &smp);
3643 return 0;
3644 }
3645
hlua_applet_tcp_unset_var(lua_State * L)3646 __LJMP static int hlua_applet_tcp_unset_var(lua_State *L)
3647 {
3648 struct hlua_appctx *appctx;
3649 struct stream *s;
3650 const char *name;
3651 size_t len;
3652 struct sample smp;
3653
3654 MAY_LJMP(check_args(L, 2, "unset_var"));
3655
3656 /* It is useles to retrieve the stream, but this function
3657 * runs only in a stream context.
3658 */
3659 appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3660 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3661 s = appctx->htxn.s;
3662
3663 /* Unset the variable. */
3664 smp_set_owner(&smp, s->be, s->sess, s, 0);
3665 vars_unset_by_name(name, len, &smp);
3666 return 0;
3667 }
3668
hlua_applet_tcp_get_var(lua_State * L)3669 __LJMP static int hlua_applet_tcp_get_var(lua_State *L)
3670 {
3671 struct hlua_appctx *appctx;
3672 struct stream *s;
3673 const char *name;
3674 size_t len;
3675 struct sample smp;
3676
3677 MAY_LJMP(check_args(L, 2, "get_var"));
3678
3679 /* It is useles to retrieve the stream, but this function
3680 * runs only in a stream context.
3681 */
3682 appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3683 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
3684 s = appctx->htxn.s;
3685
3686 smp_set_owner(&smp, s->be, s->sess, s, 0);
3687 if (!vars_get_by_name(name, len, &smp)) {
3688 lua_pushnil(L);
3689 return 1;
3690 }
3691
3692 return hlua_smp2lua(L, &smp);
3693 }
3694
hlua_applet_tcp_set_priv(lua_State * L)3695 __LJMP static int hlua_applet_tcp_set_priv(lua_State *L)
3696 {
3697 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3698 struct stream *s = appctx->htxn.s;
3699 struct hlua *hlua;
3700
3701 /* Note that this hlua struct is from the session and not from the applet. */
3702 if (!s->hlua)
3703 return 0;
3704 hlua = s->hlua;
3705
3706 MAY_LJMP(check_args(L, 2, "set_priv"));
3707
3708 /* Remove previous value. */
3709 luaL_unref(L, LUA_REGISTRYINDEX, hlua->Mref);
3710
3711 /* Get and store new value. */
3712 lua_pushvalue(L, 2); /* Copy the element 2 at the top of the stack. */
3713 hlua->Mref = luaL_ref(L, LUA_REGISTRYINDEX); /* pop the previously pushed value. */
3714
3715 return 0;
3716 }
3717
hlua_applet_tcp_get_priv(lua_State * L)3718 __LJMP static int hlua_applet_tcp_get_priv(lua_State *L)
3719 {
3720 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3721 struct stream *s = appctx->htxn.s;
3722 struct hlua *hlua;
3723
3724 /* Note that this hlua struct is from the session and not from the applet. */
3725 if (!s->hlua) {
3726 lua_pushnil(L);
3727 return 1;
3728 }
3729 hlua = s->hlua;
3730
3731 /* Push configuration index in the stack. */
3732 lua_rawgeti(L, LUA_REGISTRYINDEX, hlua->Mref);
3733
3734 return 1;
3735 }
3736
3737 /* If expected data not yet available, it returns a yield. This function
3738 * consumes the data in the buffer. It returns a string containing the
3739 * data. This string can be empty.
3740 */
hlua_applet_tcp_getline_yield(lua_State * L,int status,lua_KContext ctx)3741 __LJMP static int hlua_applet_tcp_getline_yield(lua_State *L, int status, lua_KContext ctx)
3742 {
3743 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3744 struct stream_interface *si = appctx->appctx->owner;
3745 int ret;
3746 const char *blk1;
3747 size_t len1;
3748 const char *blk2;
3749 size_t len2;
3750
3751 /* Read the maximum amount of data available. */
3752 ret = co_getline_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
3753
3754 /* Data not yet available. return yield. */
3755 if (ret == 0) {
3756 si_cant_get(si);
3757 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_getline_yield, TICK_ETERNITY, 0));
3758 }
3759
3760 /* End of data: commit the total strings and return. */
3761 if (ret < 0) {
3762 luaL_pushresult(&appctx->b);
3763 return 1;
3764 }
3765
3766 /* Ensure that the block 2 length is usable. */
3767 if (ret == 1)
3768 len2 = 0;
3769
3770 /* dont check the max length read and dont check. */
3771 luaL_addlstring(&appctx->b, blk1, len1);
3772 luaL_addlstring(&appctx->b, blk2, len2);
3773
3774 /* Consume input channel output buffer data. */
3775 co_skip(si_oc(si), len1 + len2);
3776 luaL_pushresult(&appctx->b);
3777 return 1;
3778 }
3779
3780 /* Check arguments for the function "hlua_channel_get_yield". */
hlua_applet_tcp_getline(lua_State * L)3781 __LJMP static int hlua_applet_tcp_getline(lua_State *L)
3782 {
3783 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3784
3785 /* Initialise the string catenation. */
3786 luaL_buffinit(L, &appctx->b);
3787
3788 return MAY_LJMP(hlua_applet_tcp_getline_yield(L, 0, 0));
3789 }
3790
3791 /* If expected data not yet available, it returns a yield. This function
3792 * consumes the data in the buffer. It returns a string containing the
3793 * data. This string can be empty.
3794 */
hlua_applet_tcp_recv_yield(lua_State * L,int status,lua_KContext ctx)3795 __LJMP static int hlua_applet_tcp_recv_yield(lua_State *L, int status, lua_KContext ctx)
3796 {
3797 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3798 struct stream_interface *si = appctx->appctx->owner;
3799 size_t len = MAY_LJMP(luaL_checkinteger(L, 2));
3800 int ret;
3801 const char *blk1;
3802 size_t len1;
3803 const char *blk2;
3804 size_t len2;
3805
3806 /* Read the maximum amount of data available. */
3807 ret = co_getblk_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
3808
3809 /* Data not yet available. return yield. */
3810 if (ret == 0) {
3811 si_cant_get(si);
3812 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_recv_yield, TICK_ETERNITY, 0));
3813 }
3814
3815 /* End of data: commit the total strings and return. */
3816 if (ret < 0) {
3817 luaL_pushresult(&appctx->b);
3818 return 1;
3819 }
3820
3821 /* Ensure that the block 2 length is usable. */
3822 if (ret == 1)
3823 len2 = 0;
3824
3825 if (len == -1) {
3826
3827 /* If len == -1, catenate all the data avalaile and
3828 * yield because we want to get all the data until
3829 * the end of data stream.
3830 */
3831 luaL_addlstring(&appctx->b, blk1, len1);
3832 luaL_addlstring(&appctx->b, blk2, len2);
3833 co_skip(si_oc(si), len1 + len2);
3834 si_cant_get(si);
3835 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_recv_yield, TICK_ETERNITY, 0));
3836
3837 } else {
3838
3839 /* Copy the fisrt block caping to the length required. */
3840 if (len1 > len)
3841 len1 = len;
3842 luaL_addlstring(&appctx->b, blk1, len1);
3843 len -= len1;
3844
3845 /* Copy the second block. */
3846 if (len2 > len)
3847 len2 = len;
3848 luaL_addlstring(&appctx->b, blk2, len2);
3849 len -= len2;
3850
3851 /* Consume input channel output buffer data. */
3852 co_skip(si_oc(si), len1 + len2);
3853
3854 /* If there is no other data available, yield waiting for new data. */
3855 if (len > 0) {
3856 lua_pushinteger(L, len);
3857 lua_replace(L, 2);
3858 si_cant_get(si);
3859 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_recv_yield, TICK_ETERNITY, 0));
3860 }
3861
3862 /* return the result. */
3863 luaL_pushresult(&appctx->b);
3864 return 1;
3865 }
3866
3867 /* we never execute this */
3868 hlua_pusherror(L, "Lua: internal error");
3869 WILL_LJMP(lua_error(L));
3870 return 0;
3871 }
3872
3873 /* Check arguments for the function "hlua_channel_get_yield". */
hlua_applet_tcp_recv(lua_State * L)3874 __LJMP static int hlua_applet_tcp_recv(lua_State *L)
3875 {
3876 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3877 int len = -1;
3878
3879 if (lua_gettop(L) > 2)
3880 WILL_LJMP(luaL_error(L, "The 'recv' function requires between 1 and 2 arguments."));
3881 if (lua_gettop(L) >= 2) {
3882 len = MAY_LJMP(luaL_checkinteger(L, 2));
3883 lua_pop(L, 1);
3884 }
3885
3886 /* Confirm or set the required length */
3887 lua_pushinteger(L, len);
3888
3889 /* Initialise the string catenation. */
3890 luaL_buffinit(L, &appctx->b);
3891
3892 return MAY_LJMP(hlua_applet_tcp_recv_yield(L, 0, 0));
3893 }
3894
3895 /* Append data in the output side of the buffer. This data is immediately
3896 * sent. The function returns the amount of data written. If the buffer
3897 * cannot contain the data, the function yields. The function returns -1
3898 * if the channel is closed.
3899 */
hlua_applet_tcp_send_yield(lua_State * L,int status,lua_KContext ctx)3900 __LJMP static int hlua_applet_tcp_send_yield(lua_State *L, int status, lua_KContext ctx)
3901 {
3902 size_t len;
3903 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_tcp(L, 1));
3904 const char *str = MAY_LJMP(luaL_checklstring(L, 2, &len));
3905 int l = MAY_LJMP(luaL_checkinteger(L, 3));
3906 struct stream_interface *si = appctx->appctx->owner;
3907 struct channel *chn = si_ic(si);
3908 int max;
3909
3910 /* Get the max amount of data which can write as input in the channel. */
3911 max = channel_recv_max(chn);
3912 if (max > (len - l))
3913 max = len - l;
3914
3915 /* Copy data. */
3916 ci_putblk(chn, str + l, max);
3917
3918 /* update counters. */
3919 l += max;
3920 lua_pop(L, 1);
3921 lua_pushinteger(L, l);
3922
3923 /* If some data is not send, declares the situation to the
3924 * applet, and returns a yield.
3925 */
3926 if (l < len) {
3927 si_rx_room_blk(si);
3928 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_tcp_send_yield, TICK_ETERNITY, 0));
3929 }
3930
3931 return 1;
3932 }
3933
3934 /* Just a wraper of "hlua_applet_tcp_send_yield". This wrapper permits
3935 * yield the LUA process, and resume it without checking the
3936 * input arguments.
3937 */
hlua_applet_tcp_send(lua_State * L)3938 __LJMP static int hlua_applet_tcp_send(lua_State *L)
3939 {
3940 MAY_LJMP(check_args(L, 2, "send"));
3941 lua_pushinteger(L, 0);
3942
3943 return MAY_LJMP(hlua_applet_tcp_send_yield(L, 0, 0));
3944 }
3945
3946 /*
3947 *
3948 *
3949 * Class AppletHTTP
3950 *
3951 *
3952 */
3953
3954 /* Returns a struct hlua_txn if the stack entry "ud" is
3955 * a class stream, otherwise it throws an error.
3956 */
hlua_checkapplet_http(lua_State * L,int ud)3957 __LJMP static struct hlua_appctx *hlua_checkapplet_http(lua_State *L, int ud)
3958 {
3959 return MAY_LJMP(hlua_checkudata(L, ud, class_applet_http_ref));
3960 }
3961
3962 /* This function creates and push in the stack an Applet object
3963 * according with a current TXN.
3964 */
hlua_applet_http_new(lua_State * L,struct appctx * ctx)3965 static int hlua_applet_http_new(lua_State *L, struct appctx *ctx)
3966 {
3967 struct hlua_appctx *appctx;
3968 struct hlua_txn htxn;
3969 struct stream_interface *si = ctx->owner;
3970 struct stream *s = si_strm(si);
3971 struct proxy *px = s->be;
3972 struct htx *htx;
3973 struct htx_blk *blk;
3974 struct htx_sl *sl;
3975 struct ist path;
3976 unsigned long long len = 0;
3977 int32_t pos;
3978
3979 /* Check stack size. */
3980 if (!lua_checkstack(L, 3))
3981 return 0;
3982
3983 /* Create the object: obj[0] = userdata.
3984 * Note that the base of the Converters object is the
3985 * same than the TXN object.
3986 */
3987 lua_newtable(L);
3988 appctx = lua_newuserdata(L, sizeof(*appctx));
3989 lua_rawseti(L, -2, 0);
3990 appctx->appctx = ctx;
3991 appctx->appctx->ctx.hlua_apphttp.status = 200; /* Default status code returned. */
3992 appctx->appctx->ctx.hlua_apphttp.reason = NULL; /* Use default reason based on status */
3993 appctx->htxn.s = s;
3994 appctx->htxn.p = px;
3995
3996 /* Create the "f" field that contains a list of fetches. */
3997 lua_pushstring(L, "f");
3998 if (!hlua_fetches_new(L, &appctx->htxn, 0))
3999 return 0;
4000 lua_settable(L, -3);
4001
4002 /* Create the "sf" field that contains a list of stringsafe fetches. */
4003 lua_pushstring(L, "sf");
4004 if (!hlua_fetches_new(L, &appctx->htxn, HLUA_F_AS_STRING))
4005 return 0;
4006 lua_settable(L, -3);
4007
4008 /* Create the "c" field that contains a list of converters. */
4009 lua_pushstring(L, "c");
4010 if (!hlua_converters_new(L, &appctx->htxn, 0))
4011 return 0;
4012 lua_settable(L, -3);
4013
4014 /* Create the "sc" field that contains a list of stringsafe converters. */
4015 lua_pushstring(L, "sc");
4016 if (!hlua_converters_new(L, &appctx->htxn, HLUA_F_AS_STRING))
4017 return 0;
4018 lua_settable(L, -3);
4019
4020 htx = htxbuf(&s->req.buf);
4021 blk = htx_get_first_blk(htx);
4022 BUG_ON(!blk || htx_get_blk_type(blk) != HTX_BLK_REQ_SL);
4023 sl = htx_get_blk_ptr(htx, blk);
4024
4025 /* Stores the request method. */
4026 lua_pushstring(L, "method");
4027 lua_pushlstring(L, HTX_SL_REQ_MPTR(sl), HTX_SL_REQ_MLEN(sl));
4028 lua_settable(L, -3);
4029
4030 /* Stores the http version. */
4031 lua_pushstring(L, "version");
4032 lua_pushlstring(L, HTX_SL_REQ_VPTR(sl), HTX_SL_REQ_VLEN(sl));
4033 lua_settable(L, -3);
4034
4035 /* creates an array of headers. hlua_http_get_headers() crates and push
4036 * the array on the top of the stack.
4037 */
4038 lua_pushstring(L, "headers");
4039 htxn.s = s;
4040 htxn.p = px;
4041 htxn.dir = SMP_OPT_DIR_REQ;
4042 if (!hlua_http_get_headers(L, &htxn, &htxn.s->txn->req))
4043 return 0;
4044 lua_settable(L, -3);
4045
4046 path = http_get_path(htx_sl_req_uri(sl));
4047 if (path.ptr) {
4048 char *p, *q, *end;
4049
4050 p = path.ptr;
4051 end = path.ptr + path.len;
4052 q = p;
4053 while (q < end && *q != '?')
4054 q++;
4055
4056 /* Stores the request path. */
4057 lua_pushstring(L, "path");
4058 lua_pushlstring(L, p, q - p);
4059 lua_settable(L, -3);
4060
4061 /* Stores the query string. */
4062 lua_pushstring(L, "qs");
4063 if (*q == '?')
4064 q++;
4065 lua_pushlstring(L, q, end - q);
4066 lua_settable(L, -3);
4067 }
4068
4069 for (pos = htx_get_first(htx); pos != -1; pos = htx_get_next(htx, pos)) {
4070 struct htx_blk *blk = htx_get_blk(htx, pos);
4071 enum htx_blk_type type = htx_get_blk_type(blk);
4072
4073 if (type == HTX_BLK_EOM || type == HTX_BLK_TLR || type == HTX_BLK_EOT)
4074 break;
4075 if (type == HTX_BLK_DATA)
4076 len += htx_get_blksz(blk);
4077 }
4078 if (htx->extra != ULLONG_MAX)
4079 len += htx->extra;
4080
4081 /* Stores the request path. */
4082 lua_pushstring(L, "length");
4083 lua_pushinteger(L, len);
4084 lua_settable(L, -3);
4085
4086 /* Create an empty array of HTTP request headers. */
4087 lua_pushstring(L, "response");
4088 lua_newtable(L);
4089 lua_settable(L, -3);
4090
4091 /* Pop a class stream metatable and affect it to the table. */
4092 lua_rawgeti(L, LUA_REGISTRYINDEX, class_applet_http_ref);
4093 lua_setmetatable(L, -2);
4094
4095 return 1;
4096 }
4097
hlua_applet_http_set_var(lua_State * L)4098 __LJMP static int hlua_applet_http_set_var(lua_State *L)
4099 {
4100 struct hlua_appctx *appctx;
4101 struct stream *s;
4102 const char *name;
4103 size_t len;
4104 struct sample smp;
4105
4106 MAY_LJMP(check_args(L, 3, "set_var"));
4107
4108 /* It is useles to retrieve the stream, but this function
4109 * runs only in a stream context.
4110 */
4111 appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4112 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
4113 s = appctx->htxn.s;
4114
4115 /* Converts the third argument in a sample. */
4116 memset(&smp, 0, sizeof(smp));
4117 hlua_lua2smp(L, 3, &smp);
4118
4119 /* Store the sample in a variable. */
4120 smp_set_owner(&smp, s->be, s->sess, s, 0);
4121 vars_set_by_name(name, len, &smp);
4122 return 0;
4123 }
4124
hlua_applet_http_unset_var(lua_State * L)4125 __LJMP static int hlua_applet_http_unset_var(lua_State *L)
4126 {
4127 struct hlua_appctx *appctx;
4128 struct stream *s;
4129 const char *name;
4130 size_t len;
4131 struct sample smp;
4132
4133 MAY_LJMP(check_args(L, 2, "unset_var"));
4134
4135 /* It is useles to retrieve the stream, but this function
4136 * runs only in a stream context.
4137 */
4138 appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4139 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
4140 s = appctx->htxn.s;
4141
4142 /* Unset the variable. */
4143 smp_set_owner(&smp, s->be, s->sess, s, 0);
4144 vars_unset_by_name(name, len, &smp);
4145 return 0;
4146 }
4147
hlua_applet_http_get_var(lua_State * L)4148 __LJMP static int hlua_applet_http_get_var(lua_State *L)
4149 {
4150 struct hlua_appctx *appctx;
4151 struct stream *s;
4152 const char *name;
4153 size_t len;
4154 struct sample smp;
4155
4156 MAY_LJMP(check_args(L, 2, "get_var"));
4157
4158 /* It is useles to retrieve the stream, but this function
4159 * runs only in a stream context.
4160 */
4161 appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4162 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
4163 s = appctx->htxn.s;
4164
4165 smp_set_owner(&smp, s->be, s->sess, s, 0);
4166 if (!vars_get_by_name(name, len, &smp)) {
4167 lua_pushnil(L);
4168 return 1;
4169 }
4170
4171 return hlua_smp2lua(L, &smp);
4172 }
4173
hlua_applet_http_set_priv(lua_State * L)4174 __LJMP static int hlua_applet_http_set_priv(lua_State *L)
4175 {
4176 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4177 struct stream *s = appctx->htxn.s;
4178 struct hlua *hlua;
4179
4180 /* Note that this hlua struct is from the session and not from the applet. */
4181 if (!s->hlua)
4182 return 0;
4183 hlua = s->hlua;
4184
4185 MAY_LJMP(check_args(L, 2, "set_priv"));
4186
4187 /* Remove previous value. */
4188 luaL_unref(L, LUA_REGISTRYINDEX, hlua->Mref);
4189
4190 /* Get and store new value. */
4191 lua_pushvalue(L, 2); /* Copy the element 2 at the top of the stack. */
4192 hlua->Mref = luaL_ref(L, LUA_REGISTRYINDEX); /* pop the previously pushed value. */
4193
4194 return 0;
4195 }
4196
hlua_applet_http_get_priv(lua_State * L)4197 __LJMP static int hlua_applet_http_get_priv(lua_State *L)
4198 {
4199 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4200 struct stream *s = appctx->htxn.s;
4201 struct hlua *hlua;
4202
4203 /* Note that this hlua struct is from the session and not from the applet. */
4204 if (!s->hlua) {
4205 lua_pushnil(L);
4206 return 1;
4207 }
4208 hlua = s->hlua;
4209
4210 /* Push configuration index in the stack. */
4211 lua_rawgeti(L, LUA_REGISTRYINDEX, hlua->Mref);
4212
4213 return 1;
4214 }
4215
4216 /* If expected data not yet available, it returns a yield. This function
4217 * consumes the data in the buffer. It returns a string containing the
4218 * data. This string can be empty.
4219 */
hlua_applet_http_getline_yield(lua_State * L,int status,lua_KContext ctx)4220 __LJMP static int hlua_applet_http_getline_yield(lua_State *L, int status, lua_KContext ctx)
4221 {
4222 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4223 struct stream_interface *si = appctx->appctx->owner;
4224 struct channel *req = si_oc(si);
4225 struct htx *htx;
4226 struct htx_blk *blk;
4227 size_t count;
4228 int stop = 0;
4229
4230 htx = htx_from_buf(&req->buf);
4231 count = co_data(req);
4232 blk = htx_get_first_blk(htx);
4233
4234 while (count && !stop && blk) {
4235 enum htx_blk_type type = htx_get_blk_type(blk);
4236 uint32_t sz = htx_get_blksz(blk);
4237 struct ist v;
4238 uint32_t vlen;
4239 char *nl;
4240
4241 if (type == HTX_BLK_EOM) {
4242 stop = 1;
4243 break;
4244 }
4245
4246 vlen = sz;
4247 if (vlen > count) {
4248 if (type != HTX_BLK_DATA)
4249 break;
4250 vlen = count;
4251 }
4252
4253 switch (type) {
4254 case HTX_BLK_UNUSED:
4255 break;
4256
4257 case HTX_BLK_DATA:
4258 v = htx_get_blk_value(htx, blk);
4259 v.len = vlen;
4260 nl = istchr(v, '\n');
4261 if (nl != NULL) {
4262 stop = 1;
4263 vlen = nl - v.ptr + 1;
4264 }
4265 luaL_addlstring(&appctx->b, v.ptr, vlen);
4266 break;
4267
4268 case HTX_BLK_TLR:
4269 case HTX_BLK_EOM:
4270 stop = 1;
4271 break;
4272
4273 default:
4274 break;
4275 }
4276
4277 co_set_data(req, co_data(req) - vlen);
4278 count -= vlen;
4279 if (sz == vlen)
4280 blk = htx_remove_blk(htx, blk);
4281 else {
4282 htx_cut_data_blk(htx, blk, vlen);
4283 break;
4284 }
4285 }
4286
4287 htx_to_buf(htx, &req->buf);
4288 if (!stop) {
4289 si_cant_get(si);
4290 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_getline_yield, TICK_ETERNITY, 0));
4291 }
4292
4293 /* return the result. */
4294 luaL_pushresult(&appctx->b);
4295 return 1;
4296 }
4297
4298
4299 /* Check arguments for the function "hlua_channel_get_yield". */
hlua_applet_http_getline(lua_State * L)4300 __LJMP static int hlua_applet_http_getline(lua_State *L)
4301 {
4302 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4303
4304 /* Initialise the string catenation. */
4305 luaL_buffinit(L, &appctx->b);
4306
4307 return MAY_LJMP(hlua_applet_http_getline_yield(L, 0, 0));
4308 }
4309
4310 /* If expected data not yet available, it returns a yield. This function
4311 * consumes the data in the buffer. It returns a string containing the
4312 * data. This string can be empty.
4313 */
hlua_applet_http_recv_yield(lua_State * L,int status,lua_KContext ctx)4314 __LJMP static int hlua_applet_http_recv_yield(lua_State *L, int status, lua_KContext ctx)
4315 {
4316 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4317 struct stream_interface *si = appctx->appctx->owner;
4318 struct channel *req = si_oc(si);
4319 struct htx *htx;
4320 struct htx_blk *blk;
4321 size_t count;
4322 int len;
4323
4324 htx = htx_from_buf(&req->buf);
4325 len = MAY_LJMP(luaL_checkinteger(L, 2));
4326 count = co_data(req);
4327 blk = htx_get_head_blk(htx);
4328 while (count && len && blk) {
4329 enum htx_blk_type type = htx_get_blk_type(blk);
4330 uint32_t sz = htx_get_blksz(blk);
4331 struct ist v;
4332 uint32_t vlen;
4333
4334 if (type == HTX_BLK_EOM) {
4335 len = 0;
4336 break;
4337 }
4338
4339 vlen = sz;
4340 if (len > 0 && vlen > len)
4341 vlen = len;
4342 if (vlen > count) {
4343 if (type != HTX_BLK_DATA)
4344 break;
4345 vlen = count;
4346 }
4347
4348 switch (type) {
4349 case HTX_BLK_UNUSED:
4350 break;
4351
4352 case HTX_BLK_DATA:
4353 v = htx_get_blk_value(htx, blk);
4354 luaL_addlstring(&appctx->b, v.ptr, vlen);
4355 break;
4356
4357 case HTX_BLK_TLR:
4358 case HTX_BLK_EOM:
4359 len = 0;
4360 break;
4361
4362 default:
4363 break;
4364 }
4365
4366 co_set_data(req, co_data(req) - vlen);
4367 count -= vlen;
4368 if (len > 0)
4369 len -= vlen;
4370 if (sz == vlen)
4371 blk = htx_remove_blk(htx, blk);
4372 else {
4373 htx_cut_data_blk(htx, blk, vlen);
4374 break;
4375 }
4376 }
4377
4378 htx_to_buf(htx, &req->buf);
4379
4380 /* If we are no other data available, yield waiting for new data. */
4381 if (len) {
4382 if (len > 0) {
4383 lua_pushinteger(L, len);
4384 lua_replace(L, 2);
4385 }
4386 si_cant_get(si);
4387 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_recv_yield, TICK_ETERNITY, 0));
4388 }
4389
4390 /* return the result. */
4391 luaL_pushresult(&appctx->b);
4392 return 1;
4393 }
4394
4395 /* Check arguments for the function "hlua_channel_get_yield". */
hlua_applet_http_recv(lua_State * L)4396 __LJMP static int hlua_applet_http_recv(lua_State *L)
4397 {
4398 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4399 int len = -1;
4400
4401 /* Check arguments. */
4402 if (lua_gettop(L) > 2)
4403 WILL_LJMP(luaL_error(L, "The 'recv' function requires between 1 and 2 arguments."));
4404 if (lua_gettop(L) >= 2) {
4405 len = MAY_LJMP(luaL_checkinteger(L, 2));
4406 lua_pop(L, 1);
4407 }
4408
4409 lua_pushinteger(L, len);
4410
4411 /* Initialise the string catenation. */
4412 luaL_buffinit(L, &appctx->b);
4413
4414 return MAY_LJMP(hlua_applet_http_recv_yield(L, 0, 0));
4415 }
4416
4417 /* Append data in the output side of the buffer. This data is immediately
4418 * sent. The function returns the amount of data written. If the buffer
4419 * cannot contain the data, the function yields. The function returns -1
4420 * if the channel is closed.
4421 */
hlua_applet_http_send_yield(lua_State * L,int status,lua_KContext ctx)4422 __LJMP static int hlua_applet_http_send_yield(lua_State *L, int status, lua_KContext ctx)
4423 {
4424 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4425 struct stream_interface *si = appctx->appctx->owner;
4426 struct channel *res = si_ic(si);
4427 struct htx *htx = htx_from_buf(&res->buf);
4428 const char *data;
4429 size_t len;
4430 int l = MAY_LJMP(luaL_checkinteger(L, 3));
4431 int max;
4432
4433 max = htx_get_max_blksz(htx, channel_htx_recv_max(res, htx));
4434 if (!max)
4435 goto snd_yield;
4436
4437 data = MAY_LJMP(luaL_checklstring(L, 2, &len));
4438
4439 /* Get the max amount of data which can write as input in the channel. */
4440 if (max > (len - l))
4441 max = len - l;
4442
4443 /* Copy data. */
4444 max = htx_add_data(htx, ist2(data + l, max));
4445 channel_add_input(res, max);
4446
4447 /* update counters. */
4448 l += max;
4449 lua_pop(L, 1);
4450 lua_pushinteger(L, l);
4451
4452 /* If some data is not send, declares the situation to the
4453 * applet, and returns a yield.
4454 */
4455 if (l < len) {
4456 snd_yield:
4457 htx_to_buf(htx, &res->buf);
4458 si_rx_room_blk(si);
4459 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_send_yield, TICK_ETERNITY, 0));
4460 }
4461
4462 htx_to_buf(htx, &res->buf);
4463 return 1;
4464 }
4465
4466 /* Just a wraper of "hlua_applet_send_yield". This wrapper permits
4467 * yield the LUA process, and resume it without checking the
4468 * input arguments.
4469 */
hlua_applet_http_send(lua_State * L)4470 __LJMP static int hlua_applet_http_send(lua_State *L)
4471 {
4472 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4473
4474 /* We want to send some data. Headers must be sent. */
4475 if (!(appctx->appctx->ctx.hlua_apphttp.flags & APPLET_HDR_SENT)) {
4476 hlua_pusherror(L, "Lua: 'send' you must call start_response() before sending data.");
4477 WILL_LJMP(lua_error(L));
4478 }
4479
4480 /* This interger is used for followinf the amount of data sent. */
4481 lua_pushinteger(L, 0);
4482
4483 return MAY_LJMP(hlua_applet_http_send_yield(L, 0, 0));
4484 }
4485
hlua_applet_http_addheader(lua_State * L)4486 __LJMP static int hlua_applet_http_addheader(lua_State *L)
4487 {
4488 const char *name;
4489 int ret;
4490
4491 MAY_LJMP(hlua_checkapplet_http(L, 1));
4492 name = MAY_LJMP(luaL_checkstring(L, 2));
4493 MAY_LJMP(luaL_checkstring(L, 3));
4494
4495 /* Push in the stack the "response" entry. */
4496 ret = lua_getfield(L, 1, "response");
4497 if (ret != LUA_TTABLE) {
4498 hlua_pusherror(L, "Lua: 'add_header' internal error: AppletHTTP['response'] "
4499 "is expected as an array. %s found", lua_typename(L, ret));
4500 WILL_LJMP(lua_error(L));
4501 }
4502
4503 /* check if the header is already registered if it is not
4504 * the case, register it.
4505 */
4506 ret = lua_getfield(L, -1, name);
4507 if (ret == LUA_TNIL) {
4508
4509 /* Entry not found. */
4510 lua_pop(L, 1); /* remove the nil. The "response" table is the top of the stack. */
4511
4512 /* Insert the new header name in the array in the top of the stack.
4513 * It left the new array in the top of the stack.
4514 */
4515 lua_newtable(L);
4516 lua_pushvalue(L, 2);
4517 lua_pushvalue(L, -2);
4518 lua_settable(L, -4);
4519
4520 } else if (ret != LUA_TTABLE) {
4521
4522 /* corruption error. */
4523 hlua_pusherror(L, "Lua: 'add_header' internal error: AppletHTTP['response']['%s'] "
4524 "is expected as an array. %s found", name, lua_typename(L, ret));
4525 WILL_LJMP(lua_error(L));
4526 }
4527
4528 /* Now the top od thestack is an array of values. We push
4529 * the header value as new entry.
4530 */
4531 lua_pushvalue(L, 3);
4532 ret = lua_rawlen(L, -2);
4533 lua_rawseti(L, -2, ret + 1);
4534 lua_pushboolean(L, 1);
4535 return 1;
4536 }
4537
hlua_applet_http_status(lua_State * L)4538 __LJMP static int hlua_applet_http_status(lua_State *L)
4539 {
4540 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4541 int status = MAY_LJMP(luaL_checkinteger(L, 2));
4542 const char *reason = MAY_LJMP(luaL_optlstring(L, 3, NULL, NULL));
4543
4544 if (status < 100 || status > 599) {
4545 lua_pushboolean(L, 0);
4546 return 1;
4547 }
4548
4549 appctx->appctx->ctx.hlua_apphttp.status = status;
4550 appctx->appctx->ctx.hlua_apphttp.reason = reason;
4551 lua_pushboolean(L, 1);
4552 return 1;
4553 }
4554
4555
hlua_applet_http_send_response(lua_State * L)4556 __LJMP static int hlua_applet_http_send_response(lua_State *L)
4557 {
4558 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4559 struct stream_interface *si = appctx->appctx->owner;
4560 struct channel *res = si_ic(si);
4561 struct htx *htx;
4562 struct htx_sl *sl;
4563 struct h1m h1m;
4564 const char *status, *reason;
4565 const char *name, *value;
4566 size_t nlen, vlen;
4567 unsigned int flags;
4568
4569 /* Send the message at once. */
4570 htx = htx_from_buf(&res->buf);
4571 h1m_init_res(&h1m);
4572
4573 /* Use the same http version than the request. */
4574 status = ultoa_r(appctx->appctx->ctx.hlua_apphttp.status, trash.area, trash.size);
4575 reason = appctx->appctx->ctx.hlua_apphttp.reason;
4576 if (reason == NULL)
4577 reason = http_get_reason(appctx->appctx->ctx.hlua_apphttp.status);
4578 if (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_HTTP11) {
4579 flags = (HTX_SL_F_IS_RESP|HTX_SL_F_VER_11);
4580 sl = htx_add_stline(htx, HTX_BLK_RES_SL, flags, ist("HTTP/1.1"), ist(status), ist(reason));
4581 }
4582 else {
4583 flags = HTX_SL_F_IS_RESP;
4584 sl = htx_add_stline(htx, HTX_BLK_RES_SL, flags, ist("HTTP/1.0"), ist(status), ist(reason));
4585 }
4586 if (!sl) {
4587 hlua_pusherror(L, "Lua applet http '%s': Failed to create response.\n",
4588 appctx->appctx->rule->arg.hlua_rule->fcn.name);
4589 WILL_LJMP(lua_error(L));
4590 }
4591 sl->info.res.status = appctx->appctx->ctx.hlua_apphttp.status;
4592
4593 /* Get the array associated to the field "response" in the object AppletHTTP. */
4594 lua_pushvalue(L, 0);
4595 if (lua_getfield(L, 1, "response") != LUA_TTABLE) {
4596 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response'] missing.\n",
4597 appctx->appctx->rule->arg.hlua_rule->fcn.name);
4598 WILL_LJMP(lua_error(L));
4599 }
4600
4601 /* Browse the list of headers. */
4602 lua_pushnil(L);
4603 while(lua_next(L, -2) != 0) {
4604 /* We expect a string as -2. */
4605 if (lua_type(L, -2) != LUA_TSTRING) {
4606 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response'][] element must be a string. got %s.\n",
4607 appctx->appctx->rule->arg.hlua_rule->fcn.name,
4608 lua_typename(L, lua_type(L, -2)));
4609 WILL_LJMP(lua_error(L));
4610 }
4611 name = lua_tolstring(L, -2, &nlen);
4612
4613 /* We expect an array as -1. */
4614 if (lua_type(L, -1) != LUA_TTABLE) {
4615 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response']['%s'] element must be an table. got %s.\n",
4616 appctx->appctx->rule->arg.hlua_rule->fcn.name,
4617 name,
4618 lua_typename(L, lua_type(L, -1)));
4619 WILL_LJMP(lua_error(L));
4620 }
4621
4622 /* Browse the table who is on the top of the stack. */
4623 lua_pushnil(L);
4624 while(lua_next(L, -2) != 0) {
4625 int id;
4626
4627 /* We expect a number as -2. */
4628 if (lua_type(L, -2) != LUA_TNUMBER) {
4629 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response']['%s'][] element must be a number. got %s.\n",
4630 appctx->appctx->rule->arg.hlua_rule->fcn.name,
4631 name,
4632 lua_typename(L, lua_type(L, -2)));
4633 WILL_LJMP(lua_error(L));
4634 }
4635 id = lua_tointeger(L, -2);
4636
4637 /* We expect a string as -2. */
4638 if (lua_type(L, -1) != LUA_TSTRING) {
4639 hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response']['%s'][%d] element must be a string. got %s.\n",
4640 appctx->appctx->rule->arg.hlua_rule->fcn.name,
4641 name, id,
4642 lua_typename(L, lua_type(L, -1)));
4643 WILL_LJMP(lua_error(L));
4644 }
4645 value = lua_tolstring(L, -1, &vlen);
4646
4647 /* Simple Protocol checks. */
4648 if (isteqi(ist2(name, nlen), ist("transfer-encoding")))
4649 h1_parse_xfer_enc_header(&h1m, ist2(name, nlen));
4650 else if (isteqi(ist2(name, nlen), ist("content-length"))) {
4651 struct ist v = ist2(value, vlen);
4652 int ret;
4653
4654 ret = h1_parse_cont_len_header(&h1m, &v);
4655 if (ret < 0) {
4656 hlua_pusherror(L, "Lua applet http '%s': Invalid '%s' header.\n",
4657 appctx->appctx->rule->arg.hlua_rule->fcn.name,
4658 name);
4659 WILL_LJMP(lua_error(L));
4660 }
4661 else if (ret == 0)
4662 goto next; /* Skip it */
4663 }
4664
4665 /* Add a new header */
4666 if (!htx_add_header(htx, ist2(name, nlen), ist2(value, vlen))) {
4667 hlua_pusherror(L, "Lua applet http '%s': Failed to add header '%s' in the response.\n",
4668 appctx->appctx->rule->arg.hlua_rule->fcn.name,
4669 name);
4670 WILL_LJMP(lua_error(L));
4671 }
4672 next:
4673 /* Remove the array from the stack, and get next element with a remaining string. */
4674 lua_pop(L, 1);
4675 }
4676
4677 /* Remove the array from the stack, and get next element with a remaining string. */
4678 lua_pop(L, 1);
4679 }
4680
4681 if (h1m.flags & H1_MF_CHNK)
4682 h1m.flags &= ~H1_MF_CLEN;
4683 if (h1m.flags & (H1_MF_CLEN|H1_MF_CHNK))
4684 h1m.flags |= H1_MF_XFER_LEN;
4685
4686 /* Uset HTX start-line flags */
4687 if (h1m.flags & H1_MF_XFER_ENC)
4688 flags |= HTX_SL_F_XFER_ENC;
4689 if (h1m.flags & H1_MF_XFER_LEN) {
4690 flags |= HTX_SL_F_XFER_LEN;
4691 if (h1m.flags & H1_MF_CHNK)
4692 flags |= HTX_SL_F_CHNK;
4693 else if (h1m.flags & H1_MF_CLEN)
4694 flags |= HTX_SL_F_CLEN;
4695 if (h1m.body_len == 0)
4696 flags |= HTX_SL_F_BODYLESS;
4697 }
4698 sl->flags |= flags;
4699
4700 /* If we dont have a content-length set, and the HTTP version is 1.1
4701 * and the status code implies the presence of a message body, we must
4702 * announce a transfer encoding chunked. This is required by haproxy
4703 * for the keepalive compliance. If the applet annouces a transfer-encoding
4704 * chunked itslef, don't do anything.
4705 */
4706 if ((flags & (HTX_SL_F_VER_11|HTX_SL_F_XFER_LEN)) == HTX_SL_F_VER_11 &&
4707 appctx->appctx->ctx.hlua_apphttp.status >= 200 &&
4708 appctx->appctx->ctx.hlua_apphttp.status != 204 &&
4709 appctx->appctx->ctx.hlua_apphttp.status != 304) {
4710 /* Add a new header */
4711 sl->flags |= (HTX_SL_F_XFER_ENC|H1_MF_CHNK|H1_MF_XFER_LEN);
4712 if (!htx_add_header(htx, ist("transfer-encoding"), ist("chunked"))) {
4713 hlua_pusherror(L, "Lua applet http '%s': Failed to add header 'transfer-encoding' in the response.\n",
4714 appctx->appctx->rule->arg.hlua_rule->fcn.name);
4715 WILL_LJMP(lua_error(L));
4716 }
4717 }
4718
4719 /* Finalize headers. */
4720 if (!htx_add_endof(htx, HTX_BLK_EOH)) {
4721 hlua_pusherror(L, "Lua applet http '%s': Failed create the response.\n",
4722 appctx->appctx->rule->arg.hlua_rule->fcn.name);
4723 WILL_LJMP(lua_error(L));
4724 }
4725
4726 if (htx_used_space(htx) > b_size(&res->buf) - global.tune.maxrewrite) {
4727 b_reset(&res->buf);
4728 hlua_pusherror(L, "Lua: 'start_response': response header block too big");
4729 WILL_LJMP(lua_error(L));
4730 }
4731
4732 htx_to_buf(htx, &res->buf);
4733 channel_add_input(res, htx->data);
4734
4735 /* Headers sent, set the flag. */
4736 appctx->appctx->ctx.hlua_apphttp.flags |= APPLET_HDR_SENT;
4737 return 0;
4738
4739 }
4740 /* We will build the status line and the headers of the HTTP response.
4741 * We will try send at once if its not possible, we give back the hand
4742 * waiting for more room.
4743 */
hlua_applet_http_start_response_yield(lua_State * L,int status,lua_KContext ctx)4744 __LJMP static int hlua_applet_http_start_response_yield(lua_State *L, int status, lua_KContext ctx)
4745 {
4746 struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
4747 struct stream_interface *si = appctx->appctx->owner;
4748 struct channel *res = si_ic(si);
4749
4750 if (co_data(res)) {
4751 si_rx_room_blk(si);
4752 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_start_response_yield, TICK_ETERNITY, 0));
4753 }
4754 return MAY_LJMP(hlua_applet_http_send_response(L));
4755 }
4756
4757
hlua_applet_http_start_response(lua_State * L)4758 __LJMP static int hlua_applet_http_start_response(lua_State *L)
4759 {
4760 return MAY_LJMP(hlua_applet_http_start_response_yield(L, 0, 0));
4761 }
4762
4763 /*
4764 *
4765 *
4766 * Class HTTP
4767 *
4768 *
4769 */
4770
4771 /* Returns a struct hlua_txn if the stack entry "ud" is
4772 * a class stream, otherwise it throws an error.
4773 */
hlua_checkhttp(lua_State * L,int ud)4774 __LJMP static struct hlua_txn *hlua_checkhttp(lua_State *L, int ud)
4775 {
4776 return MAY_LJMP(hlua_checkudata(L, ud, class_http_ref));
4777 }
4778
4779 /* This function creates and push in the stack a HTTP object
4780 * according with a current TXN.
4781 */
hlua_http_new(lua_State * L,struct hlua_txn * txn)4782 static int hlua_http_new(lua_State *L, struct hlua_txn *txn)
4783 {
4784 struct hlua_txn *htxn;
4785
4786 /* Check stack size. */
4787 if (!lua_checkstack(L, 3))
4788 return 0;
4789
4790 /* Create the object: obj[0] = userdata.
4791 * Note that the base of the Converters object is the
4792 * same than the TXN object.
4793 */
4794 lua_newtable(L);
4795 htxn = lua_newuserdata(L, sizeof(*htxn));
4796 lua_rawseti(L, -2, 0);
4797
4798 htxn->s = txn->s;
4799 htxn->p = txn->p;
4800 htxn->dir = txn->dir;
4801 htxn->flags = txn->flags;
4802
4803 /* Pop a class stream metatable and affect it to the table. */
4804 lua_rawgeti(L, LUA_REGISTRYINDEX, class_http_ref);
4805 lua_setmetatable(L, -2);
4806
4807 return 1;
4808 }
4809
4810 /* This function creates ans returns an array of HTTP headers.
4811 * This function does not fails. It is used as wrapper with the
4812 * 2 following functions.
4813 */
hlua_http_get_headers(lua_State * L,struct hlua_txn * htxn,struct http_msg * msg)4814 __LJMP static int hlua_http_get_headers(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg)
4815 {
4816 struct htx *htx;
4817 int32_t pos;
4818
4819 /* Create the table. */
4820 lua_newtable(L);
4821
4822 if (!htxn->s->txn)
4823 return 1;
4824
4825 htx = htxbuf(&msg->chn->buf);
4826 for (pos = htx_get_first(htx); pos != -1; pos = htx_get_next(htx, pos)) {
4827 struct htx_blk *blk = htx_get_blk(htx, pos);
4828 enum htx_blk_type type = htx_get_blk_type(blk);
4829 struct ist n, v;
4830 int len;
4831
4832 if (type == HTX_BLK_HDR) {
4833 n = htx_get_blk_name(htx,blk);
4834 v = htx_get_blk_value(htx, blk);
4835 }
4836 else if (type == HTX_BLK_EOH)
4837 break;
4838 else
4839 continue;
4840
4841 /* Check for existing entry:
4842 * assume that the table is on the top of the stack, and
4843 * push the key in the stack, the function lua_gettable()
4844 * perform the lookup.
4845 */
4846 lua_pushlstring(L, n.ptr, n.len);
4847 lua_gettable(L, -2);
4848
4849 switch (lua_type(L, -1)) {
4850 case LUA_TNIL:
4851 /* Table not found, create it. */
4852 lua_pop(L, 1); /* remove the nil value. */
4853 lua_pushlstring(L, n.ptr, n.len); /* push the header name as key. */
4854 lua_newtable(L); /* create and push empty table. */
4855 lua_pushlstring(L, v.ptr, v.len); /* push header value. */
4856 lua_rawseti(L, -2, 0); /* index header value (pop it). */
4857 lua_rawset(L, -3); /* index new table with header name (pop the values). */
4858 break;
4859
4860 case LUA_TTABLE:
4861 /* Entry found: push the value in the table. */
4862 len = lua_rawlen(L, -1);
4863 lua_pushlstring(L, v.ptr, v.len); /* push header value. */
4864 lua_rawseti(L, -2, len+1); /* index header value (pop it). */
4865 lua_pop(L, 1); /* remove the table (it is stored in the main table). */
4866 break;
4867
4868 default:
4869 /* Other cases are errors. */
4870 hlua_pusherror(L, "internal error during the parsing of headers.");
4871 WILL_LJMP(lua_error(L));
4872 }
4873 }
4874 return 1;
4875 }
4876
hlua_http_req_get_headers(lua_State * L)4877 __LJMP static int hlua_http_req_get_headers(lua_State *L)
4878 {
4879 struct hlua_txn *htxn;
4880
4881 MAY_LJMP(check_args(L, 1, "req_get_headers"));
4882 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4883
4884 if (htxn->dir != SMP_OPT_DIR_REQ || !(htxn->flags & HLUA_TXN_HTTP_RDY))
4885 WILL_LJMP(lua_error(L));
4886
4887 return hlua_http_get_headers(L, htxn, &htxn->s->txn->req);
4888 }
4889
hlua_http_res_get_headers(lua_State * L)4890 __LJMP static int hlua_http_res_get_headers(lua_State *L)
4891 {
4892 struct hlua_txn *htxn;
4893
4894 MAY_LJMP(check_args(L, 1, "res_get_headers"));
4895 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4896
4897 if (htxn->dir != SMP_OPT_DIR_RES || !(htxn->flags & HLUA_TXN_HTTP_RDY))
4898 WILL_LJMP(lua_error(L));
4899
4900 return hlua_http_get_headers(L, htxn, &htxn->s->txn->rsp);
4901 }
4902
4903 /* This function replace full header, or just a value in
4904 * the request or in the response. It is a wrapper fir the
4905 * 4 following functions.
4906 */
hlua_http_rep_hdr(lua_State * L,struct hlua_txn * htxn,struct http_msg * msg,int action)4907 __LJMP static inline int hlua_http_rep_hdr(lua_State *L, struct hlua_txn *htxn,
4908 struct http_msg *msg, int action)
4909 {
4910 size_t name_len;
4911 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
4912 const char *reg = MAY_LJMP(luaL_checkstring(L, 3));
4913 const char *value = MAY_LJMP(luaL_checkstring(L, 4));
4914 struct htx *htx;
4915 struct my_regex *re;
4916
4917 if (!(re = regex_comp(reg, 1, 1, NULL)))
4918 WILL_LJMP(luaL_argerror(L, 3, "invalid regex"));
4919
4920 htx = htxbuf(&msg->chn->buf);
4921 http_transform_header_str(htxn->s, msg->chn, htx, ist2(name, name_len), value, re, action);
4922 regex_free(re);
4923 return 0;
4924 }
4925
hlua_http_req_rep_hdr(lua_State * L)4926 __LJMP static int hlua_http_req_rep_hdr(lua_State *L)
4927 {
4928 struct hlua_txn *htxn;
4929
4930 MAY_LJMP(check_args(L, 4, "req_rep_hdr"));
4931 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4932
4933 if (htxn->dir != SMP_OPT_DIR_REQ || !(htxn->flags & HLUA_TXN_HTTP_RDY))
4934 WILL_LJMP(lua_error(L));
4935
4936 return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->req, ACT_HTTP_REPLACE_HDR));
4937 }
4938
hlua_http_res_rep_hdr(lua_State * L)4939 __LJMP static int hlua_http_res_rep_hdr(lua_State *L)
4940 {
4941 struct hlua_txn *htxn;
4942
4943 MAY_LJMP(check_args(L, 4, "res_rep_hdr"));
4944 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4945
4946 if (htxn->dir != SMP_OPT_DIR_RES || !(htxn->flags & HLUA_TXN_HTTP_RDY))
4947 WILL_LJMP(lua_error(L));
4948
4949 return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->rsp, ACT_HTTP_REPLACE_HDR));
4950 }
4951
hlua_http_req_rep_val(lua_State * L)4952 __LJMP static int hlua_http_req_rep_val(lua_State *L)
4953 {
4954 struct hlua_txn *htxn;
4955
4956 MAY_LJMP(check_args(L, 4, "req_rep_hdr"));
4957 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4958
4959 if (htxn->dir != SMP_OPT_DIR_REQ || !(htxn->flags & HLUA_TXN_HTTP_RDY))
4960 WILL_LJMP(lua_error(L));
4961
4962 return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->req, ACT_HTTP_REPLACE_VAL));
4963 }
4964
hlua_http_res_rep_val(lua_State * L)4965 __LJMP static int hlua_http_res_rep_val(lua_State *L)
4966 {
4967 struct hlua_txn *htxn;
4968
4969 MAY_LJMP(check_args(L, 4, "res_rep_val"));
4970 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
4971
4972 if (htxn->dir != SMP_OPT_DIR_RES || !(htxn->flags & HLUA_TXN_HTTP_RDY))
4973 WILL_LJMP(lua_error(L));
4974
4975 return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->rsp, ACT_HTTP_REPLACE_VAL));
4976 }
4977
4978 /* This function deletes all the occurrences of an header.
4979 * It is a wrapper for the 2 following functions.
4980 */
hlua_http_del_hdr(lua_State * L,struct hlua_txn * htxn,struct http_msg * msg)4981 __LJMP static inline int hlua_http_del_hdr(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg)
4982 {
4983 size_t len;
4984 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &len));
4985 struct htx *htx = htxbuf(&msg->chn->buf);
4986 struct http_hdr_ctx ctx;
4987
4988 ctx.blk = NULL;
4989 while (http_find_header(htx, ist2(name, len), &ctx, 1))
4990 http_remove_header(htx, &ctx);
4991 return 0;
4992 }
4993
hlua_http_req_del_hdr(lua_State * L)4994 __LJMP static int hlua_http_req_del_hdr(lua_State *L)
4995 {
4996 struct hlua_txn *htxn;
4997
4998 MAY_LJMP(check_args(L, 2, "req_del_hdr"));
4999 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
5000
5001 if (htxn->dir != SMP_OPT_DIR_REQ || !(htxn->flags & HLUA_TXN_HTTP_RDY))
5002 WILL_LJMP(lua_error(L));
5003
5004 return hlua_http_del_hdr(L, htxn, &htxn->s->txn->req);
5005 }
5006
hlua_http_res_del_hdr(lua_State * L)5007 __LJMP static int hlua_http_res_del_hdr(lua_State *L)
5008 {
5009 struct hlua_txn *htxn;
5010
5011 MAY_LJMP(check_args(L, 2, "res_del_hdr"));
5012 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
5013
5014 if (htxn->dir != SMP_OPT_DIR_RES || !(htxn->flags & HLUA_TXN_HTTP_RDY))
5015 WILL_LJMP(lua_error(L));
5016
5017 return hlua_http_del_hdr(L, htxn, &htxn->s->txn->rsp);
5018 }
5019
5020 /* This function adds an header. It is a wrapper used by
5021 * the 2 following functions.
5022 */
hlua_http_add_hdr(lua_State * L,struct hlua_txn * htxn,struct http_msg * msg)5023 __LJMP static inline int hlua_http_add_hdr(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg)
5024 {
5025 size_t name_len;
5026 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
5027 size_t value_len;
5028 const char *value = MAY_LJMP(luaL_checklstring(L, 3, &value_len));
5029 struct htx *htx = htxbuf(&msg->chn->buf);
5030
5031 lua_pushboolean(L, http_add_header(htx, ist2(name, name_len),
5032 ist2(value, value_len)));
5033 return 0;
5034 }
5035
hlua_http_req_add_hdr(lua_State * L)5036 __LJMP static int hlua_http_req_add_hdr(lua_State *L)
5037 {
5038 struct hlua_txn *htxn;
5039
5040 MAY_LJMP(check_args(L, 3, "req_add_hdr"));
5041 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
5042
5043 if (htxn->dir != SMP_OPT_DIR_REQ || !(htxn->flags & HLUA_TXN_HTTP_RDY))
5044 WILL_LJMP(lua_error(L));
5045
5046 return hlua_http_add_hdr(L, htxn, &htxn->s->txn->req);
5047 }
5048
hlua_http_res_add_hdr(lua_State * L)5049 __LJMP static int hlua_http_res_add_hdr(lua_State *L)
5050 {
5051 struct hlua_txn *htxn;
5052
5053 MAY_LJMP(check_args(L, 3, "res_add_hdr"));
5054 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
5055
5056 if (htxn->dir != SMP_OPT_DIR_RES || !(htxn->flags & HLUA_TXN_HTTP_RDY))
5057 WILL_LJMP(lua_error(L));
5058
5059 return hlua_http_add_hdr(L, htxn, &htxn->s->txn->rsp);
5060 }
5061
hlua_http_req_set_hdr(lua_State * L)5062 static int hlua_http_req_set_hdr(lua_State *L)
5063 {
5064 struct hlua_txn *htxn;
5065
5066 MAY_LJMP(check_args(L, 3, "req_set_hdr"));
5067 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
5068
5069 if (htxn->dir != SMP_OPT_DIR_REQ || !(htxn->flags & HLUA_TXN_HTTP_RDY))
5070 WILL_LJMP(lua_error(L));
5071
5072 hlua_http_del_hdr(L, htxn, &htxn->s->txn->req);
5073 return hlua_http_add_hdr(L, htxn, &htxn->s->txn->req);
5074 }
5075
hlua_http_res_set_hdr(lua_State * L)5076 static int hlua_http_res_set_hdr(lua_State *L)
5077 {
5078 struct hlua_txn *htxn;
5079
5080 MAY_LJMP(check_args(L, 3, "res_set_hdr"));
5081 htxn = MAY_LJMP(hlua_checkhttp(L, 1));
5082
5083 if (htxn->dir != SMP_OPT_DIR_RES || !(htxn->flags & HLUA_TXN_HTTP_RDY))
5084 WILL_LJMP(lua_error(L));
5085
5086 hlua_http_del_hdr(L, htxn, &htxn->s->txn->rsp);
5087 return hlua_http_add_hdr(L, htxn, &htxn->s->txn->rsp);
5088 }
5089
5090 /* This function set the method. */
hlua_http_req_set_meth(lua_State * L)5091 static int hlua_http_req_set_meth(lua_State *L)
5092 {
5093 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
5094 size_t name_len;
5095 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
5096
5097 if (htxn->dir != SMP_OPT_DIR_REQ || !(htxn->flags & HLUA_TXN_HTTP_RDY))
5098 WILL_LJMP(lua_error(L));
5099
5100 lua_pushboolean(L, http_req_replace_stline(0, name, name_len, htxn->p, htxn->s) != -1);
5101 return 1;
5102 }
5103
5104 /* This function set the method. */
hlua_http_req_set_path(lua_State * L)5105 static int hlua_http_req_set_path(lua_State *L)
5106 {
5107 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
5108 size_t name_len;
5109 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
5110
5111 if (htxn->dir != SMP_OPT_DIR_REQ || !(htxn->flags & HLUA_TXN_HTTP_RDY))
5112 WILL_LJMP(lua_error(L));
5113
5114 lua_pushboolean(L, http_req_replace_stline(1, name, name_len, htxn->p, htxn->s) != -1);
5115 return 1;
5116 }
5117
5118 /* This function set the query-string. */
hlua_http_req_set_query(lua_State * L)5119 static int hlua_http_req_set_query(lua_State *L)
5120 {
5121 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
5122 size_t name_len;
5123 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
5124
5125 if (htxn->dir != SMP_OPT_DIR_REQ || !(htxn->flags & HLUA_TXN_HTTP_RDY))
5126 WILL_LJMP(lua_error(L));
5127
5128 /* Check length. */
5129 if (name_len > trash.size - 1) {
5130 lua_pushboolean(L, 0);
5131 return 1;
5132 }
5133
5134 /* Add the mark question as prefix. */
5135 chunk_reset(&trash);
5136 trash.area[trash.data++] = '?';
5137 memcpy(trash.area + trash.data, name, name_len);
5138 trash.data += name_len;
5139
5140 lua_pushboolean(L,
5141 http_req_replace_stline(2, trash.area, trash.data, htxn->p, htxn->s) != -1);
5142 return 1;
5143 }
5144
5145 /* This function set the uri. */
hlua_http_req_set_uri(lua_State * L)5146 static int hlua_http_req_set_uri(lua_State *L)
5147 {
5148 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
5149 size_t name_len;
5150 const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
5151
5152 if (htxn->dir != SMP_OPT_DIR_REQ || !(htxn->flags & HLUA_TXN_HTTP_RDY))
5153 WILL_LJMP(lua_error(L));
5154
5155 lua_pushboolean(L, http_req_replace_stline(3, name, name_len, htxn->p, htxn->s) != -1);
5156 return 1;
5157 }
5158
5159 /* This function set the response code & optionally reason. */
hlua_http_res_set_status(lua_State * L)5160 static int hlua_http_res_set_status(lua_State *L)
5161 {
5162 struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
5163 unsigned int code = MAY_LJMP(luaL_checkinteger(L, 2));
5164 const char *reason = MAY_LJMP(luaL_optlstring(L, 3, NULL, NULL));
5165
5166 if (htxn->dir != SMP_OPT_DIR_RES || !(htxn->flags & HLUA_TXN_HTTP_RDY))
5167 WILL_LJMP(lua_error(L));
5168
5169 http_res_set_status(code, reason, htxn->s);
5170 return 0;
5171 }
5172
5173 /*
5174 *
5175 *
5176 * Class TXN
5177 *
5178 *
5179 */
5180
5181 /* Returns a struct hlua_session if the stack entry "ud" is
5182 * a class stream, otherwise it throws an error.
5183 */
hlua_checktxn(lua_State * L,int ud)5184 __LJMP static struct hlua_txn *hlua_checktxn(lua_State *L, int ud)
5185 {
5186 return MAY_LJMP(hlua_checkudata(L, ud, class_txn_ref));
5187 }
5188
hlua_set_var(lua_State * L)5189 __LJMP static int hlua_set_var(lua_State *L)
5190 {
5191 struct hlua_txn *htxn;
5192 const char *name;
5193 size_t len;
5194 struct sample smp;
5195
5196 MAY_LJMP(check_args(L, 3, "set_var"));
5197
5198 /* It is useles to retrieve the stream, but this function
5199 * runs only in a stream context.
5200 */
5201 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5202 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
5203
5204 /* Converts the third argument in a sample. */
5205 memset(&smp, 0, sizeof(smp));
5206 hlua_lua2smp(L, 3, &smp);
5207
5208 /* Store the sample in a variable. */
5209 smp_set_owner(&smp, htxn->p, htxn->s->sess, htxn->s, htxn->dir & SMP_OPT_DIR);
5210 vars_set_by_name(name, len, &smp);
5211 return 0;
5212 }
5213
hlua_unset_var(lua_State * L)5214 __LJMP static int hlua_unset_var(lua_State *L)
5215 {
5216 struct hlua_txn *htxn;
5217 const char *name;
5218 size_t len;
5219 struct sample smp;
5220
5221 MAY_LJMP(check_args(L, 2, "unset_var"));
5222
5223 /* It is useles to retrieve the stream, but this function
5224 * runs only in a stream context.
5225 */
5226 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5227 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
5228
5229 /* Unset the variable. */
5230 smp_set_owner(&smp, htxn->p, htxn->s->sess, htxn->s, htxn->dir & SMP_OPT_DIR);
5231 vars_unset_by_name(name, len, &smp);
5232 return 0;
5233 }
5234
hlua_get_var(lua_State * L)5235 __LJMP static int hlua_get_var(lua_State *L)
5236 {
5237 struct hlua_txn *htxn;
5238 const char *name;
5239 size_t len;
5240 struct sample smp;
5241
5242 MAY_LJMP(check_args(L, 2, "get_var"));
5243
5244 /* It is useles to retrieve the stream, but this function
5245 * runs only in a stream context.
5246 */
5247 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5248 name = MAY_LJMP(luaL_checklstring(L, 2, &len));
5249
5250 smp_set_owner(&smp, htxn->p, htxn->s->sess, htxn->s, htxn->dir & SMP_OPT_DIR);
5251 if (!vars_get_by_name(name, len, &smp)) {
5252 lua_pushnil(L);
5253 return 1;
5254 }
5255
5256 return hlua_smp2lua(L, &smp);
5257 }
5258
hlua_set_priv(lua_State * L)5259 __LJMP static int hlua_set_priv(lua_State *L)
5260 {
5261 struct hlua *hlua;
5262
5263 MAY_LJMP(check_args(L, 2, "set_priv"));
5264
5265 /* It is useles to retrieve the stream, but this function
5266 * runs only in a stream context.
5267 */
5268 MAY_LJMP(hlua_checktxn(L, 1));
5269 hlua = hlua_gethlua(L);
5270
5271 /* Remove previous value. */
5272 luaL_unref(L, LUA_REGISTRYINDEX, hlua->Mref);
5273
5274 /* Get and store new value. */
5275 lua_pushvalue(L, 2); /* Copy the element 2 at the top of the stack. */
5276 hlua->Mref = luaL_ref(L, LUA_REGISTRYINDEX); /* pop the previously pushed value. */
5277
5278 return 0;
5279 }
5280
hlua_get_priv(lua_State * L)5281 __LJMP static int hlua_get_priv(lua_State *L)
5282 {
5283 struct hlua *hlua;
5284
5285 MAY_LJMP(check_args(L, 1, "get_priv"));
5286
5287 /* It is useles to retrieve the stream, but this function
5288 * runs only in a stream context.
5289 */
5290 MAY_LJMP(hlua_checktxn(L, 1));
5291 hlua = hlua_gethlua(L);
5292
5293 /* Push configuration index in the stack. */
5294 lua_rawgeti(L, LUA_REGISTRYINDEX, hlua->Mref);
5295
5296 return 1;
5297 }
5298
5299 /* Create stack entry containing a class TXN. This function
5300 * return 0 if the stack does not contains free slots,
5301 * otherwise it returns 1.
5302 */
hlua_txn_new(lua_State * L,struct stream * s,struct proxy * p,int dir,int flags)5303 static int hlua_txn_new(lua_State *L, struct stream *s, struct proxy *p, int dir, int flags)
5304 {
5305 struct hlua_txn *htxn;
5306
5307 /* Check stack size. */
5308 if (!lua_checkstack(L, 3))
5309 return 0;
5310
5311 /* NOTE: The allocation never fails. The failure
5312 * throw an error, and the function never returns.
5313 * if the throw is not available, the process is aborted.
5314 */
5315 /* Create the object: obj[0] = userdata. */
5316 lua_newtable(L);
5317 htxn = lua_newuserdata(L, sizeof(*htxn));
5318 lua_rawseti(L, -2, 0);
5319
5320 htxn->s = s;
5321 htxn->p = p;
5322 htxn->dir = dir;
5323 htxn->flags = flags;
5324
5325 /* Create the "f" field that contains a list of fetches. */
5326 lua_pushstring(L, "f");
5327 if (!hlua_fetches_new(L, htxn, HLUA_F_MAY_USE_HTTP))
5328 return 0;
5329 lua_rawset(L, -3);
5330
5331 /* Create the "sf" field that contains a list of stringsafe fetches. */
5332 lua_pushstring(L, "sf");
5333 if (!hlua_fetches_new(L, htxn, HLUA_F_MAY_USE_HTTP | HLUA_F_AS_STRING))
5334 return 0;
5335 lua_rawset(L, -3);
5336
5337 /* Create the "c" field that contains a list of converters. */
5338 lua_pushstring(L, "c");
5339 if (!hlua_converters_new(L, htxn, 0))
5340 return 0;
5341 lua_rawset(L, -3);
5342
5343 /* Create the "sc" field that contains a list of stringsafe converters. */
5344 lua_pushstring(L, "sc");
5345 if (!hlua_converters_new(L, htxn, HLUA_F_AS_STRING))
5346 return 0;
5347 lua_rawset(L, -3);
5348
5349 /* Create the "req" field that contains the request channel object. */
5350 lua_pushstring(L, "req");
5351 if (!hlua_channel_new(L, &s->req))
5352 return 0;
5353 lua_rawset(L, -3);
5354
5355 /* Create the "res" field that contains the response channel object. */
5356 lua_pushstring(L, "res");
5357 if (!hlua_channel_new(L, &s->res))
5358 return 0;
5359 lua_rawset(L, -3);
5360
5361 /* Creates the HTTP object is the current proxy allows http. */
5362 lua_pushstring(L, "http");
5363 if (p->mode == PR_MODE_HTTP) {
5364 if (!hlua_http_new(L, htxn))
5365 return 0;
5366 }
5367 else
5368 lua_pushnil(L);
5369 lua_rawset(L, -3);
5370
5371 /* Pop a class sesison metatable and affect it to the userdata. */
5372 lua_rawgeti(L, LUA_REGISTRYINDEX, class_txn_ref);
5373 lua_setmetatable(L, -2);
5374
5375 return 1;
5376 }
5377
hlua_txn_deflog(lua_State * L)5378 __LJMP static int hlua_txn_deflog(lua_State *L)
5379 {
5380 const char *msg;
5381 struct hlua_txn *htxn;
5382
5383 MAY_LJMP(check_args(L, 2, "deflog"));
5384 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5385 msg = MAY_LJMP(luaL_checkstring(L, 2));
5386
5387 hlua_sendlog(htxn->s->be, htxn->s->logs.level, msg);
5388 return 0;
5389 }
5390
hlua_txn_log(lua_State * L)5391 __LJMP static int hlua_txn_log(lua_State *L)
5392 {
5393 int level;
5394 const char *msg;
5395 struct hlua_txn *htxn;
5396
5397 MAY_LJMP(check_args(L, 3, "log"));
5398 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5399 level = MAY_LJMP(luaL_checkinteger(L, 2));
5400 msg = MAY_LJMP(luaL_checkstring(L, 3));
5401
5402 if (level < 0 || level >= NB_LOG_LEVELS)
5403 WILL_LJMP(luaL_argerror(L, 1, "Invalid loglevel."));
5404
5405 hlua_sendlog(htxn->s->be, level, msg);
5406 return 0;
5407 }
5408
hlua_txn_log_debug(lua_State * L)5409 __LJMP static int hlua_txn_log_debug(lua_State *L)
5410 {
5411 const char *msg;
5412 struct hlua_txn *htxn;
5413
5414 MAY_LJMP(check_args(L, 2, "Debug"));
5415 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5416 msg = MAY_LJMP(luaL_checkstring(L, 2));
5417 hlua_sendlog(htxn->s->be, LOG_DEBUG, msg);
5418 return 0;
5419 }
5420
hlua_txn_log_info(lua_State * L)5421 __LJMP static int hlua_txn_log_info(lua_State *L)
5422 {
5423 const char *msg;
5424 struct hlua_txn *htxn;
5425
5426 MAY_LJMP(check_args(L, 2, "Info"));
5427 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5428 msg = MAY_LJMP(luaL_checkstring(L, 2));
5429 hlua_sendlog(htxn->s->be, LOG_INFO, msg);
5430 return 0;
5431 }
5432
hlua_txn_log_warning(lua_State * L)5433 __LJMP static int hlua_txn_log_warning(lua_State *L)
5434 {
5435 const char *msg;
5436 struct hlua_txn *htxn;
5437
5438 MAY_LJMP(check_args(L, 2, "Warning"));
5439 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5440 msg = MAY_LJMP(luaL_checkstring(L, 2));
5441 hlua_sendlog(htxn->s->be, LOG_WARNING, msg);
5442 return 0;
5443 }
5444
hlua_txn_log_alert(lua_State * L)5445 __LJMP static int hlua_txn_log_alert(lua_State *L)
5446 {
5447 const char *msg;
5448 struct hlua_txn *htxn;
5449
5450 MAY_LJMP(check_args(L, 2, "Alert"));
5451 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5452 msg = MAY_LJMP(luaL_checkstring(L, 2));
5453 hlua_sendlog(htxn->s->be, LOG_ALERT, msg);
5454 return 0;
5455 }
5456
hlua_txn_set_loglevel(lua_State * L)5457 __LJMP static int hlua_txn_set_loglevel(lua_State *L)
5458 {
5459 struct hlua_txn *htxn;
5460 int ll;
5461
5462 MAY_LJMP(check_args(L, 2, "set_loglevel"));
5463 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5464 ll = MAY_LJMP(luaL_checkinteger(L, 2));
5465
5466 if (ll < 0 || ll > 7)
5467 WILL_LJMP(luaL_argerror(L, 2, "Bad log level. It must be between 0 and 7"));
5468
5469 htxn->s->logs.level = ll;
5470 return 0;
5471 }
5472
hlua_txn_set_tos(lua_State * L)5473 __LJMP static int hlua_txn_set_tos(lua_State *L)
5474 {
5475 struct hlua_txn *htxn;
5476 int tos;
5477
5478 MAY_LJMP(check_args(L, 2, "set_tos"));
5479 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5480 tos = MAY_LJMP(luaL_checkinteger(L, 2));
5481
5482 conn_set_tos(objt_conn(htxn->s->sess->origin), tos);
5483 return 0;
5484 }
5485
hlua_txn_set_mark(lua_State * L)5486 __LJMP static int hlua_txn_set_mark(lua_State *L)
5487 {
5488 struct hlua_txn *htxn;
5489 int mark;
5490
5491 MAY_LJMP(check_args(L, 2, "set_mark"));
5492 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5493 mark = MAY_LJMP(luaL_checkinteger(L, 2));
5494
5495 conn_set_mark(objt_conn(htxn->s->sess->origin), mark);
5496 return 0;
5497 }
5498
hlua_txn_set_priority_class(lua_State * L)5499 __LJMP static int hlua_txn_set_priority_class(lua_State *L)
5500 {
5501 struct hlua_txn *htxn;
5502
5503 MAY_LJMP(check_args(L, 2, "set_priority_class"));
5504 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5505 htxn->s->priority_class = queue_limit_class(MAY_LJMP(luaL_checkinteger(L, 2)));
5506 return 0;
5507 }
5508
hlua_txn_set_priority_offset(lua_State * L)5509 __LJMP static int hlua_txn_set_priority_offset(lua_State *L)
5510 {
5511 struct hlua_txn *htxn;
5512
5513 MAY_LJMP(check_args(L, 2, "set_priority_offset"));
5514 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5515 htxn->s->priority_offset = queue_limit_offset(MAY_LJMP(luaL_checkinteger(L, 2)));
5516 return 0;
5517 }
5518
5519 /* This function is an Lua binding that send pending data
5520 * to the client, and close the stream interface.
5521 */
hlua_txn_done(lua_State * L)5522 __LJMP static int hlua_txn_done(lua_State *L)
5523 {
5524 struct hlua_txn *htxn;
5525 struct hlua *hlua;
5526 struct channel *ic, *oc;
5527
5528 MAY_LJMP(check_args(L, 1, "close"));
5529 htxn = MAY_LJMP(hlua_checktxn(L, 1));
5530 hlua = hlua_gethlua(L);
5531
5532 /* If the flags NOTERM is set, we cannot terminate the http
5533 * session, so we just end the execution of the current
5534 * lua code.
5535 */
5536 if (htxn->flags & HLUA_TXN_NOTERM) {
5537 WILL_LJMP(hlua_done(L));
5538 return 0;
5539 }
5540
5541 ic = &htxn->s->req;
5542 oc = &htxn->s->res;
5543
5544 if (IS_HTX_STRM(htxn->s)) {
5545 htxn->s->txn->status = 0;
5546 http_reply_and_close(htxn->s, 0, NULL);
5547 }
5548 else {
5549 channel_auto_read(ic);
5550 channel_abort(ic);
5551 channel_auto_close(ic);
5552 channel_erase(ic);
5553
5554 oc->wex = tick_add_ifset(now_ms, oc->wto);
5555 channel_auto_read(oc);
5556 channel_auto_close(oc);
5557 channel_shutr_now(oc);
5558
5559 }
5560
5561 ic->analysers &= AN_REQ_FLT_END;
5562 oc->analysers &= AN_RES_FLT_END;
5563
5564 if (!(htxn->s->flags & SF_ERR_MASK)) // this is not really an error but it is
5565 htxn->s->flags |= SF_ERR_LOCAL; // to mark that it comes from the proxy
5566
5567 hlua->flags |= HLUA_STOP;
5568 WILL_LJMP(hlua_done(L));
5569 return 0;
5570 }
5571
hlua_log(lua_State * L)5572 __LJMP static int hlua_log(lua_State *L)
5573 {
5574 int level;
5575 const char *msg;
5576
5577 MAY_LJMP(check_args(L, 2, "log"));
5578 level = MAY_LJMP(luaL_checkinteger(L, 1));
5579 msg = MAY_LJMP(luaL_checkstring(L, 2));
5580
5581 if (level < 0 || level >= NB_LOG_LEVELS)
5582 WILL_LJMP(luaL_argerror(L, 1, "Invalid loglevel."));
5583
5584 hlua_sendlog(NULL, level, msg);
5585 return 0;
5586 }
5587
hlua_log_debug(lua_State * L)5588 __LJMP static int hlua_log_debug(lua_State *L)
5589 {
5590 const char *msg;
5591
5592 MAY_LJMP(check_args(L, 1, "debug"));
5593 msg = MAY_LJMP(luaL_checkstring(L, 1));
5594 hlua_sendlog(NULL, LOG_DEBUG, msg);
5595 return 0;
5596 }
5597
hlua_log_info(lua_State * L)5598 __LJMP static int hlua_log_info(lua_State *L)
5599 {
5600 const char *msg;
5601
5602 MAY_LJMP(check_args(L, 1, "info"));
5603 msg = MAY_LJMP(luaL_checkstring(L, 1));
5604 hlua_sendlog(NULL, LOG_INFO, msg);
5605 return 0;
5606 }
5607
hlua_log_warning(lua_State * L)5608 __LJMP static int hlua_log_warning(lua_State *L)
5609 {
5610 const char *msg;
5611
5612 MAY_LJMP(check_args(L, 1, "warning"));
5613 msg = MAY_LJMP(luaL_checkstring(L, 1));
5614 hlua_sendlog(NULL, LOG_WARNING, msg);
5615 return 0;
5616 }
5617
hlua_log_alert(lua_State * L)5618 __LJMP static int hlua_log_alert(lua_State *L)
5619 {
5620 const char *msg;
5621
5622 MAY_LJMP(check_args(L, 1, "alert"));
5623 msg = MAY_LJMP(luaL_checkstring(L, 1));
5624 hlua_sendlog(NULL, LOG_ALERT, msg);
5625 return 0;
5626 }
5627
hlua_sleep_yield(lua_State * L,int status,lua_KContext ctx)5628 __LJMP static int hlua_sleep_yield(lua_State *L, int status, lua_KContext ctx)
5629 {
5630 int wakeup_ms = lua_tointeger(L, -1);
5631 if (now_ms < wakeup_ms)
5632 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_sleep_yield, wakeup_ms, 0));
5633 return 0;
5634 }
5635
hlua_sleep(lua_State * L)5636 __LJMP static int hlua_sleep(lua_State *L)
5637 {
5638 unsigned int delay;
5639 unsigned int wakeup_ms;
5640
5641 MAY_LJMP(check_args(L, 1, "sleep"));
5642
5643 delay = MAY_LJMP(luaL_checkinteger(L, 1)) * 1000;
5644 wakeup_ms = tick_add(now_ms, delay);
5645 lua_pushinteger(L, wakeup_ms);
5646
5647 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_sleep_yield, wakeup_ms, 0));
5648 return 0;
5649 }
5650
hlua_msleep(lua_State * L)5651 __LJMP static int hlua_msleep(lua_State *L)
5652 {
5653 unsigned int delay;
5654 unsigned int wakeup_ms;
5655
5656 MAY_LJMP(check_args(L, 1, "msleep"));
5657
5658 delay = MAY_LJMP(luaL_checkinteger(L, 1));
5659 wakeup_ms = tick_add(now_ms, delay);
5660 lua_pushinteger(L, wakeup_ms);
5661
5662 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_sleep_yield, wakeup_ms, 0));
5663 return 0;
5664 }
5665
5666 /* This functionis an LUA binding. it permits to give back
5667 * the hand at the HAProxy scheduler. It is used when the
5668 * LUA processing consumes a lot of time.
5669 */
hlua_yield_yield(lua_State * L,int status,lua_KContext ctx)5670 __LJMP static int hlua_yield_yield(lua_State *L, int status, lua_KContext ctx)
5671 {
5672 return 0;
5673 }
5674
hlua_yield(lua_State * L)5675 __LJMP static int hlua_yield(lua_State *L)
5676 {
5677 MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_yield_yield, TICK_ETERNITY, HLUA_CTRLYIELD));
5678 return 0;
5679 }
5680
5681 /* This function change the nice of the currently executed
5682 * task. It is used set low or high priority at the current
5683 * task.
5684 */
hlua_set_nice(lua_State * L)5685 __LJMP static int hlua_set_nice(lua_State *L)
5686 {
5687 struct hlua *hlua;
5688 int nice;
5689
5690 MAY_LJMP(check_args(L, 1, "set_nice"));
5691 hlua = hlua_gethlua(L);
5692 nice = MAY_LJMP(luaL_checkinteger(L, 1));
5693
5694 /* If he task is not set, I'm in a start mode. */
5695 if (!hlua || !hlua->task)
5696 return 0;
5697
5698 if (nice < -1024)
5699 nice = -1024;
5700 else if (nice > 1024)
5701 nice = 1024;
5702
5703 hlua->task->nice = nice;
5704 return 0;
5705 }
5706
5707 /* This function is used as a callback of a task. It is called by the
5708 * HAProxy task subsystem when the task is awaked. The LUA runtime can
5709 * return an E_AGAIN signal, the emmiter of this signal must set a
5710 * signal to wake the task.
5711 *
5712 * Task wrapper are longjmp safe because the only one Lua code
5713 * executed is the safe hlua_ctx_resume();
5714 */
hlua_process_task(struct task * task,void * context,unsigned short state)5715 struct task *hlua_process_task(struct task *task, void *context, unsigned short state)
5716 {
5717 struct hlua *hlua = context;
5718 enum hlua_exec status;
5719
5720 if (task->thread_mask == MAX_THREADS_MASK)
5721 task_set_affinity(task, tid_bit);
5722
5723 /* If it is the first call to the task, we must initialize the
5724 * execution timeouts.
5725 */
5726 if (!HLUA_IS_RUNNING(hlua))
5727 hlua->max_time = hlua_timeout_task;
5728
5729 /* Execute the Lua code. */
5730 status = hlua_ctx_resume(hlua, 1);
5731
5732 switch (status) {
5733 /* finished or yield */
5734 case HLUA_E_OK:
5735 hlua_ctx_destroy(hlua);
5736 task_destroy(task);
5737 task = NULL;
5738 break;
5739
5740 case HLUA_E_AGAIN: /* co process or timeout wake me later. */
5741 notification_gc(&hlua->com);
5742 task->expire = hlua->wake_time;
5743 break;
5744
5745 /* finished with error. */
5746 case HLUA_E_ERRMSG:
5747 SEND_ERR(NULL, "Lua task: %s.\n", lua_tostring(hlua->T, -1));
5748 hlua_ctx_destroy(hlua);
5749 task_destroy(task);
5750 task = NULL;
5751 break;
5752
5753 case HLUA_E_ERR:
5754 default:
5755 SEND_ERR(NULL, "Lua task: unknown error.\n");
5756 hlua_ctx_destroy(hlua);
5757 task_destroy(task);
5758 task = NULL;
5759 break;
5760 }
5761 return task;
5762 }
5763
5764 /* This function is an LUA binding that register LUA function to be
5765 * executed after the HAProxy configuration parsing and before the
5766 * HAProxy scheduler starts. This function expect only one LUA
5767 * argument that is a function. This function returns nothing, but
5768 * throws if an error is encountered.
5769 */
hlua_register_init(lua_State * L)5770 __LJMP static int hlua_register_init(lua_State *L)
5771 {
5772 struct hlua_init_function *init;
5773 int ref;
5774
5775 MAY_LJMP(check_args(L, 1, "register_init"));
5776
5777 ref = MAY_LJMP(hlua_checkfunction(L, 1));
5778
5779 init = calloc(1, sizeof(*init));
5780 if (!init)
5781 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
5782
5783 init->function_ref = ref;
5784 LIST_ADDQ(&hlua_init_functions, &init->l);
5785 return 0;
5786 }
5787
5788 /* This functio is an LUA binding. It permits to register a task
5789 * executed in parallel of the main HAroxy activity. The task is
5790 * created and it is set in the HAProxy scheduler. It can be called
5791 * from the "init" section, "post init" or during the runtime.
5792 *
5793 * Lua prototype:
5794 *
5795 * <none> core.register_task(<function>)
5796 */
hlua_register_task(lua_State * L)5797 static int hlua_register_task(lua_State *L)
5798 {
5799 struct hlua *hlua;
5800 struct task *task;
5801 int ref;
5802
5803 MAY_LJMP(check_args(L, 1, "register_task"));
5804
5805 ref = MAY_LJMP(hlua_checkfunction(L, 1));
5806
5807 hlua = pool_alloc(pool_head_hlua);
5808 if (!hlua)
5809 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
5810
5811 task = task_new(MAX_THREADS_MASK);
5812 if (!task)
5813 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
5814
5815 task->context = hlua;
5816 task->process = hlua_process_task;
5817
5818 if (!hlua_ctx_init(hlua, task, 1))
5819 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
5820
5821 /* Restore the function in the stack. */
5822 lua_rawgeti(hlua->T, LUA_REGISTRYINDEX, ref);
5823 hlua->nargs = 0;
5824
5825 /* Schedule task. */
5826 task_schedule(task, now_ms);
5827
5828 return 0;
5829 }
5830
5831 /* Wrapper called by HAProxy to execute an LUA converter. This wrapper
5832 * doesn't allow "yield" functions because the HAProxy engine cannot
5833 * resume converters.
5834 */
hlua_sample_conv_wrapper(const struct arg * arg_p,struct sample * smp,void * private)5835 static int hlua_sample_conv_wrapper(const struct arg *arg_p, struct sample *smp, void *private)
5836 {
5837 struct hlua_function *fcn = private;
5838 struct stream *stream = smp->strm;
5839 const char *error;
5840
5841 if (!stream)
5842 return 0;
5843
5844 /* In the execution wrappers linked with a stream, the
5845 * Lua context can be not initialized. This behavior
5846 * permits to save performances because a systematic
5847 * Lua initialization cause 5% performances loss.
5848 */
5849 if (!stream->hlua) {
5850 stream->hlua = pool_alloc(pool_head_hlua);
5851 if (!stream->hlua) {
5852 SEND_ERR(stream->be, "Lua converter '%s': can't initialize Lua context.\n", fcn->name);
5853 return 0;
5854 }
5855 if (!hlua_ctx_init(stream->hlua, stream->task, 0)) {
5856 SEND_ERR(stream->be, "Lua converter '%s': can't initialize Lua context.\n", fcn->name);
5857 return 0;
5858 }
5859 }
5860
5861 /* If it is the first run, initialize the data for the call. */
5862 if (!HLUA_IS_RUNNING(stream->hlua)) {
5863
5864 /* The following Lua calls can fail. */
5865 if (!SET_SAFE_LJMP(stream->hlua->T)) {
5866 if (lua_type(stream->hlua->T, -1) == LUA_TSTRING)
5867 error = lua_tostring(stream->hlua->T, -1);
5868 else
5869 error = "critical error";
5870 SEND_ERR(stream->be, "Lua converter '%s': %s.\n", fcn->name, error);
5871 return 0;
5872 }
5873
5874 /* Check stack available size. */
5875 if (!lua_checkstack(stream->hlua->T, 1)) {
5876 SEND_ERR(stream->be, "Lua converter '%s': full stack.\n", fcn->name);
5877 RESET_SAFE_LJMP(stream->hlua->T);
5878 return 0;
5879 }
5880
5881 /* Restore the function in the stack. */
5882 lua_rawgeti(stream->hlua->T, LUA_REGISTRYINDEX, fcn->function_ref);
5883
5884 /* convert input sample and pust-it in the stack. */
5885 if (!lua_checkstack(stream->hlua->T, 1)) {
5886 SEND_ERR(stream->be, "Lua converter '%s': full stack.\n", fcn->name);
5887 RESET_SAFE_LJMP(stream->hlua->T);
5888 return 0;
5889 }
5890 hlua_smp2lua(stream->hlua->T, smp);
5891 stream->hlua->nargs = 1;
5892
5893 /* push keywords in the stack. */
5894 if (arg_p) {
5895 for (; arg_p->type != ARGT_STOP; arg_p++) {
5896 if (!lua_checkstack(stream->hlua->T, 1)) {
5897 SEND_ERR(stream->be, "Lua converter '%s': full stack.\n", fcn->name);
5898 RESET_SAFE_LJMP(stream->hlua->T);
5899 return 0;
5900 }
5901 hlua_arg2lua(stream->hlua->T, arg_p);
5902 stream->hlua->nargs++;
5903 }
5904 }
5905
5906 /* We must initialize the execution timeouts. */
5907 stream->hlua->max_time = hlua_timeout_session;
5908
5909 /* At this point the execution is safe. */
5910 RESET_SAFE_LJMP(stream->hlua->T);
5911 }
5912
5913 /* Execute the function. */
5914 switch (hlua_ctx_resume(stream->hlua, 0)) {
5915 /* finished. */
5916 case HLUA_E_OK:
5917 /* If the stack is empty, the function fails. */
5918 if (lua_gettop(stream->hlua->T) <= 0)
5919 return 0;
5920
5921 /* Convert the returned value in sample. */
5922 hlua_lua2smp(stream->hlua->T, -1, smp);
5923 lua_pop(stream->hlua->T, 1);
5924 return 1;
5925
5926 /* yield. */
5927 case HLUA_E_AGAIN:
5928 SEND_ERR(stream->be, "Lua converter '%s': cannot use yielded functions.\n", fcn->name);
5929 return 0;
5930
5931 /* finished with error. */
5932 case HLUA_E_ERRMSG:
5933 /* Display log. */
5934 SEND_ERR(stream->be, "Lua converter '%s': %s.\n",
5935 fcn->name, lua_tostring(stream->hlua->T, -1));
5936 lua_pop(stream->hlua->T, 1);
5937 return 0;
5938
5939 case HLUA_E_ETMOUT:
5940 SEND_ERR(stream->be, "Lua converter '%s': execution timeout.\n", fcn->name);
5941 return 0;
5942
5943 case HLUA_E_NOMEM:
5944 SEND_ERR(stream->be, "Lua converter '%s': out of memory error.\n", fcn->name);
5945 return 0;
5946
5947 case HLUA_E_YIELD:
5948 SEND_ERR(stream->be, "Lua converter '%s': yield functions like core.tcp() or core.sleep() are not allowed.\n", fcn->name);
5949 return 0;
5950
5951 case HLUA_E_ERR:
5952 /* Display log. */
5953 SEND_ERR(stream->be, "Lua converter '%s' returns an unknown error.\n", fcn->name);
5954
5955 default:
5956 return 0;
5957 }
5958 }
5959
5960 /* Wrapper called by HAProxy to execute a sample-fetch. this wrapper
5961 * doesn't allow "yield" functions because the HAProxy engine cannot
5962 * resume sample-fetches. This function will be called by the sample
5963 * fetch engine to call lua-based fetch operations.
5964 */
hlua_sample_fetch_wrapper(const struct arg * arg_p,struct sample * smp,const char * kw,void * private)5965 static int hlua_sample_fetch_wrapper(const struct arg *arg_p, struct sample *smp,
5966 const char *kw, void *private)
5967 {
5968 struct hlua_function *fcn = private;
5969 struct stream *stream = smp->strm;
5970 const char *error;
5971 const struct buffer msg = { };
5972 unsigned int hflags = HLUA_TXN_NOTERM;
5973
5974 if (!stream)
5975 return 0;
5976
5977 /* In the execution wrappers linked with a stream, the
5978 * Lua context can be not initialized. This behavior
5979 * permits to save performances because a systematic
5980 * Lua initialization cause 5% performances loss.
5981 */
5982 if (!stream->hlua) {
5983 stream->hlua = pool_alloc(pool_head_hlua);
5984 if (!stream->hlua) {
5985 SEND_ERR(stream->be, "Lua sample-fetch '%s': can't initialize Lua context.\n", fcn->name);
5986 return 0;
5987 }
5988 if (!hlua_ctx_init(stream->hlua, stream->task, 0)) {
5989 SEND_ERR(stream->be, "Lua sample-fetch '%s': can't initialize Lua context.\n", fcn->name);
5990 return 0;
5991 }
5992 }
5993
5994 consistency_set(stream, smp->opt, &stream->hlua->cons);
5995
5996 if (stream->be->mode == PR_MODE_HTTP) {
5997 if ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_REQ)
5998 hflags |= ((stream->txn->req.msg_state < HTTP_MSG_BODY) ? 0 : HLUA_TXN_HTTP_RDY);
5999 else
6000 hflags |= ((stream->txn->rsp.msg_state < HTTP_MSG_BODY) ? 0 : HLUA_TXN_HTTP_RDY);
6001 }
6002
6003 /* If it is the first run, initialize the data for the call. */
6004 if (!HLUA_IS_RUNNING(stream->hlua)) {
6005
6006 /* The following Lua calls can fail. */
6007 if (!SET_SAFE_LJMP(stream->hlua->T)) {
6008 if (lua_type(stream->hlua->T, -1) == LUA_TSTRING)
6009 error = lua_tostring(stream->hlua->T, -1);
6010 else
6011 error = "critical error";
6012 SEND_ERR(smp->px, "Lua sample-fetch '%s': %s.\n", fcn->name, error);
6013 return 0;
6014 }
6015
6016 /* Check stack available size. */
6017 if (!lua_checkstack(stream->hlua->T, 2)) {
6018 SEND_ERR(smp->px, "Lua sample-fetch '%s': full stack.\n", fcn->name);
6019 RESET_SAFE_LJMP(stream->hlua->T);
6020 return 0;
6021 }
6022
6023 /* Restore the function in the stack. */
6024 lua_rawgeti(stream->hlua->T, LUA_REGISTRYINDEX, fcn->function_ref);
6025
6026 /* push arguments in the stack. */
6027 if (!hlua_txn_new(stream->hlua->T, stream, smp->px, smp->opt & SMP_OPT_DIR, hflags)) {
6028 SEND_ERR(smp->px, "Lua sample-fetch '%s': full stack.\n", fcn->name);
6029 RESET_SAFE_LJMP(stream->hlua->T);
6030 return 0;
6031 }
6032 stream->hlua->nargs = 1;
6033
6034 /* push keywords in the stack. */
6035 for (; arg_p && arg_p->type != ARGT_STOP; arg_p++) {
6036 /* Check stack available size. */
6037 if (!lua_checkstack(stream->hlua->T, 1)) {
6038 SEND_ERR(smp->px, "Lua sample-fetch '%s': full stack.\n", fcn->name);
6039 RESET_SAFE_LJMP(stream->hlua->T);
6040 return 0;
6041 }
6042 hlua_arg2lua(stream->hlua->T, arg_p);
6043 stream->hlua->nargs++;
6044 }
6045
6046 /* We must initialize the execution timeouts. */
6047 stream->hlua->max_time = hlua_timeout_session;
6048
6049 /* At this point the execution is safe. */
6050 RESET_SAFE_LJMP(stream->hlua->T);
6051 }
6052
6053 /* Execute the function. */
6054 switch (hlua_ctx_resume(stream->hlua, 0)) {
6055 /* finished. */
6056 case HLUA_E_OK:
6057 if (!consistency_check(stream, smp->opt, &stream->hlua->cons)) {
6058 si_retnclose(&stream->si[0], &msg);
6059 return 0;
6060 }
6061 /* If the stack is empty, the function fails. */
6062 if (lua_gettop(stream->hlua->T) <= 0)
6063 return 0;
6064
6065 /* Convert the returned value in sample. */
6066 hlua_lua2smp(stream->hlua->T, -1, smp);
6067 lua_pop(stream->hlua->T, 1);
6068
6069 /* Set the end of execution flag. */
6070 smp->flags &= ~SMP_F_MAY_CHANGE;
6071 return 1;
6072
6073 /* yield. */
6074 case HLUA_E_AGAIN:
6075 if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
6076 si_retnclose(&stream->si[0], &msg);
6077 SEND_ERR(smp->px, "Lua sample-fetch '%s': cannot use yielded functions.\n", fcn->name);
6078 return 0;
6079
6080 /* finished with error. */
6081 case HLUA_E_ERRMSG:
6082 if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
6083 si_retnclose(&stream->si[0], &msg);
6084 /* Display log. */
6085 SEND_ERR(smp->px, "Lua sample-fetch '%s': %s.\n",
6086 fcn->name, lua_tostring(stream->hlua->T, -1));
6087 lua_pop(stream->hlua->T, 1);
6088 return 0;
6089
6090 case HLUA_E_ETMOUT:
6091 if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
6092 si_retnclose(&stream->si[0], &msg);
6093 SEND_ERR(smp->px, "Lua sample-fetch '%s': execution timeout.\n", fcn->name);
6094 return 0;
6095
6096 case HLUA_E_NOMEM:
6097 if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
6098 si_retnclose(&stream->si[0], &msg);
6099 SEND_ERR(smp->px, "Lua sample-fetch '%s': out of memory error.\n", fcn->name);
6100 return 0;
6101
6102 case HLUA_E_YIELD:
6103 if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
6104 si_retnclose(&stream->si[0], &msg);
6105 SEND_ERR(smp->px, "Lua sample-fetch '%s': yield not allowed.\n", fcn->name);
6106 return 0;
6107
6108 case HLUA_E_ERR:
6109 if (!consistency_check(stream, smp->opt, &stream->hlua->cons))
6110 si_retnclose(&stream->si[0], &msg);
6111 /* Display log. */
6112 SEND_ERR(smp->px, "Lua sample-fetch '%s' returns an unknown error.\n", fcn->name);
6113
6114 default:
6115 return 0;
6116 }
6117 }
6118
6119 /* This function is an LUA binding used for registering
6120 * "sample-conv" functions. It expects a converter name used
6121 * in the haproxy configuration file, and an LUA function.
6122 */
hlua_register_converters(lua_State * L)6123 __LJMP static int hlua_register_converters(lua_State *L)
6124 {
6125 struct sample_conv_kw_list *sck;
6126 const char *name;
6127 int ref;
6128 int len;
6129 struct hlua_function *fcn;
6130 struct sample_conv *sc;
6131 struct buffer *trash;
6132
6133 MAY_LJMP(check_args(L, 2, "register_converters"));
6134
6135 /* First argument : converter name. */
6136 name = MAY_LJMP(luaL_checkstring(L, 1));
6137
6138 /* Second argument : lua function. */
6139 ref = MAY_LJMP(hlua_checkfunction(L, 2));
6140
6141 /* Check if the converter is already registered */
6142 trash = get_trash_chunk();
6143 chunk_printf(trash, "lua.%s", name);
6144 sc = find_sample_conv(trash->area, trash->data);
6145 if (sc != NULL) {
6146 ha_warning("Trying to register converter 'lua.%s' more than once. "
6147 "This will become a hard error in version 2.5.\n", name);
6148 }
6149
6150 /* Allocate and fill the sample fetch keyword struct. */
6151 sck = calloc(1, sizeof(*sck) + sizeof(struct sample_conv) * 2);
6152 if (!sck)
6153 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
6154 fcn = calloc(1, sizeof(*fcn));
6155 if (!fcn)
6156 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
6157
6158 /* Fill fcn. */
6159 fcn->name = strdup(name);
6160 if (!fcn->name)
6161 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
6162 fcn->function_ref = ref;
6163
6164 /* List head */
6165 sck->list.n = sck->list.p = NULL;
6166
6167 /* converter keyword. */
6168 len = strlen("lua.") + strlen(name) + 1;
6169 sck->kw[0].kw = calloc(1, len);
6170 if (!sck->kw[0].kw)
6171 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
6172
6173 snprintf((char *)sck->kw[0].kw, len, "lua.%s", name);
6174 sck->kw[0].process = hlua_sample_conv_wrapper;
6175 sck->kw[0].arg_mask = ARG12(0,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR);
6176 sck->kw[0].val_args = NULL;
6177 sck->kw[0].in_type = SMP_T_STR;
6178 sck->kw[0].out_type = SMP_T_STR;
6179 sck->kw[0].private = fcn;
6180
6181 /* Register this new converter */
6182 sample_register_convs(sck);
6183
6184 return 0;
6185 }
6186
6187 /* This function is an LUA binding used for registering
6188 * "sample-fetch" functions. It expects a converter name used
6189 * in the haproxy configuration file, and an LUA function.
6190 */
hlua_register_fetches(lua_State * L)6191 __LJMP static int hlua_register_fetches(lua_State *L)
6192 {
6193 const char *name;
6194 int ref;
6195 int len;
6196 struct sample_fetch_kw_list *sfk;
6197 struct hlua_function *fcn;
6198 struct sample_fetch *sf;
6199 struct buffer *trash;
6200
6201 MAY_LJMP(check_args(L, 2, "register_fetches"));
6202
6203 /* First argument : sample-fetch name. */
6204 name = MAY_LJMP(luaL_checkstring(L, 1));
6205
6206 /* Second argument : lua function. */
6207 ref = MAY_LJMP(hlua_checkfunction(L, 2));
6208
6209 /* Check if the sample-fetch is already registered */
6210 trash = get_trash_chunk();
6211 chunk_printf(trash, "lua.%s", name);
6212 sf = find_sample_fetch(trash->area, trash->data);
6213 if (sf != NULL) {
6214 ha_warning("Trying to register sample-fetch 'lua.%s' more than once. "
6215 "This will become a hard error in version 2.5.\n", name);
6216 }
6217
6218 /* Allocate and fill the sample fetch keyword struct. */
6219 sfk = calloc(1, sizeof(*sfk) + sizeof(struct sample_fetch) * 2);
6220 if (!sfk)
6221 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
6222 fcn = calloc(1, sizeof(*fcn));
6223 if (!fcn)
6224 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
6225
6226 /* Fill fcn. */
6227 fcn->name = strdup(name);
6228 if (!fcn->name)
6229 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
6230 fcn->function_ref = ref;
6231
6232 /* List head */
6233 sfk->list.n = sfk->list.p = NULL;
6234
6235 /* sample-fetch keyword. */
6236 len = strlen("lua.") + strlen(name) + 1;
6237 sfk->kw[0].kw = calloc(1, len);
6238 if (!sfk->kw[0].kw)
6239 return luaL_error(L, "Lua out of memory error.");
6240
6241 snprintf((char *)sfk->kw[0].kw, len, "lua.%s", name);
6242 sfk->kw[0].process = hlua_sample_fetch_wrapper;
6243 sfk->kw[0].arg_mask = ARG12(0,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR);
6244 sfk->kw[0].val_args = NULL;
6245 sfk->kw[0].out_type = SMP_T_STR;
6246 sfk->kw[0].use = SMP_USE_HTTP_ANY;
6247 sfk->kw[0].val = 0;
6248 sfk->kw[0].private = fcn;
6249
6250 /* Register this new fetch. */
6251 sample_register_fetches(sfk);
6252
6253 return 0;
6254 }
6255
6256 /* This function is a wrapper to execute each LUA function declared
6257 * as an action wrapper during the initialisation period. This function
6258 * return ACT_RET_CONT if the processing is finished (with or without
6259 * error) and return ACT_RET_YIELD if the function must be called again
6260 * because the LUA returns a yield.
6261 */
hlua_action(struct act_rule * rule,struct proxy * px,struct session * sess,struct stream * s,int flags)6262 static enum act_return hlua_action(struct act_rule *rule, struct proxy *px,
6263 struct session *sess, struct stream *s, int flags)
6264 {
6265 char **arg;
6266 unsigned int hflags = 0;
6267 int dir;
6268 const char *error;
6269 const struct buffer msg = { };
6270
6271 switch (rule->from) {
6272 case ACT_F_TCP_REQ_CNT: ; dir = SMP_OPT_DIR_REQ; break;
6273 case ACT_F_TCP_RES_CNT: ; dir = SMP_OPT_DIR_RES; break;
6274 case ACT_F_HTTP_REQ: hflags = HLUA_TXN_HTTP_RDY ; dir = SMP_OPT_DIR_REQ; break;
6275 case ACT_F_HTTP_RES: hflags = HLUA_TXN_HTTP_RDY ; dir = SMP_OPT_DIR_RES; break;
6276 default:
6277 SEND_ERR(px, "Lua: internal error while execute action.\n");
6278 return ACT_RET_CONT;
6279 }
6280
6281 /* In the execution wrappers linked with a stream, the
6282 * Lua context can be not initialized. This behavior
6283 * permits to save performances because a systematic
6284 * Lua initialization cause 5% performances loss.
6285 */
6286 if (!s->hlua) {
6287 s->hlua = pool_alloc(pool_head_hlua);
6288 if (!s->hlua) {
6289 SEND_ERR(px, "Lua action '%s': can't initialize Lua context.\n",
6290 rule->arg.hlua_rule->fcn.name);
6291 return ACT_RET_CONT;
6292 }
6293 if (!hlua_ctx_init(s->hlua, s->task, 0)) {
6294 SEND_ERR(px, "Lua action '%s': can't initialize Lua context.\n",
6295 rule->arg.hlua_rule->fcn.name);
6296 return ACT_RET_CONT;
6297 }
6298 }
6299
6300 consistency_set(s, dir, &s->hlua->cons);
6301
6302 /* If it is the first run, initialize the data for the call. */
6303 if (!HLUA_IS_RUNNING(s->hlua)) {
6304
6305 /* The following Lua calls can fail. */
6306 if (!SET_SAFE_LJMP(s->hlua->T)) {
6307 if (lua_type(s->hlua->T, -1) == LUA_TSTRING)
6308 error = lua_tostring(s->hlua->T, -1);
6309 else
6310 error = "critical error";
6311 SEND_ERR(px, "Lua function '%s': %s.\n",
6312 rule->arg.hlua_rule->fcn.name, error);
6313 return ACT_RET_CONT;
6314 }
6315
6316 /* Check stack available size. */
6317 if (!lua_checkstack(s->hlua->T, 1)) {
6318 SEND_ERR(px, "Lua function '%s': full stack.\n",
6319 rule->arg.hlua_rule->fcn.name);
6320 RESET_SAFE_LJMP(s->hlua->T);
6321 return ACT_RET_CONT;
6322 }
6323
6324 /* Restore the function in the stack. */
6325 lua_rawgeti(s->hlua->T, LUA_REGISTRYINDEX, rule->arg.hlua_rule->fcn.function_ref);
6326
6327 /* Create and and push object stream in the stack. */
6328 if (!hlua_txn_new(s->hlua->T, s, px, dir, hflags)) {
6329 SEND_ERR(px, "Lua function '%s': full stack.\n",
6330 rule->arg.hlua_rule->fcn.name);
6331 RESET_SAFE_LJMP(s->hlua->T);
6332 return ACT_RET_CONT;
6333 }
6334 s->hlua->nargs = 1;
6335
6336 /* push keywords in the stack. */
6337 for (arg = rule->arg.hlua_rule->args; arg && *arg; arg++) {
6338 if (!lua_checkstack(s->hlua->T, 1)) {
6339 SEND_ERR(px, "Lua function '%s': full stack.\n",
6340 rule->arg.hlua_rule->fcn.name);
6341 RESET_SAFE_LJMP(s->hlua->T);
6342 return ACT_RET_CONT;
6343 }
6344 lua_pushstring(s->hlua->T, *arg);
6345 s->hlua->nargs++;
6346 }
6347
6348 /* Now the execution is safe. */
6349 RESET_SAFE_LJMP(s->hlua->T);
6350
6351 /* We must initialize the execution timeouts. */
6352 s->hlua->max_time = hlua_timeout_session;
6353 }
6354
6355 /* Always reset the analyse expiration timeout for the corresponding
6356 * channel in case the lua script yield, to be sure to not keep an
6357 * expired timeout.
6358 */
6359 if (dir == SMP_OPT_DIR_REQ)
6360 s->req.analyse_exp = TICK_ETERNITY;
6361 else
6362 s->res.analyse_exp = TICK_ETERNITY;
6363
6364 /* Execute the function. */
6365 switch (hlua_ctx_resume(s->hlua, !(flags & ACT_FLAG_FINAL))) {
6366 /* finished. */
6367 case HLUA_E_OK:
6368 if (!consistency_check(s, dir, &s->hlua->cons)) {
6369 si_retnclose(&s->si[0], &msg);
6370 return ACT_RET_ERR;
6371 }
6372 if (s->hlua->flags & HLUA_STOP)
6373 return ACT_RET_DONE;
6374 return ACT_RET_CONT;
6375
6376 /* yield. */
6377 case HLUA_E_AGAIN:
6378 /* Set timeout in the required channel. */
6379 if (s->hlua->wake_time != TICK_ETERNITY) {
6380 if (dir == SMP_OPT_DIR_REQ)
6381 s->req.analyse_exp = s->hlua->wake_time;
6382 else
6383 s->res.analyse_exp = s->hlua->wake_time;
6384 }
6385 /* Some actions can be wake up when a "write" event
6386 * is detected on a response channel. This is useful
6387 * only for actions targeted on the requests.
6388 */
6389 if (HLUA_IS_WAKERESWR(s->hlua))
6390 s->res.flags |= CF_WAKE_WRITE;
6391 if (HLUA_IS_WAKEREQWR(s->hlua))
6392 s->req.flags |= CF_WAKE_WRITE;
6393 /* We can quit the function without consistency check
6394 * because HAProxy is not able to manipulate data, it
6395 * is only allowed to call me again. */
6396 return ACT_RET_YIELD;
6397
6398 /* finished with error. */
6399 case HLUA_E_ERRMSG:
6400 if (!consistency_check(s, dir, &s->hlua->cons)) {
6401 si_retnclose(&s->si[0], &msg);
6402 return ACT_RET_ERR;
6403 }
6404 /* Display log. */
6405 SEND_ERR(px, "Lua function '%s': %s.\n",
6406 rule->arg.hlua_rule->fcn.name, lua_tostring(s->hlua->T, -1));
6407 lua_pop(s->hlua->T, 1);
6408 return ACT_RET_CONT;
6409
6410 case HLUA_E_ETMOUT:
6411 if (!consistency_check(s, dir, &s->hlua->cons)) {
6412 si_retnclose(&s->si[0], &msg);
6413 return ACT_RET_ERR;
6414 }
6415 SEND_ERR(px, "Lua function '%s': execution timeout.\n", rule->arg.hlua_rule->fcn.name);
6416 return 0;
6417
6418 case HLUA_E_NOMEM:
6419 if (!consistency_check(s, dir, &s->hlua->cons)) {
6420 si_retnclose(&s->si[0], &msg);
6421 return ACT_RET_ERR;
6422 }
6423 SEND_ERR(px, "Lua function '%s': out of memory error.\n", rule->arg.hlua_rule->fcn.name);
6424 return 0;
6425
6426 case HLUA_E_YIELD:
6427 if (!consistency_check(s, dir, &s->hlua->cons)) {
6428 si_retnclose(&s->si[0], &msg);
6429 return ACT_RET_ERR;
6430 }
6431 SEND_ERR(px, "Lua function '%s': aborting Lua processing on expired timeout.\n",
6432 rule->arg.hlua_rule->fcn.name);
6433 return 0;
6434
6435 case HLUA_E_ERR:
6436 if (!consistency_check(s, dir, &s->hlua->cons)) {
6437 si_retnclose(&s->si[0], &msg);
6438 return ACT_RET_ERR;
6439 }
6440 /* Display log. */
6441 SEND_ERR(px, "Lua function '%s' return an unknown error.\n",
6442 rule->arg.hlua_rule->fcn.name);
6443
6444 default:
6445 return ACT_RET_CONT;
6446 }
6447 }
6448
hlua_applet_wakeup(struct task * t,void * context,unsigned short state)6449 struct task *hlua_applet_wakeup(struct task *t, void *context, unsigned short state)
6450 {
6451 struct appctx *ctx = context;
6452
6453 appctx_wakeup(ctx);
6454 t->expire = TICK_ETERNITY;
6455 return t;
6456 }
6457
hlua_applet_tcp_init(struct appctx * ctx,struct proxy * px,struct stream * strm)6458 static int hlua_applet_tcp_init(struct appctx *ctx, struct proxy *px, struct stream *strm)
6459 {
6460 struct stream_interface *si = ctx->owner;
6461 struct hlua *hlua;
6462 struct task *task;
6463 char **arg;
6464 const char *error;
6465
6466 hlua = pool_alloc(pool_head_hlua);
6467 if (!hlua) {
6468 SEND_ERR(px, "Lua applet tcp '%s': out of memory.\n",
6469 ctx->rule->arg.hlua_rule->fcn.name);
6470 return 0;
6471 }
6472 HLUA_INIT(hlua);
6473 ctx->ctx.hlua_apptcp.hlua = hlua;
6474 ctx->ctx.hlua_apptcp.flags = 0;
6475
6476 /* Create task used by signal to wakeup applets. */
6477 task = task_new(tid_bit);
6478 if (!task) {
6479 SEND_ERR(px, "Lua applet tcp '%s': out of memory.\n",
6480 ctx->rule->arg.hlua_rule->fcn.name);
6481 return 0;
6482 }
6483 task->nice = 0;
6484 task->context = ctx;
6485 task->process = hlua_applet_wakeup;
6486 ctx->ctx.hlua_apptcp.task = task;
6487
6488 /* In the execution wrappers linked with a stream, the
6489 * Lua context can be not initialized. This behavior
6490 * permits to save performances because a systematic
6491 * Lua initialization cause 5% performances loss.
6492 */
6493 if (!hlua_ctx_init(hlua, task, 0)) {
6494 SEND_ERR(px, "Lua applet tcp '%s': can't initialize Lua context.\n",
6495 ctx->rule->arg.hlua_rule->fcn.name);
6496 return 0;
6497 }
6498
6499 /* Set timeout according with the applet configuration. */
6500 hlua->max_time = ctx->applet->timeout;
6501
6502 /* The following Lua calls can fail. */
6503 if (!SET_SAFE_LJMP(hlua->T)) {
6504 if (lua_type(hlua->T, -1) == LUA_TSTRING)
6505 error = lua_tostring(hlua->T, -1);
6506 else
6507 error = "critical error";
6508 SEND_ERR(px, "Lua applet tcp '%s': %s.\n",
6509 ctx->rule->arg.hlua_rule->fcn.name, error);
6510 return 0;
6511 }
6512
6513 /* Check stack available size. */
6514 if (!lua_checkstack(hlua->T, 1)) {
6515 SEND_ERR(px, "Lua applet tcp '%s': full stack.\n",
6516 ctx->rule->arg.hlua_rule->fcn.name);
6517 RESET_SAFE_LJMP(hlua->T);
6518 return 0;
6519 }
6520
6521 /* Restore the function in the stack. */
6522 lua_rawgeti(hlua->T, LUA_REGISTRYINDEX, ctx->rule->arg.hlua_rule->fcn.function_ref);
6523
6524 /* Create and and push object stream in the stack. */
6525 if (!hlua_applet_tcp_new(hlua->T, ctx)) {
6526 SEND_ERR(px, "Lua applet tcp '%s': full stack.\n",
6527 ctx->rule->arg.hlua_rule->fcn.name);
6528 RESET_SAFE_LJMP(hlua->T);
6529 return 0;
6530 }
6531 hlua->nargs = 1;
6532
6533 /* push keywords in the stack. */
6534 for (arg = ctx->rule->arg.hlua_rule->args; arg && *arg; arg++) {
6535 if (!lua_checkstack(hlua->T, 1)) {
6536 SEND_ERR(px, "Lua applet tcp '%s': full stack.\n",
6537 ctx->rule->arg.hlua_rule->fcn.name);
6538 RESET_SAFE_LJMP(hlua->T);
6539 return 0;
6540 }
6541 lua_pushstring(hlua->T, *arg);
6542 hlua->nargs++;
6543 }
6544
6545 RESET_SAFE_LJMP(hlua->T);
6546
6547 /* Wakeup the applet ASAP. */
6548 si_cant_get(si);
6549 si_rx_endp_more(si);
6550
6551 return 1;
6552 }
6553
hlua_applet_tcp_fct(struct appctx * ctx)6554 void hlua_applet_tcp_fct(struct appctx *ctx)
6555 {
6556 struct stream_interface *si = ctx->owner;
6557 struct stream *strm = si_strm(si);
6558 struct channel *res = si_ic(si);
6559 struct act_rule *rule = ctx->rule;
6560 struct proxy *px = strm->be;
6561 struct hlua *hlua = ctx->ctx.hlua_apptcp.hlua;
6562
6563 /* The applet execution is already done. */
6564 if (ctx->ctx.hlua_apptcp.flags & APPLET_DONE) {
6565 /* eat the whole request */
6566 co_skip(si_oc(si), co_data(si_oc(si)));
6567 return;
6568 }
6569
6570 /* If the stream is disconnect or closed, ldo nothing. */
6571 if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO))
6572 return;
6573
6574 /* Execute the function. */
6575 switch (hlua_ctx_resume(hlua, 1)) {
6576 /* finished. */
6577 case HLUA_E_OK:
6578 ctx->ctx.hlua_apptcp.flags |= APPLET_DONE;
6579
6580 /* eat the whole request */
6581 co_skip(si_oc(si), co_data(si_oc(si)));
6582 res->flags |= CF_READ_NULL;
6583 si_shutr(si);
6584 return;
6585
6586 /* yield. */
6587 case HLUA_E_AGAIN:
6588 if (hlua->wake_time != TICK_ETERNITY)
6589 task_schedule(ctx->ctx.hlua_apptcp.task, hlua->wake_time);
6590 return;
6591
6592 /* finished with error. */
6593 case HLUA_E_ERRMSG:
6594 /* Display log. */
6595 SEND_ERR(px, "Lua applet tcp '%s': %s.\n",
6596 rule->arg.hlua_rule->fcn.name, lua_tostring(hlua->T, -1));
6597 lua_pop(hlua->T, 1);
6598 goto error;
6599
6600 case HLUA_E_ETMOUT:
6601 SEND_ERR(px, "Lua applet tcp '%s': execution timeout.\n",
6602 rule->arg.hlua_rule->fcn.name);
6603 goto error;
6604
6605 case HLUA_E_NOMEM:
6606 SEND_ERR(px, "Lua applet tcp '%s': out of memory error.\n",
6607 rule->arg.hlua_rule->fcn.name);
6608 goto error;
6609
6610 case HLUA_E_YIELD: /* unexpected */
6611 SEND_ERR(px, "Lua applet tcp '%s': yield not allowed.\n",
6612 rule->arg.hlua_rule->fcn.name);
6613 goto error;
6614
6615 case HLUA_E_ERR:
6616 /* Display log. */
6617 SEND_ERR(px, "Lua applet tcp '%s' return an unknown error.\n",
6618 rule->arg.hlua_rule->fcn.name);
6619 goto error;
6620
6621 default:
6622 goto error;
6623 }
6624
6625 error:
6626
6627 /* For all other cases, just close the stream. */
6628 si_shutw(si);
6629 si_shutr(si);
6630 ctx->ctx.hlua_apptcp.flags |= APPLET_DONE;
6631 }
6632
hlua_applet_tcp_release(struct appctx * ctx)6633 static void hlua_applet_tcp_release(struct appctx *ctx)
6634 {
6635 task_destroy(ctx->ctx.hlua_apptcp.task);
6636 ctx->ctx.hlua_apptcp.task = NULL;
6637 hlua_ctx_destroy(ctx->ctx.hlua_apptcp.hlua);
6638 ctx->ctx.hlua_apptcp.hlua = NULL;
6639 }
6640
6641 /* The function returns 1 if the initialisation is complete, 0 if
6642 * an errors occurs and -1 if more data are required for initializing
6643 * the applet.
6644 */
hlua_applet_http_init(struct appctx * ctx,struct proxy * px,struct stream * strm)6645 static int hlua_applet_http_init(struct appctx *ctx, struct proxy *px, struct stream *strm)
6646 {
6647 struct stream_interface *si = ctx->owner;
6648 struct http_txn *txn;
6649 struct hlua *hlua;
6650 char **arg;
6651 struct task *task;
6652 const char *error;
6653
6654 txn = strm->txn;
6655 hlua = pool_alloc(pool_head_hlua);
6656 if (!hlua) {
6657 SEND_ERR(px, "Lua applet http '%s': out of memory.\n",
6658 ctx->rule->arg.hlua_rule->fcn.name);
6659 return 0;
6660 }
6661 HLUA_INIT(hlua);
6662 ctx->ctx.hlua_apphttp.hlua = hlua;
6663 ctx->ctx.hlua_apphttp.left_bytes = -1;
6664 ctx->ctx.hlua_apphttp.flags = 0;
6665
6666 if (txn->req.flags & HTTP_MSGF_VER_11)
6667 ctx->ctx.hlua_apphttp.flags |= APPLET_HTTP11;
6668
6669 /* Create task used by signal to wakeup applets. */
6670 task = task_new(tid_bit);
6671 if (!task) {
6672 SEND_ERR(px, "Lua applet http '%s': out of memory.\n",
6673 ctx->rule->arg.hlua_rule->fcn.name);
6674 return 0;
6675 }
6676 task->nice = 0;
6677 task->context = ctx;
6678 task->process = hlua_applet_wakeup;
6679 ctx->ctx.hlua_apphttp.task = task;
6680
6681 /* In the execution wrappers linked with a stream, the
6682 * Lua context can be not initialized. This behavior
6683 * permits to save performances because a systematic
6684 * Lua initialization cause 5% performances loss.
6685 */
6686 if (!hlua_ctx_init(hlua, task, 0)) {
6687 SEND_ERR(px, "Lua applet http '%s': can't initialize Lua context.\n",
6688 ctx->rule->arg.hlua_rule->fcn.name);
6689 return 0;
6690 }
6691
6692 /* Set timeout according with the applet configuration. */
6693 hlua->max_time = ctx->applet->timeout;
6694
6695 /* The following Lua calls can fail. */
6696 if (!SET_SAFE_LJMP(hlua->T)) {
6697 if (lua_type(hlua->T, -1) == LUA_TSTRING)
6698 error = lua_tostring(hlua->T, -1);
6699 else
6700 error = "critical error";
6701 SEND_ERR(px, "Lua applet http '%s': %s.\n",
6702 ctx->rule->arg.hlua_rule->fcn.name, error);
6703 return 0;
6704 }
6705
6706 /* Check stack available size. */
6707 if (!lua_checkstack(hlua->T, 1)) {
6708 SEND_ERR(px, "Lua applet http '%s': full stack.\n",
6709 ctx->rule->arg.hlua_rule->fcn.name);
6710 RESET_SAFE_LJMP(hlua->T);
6711 return 0;
6712 }
6713
6714 /* Restore the function in the stack. */
6715 lua_rawgeti(hlua->T, LUA_REGISTRYINDEX, ctx->rule->arg.hlua_rule->fcn.function_ref);
6716
6717 /* Create and and push object stream in the stack. */
6718 if (!hlua_applet_http_new(hlua->T, ctx)) {
6719 SEND_ERR(px, "Lua applet http '%s': full stack.\n",
6720 ctx->rule->arg.hlua_rule->fcn.name);
6721 RESET_SAFE_LJMP(hlua->T);
6722 return 0;
6723 }
6724 hlua->nargs = 1;
6725
6726 /* push keywords in the stack. */
6727 for (arg = ctx->rule->arg.hlua_rule->args; arg && *arg; arg++) {
6728 if (!lua_checkstack(hlua->T, 1)) {
6729 SEND_ERR(px, "Lua applet http '%s': full stack.\n",
6730 ctx->rule->arg.hlua_rule->fcn.name);
6731 RESET_SAFE_LJMP(hlua->T);
6732 return 0;
6733 }
6734 lua_pushstring(hlua->T, *arg);
6735 hlua->nargs++;
6736 }
6737
6738 RESET_SAFE_LJMP(hlua->T);
6739
6740 /* Wakeup the applet when data is ready for read. */
6741 si_cant_get(si);
6742
6743 return 1;
6744 }
6745
hlua_applet_http_fct(struct appctx * ctx)6746 void hlua_applet_http_fct(struct appctx *ctx)
6747 {
6748 struct stream_interface *si = ctx->owner;
6749 struct stream *strm = si_strm(si);
6750 struct channel *req = si_oc(si);
6751 struct channel *res = si_ic(si);
6752 struct act_rule *rule = ctx->rule;
6753 struct proxy *px = strm->be;
6754 struct hlua *hlua = ctx->ctx.hlua_apphttp.hlua;
6755 struct htx *req_htx, *res_htx;
6756
6757 res_htx = htx_from_buf(&res->buf);
6758
6759 /* If the stream is disconnect or closed, ldo nothing. */
6760 if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO))
6761 goto out;
6762
6763 /* Check if the input buffer is avalaible. */
6764 if (!b_size(&res->buf)) {
6765 si_rx_room_blk(si);
6766 goto out;
6767 }
6768 /* check that the output is not closed */
6769 if (res->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_SHUTR))
6770 ctx->ctx.hlua_apphttp.flags |= APPLET_DONE;
6771
6772 /* Set the currently running flag. */
6773 if (!HLUA_IS_RUNNING(hlua) &&
6774 !(ctx->ctx.hlua_apphttp.flags & APPLET_DONE)) {
6775 struct htx_blk *blk;
6776 size_t count = co_data(req);
6777
6778 if (!count) {
6779 si_cant_get(si);
6780 goto out;
6781 }
6782
6783 /* We need to flush the request header. This left the body for
6784 * the Lua.
6785 */
6786 req_htx = htx_from_buf(&req->buf);
6787 blk = htx_get_first_blk(req_htx);
6788 while (count && blk) {
6789 enum htx_blk_type type = htx_get_blk_type(blk);
6790 uint32_t sz = htx_get_blksz(blk);
6791
6792 if (sz > count) {
6793 si_cant_get(si);
6794 htx_to_buf(req_htx, &req->buf);
6795 goto out;
6796 }
6797
6798 count -= sz;
6799 co_set_data(req, co_data(req) - sz);
6800 blk = htx_remove_blk(req_htx, blk);
6801
6802 if (type == HTX_BLK_EOH)
6803 break;
6804 }
6805 htx_to_buf(req_htx, &req->buf);
6806 }
6807
6808 /* Executes The applet if it is not done. */
6809 if (!(ctx->ctx.hlua_apphttp.flags & APPLET_DONE)) {
6810
6811 /* Execute the function. */
6812 switch (hlua_ctx_resume(hlua, 1)) {
6813 /* finished. */
6814 case HLUA_E_OK:
6815 ctx->ctx.hlua_apphttp.flags |= APPLET_DONE;
6816 break;
6817
6818 /* yield. */
6819 case HLUA_E_AGAIN:
6820 if (hlua->wake_time != TICK_ETERNITY)
6821 task_schedule(ctx->ctx.hlua_apphttp.task, hlua->wake_time);
6822 goto out;
6823
6824 /* finished with error. */
6825 case HLUA_E_ERRMSG:
6826 /* Display log. */
6827 SEND_ERR(px, "Lua applet http '%s': %s.\n",
6828 rule->arg.hlua_rule->fcn.name, lua_tostring(hlua->T, -1));
6829 lua_pop(hlua->T, 1);
6830 goto error;
6831
6832 case HLUA_E_ETMOUT:
6833 SEND_ERR(px, "Lua applet http '%s': execution timeout.\n",
6834 rule->arg.hlua_rule->fcn.name);
6835 goto error;
6836
6837 case HLUA_E_NOMEM:
6838 SEND_ERR(px, "Lua applet http '%s': out of memory error.\n",
6839 rule->arg.hlua_rule->fcn.name);
6840 goto error;
6841
6842 case HLUA_E_YIELD: /* unexpected */
6843 SEND_ERR(px, "Lua applet http '%s': yield not allowed.\n",
6844 rule->arg.hlua_rule->fcn.name);
6845 goto error;
6846
6847 case HLUA_E_ERR:
6848 /* Display log. */
6849 SEND_ERR(px, "Lua applet http '%s' return an unknown error.\n",
6850 rule->arg.hlua_rule->fcn.name);
6851 goto error;
6852
6853 default:
6854 goto error;
6855 }
6856 }
6857
6858 if (ctx->ctx.hlua_apphttp.flags & APPLET_DONE) {
6859 if (ctx->ctx.hlua_apphttp.flags & APPLET_RSP_SENT)
6860 goto done;
6861
6862 if (!(ctx->ctx.hlua_apphttp.flags & APPLET_HDR_SENT))
6863 goto error;
6864
6865 /* Don't add TLR because mux-h1 will take care of it */
6866 if (!htx_add_endof(res_htx, HTX_BLK_EOM)) {
6867 si_rx_room_blk(si);
6868 goto out;
6869 }
6870 channel_add_input(res, 1);
6871 strm->txn->status = ctx->ctx.hlua_apphttp.status;
6872 ctx->ctx.hlua_apphttp.flags |= APPLET_RSP_SENT;
6873 }
6874
6875 done:
6876 if (ctx->ctx.hlua_apphttp.flags & APPLET_DONE) {
6877 if (!(res->flags & CF_SHUTR)) {
6878 res->flags |= CF_READ_NULL;
6879 si_shutr(si);
6880 }
6881
6882 /* eat the whole request */
6883 if (co_data(req)) {
6884 req_htx = htx_from_buf(&req->buf);
6885 co_htx_skip(req, req_htx, co_data(req));
6886 htx_to_buf(req_htx, &req->buf);
6887 }
6888 }
6889
6890 out:
6891 htx_to_buf(res_htx, &res->buf);
6892 return;
6893
6894 error:
6895
6896 /* If we are in HTTP mode, and we are not send any
6897 * data, return a 500 server error in best effort:
6898 * if there is no room available in the buffer,
6899 * just close the connection.
6900 */
6901 if (!(ctx->ctx.hlua_apphttp.flags & APPLET_HDR_SENT)) {
6902 struct buffer *err = &http_err_chunks[HTTP_ERR_500];
6903
6904 channel_erase(res);
6905 res->buf.data = b_data(err);
6906 memcpy(res->buf.area, b_head(err), b_data(err));
6907 res_htx = htx_from_buf(&res->buf);
6908 channel_add_input(res, res_htx->data);
6909 }
6910 if (!(strm->flags & SF_ERR_MASK))
6911 strm->flags |= SF_ERR_RESOURCE;
6912 ctx->ctx.hlua_apphttp.flags |= APPLET_DONE;
6913 goto done;
6914 }
6915
hlua_applet_http_release(struct appctx * ctx)6916 static void hlua_applet_http_release(struct appctx *ctx)
6917 {
6918 task_destroy(ctx->ctx.hlua_apphttp.task);
6919 ctx->ctx.hlua_apphttp.task = NULL;
6920 hlua_ctx_destroy(ctx->ctx.hlua_apphttp.hlua);
6921 ctx->ctx.hlua_apphttp.hlua = NULL;
6922 }
6923
6924 /* global {tcp|http}-request parser. Return ACT_RET_PRS_OK in
6925 * succes case, else return ACT_RET_PRS_ERR.
6926 *
6927 * This function can fail with an abort() due to an Lua critical error.
6928 * We are in the configuration parsing process of HAProxy, this abort() is
6929 * tolerated.
6930 */
action_register_lua(const char ** args,int * cur_arg,struct proxy * px,struct act_rule * rule,char ** err)6931 static enum act_parse_ret action_register_lua(const char **args, int *cur_arg, struct proxy *px,
6932 struct act_rule *rule, char **err)
6933 {
6934 struct hlua_function *fcn = rule->kw->private;
6935 int i;
6936
6937 /* Memory for the rule. */
6938 rule->arg.hlua_rule = calloc(1, sizeof(*rule->arg.hlua_rule));
6939 if (!rule->arg.hlua_rule) {
6940 memprintf(err, "out of memory error");
6941 return ACT_RET_PRS_ERR;
6942 }
6943
6944 /* Memory for arguments. */
6945 rule->arg.hlua_rule->args = calloc(fcn->nargs + 1, sizeof(char *));
6946 if (!rule->arg.hlua_rule->args) {
6947 memprintf(err, "out of memory error");
6948 return ACT_RET_PRS_ERR;
6949 }
6950
6951 /* Reference the Lua function and store the reference. */
6952 rule->arg.hlua_rule->fcn = *fcn;
6953
6954 /* Expect some arguments */
6955 for (i = 0; i < fcn->nargs; i++) {
6956 if (*args[*cur_arg] == '\0') {
6957 memprintf(err, "expect %d arguments", fcn->nargs);
6958 return ACT_RET_PRS_ERR;
6959 }
6960 rule->arg.hlua_rule->args[i] = strdup(args[*cur_arg]);
6961 if (!rule->arg.hlua_rule->args[i]) {
6962 memprintf(err, "out of memory error");
6963 return ACT_RET_PRS_ERR;
6964 }
6965 (*cur_arg)++;
6966 }
6967 rule->arg.hlua_rule->args[i] = NULL;
6968
6969 rule->action = ACT_CUSTOM;
6970 rule->action_ptr = hlua_action;
6971 return ACT_RET_PRS_OK;
6972 }
6973
action_register_service_http(const char ** args,int * cur_arg,struct proxy * px,struct act_rule * rule,char ** err)6974 static enum act_parse_ret action_register_service_http(const char **args, int *cur_arg, struct proxy *px,
6975 struct act_rule *rule, char **err)
6976 {
6977 struct hlua_function *fcn = rule->kw->private;
6978
6979 /* HTTP applets are forbidden in tcp-request rules.
6980 * HTTP applet request requires everything initilized by
6981 * "http_process_request" (analyzer flag AN_REQ_HTTP_INNER).
6982 * The applet will be immediately initilized, but its before
6983 * the call of this analyzer.
6984 */
6985 if (rule->from != ACT_F_HTTP_REQ) {
6986 memprintf(err, "HTTP applets are forbidden from 'tcp-request' rulesets");
6987 return ACT_RET_PRS_ERR;
6988 }
6989
6990 /* Memory for the rule. */
6991 rule->arg.hlua_rule = calloc(1, sizeof(*rule->arg.hlua_rule));
6992 if (!rule->arg.hlua_rule) {
6993 memprintf(err, "out of memory error");
6994 return ACT_RET_PRS_ERR;
6995 }
6996
6997 /* Reference the Lua function and store the reference. */
6998 rule->arg.hlua_rule->fcn = *fcn;
6999
7000 /* TODO: later accept arguments. */
7001 rule->arg.hlua_rule->args = NULL;
7002
7003 /* Add applet pointer in the rule. */
7004 rule->applet.obj_type = OBJ_TYPE_APPLET;
7005 rule->applet.name = fcn->name;
7006 rule->applet.init = hlua_applet_http_init;
7007 rule->applet.fct = hlua_applet_http_fct;
7008 rule->applet.release = hlua_applet_http_release;
7009 rule->applet.timeout = hlua_timeout_applet;
7010
7011 return ACT_RET_PRS_OK;
7012 }
7013
7014 /* This function is an LUA binding used for registering
7015 * "sample-conv" functions. It expects a converter name used
7016 * in the haproxy configuration file, and an LUA function.
7017 */
hlua_register_action(lua_State * L)7018 __LJMP static int hlua_register_action(lua_State *L)
7019 {
7020 struct action_kw_list *akl;
7021 const char *name;
7022 int ref;
7023 int len;
7024 struct hlua_function *fcn;
7025 int nargs;
7026 struct buffer *trash;
7027 struct action_kw *akw;
7028
7029 /* Initialise the number of expected arguments at 0. */
7030 nargs = 0;
7031
7032 if (lua_gettop(L) < 3 || lua_gettop(L) > 4)
7033 WILL_LJMP(luaL_error(L, "'register_action' needs between 3 and 4 arguments"));
7034
7035 /* First argument : converter name. */
7036 name = MAY_LJMP(luaL_checkstring(L, 1));
7037
7038 /* Second argument : environment. */
7039 if (lua_type(L, 2) != LUA_TTABLE)
7040 WILL_LJMP(luaL_error(L, "register_action: second argument must be a table of strings"));
7041
7042 /* Third argument : lua function. */
7043 ref = MAY_LJMP(hlua_checkfunction(L, 3));
7044
7045 /* Fourth argument : number of mandatory arguments expected on the configuration line. */
7046 if (lua_gettop(L) >= 4)
7047 nargs = MAY_LJMP(luaL_checkinteger(L, 4));
7048
7049 /* browse the second argument as an array. */
7050 lua_pushnil(L);
7051 while (lua_next(L, 2) != 0) {
7052 if (lua_type(L, -1) != LUA_TSTRING)
7053 WILL_LJMP(luaL_error(L, "register_action: second argument must be a table of strings"));
7054
7055 /* Check if action exists */
7056 trash = get_trash_chunk();
7057 chunk_printf(trash, "lua.%s", name);
7058 if (strcmp(lua_tostring(L, -1), "tcp-req") == 0) {
7059 akw = tcp_req_cont_action(trash->area);
7060 } else if (strcmp(lua_tostring(L, -1), "tcp-res") == 0) {
7061 akw = tcp_res_cont_action(trash->area);
7062 } else if (strcmp(lua_tostring(L, -1), "http-req") == 0) {
7063 akw = action_http_req_custom(trash->area);
7064 } else if (strcmp(lua_tostring(L, -1), "http-res") == 0) {
7065 akw = action_http_res_custom(trash->area);
7066 } else {
7067 akw = NULL;
7068 }
7069 if (akw != NULL) {
7070 ha_warning("Trying to register action 'lua.%s' more than once. "
7071 "This will become a hard error in version 2.5.\n", name);
7072 }
7073
7074 /* Check required environment. Only accepted "http" or "tcp". */
7075 /* Allocate and fill the sample fetch keyword struct. */
7076 akl = calloc(1, sizeof(*akl) + sizeof(struct action_kw) * 2);
7077 if (!akl)
7078 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
7079 fcn = calloc(1, sizeof(*fcn));
7080 if (!fcn)
7081 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
7082
7083 /* Fill fcn. */
7084 fcn->name = strdup(name);
7085 if (!fcn->name)
7086 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
7087 fcn->function_ref = ref;
7088
7089 /* Set the expected number od arguments. */
7090 fcn->nargs = nargs;
7091
7092 /* List head */
7093 akl->list.n = akl->list.p = NULL;
7094
7095 /* action keyword. */
7096 len = strlen("lua.") + strlen(name) + 1;
7097 akl->kw[0].kw = calloc(1, len);
7098 if (!akl->kw[0].kw)
7099 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
7100
7101 snprintf((char *)akl->kw[0].kw, len, "lua.%s", name);
7102
7103 akl->kw[0].match_pfx = 0;
7104 akl->kw[0].private = fcn;
7105 akl->kw[0].parse = action_register_lua;
7106
7107 /* select the action registering point. */
7108 if (strcmp(lua_tostring(L, -1), "tcp-req") == 0)
7109 tcp_req_cont_keywords_register(akl);
7110 else if (strcmp(lua_tostring(L, -1), "tcp-res") == 0)
7111 tcp_res_cont_keywords_register(akl);
7112 else if (strcmp(lua_tostring(L, -1), "http-req") == 0)
7113 http_req_keywords_register(akl);
7114 else if (strcmp(lua_tostring(L, -1), "http-res") == 0)
7115 http_res_keywords_register(akl);
7116 else
7117 WILL_LJMP(luaL_error(L, "Lua action environment '%s' is unknown. "
7118 "'tcp-req', 'tcp-res', 'http-req' or 'http-res' "
7119 "are expected.", lua_tostring(L, -1)));
7120
7121 /* pop the environment string. */
7122 lua_pop(L, 1);
7123 }
7124 return ACT_RET_PRS_OK;
7125 }
7126
action_register_service_tcp(const char ** args,int * cur_arg,struct proxy * px,struct act_rule * rule,char ** err)7127 static enum act_parse_ret action_register_service_tcp(const char **args, int *cur_arg, struct proxy *px,
7128 struct act_rule *rule, char **err)
7129 {
7130 struct hlua_function *fcn = rule->kw->private;
7131
7132 if (px->mode == PR_MODE_HTTP) {
7133 memprintf(err, "Lua TCP services cannot be used on HTTP proxies");
7134 return ACT_RET_PRS_ERR;
7135 }
7136
7137 /* Memory for the rule. */
7138 rule->arg.hlua_rule = calloc(1, sizeof(*rule->arg.hlua_rule));
7139 if (!rule->arg.hlua_rule) {
7140 memprintf(err, "out of memory error");
7141 return ACT_RET_PRS_ERR;
7142 }
7143
7144 /* Reference the Lua function and store the reference. */
7145 rule->arg.hlua_rule->fcn = *fcn;
7146
7147 /* TODO: later accept arguments. */
7148 rule->arg.hlua_rule->args = NULL;
7149
7150 /* Add applet pointer in the rule. */
7151 rule->applet.obj_type = OBJ_TYPE_APPLET;
7152 rule->applet.name = fcn->name;
7153 rule->applet.init = hlua_applet_tcp_init;
7154 rule->applet.fct = hlua_applet_tcp_fct;
7155 rule->applet.release = hlua_applet_tcp_release;
7156 rule->applet.timeout = hlua_timeout_applet;
7157
7158 return 0;
7159 }
7160
7161 /* This function is an LUA binding used for registering
7162 * "sample-conv" functions. It expects a converter name used
7163 * in the haproxy configuration file, and an LUA function.
7164 */
hlua_register_service(lua_State * L)7165 __LJMP static int hlua_register_service(lua_State *L)
7166 {
7167 struct action_kw_list *akl;
7168 const char *name;
7169 const char *env;
7170 int ref;
7171 int len;
7172 struct hlua_function *fcn;
7173 struct buffer *trash;
7174 struct action_kw *akw;
7175
7176 MAY_LJMP(check_args(L, 3, "register_service"));
7177
7178 /* First argument : converter name. */
7179 name = MAY_LJMP(luaL_checkstring(L, 1));
7180
7181 /* Second argument : environment. */
7182 env = MAY_LJMP(luaL_checkstring(L, 2));
7183
7184 /* Third argument : lua function. */
7185 ref = MAY_LJMP(hlua_checkfunction(L, 3));
7186
7187 /* Check for service already registered */
7188 trash = get_trash_chunk();
7189 chunk_printf(trash, "lua.%s", name);
7190 akw = service_find(trash->area);
7191 if (akw != NULL) {
7192 ha_warning("Trying to register service 'lua.%s' more than once. "
7193 "This will become a hard error in version 2.5.\n", name);
7194 }
7195
7196 /* Allocate and fill the sample fetch keyword struct. */
7197 akl = calloc(1, sizeof(*akl) + sizeof(struct action_kw) * 2);
7198 if (!akl)
7199 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
7200 fcn = calloc(1, sizeof(*fcn));
7201 if (!fcn)
7202 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
7203
7204 /* Fill fcn. */
7205 len = strlen("<lua.>") + strlen(name) + 1;
7206 fcn->name = calloc(1, len);
7207 if (!fcn->name)
7208 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
7209 snprintf((char *)fcn->name, len, "<lua.%s>", name);
7210 fcn->function_ref = ref;
7211
7212 /* List head */
7213 akl->list.n = akl->list.p = NULL;
7214
7215 /* converter keyword. */
7216 len = strlen("lua.") + strlen(name) + 1;
7217 akl->kw[0].kw = calloc(1, len);
7218 if (!akl->kw[0].kw)
7219 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
7220
7221 snprintf((char *)akl->kw[0].kw, len, "lua.%s", name);
7222
7223 /* Check required environment. Only accepted "http" or "tcp". */
7224 if (strcmp(env, "tcp") == 0)
7225 akl->kw[0].parse = action_register_service_tcp;
7226 else if (strcmp(env, "http") == 0)
7227 akl->kw[0].parse = action_register_service_http;
7228 else
7229 WILL_LJMP(luaL_error(L, "Lua service environment '%s' is unknown. "
7230 "'tcp' or 'http' are expected.", env));
7231
7232 akl->kw[0].match_pfx = 0;
7233 akl->kw[0].private = fcn;
7234
7235 /* End of array. */
7236 memset(&akl->kw[1], 0, sizeof(*akl->kw));
7237
7238 /* Register this new converter */
7239 service_keywords_register(akl);
7240
7241 return 0;
7242 }
7243
7244 /* This function initialises Lua cli handler. It copies the
7245 * arguments in the Lua stack and create channel IO objects.
7246 */
hlua_cli_parse_fct(char ** args,char * payload,struct appctx * appctx,void * private)7247 static int hlua_cli_parse_fct(char **args, char *payload, struct appctx *appctx, void *private)
7248 {
7249 struct hlua *hlua;
7250 struct hlua_function *fcn;
7251 int i;
7252 const char *error;
7253
7254 fcn = private;
7255 appctx->ctx.hlua_cli.fcn = private;
7256
7257 hlua = pool_alloc(pool_head_hlua);
7258 if (!hlua) {
7259 SEND_ERR(NULL, "Lua cli '%s': out of memory.\n", fcn->name);
7260 return 1;
7261 }
7262 HLUA_INIT(hlua);
7263 appctx->ctx.hlua_cli.hlua = hlua;
7264
7265 /* Create task used by signal to wakeup applets.
7266 * We use the same wakeup fonction than the Lua applet_tcp and
7267 * applet_http. It is absolutely compatible.
7268 */
7269 appctx->ctx.hlua_cli.task = task_new(tid_bit);
7270 if (!appctx->ctx.hlua_cli.task) {
7271 SEND_ERR(NULL, "Lua cli '%s': out of memory.\n", fcn->name);
7272 goto error;
7273 }
7274 appctx->ctx.hlua_cli.task->nice = 0;
7275 appctx->ctx.hlua_cli.task->context = appctx;
7276 appctx->ctx.hlua_cli.task->process = hlua_applet_wakeup;
7277
7278 /* Initialises the Lua context */
7279 if (!hlua_ctx_init(hlua, appctx->ctx.hlua_cli.task, 0)) {
7280 SEND_ERR(NULL, "Lua cli '%s': can't initialize Lua context.\n", fcn->name);
7281 goto error;
7282 }
7283
7284 /* The following Lua calls can fail. */
7285 if (!SET_SAFE_LJMP(hlua->T)) {
7286 if (lua_type(hlua->T, -1) == LUA_TSTRING)
7287 error = lua_tostring(hlua->T, -1);
7288 else
7289 error = "critical error";
7290 SEND_ERR(NULL, "Lua cli '%s': %s.\n", fcn->name, error);
7291 goto error;
7292 }
7293
7294 /* Check stack available size. */
7295 if (!lua_checkstack(hlua->T, 2)) {
7296 SEND_ERR(NULL, "Lua cli '%s': full stack.\n", fcn->name);
7297 goto error;
7298 }
7299
7300 /* Restore the function in the stack. */
7301 lua_rawgeti(hlua->T, LUA_REGISTRYINDEX, fcn->function_ref);
7302
7303 /* Once the arguments parsed, the CLI is like an AppletTCP,
7304 * so push AppletTCP in the stack.
7305 */
7306 if (!hlua_applet_tcp_new(hlua->T, appctx)) {
7307 SEND_ERR(NULL, "Lua cli '%s': full stack.\n", fcn->name);
7308 goto error;
7309 }
7310 hlua->nargs = 1;
7311
7312 /* push keywords in the stack. */
7313 for (i = 0; *args[i]; i++) {
7314 /* Check stack available size. */
7315 if (!lua_checkstack(hlua->T, 1)) {
7316 SEND_ERR(NULL, "Lua cli '%s': full stack.\n", fcn->name);
7317 goto error;
7318 }
7319 lua_pushstring(hlua->T, args[i]);
7320 hlua->nargs++;
7321 }
7322
7323 /* We must initialize the execution timeouts. */
7324 hlua->max_time = hlua_timeout_session;
7325
7326 /* At this point the execution is safe. */
7327 RESET_SAFE_LJMP(hlua->T);
7328
7329 /* It's ok */
7330 return 0;
7331
7332 /* It's not ok. */
7333 error:
7334 RESET_SAFE_LJMP(hlua->T);
7335 hlua_ctx_destroy(hlua);
7336 appctx->ctx.hlua_cli.hlua = NULL;
7337 return 1;
7338 }
7339
hlua_cli_io_handler_fct(struct appctx * appctx)7340 static int hlua_cli_io_handler_fct(struct appctx *appctx)
7341 {
7342 struct hlua *hlua;
7343 struct stream_interface *si;
7344 struct hlua_function *fcn;
7345
7346 hlua = appctx->ctx.hlua_cli.hlua;
7347 si = appctx->owner;
7348 fcn = appctx->ctx.hlua_cli.fcn;
7349
7350 /* If the stream is disconnect or closed, ldo nothing. */
7351 if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO))
7352 return 1;
7353
7354 /* Execute the function. */
7355 switch (hlua_ctx_resume(hlua, 1)) {
7356
7357 /* finished. */
7358 case HLUA_E_OK:
7359 return 1;
7360
7361 /* yield. */
7362 case HLUA_E_AGAIN:
7363 /* We want write. */
7364 if (HLUA_IS_WAKERESWR(hlua))
7365 si_rx_room_blk(si);
7366 /* Set the timeout. */
7367 if (hlua->wake_time != TICK_ETERNITY)
7368 task_schedule(hlua->task, hlua->wake_time);
7369 return 0;
7370
7371 /* finished with error. */
7372 case HLUA_E_ERRMSG:
7373 /* Display log. */
7374 SEND_ERR(NULL, "Lua cli '%s': %s.\n",
7375 fcn->name, lua_tostring(hlua->T, -1));
7376 lua_pop(hlua->T, 1);
7377 return 1;
7378
7379 case HLUA_E_ETMOUT:
7380 SEND_ERR(NULL, "Lua converter '%s': execution timeout.\n",
7381 fcn->name);
7382 return 1;
7383
7384 case HLUA_E_NOMEM:
7385 SEND_ERR(NULL, "Lua converter '%s': out of memory error.\n",
7386 fcn->name);
7387 return 1;
7388
7389 case HLUA_E_YIELD: /* unexpected */
7390 SEND_ERR(NULL, "Lua converter '%s': yield not allowed.\n",
7391 fcn->name);
7392 return 1;
7393
7394 case HLUA_E_ERR:
7395 /* Display log. */
7396 SEND_ERR(NULL, "Lua cli '%s' return an unknown error.\n",
7397 fcn->name);
7398 return 1;
7399
7400 default:
7401 return 1;
7402 }
7403
7404 return 1;
7405 }
7406
hlua_cli_io_release_fct(struct appctx * appctx)7407 static void hlua_cli_io_release_fct(struct appctx *appctx)
7408 {
7409 hlua_ctx_destroy(appctx->ctx.hlua_cli.hlua);
7410 appctx->ctx.hlua_cli.hlua = NULL;
7411 }
7412
7413 /* This function is an LUA binding used for registering
7414 * new keywords in the cli. It expects a list of keywords
7415 * which are the "path". It is limited to 5 keywords. A
7416 * description of the command, a function to be executed
7417 * for the parsing and a function for io handlers.
7418 */
hlua_register_cli(lua_State * L)7419 __LJMP static int hlua_register_cli(lua_State *L)
7420 {
7421 struct cli_kw_list *cli_kws;
7422 const char *message;
7423 int ref_io;
7424 int len;
7425 struct hlua_function *fcn;
7426 int index;
7427 int i;
7428 struct buffer *trash;
7429 const char *kw[5];
7430 struct cli_kw *cli_kw;
7431
7432 MAY_LJMP(check_args(L, 3, "register_cli"));
7433
7434 /* First argument : an array of maximum 5 keywords. */
7435 if (!lua_istable(L, 1))
7436 WILL_LJMP(luaL_argerror(L, 1, "1st argument must be a table"));
7437
7438 /* Second argument : string with contextual message. */
7439 message = MAY_LJMP(luaL_checkstring(L, 2));
7440
7441 /* Third and fourth argument : lua function. */
7442 ref_io = MAY_LJMP(hlua_checkfunction(L, 3));
7443
7444 /* Check for CLI service already registered */
7445 trash = get_trash_chunk();
7446 index = 0;
7447 lua_pushnil(L);
7448 memset(kw, 0, sizeof(kw));
7449 while (lua_next(L, 1) != 0) {
7450 if (index >= CLI_PREFIX_KW_NB)
7451 WILL_LJMP(luaL_argerror(L, 1, "1st argument must be a table with a maximum of 5 entries"));
7452 if (lua_type(L, -1) != LUA_TSTRING)
7453 WILL_LJMP(luaL_argerror(L, 1, "1st argument must be a table filled with strings"));
7454 kw[index] = lua_tostring(L, -1);
7455 if (index == 0)
7456 chunk_printf(trash, "%s", kw[index]);
7457 else
7458 chunk_appendf(trash, " %s", kw[index]);
7459 index++;
7460 lua_pop(L, 1);
7461 }
7462 cli_kw = cli_find_kw_exact((char **)kw);
7463 if (cli_kw != NULL) {
7464 ha_warning("Trying to register CLI keyword 'lua.%s' more than once. "
7465 "This will become a hard error in version 2.5.\n", trash->area);
7466 }
7467
7468 /* Allocate and fill the sample fetch keyword struct. */
7469 cli_kws = calloc(1, sizeof(*cli_kws) + sizeof(struct cli_kw) * 2);
7470 if (!cli_kws)
7471 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
7472 fcn = calloc(1, sizeof(*fcn));
7473 if (!fcn)
7474 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
7475
7476 /* Fill path. */
7477 index = 0;
7478 lua_pushnil(L);
7479 while(lua_next(L, 1) != 0) {
7480 if (index >= 5)
7481 WILL_LJMP(luaL_argerror(L, 1, "1st argument must be a table with a maximum of 5 entries"));
7482 if (lua_type(L, -1) != LUA_TSTRING)
7483 WILL_LJMP(luaL_argerror(L, 1, "1st argument must be a table filled with strings"));
7484 cli_kws->kw[0].str_kw[index] = strdup(lua_tostring(L, -1));
7485 if (!cli_kws->kw[0].str_kw[index])
7486 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
7487 index++;
7488 lua_pop(L, 1);
7489 }
7490
7491 /* Copy help message. */
7492 cli_kws->kw[0].usage = strdup(message);
7493 if (!cli_kws->kw[0].usage)
7494 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
7495
7496 /* Fill fcn io handler. */
7497 len = strlen("<lua.cli>") + 1;
7498 for (i = 0; i < index; i++)
7499 len += strlen(cli_kws->kw[0].str_kw[i]) + 1;
7500 fcn->name = calloc(1, len);
7501 if (!fcn->name)
7502 WILL_LJMP(luaL_error(L, "Lua out of memory error."));
7503 strncat((char *)fcn->name, "<lua.cli", len);
7504 for (i = 0; i < index; i++) {
7505 strncat((char *)fcn->name, ".", len);
7506 strncat((char *)fcn->name, cli_kws->kw[0].str_kw[i], len);
7507 }
7508 strncat((char *)fcn->name, ">", len);
7509 fcn->function_ref = ref_io;
7510
7511 /* Fill last entries. */
7512 cli_kws->kw[0].private = fcn;
7513 cli_kws->kw[0].parse = hlua_cli_parse_fct;
7514 cli_kws->kw[0].io_handler = hlua_cli_io_handler_fct;
7515 cli_kws->kw[0].io_release = hlua_cli_io_release_fct;
7516
7517 /* Register this new converter */
7518 cli_register_kw(cli_kws);
7519
7520 return 0;
7521 }
7522
hlua_read_timeout(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err,unsigned int * timeout)7523 static int hlua_read_timeout(char **args, int section_type, struct proxy *curpx,
7524 struct proxy *defpx, const char *file, int line,
7525 char **err, unsigned int *timeout)
7526 {
7527 const char *error;
7528
7529 error = parse_time_err(args[1], timeout, TIME_UNIT_MS);
7530 if (error == PARSE_TIME_OVER) {
7531 memprintf(err, "timer overflow in argument <%s> to <%s> (maximum value is 2147483647 ms or ~24.8 days)",
7532 args[1], args[0]);
7533 return -1;
7534 }
7535 else if (error == PARSE_TIME_UNDER) {
7536 memprintf(err, "timer underflow in argument <%s> to <%s> (minimum non-null value is 1 ms)",
7537 args[1], args[0]);
7538 return -1;
7539 }
7540 else if (error) {
7541 memprintf(err, "%s: invalid timeout", args[0]);
7542 return -1;
7543 }
7544 return 0;
7545 }
7546
hlua_session_timeout(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)7547 static int hlua_session_timeout(char **args, int section_type, struct proxy *curpx,
7548 struct proxy *defpx, const char *file, int line,
7549 char **err)
7550 {
7551 return hlua_read_timeout(args, section_type, curpx, defpx,
7552 file, line, err, &hlua_timeout_session);
7553 }
7554
hlua_task_timeout(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)7555 static int hlua_task_timeout(char **args, int section_type, struct proxy *curpx,
7556 struct proxy *defpx, const char *file, int line,
7557 char **err)
7558 {
7559 return hlua_read_timeout(args, section_type, curpx, defpx,
7560 file, line, err, &hlua_timeout_task);
7561 }
7562
hlua_applet_timeout(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)7563 static int hlua_applet_timeout(char **args, int section_type, struct proxy *curpx,
7564 struct proxy *defpx, const char *file, int line,
7565 char **err)
7566 {
7567 return hlua_read_timeout(args, section_type, curpx, defpx,
7568 file, line, err, &hlua_timeout_applet);
7569 }
7570
hlua_forced_yield(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)7571 static int hlua_forced_yield(char **args, int section_type, struct proxy *curpx,
7572 struct proxy *defpx, const char *file, int line,
7573 char **err)
7574 {
7575 char *error;
7576
7577 hlua_nb_instruction = strtoll(args[1], &error, 10);
7578 if (*error != '\0') {
7579 memprintf(err, "%s: invalid number", args[0]);
7580 return -1;
7581 }
7582 return 0;
7583 }
7584
hlua_parse_maxmem(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)7585 static int hlua_parse_maxmem(char **args, int section_type, struct proxy *curpx,
7586 struct proxy *defpx, const char *file, int line,
7587 char **err)
7588 {
7589 char *error;
7590
7591 if (*(args[1]) == 0) {
7592 memprintf(err, "'%s' expects an integer argument (Lua memory size in MB).\n", args[0]);
7593 return -1;
7594 }
7595 hlua_global_allocator.limit = strtoll(args[1], &error, 10) * 1024L * 1024L;
7596 if (*error != '\0') {
7597 memprintf(err, "%s: invalid number %s (error at '%c')", args[0], args[1], *error);
7598 return -1;
7599 }
7600 return 0;
7601 }
7602
7603
7604 /* This function is called by the main configuration key "lua-load". It loads and
7605 * execute an lua file during the parsing of the HAProxy configuration file. It is
7606 * the main lua entry point.
7607 *
7608 * This function runs with the HAProxy keywords API. It returns -1 if an error
7609 * occurs, otherwise it returns 0.
7610 *
7611 * In some error case, LUA set an error message in top of the stack. This function
7612 * returns this error message in the HAProxy logs and pop it from the stack.
7613 *
7614 * This function can fail with an abort() due to an Lua critical error.
7615 * We are in the configuration parsing process of HAProxy, this abort() is
7616 * tolerated.
7617 */
hlua_load(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)7618 static int hlua_load(char **args, int section_type, struct proxy *curpx,
7619 struct proxy *defpx, const char *file, int line,
7620 char **err)
7621 {
7622 int error;
7623
7624 if (*(args[1]) == 0) {
7625 memprintf(err, "'%s' expects a file name as parameter.\n", args[0]);
7626 return -1;
7627 }
7628
7629 /* Just load and compile the file. */
7630 error = luaL_loadfile(gL.T, args[1]);
7631 if (error) {
7632 memprintf(err, "error in Lua file '%s': %s", args[1], lua_tostring(gL.T, -1));
7633 lua_pop(gL.T, 1);
7634 return -1;
7635 }
7636
7637 /* If no syntax error where detected, execute the code. */
7638 error = lua_pcall(gL.T, 0, LUA_MULTRET, 0);
7639 switch (error) {
7640 case LUA_OK:
7641 break;
7642 case LUA_ERRRUN:
7643 memprintf(err, "Lua runtime error: %s\n", lua_tostring(gL.T, -1));
7644 lua_pop(gL.T, 1);
7645 return -1;
7646 case LUA_ERRMEM:
7647 memprintf(err, "Lua out of memory error\n");
7648 return -1;
7649 case LUA_ERRERR:
7650 memprintf(err, "Lua message handler error: %s\n", lua_tostring(gL.T, -1));
7651 lua_pop(gL.T, 1);
7652 return -1;
7653 #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 503
7654 case LUA_ERRGCMM:
7655 memprintf(err, "Lua garbage collector error: %s\n", lua_tostring(gL.T, -1));
7656 lua_pop(gL.T, 1);
7657 return -1;
7658 #endif
7659 default:
7660 memprintf(err, "Lua unknonwn error: %s\n", lua_tostring(gL.T, -1));
7661 lua_pop(gL.T, 1);
7662 return -1;
7663 }
7664
7665 return 0;
7666 }
7667
7668 /* Prepend the given <path> followed by a semicolon to the `package.<type>` variable
7669 * in the given <ctx>.
7670 */
hlua_prepend_path(struct hlua ctx,char * type,char * path)7671 static int hlua_prepend_path(struct hlua ctx, char *type, char *path)
7672 {
7673 lua_getglobal(ctx.T, "package"); /* push package variable */
7674 lua_pushstring(ctx.T, path); /* push given path */
7675 lua_pushstring(ctx.T, ";"); /* push semicolon */
7676 lua_getfield(ctx.T, -3, type); /* push old path */
7677 lua_concat(ctx.T, 3); /* concatenate to new path */
7678 lua_setfield(ctx.T, -2, type); /* store new path */
7679 lua_pop(ctx.T, 1); /* pop package variable */
7680
7681 return 0;
7682 }
7683
hlua_config_prepend_path(char ** args,int section_type,struct proxy * curpx,struct proxy * defpx,const char * file,int line,char ** err)7684 static int hlua_config_prepend_path(char **args, int section_type, struct proxy *curpx,
7685 struct proxy *defpx, const char *file, int line,
7686 char **err)
7687 {
7688 char *path;
7689 char *type = "path";
7690 if (too_many_args(2, args, err, NULL)) {
7691 return -1;
7692 }
7693
7694 if (!(*args[1])) {
7695 memprintf(err, "'%s' expects to receive a <path> as argument", args[0]);
7696 return -1;
7697 }
7698 path = args[1];
7699
7700 if (*args[2]) {
7701 if (strcmp(args[2], "path") != 0 && strcmp(args[2], "cpath") != 0) {
7702 memprintf(err, "'%s' expects <type> to either be 'path' or 'cpath'", args[0]);
7703 return -1;
7704 }
7705 type = args[2];
7706 }
7707
7708 return hlua_prepend_path(gL, type, path);
7709 }
7710
7711 /* configuration keywords declaration */
7712 static struct cfg_kw_list cfg_kws = {{ },{
7713 { CFG_GLOBAL, "lua-prepend-path", hlua_config_prepend_path },
7714 { CFG_GLOBAL, "lua-load", hlua_load },
7715 { CFG_GLOBAL, "tune.lua.session-timeout", hlua_session_timeout },
7716 { CFG_GLOBAL, "tune.lua.task-timeout", hlua_task_timeout },
7717 { CFG_GLOBAL, "tune.lua.service-timeout", hlua_applet_timeout },
7718 { CFG_GLOBAL, "tune.lua.forced-yield", hlua_forced_yield },
7719 { CFG_GLOBAL, "tune.lua.maxmem", hlua_parse_maxmem },
7720 { 0, NULL, NULL },
7721 }};
7722
7723 INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
7724
7725
7726 /* This function can fail with an abort() due to an Lua critical error.
7727 * We are in the initialisation process of HAProxy, this abort() is
7728 * tolerated.
7729 */
hlua_post_init()7730 int hlua_post_init()
7731 {
7732 struct hlua_init_function *init;
7733 const char *msg;
7734 enum hlua_exec ret;
7735 const char *error;
7736
7737 /* Call post initialisation function in safe environement. */
7738 if (!SET_SAFE_LJMP(gL.T)) {
7739 if (lua_type(gL.T, -1) == LUA_TSTRING)
7740 error = lua_tostring(gL.T, -1);
7741 else
7742 error = "critical error";
7743 fprintf(stderr, "Lua post-init: %s.\n", error);
7744 exit(1);
7745 }
7746
7747 #if USE_OPENSSL
7748 /* Initialize SSL server. */
7749 if (socket_ssl.xprt->prepare_srv) {
7750 int saved_used_backed = global.ssl_used_backend;
7751 // don't affect maxconn automatic computation
7752 socket_ssl.xprt->prepare_srv(&socket_ssl);
7753 global.ssl_used_backend = saved_used_backed;
7754 }
7755 #endif
7756
7757 hlua_fcn_post_init(gL.T);
7758 RESET_SAFE_LJMP(gL.T);
7759
7760 list_for_each_entry(init, &hlua_init_functions, l) {
7761 lua_rawgeti(gL.T, LUA_REGISTRYINDEX, init->function_ref);
7762 ret = hlua_ctx_resume(&gL, 0);
7763 switch (ret) {
7764 case HLUA_E_OK:
7765 lua_pop(gL.T, -1);
7766 break;
7767 case HLUA_E_AGAIN:
7768 ha_alert("Lua init: yield not allowed.\n");
7769 return 0;
7770 case HLUA_E_ERRMSG:
7771 msg = lua_tostring(gL.T, -1);
7772 ha_alert("lua init: %s.\n", msg);
7773 return 0;
7774 case HLUA_E_ERR:
7775 default:
7776 ha_alert("Lua init: unknown runtime error.\n");
7777 return 0;
7778 }
7779 }
7780 return 1;
7781 }
7782
7783 /* The memory allocator used by the Lua stack. <ud> is a pointer to the
7784 * allocator's context. <ptr> is the pointer to alloc/free/realloc. <osize>
7785 * is the previously allocated size or the kind of object in case of a new
7786 * allocation. <nsize> is the requested new size.
7787 */
hlua_alloc(void * ud,void * ptr,size_t osize,size_t nsize)7788 static void *hlua_alloc(void *ud, void *ptr, size_t osize, size_t nsize)
7789 {
7790 struct hlua_mem_allocator *zone = ud;
7791
7792 if (nsize == 0) {
7793 /* it's a free */
7794 if (ptr)
7795 zone->allocated -= osize;
7796 free(ptr);
7797 return NULL;
7798 }
7799
7800 if (!ptr) {
7801 /* it's a new allocation */
7802 if (zone->limit && zone->allocated + nsize > zone->limit)
7803 return NULL;
7804
7805 ptr = malloc(nsize);
7806 if (ptr)
7807 zone->allocated += nsize;
7808 return ptr;
7809 }
7810
7811 /* it's a realloc */
7812 if (zone->limit && zone->allocated + nsize - osize > zone->limit)
7813 return NULL;
7814
7815 ptr = realloc(ptr, nsize);
7816 if (ptr)
7817 zone->allocated += nsize - osize;
7818 return ptr;
7819 }
7820
7821 /* Ithis function can fail with an abort() due to an Lua critical error.
7822 * We are in the initialisation process of HAProxy, this abort() is
7823 * tolerated.
7824 */
hlua_init(void)7825 void hlua_init(void)
7826 {
7827 int i;
7828 int idx;
7829 struct sample_fetch *sf;
7830 struct sample_conv *sc;
7831 char *p;
7832 const char *error_msg;
7833 #ifdef USE_OPENSSL
7834 struct srv_kw *kw;
7835 int tmp_error;
7836 char *error;
7837 char *args[] = { /* SSL client configuration. */
7838 "ssl",
7839 "verify",
7840 "none",
7841 NULL
7842 };
7843 #endif
7844
7845 /* Init main lua stack. */
7846 gL.Mref = LUA_REFNIL;
7847 gL.flags = 0;
7848 LIST_INIT(&gL.com);
7849 gL.T = lua_newstate(hlua_alloc, &hlua_global_allocator);
7850 hlua_sethlua(&gL);
7851 gL.Tref = LUA_REFNIL;
7852 gL.task = NULL;
7853
7854 /* From this point, until the end of the initialisation function,
7855 * the Lua function can fail with an abort. We are in the initialisation
7856 * process of HAProxy, this abort() is tolerated.
7857 */
7858
7859 /* Set safe environment for the initialisation. */
7860 if (!SET_SAFE_LJMP(gL.T)) {
7861 if (lua_type(gL.T, -1) == LUA_TSTRING)
7862 error_msg = lua_tostring(gL.T, -1);
7863 else
7864 error_msg = "critical error";
7865 fprintf(stderr, "Lua init: %s.\n", error_msg);
7866 exit(1);
7867 }
7868
7869 /* Initialise lua. */
7870 luaL_openlibs(gL.T);
7871 #define HLUA_PREPEND_PATH_TOSTRING1(x) #x
7872 #define HLUA_PREPEND_PATH_TOSTRING(x) HLUA_PREPEND_PATH_TOSTRING1(x)
7873 #ifdef HLUA_PREPEND_PATH
7874 hlua_prepend_path(gL, "path", HLUA_PREPEND_PATH_TOSTRING(HLUA_PREPEND_PATH));
7875 #endif
7876 #ifdef HLUA_PREPEND_CPATH
7877 hlua_prepend_path(gL, "cpath", HLUA_PREPEND_PATH_TOSTRING(HLUA_PREPEND_CPATH));
7878 #endif
7879 #undef HLUA_PREPEND_PATH_TOSTRING
7880 #undef HLUA_PREPEND_PATH_TOSTRING1
7881
7882 /*
7883 *
7884 * Create "core" object.
7885 *
7886 */
7887
7888 /* This table entry is the object "core" base. */
7889 lua_newtable(gL.T);
7890
7891 /* Push the loglevel constants. */
7892 for (i = 0; i < NB_LOG_LEVELS; i++)
7893 hlua_class_const_int(gL.T, log_levels[i], i);
7894
7895 /* Register special functions. */
7896 hlua_class_function(gL.T, "register_init", hlua_register_init);
7897 hlua_class_function(gL.T, "register_task", hlua_register_task);
7898 hlua_class_function(gL.T, "register_fetches", hlua_register_fetches);
7899 hlua_class_function(gL.T, "register_converters", hlua_register_converters);
7900 hlua_class_function(gL.T, "register_action", hlua_register_action);
7901 hlua_class_function(gL.T, "register_service", hlua_register_service);
7902 hlua_class_function(gL.T, "register_cli", hlua_register_cli);
7903 hlua_class_function(gL.T, "yield", hlua_yield);
7904 hlua_class_function(gL.T, "set_nice", hlua_set_nice);
7905 hlua_class_function(gL.T, "sleep", hlua_sleep);
7906 hlua_class_function(gL.T, "msleep", hlua_msleep);
7907 hlua_class_function(gL.T, "add_acl", hlua_add_acl);
7908 hlua_class_function(gL.T, "del_acl", hlua_del_acl);
7909 hlua_class_function(gL.T, "set_map", hlua_set_map);
7910 hlua_class_function(gL.T, "del_map", hlua_del_map);
7911 hlua_class_function(gL.T, "tcp", hlua_socket_new);
7912 hlua_class_function(gL.T, "log", hlua_log);
7913 hlua_class_function(gL.T, "Debug", hlua_log_debug);
7914 hlua_class_function(gL.T, "Info", hlua_log_info);
7915 hlua_class_function(gL.T, "Warning", hlua_log_warning);
7916 hlua_class_function(gL.T, "Alert", hlua_log_alert);
7917 hlua_class_function(gL.T, "done", hlua_done);
7918 hlua_fcn_reg_core_fcn(gL.T);
7919
7920 lua_setglobal(gL.T, "core");
7921
7922 /*
7923 *
7924 * Register class Map
7925 *
7926 */
7927
7928 /* This table entry is the object "Map" base. */
7929 lua_newtable(gL.T);
7930
7931 /* register pattern types. */
7932 for (i=0; i<PAT_MATCH_NUM; i++)
7933 hlua_class_const_int(gL.T, pat_match_names[i], i);
7934 for (i=0; i<PAT_MATCH_NUM; i++) {
7935 snprintf(trash.area, trash.size, "_%s", pat_match_names[i]);
7936 hlua_class_const_int(gL.T, trash.area, i);
7937 }
7938
7939 /* register constructor. */
7940 hlua_class_function(gL.T, "new", hlua_map_new);
7941
7942 /* Create and fill the metatable. */
7943 lua_newtable(gL.T);
7944
7945 /* Create and fille the __index entry. */
7946 lua_pushstring(gL.T, "__index");
7947 lua_newtable(gL.T);
7948
7949 /* Register . */
7950 hlua_class_function(gL.T, "lookup", hlua_map_lookup);
7951 hlua_class_function(gL.T, "slookup", hlua_map_slookup);
7952
7953 lua_rawset(gL.T, -3);
7954
7955 /* Register previous table in the registry with reference and named entry.
7956 * The function hlua_register_metatable() pops the stack, so we
7957 * previously create a copy of the table.
7958 */
7959 lua_pushvalue(gL.T, -1); /* Copy the -1 entry and push it on the stack. */
7960 class_map_ref = hlua_register_metatable(gL.T, CLASS_MAP);
7961
7962 /* Assign the metatable to the mai Map object. */
7963 lua_setmetatable(gL.T, -2);
7964
7965 /* Set a name to the table. */
7966 lua_setglobal(gL.T, "Map");
7967
7968 /*
7969 *
7970 * Register class Channel
7971 *
7972 */
7973
7974 /* Create and fill the metatable. */
7975 lua_newtable(gL.T);
7976
7977 /* Create and fille the __index entry. */
7978 lua_pushstring(gL.T, "__index");
7979 lua_newtable(gL.T);
7980
7981 /* Register . */
7982 hlua_class_function(gL.T, "get", hlua_channel_get);
7983 hlua_class_function(gL.T, "dup", hlua_channel_dup);
7984 hlua_class_function(gL.T, "getline", hlua_channel_getline);
7985 hlua_class_function(gL.T, "set", hlua_channel_set);
7986 hlua_class_function(gL.T, "append", hlua_channel_append);
7987 hlua_class_function(gL.T, "send", hlua_channel_send);
7988 hlua_class_function(gL.T, "forward", hlua_channel_forward);
7989 hlua_class_function(gL.T, "get_in_len", hlua_channel_get_in_len);
7990 hlua_class_function(gL.T, "get_out_len", hlua_channel_get_out_len);
7991 hlua_class_function(gL.T, "is_full", hlua_channel_is_full);
7992
7993 lua_rawset(gL.T, -3);
7994
7995 /* Register previous table in the registry with reference and named entry. */
7996 class_channel_ref = hlua_register_metatable(gL.T, CLASS_CHANNEL);
7997
7998 /*
7999 *
8000 * Register class Fetches
8001 *
8002 */
8003
8004 /* Create and fill the metatable. */
8005 lua_newtable(gL.T);
8006
8007 /* Create and fille the __index entry. */
8008 lua_pushstring(gL.T, "__index");
8009 lua_newtable(gL.T);
8010
8011 /* Browse existing fetches and create the associated
8012 * object method.
8013 */
8014 sf = NULL;
8015 while ((sf = sample_fetch_getnext(sf, &idx)) != NULL) {
8016 /* gL.Tua doesn't support '.' and '-' in the function names, replace it
8017 * by an underscore.
8018 */
8019 strncpy(trash.area, sf->kw, trash.size);
8020 trash.area[trash.size - 1] = '\0';
8021 for (p = trash.area; *p; p++)
8022 if (*p == '.' || *p == '-' || *p == '+')
8023 *p = '_';
8024
8025 /* Register the function. */
8026 lua_pushstring(gL.T, trash.area);
8027 lua_pushlightuserdata(gL.T, sf);
8028 lua_pushcclosure(gL.T, hlua_run_sample_fetch, 1);
8029 lua_rawset(gL.T, -3);
8030 }
8031
8032 lua_rawset(gL.T, -3);
8033
8034 /* Register previous table in the registry with reference and named entry. */
8035 class_fetches_ref = hlua_register_metatable(gL.T, CLASS_FETCHES);
8036
8037 /*
8038 *
8039 * Register class Converters
8040 *
8041 */
8042
8043 /* Create and fill the metatable. */
8044 lua_newtable(gL.T);
8045
8046 /* Create and fill the __index entry. */
8047 lua_pushstring(gL.T, "__index");
8048 lua_newtable(gL.T);
8049
8050 /* Browse existing converters and create the associated
8051 * object method.
8052 */
8053 sc = NULL;
8054 while ((sc = sample_conv_getnext(sc, &idx)) != NULL) {
8055 /* gL.Tua doesn't support '.' and '-' in the function names, replace it
8056 * by an underscore.
8057 */
8058 strncpy(trash.area, sc->kw, trash.size);
8059 trash.area[trash.size - 1] = '\0';
8060 for (p = trash.area; *p; p++)
8061 if (*p == '.' || *p == '-' || *p == '+')
8062 *p = '_';
8063
8064 /* Register the function. */
8065 lua_pushstring(gL.T, trash.area);
8066 lua_pushlightuserdata(gL.T, sc);
8067 lua_pushcclosure(gL.T, hlua_run_sample_conv, 1);
8068 lua_rawset(gL.T, -3);
8069 }
8070
8071 lua_rawset(gL.T, -3);
8072
8073 /* Register previous table in the registry with reference and named entry. */
8074 class_converters_ref = hlua_register_metatable(gL.T, CLASS_CONVERTERS);
8075
8076 /*
8077 *
8078 * Register class HTTP
8079 *
8080 */
8081
8082 /* Create and fill the metatable. */
8083 lua_newtable(gL.T);
8084
8085 /* Create and fille the __index entry. */
8086 lua_pushstring(gL.T, "__index");
8087 lua_newtable(gL.T);
8088
8089 /* Register Lua functions. */
8090 hlua_class_function(gL.T, "req_get_headers",hlua_http_req_get_headers);
8091 hlua_class_function(gL.T, "req_del_header", hlua_http_req_del_hdr);
8092 hlua_class_function(gL.T, "req_rep_header", hlua_http_req_rep_hdr);
8093 hlua_class_function(gL.T, "req_rep_value", hlua_http_req_rep_val);
8094 hlua_class_function(gL.T, "req_add_header", hlua_http_req_add_hdr);
8095 hlua_class_function(gL.T, "req_set_header", hlua_http_req_set_hdr);
8096 hlua_class_function(gL.T, "req_set_method", hlua_http_req_set_meth);
8097 hlua_class_function(gL.T, "req_set_path", hlua_http_req_set_path);
8098 hlua_class_function(gL.T, "req_set_query", hlua_http_req_set_query);
8099 hlua_class_function(gL.T, "req_set_uri", hlua_http_req_set_uri);
8100
8101 hlua_class_function(gL.T, "res_get_headers",hlua_http_res_get_headers);
8102 hlua_class_function(gL.T, "res_del_header", hlua_http_res_del_hdr);
8103 hlua_class_function(gL.T, "res_rep_header", hlua_http_res_rep_hdr);
8104 hlua_class_function(gL.T, "res_rep_value", hlua_http_res_rep_val);
8105 hlua_class_function(gL.T, "res_add_header", hlua_http_res_add_hdr);
8106 hlua_class_function(gL.T, "res_set_header", hlua_http_res_set_hdr);
8107 hlua_class_function(gL.T, "res_set_status", hlua_http_res_set_status);
8108
8109 lua_rawset(gL.T, -3);
8110
8111 /* Register previous table in the registry with reference and named entry. */
8112 class_http_ref = hlua_register_metatable(gL.T, CLASS_HTTP);
8113
8114 /*
8115 *
8116 * Register class AppletTCP
8117 *
8118 */
8119
8120 /* Create and fill the metatable. */
8121 lua_newtable(gL.T);
8122
8123 /* Create and fille the __index entry. */
8124 lua_pushstring(gL.T, "__index");
8125 lua_newtable(gL.T);
8126
8127 /* Register Lua functions. */
8128 hlua_class_function(gL.T, "getline", hlua_applet_tcp_getline);
8129 hlua_class_function(gL.T, "receive", hlua_applet_tcp_recv);
8130 hlua_class_function(gL.T, "send", hlua_applet_tcp_send);
8131 hlua_class_function(gL.T, "set_priv", hlua_applet_tcp_set_priv);
8132 hlua_class_function(gL.T, "get_priv", hlua_applet_tcp_get_priv);
8133 hlua_class_function(gL.T, "set_var", hlua_applet_tcp_set_var);
8134 hlua_class_function(gL.T, "unset_var", hlua_applet_tcp_unset_var);
8135 hlua_class_function(gL.T, "get_var", hlua_applet_tcp_get_var);
8136
8137 lua_settable(gL.T, -3);
8138
8139 /* Register previous table in the registry with reference and named entry. */
8140 class_applet_tcp_ref = hlua_register_metatable(gL.T, CLASS_APPLET_TCP);
8141
8142 /*
8143 *
8144 * Register class AppletHTTP
8145 *
8146 */
8147
8148 /* Create and fill the metatable. */
8149 lua_newtable(gL.T);
8150
8151 /* Create and fille the __index entry. */
8152 lua_pushstring(gL.T, "__index");
8153 lua_newtable(gL.T);
8154
8155 /* Register Lua functions. */
8156 hlua_class_function(gL.T, "set_priv", hlua_applet_http_set_priv);
8157 hlua_class_function(gL.T, "get_priv", hlua_applet_http_get_priv);
8158 hlua_class_function(gL.T, "set_var", hlua_applet_http_set_var);
8159 hlua_class_function(gL.T, "unset_var", hlua_applet_http_unset_var);
8160 hlua_class_function(gL.T, "get_var", hlua_applet_http_get_var);
8161 hlua_class_function(gL.T, "getline", hlua_applet_http_getline);
8162 hlua_class_function(gL.T, "receive", hlua_applet_http_recv);
8163 hlua_class_function(gL.T, "send", hlua_applet_http_send);
8164 hlua_class_function(gL.T, "add_header", hlua_applet_http_addheader);
8165 hlua_class_function(gL.T, "set_status", hlua_applet_http_status);
8166 hlua_class_function(gL.T, "start_response", hlua_applet_http_start_response);
8167
8168 lua_settable(gL.T, -3);
8169
8170 /* Register previous table in the registry with reference and named entry. */
8171 class_applet_http_ref = hlua_register_metatable(gL.T, CLASS_APPLET_HTTP);
8172
8173 /*
8174 *
8175 * Register class TXN
8176 *
8177 */
8178
8179 /* Create and fill the metatable. */
8180 lua_newtable(gL.T);
8181
8182 /* Create and fille the __index entry. */
8183 lua_pushstring(gL.T, "__index");
8184 lua_newtable(gL.T);
8185
8186 /* Register Lua functions. */
8187 hlua_class_function(gL.T, "set_priv", hlua_set_priv);
8188 hlua_class_function(gL.T, "get_priv", hlua_get_priv);
8189 hlua_class_function(gL.T, "set_var", hlua_set_var);
8190 hlua_class_function(gL.T, "unset_var", hlua_unset_var);
8191 hlua_class_function(gL.T, "get_var", hlua_get_var);
8192 hlua_class_function(gL.T, "done", hlua_txn_done);
8193 hlua_class_function(gL.T, "set_loglevel", hlua_txn_set_loglevel);
8194 hlua_class_function(gL.T, "set_tos", hlua_txn_set_tos);
8195 hlua_class_function(gL.T, "set_mark", hlua_txn_set_mark);
8196 hlua_class_function(gL.T, "set_priority_class", hlua_txn_set_priority_class);
8197 hlua_class_function(gL.T, "set_priority_offset", hlua_txn_set_priority_offset);
8198 hlua_class_function(gL.T, "deflog", hlua_txn_deflog);
8199 hlua_class_function(gL.T, "log", hlua_txn_log);
8200 hlua_class_function(gL.T, "Debug", hlua_txn_log_debug);
8201 hlua_class_function(gL.T, "Info", hlua_txn_log_info);
8202 hlua_class_function(gL.T, "Warning", hlua_txn_log_warning);
8203 hlua_class_function(gL.T, "Alert", hlua_txn_log_alert);
8204
8205 lua_rawset(gL.T, -3);
8206
8207 /* Register previous table in the registry with reference and named entry. */
8208 class_txn_ref = hlua_register_metatable(gL.T, CLASS_TXN);
8209
8210 /*
8211 *
8212 * Register class Socket
8213 *
8214 */
8215
8216 /* Create and fill the metatable. */
8217 lua_newtable(gL.T);
8218
8219 /* Create and fille the __index entry. */
8220 lua_pushstring(gL.T, "__index");
8221 lua_newtable(gL.T);
8222
8223 #ifdef USE_OPENSSL
8224 hlua_class_function(gL.T, "connect_ssl", hlua_socket_connect_ssl);
8225 #endif
8226 hlua_class_function(gL.T, "connect", hlua_socket_connect);
8227 hlua_class_function(gL.T, "send", hlua_socket_send);
8228 hlua_class_function(gL.T, "receive", hlua_socket_receive);
8229 hlua_class_function(gL.T, "close", hlua_socket_close);
8230 hlua_class_function(gL.T, "getpeername", hlua_socket_getpeername);
8231 hlua_class_function(gL.T, "getsockname", hlua_socket_getsockname);
8232 hlua_class_function(gL.T, "setoption", hlua_socket_setoption);
8233 hlua_class_function(gL.T, "settimeout", hlua_socket_settimeout);
8234
8235 lua_rawset(gL.T, -3); /* Push the last 2 entries in the table at index -3 */
8236
8237 /* Register the garbage collector entry. */
8238 lua_pushstring(gL.T, "__gc");
8239 lua_pushcclosure(gL.T, hlua_socket_gc, 0);
8240 lua_rawset(gL.T, -3); /* Push the last 2 entries in the table at index -3 */
8241
8242 /* Register previous table in the registry with reference and named entry. */
8243 class_socket_ref = hlua_register_metatable(gL.T, CLASS_SOCKET);
8244
8245 /* Proxy and server configuration initialisation. */
8246 memset(&socket_proxy, 0, sizeof(socket_proxy));
8247 init_new_proxy(&socket_proxy);
8248 socket_proxy.parent = NULL;
8249 socket_proxy.last_change = now.tv_sec;
8250 socket_proxy.id = "LUA-SOCKET";
8251 socket_proxy.cap = PR_CAP_FE | PR_CAP_BE;
8252 socket_proxy.maxconn = 0;
8253 socket_proxy.accept = NULL;
8254 socket_proxy.options2 |= PR_O2_INDEPSTR;
8255 socket_proxy.srv = NULL;
8256 socket_proxy.conn_retries = 0;
8257 socket_proxy.timeout.connect = 5000; /* By default the timeout connection is 5s. */
8258
8259 /* Init TCP server: unchanged parameters */
8260 memset(&socket_tcp, 0, sizeof(socket_tcp));
8261 socket_tcp.next = NULL;
8262 socket_tcp.proxy = &socket_proxy;
8263 socket_tcp.obj_type = OBJ_TYPE_SERVER;
8264 LIST_INIT(&socket_tcp.actconns);
8265 socket_tcp.pendconns = EB_ROOT;
8266 socket_tcp.priv_conns = NULL;
8267 socket_tcp.idle_conns = NULL;
8268 socket_tcp.safe_conns = NULL;
8269 socket_tcp.next_state = SRV_ST_RUNNING; /* early server setup */
8270 socket_tcp.last_change = 0;
8271 socket_tcp.id = "LUA-TCP-CONN";
8272 socket_tcp.check.state &= ~CHK_ST_ENABLED; /* Disable health checks. */
8273 socket_tcp.agent.state &= ~CHK_ST_ENABLED; /* Disable health checks. */
8274 socket_tcp.pp_opts = 0; /* Remove proxy protocol. */
8275
8276 /* XXX: Copy default parameter from default server,
8277 * but the default server is not initialized.
8278 */
8279 socket_tcp.maxqueue = socket_proxy.defsrv.maxqueue;
8280 socket_tcp.minconn = socket_proxy.defsrv.minconn;
8281 socket_tcp.maxconn = socket_proxy.defsrv.maxconn;
8282 socket_tcp.slowstart = socket_proxy.defsrv.slowstart;
8283 socket_tcp.onerror = socket_proxy.defsrv.onerror;
8284 socket_tcp.onmarkeddown = socket_proxy.defsrv.onmarkeddown;
8285 socket_tcp.onmarkedup = socket_proxy.defsrv.onmarkedup;
8286 socket_tcp.consecutive_errors_limit = socket_proxy.defsrv.consecutive_errors_limit;
8287 socket_tcp.uweight = socket_proxy.defsrv.iweight;
8288 socket_tcp.iweight = socket_proxy.defsrv.iweight;
8289
8290 socket_tcp.check.status = HCHK_STATUS_INI;
8291 socket_tcp.check.rise = socket_proxy.defsrv.check.rise;
8292 socket_tcp.check.fall = socket_proxy.defsrv.check.fall;
8293 socket_tcp.check.health = socket_tcp.check.rise; /* socket, but will fall down at first failure */
8294 socket_tcp.check.server = &socket_tcp;
8295
8296 socket_tcp.agent.status = HCHK_STATUS_INI;
8297 socket_tcp.agent.rise = socket_proxy.defsrv.agent.rise;
8298 socket_tcp.agent.fall = socket_proxy.defsrv.agent.fall;
8299 socket_tcp.agent.health = socket_tcp.agent.rise; /* socket, but will fall down at first failure */
8300 socket_tcp.agent.server = &socket_tcp;
8301
8302 socket_tcp.xprt = xprt_get(XPRT_RAW);
8303
8304 #ifdef USE_OPENSSL
8305 /* Init TCP server: unchanged parameters */
8306 memset(&socket_ssl, 0, sizeof(socket_ssl));
8307 socket_ssl.next = NULL;
8308 socket_ssl.proxy = &socket_proxy;
8309 socket_ssl.obj_type = OBJ_TYPE_SERVER;
8310 LIST_INIT(&socket_ssl.actconns);
8311 socket_ssl.pendconns = EB_ROOT;
8312 socket_ssl.priv_conns = NULL;
8313 socket_ssl.idle_conns = NULL;
8314 socket_ssl.safe_conns = NULL;
8315 socket_ssl.next_state = SRV_ST_RUNNING; /* early server setup */
8316 socket_ssl.last_change = 0;
8317 socket_ssl.id = "LUA-SSL-CONN";
8318 socket_ssl.check.state &= ~CHK_ST_ENABLED; /* Disable health checks. */
8319 socket_ssl.agent.state &= ~CHK_ST_ENABLED; /* Disable health checks. */
8320 socket_ssl.pp_opts = 0; /* Remove proxy protocol. */
8321
8322 /* XXX: Copy default parameter from default server,
8323 * but the default server is not initialized.
8324 */
8325 socket_ssl.maxqueue = socket_proxy.defsrv.maxqueue;
8326 socket_ssl.minconn = socket_proxy.defsrv.minconn;
8327 socket_ssl.maxconn = socket_proxy.defsrv.maxconn;
8328 socket_ssl.slowstart = socket_proxy.defsrv.slowstart;
8329 socket_ssl.onerror = socket_proxy.defsrv.onerror;
8330 socket_ssl.onmarkeddown = socket_proxy.defsrv.onmarkeddown;
8331 socket_ssl.onmarkedup = socket_proxy.defsrv.onmarkedup;
8332 socket_ssl.consecutive_errors_limit = socket_proxy.defsrv.consecutive_errors_limit;
8333 socket_ssl.uweight = socket_proxy.defsrv.iweight;
8334 socket_ssl.iweight = socket_proxy.defsrv.iweight;
8335
8336 socket_ssl.check.status = HCHK_STATUS_INI;
8337 socket_ssl.check.rise = socket_proxy.defsrv.check.rise;
8338 socket_ssl.check.fall = socket_proxy.defsrv.check.fall;
8339 socket_ssl.check.health = socket_ssl.check.rise; /* socket, but will fall down at first failure */
8340 socket_ssl.check.server = &socket_ssl;
8341
8342 socket_ssl.agent.status = HCHK_STATUS_INI;
8343 socket_ssl.agent.rise = socket_proxy.defsrv.agent.rise;
8344 socket_ssl.agent.fall = socket_proxy.defsrv.agent.fall;
8345 socket_ssl.agent.health = socket_ssl.agent.rise; /* socket, but will fall down at first failure */
8346 socket_ssl.agent.server = &socket_ssl;
8347
8348 socket_ssl.use_ssl = 1;
8349 socket_ssl.xprt = xprt_get(XPRT_SSL);
8350
8351 for (idx = 0; args[idx] != NULL; idx++) {
8352 if ((kw = srv_find_kw(args[idx])) != NULL) { /* Maybe it's registered server keyword */
8353 /*
8354 *
8355 * If the keyword is not known, we can search in the registered
8356 * server keywords. This is useful to configure special SSL
8357 * features like client certificates and ssl_verify.
8358 *
8359 */
8360 tmp_error = kw->parse(args, &idx, &socket_proxy, &socket_ssl, &error);
8361 if (tmp_error != 0) {
8362 fprintf(stderr, "INTERNAL ERROR: %s\n", error);
8363 abort(); /* This must be never arrives because the command line
8364 not editable by the user. */
8365 }
8366 idx += kw->skip;
8367 }
8368 }
8369 #endif
8370
8371 RESET_SAFE_LJMP(gL.T);
8372 }
8373
hlua_register_build_options(void)8374 static void hlua_register_build_options(void)
8375 {
8376 char *ptr = NULL;
8377
8378 memprintf(&ptr, "Built with Lua version : %s", LUA_RELEASE);
8379 hap_register_build_opts(ptr, 1);
8380 }
8381
8382 INITCALL0(STG_REGISTER, hlua_register_build_options);
8383