Commit Graph

595 Commits

Author SHA1 Message Date
Joseph Herlant
7fe1577cc7 MINOR: Fix typo in the error 500 output of hlua
Fixes a common typo in the output generated by the hlua subsystem when
emitting an error 500 page.
2018-11-18 22:28:09 +01:00
Joseph Herlant
b8f9c5e634 CLEANUP: fix typos in the comments of hlua
Fix typos in the code comments of the hlua subsystem.
2018-11-18 22:28:09 +01:00
Christopher Faulet
afd8f10be9 MINOR: lua/htx: Forbid lua usage when the HTX is enabled on a proxy
For now, the lua scripts are not compatible with the new HTX internal
representation of HTTP messages. Thus, for a given proxy, when the option
"http-use-htx" is enabled, an error is triggered if any lua's
action/service/sample-fetch/converter is also configured.
2018-11-18 22:10:09 +01:00
Willy Tarreau
db398435aa MINOR: stream-int: replace si_cant_put() with si_rx_room_{blk,rdy}()
Remaining calls to si_cant_put() were all for lack of room and were
turned to si_rx_room_blk(). A few places where SI_FL_RXBLK_ROOM was
cleared by hand were converted to si_rx_room_rdy().

The now unused si_cant_put() function was removed.
2018-11-18 21:41:50 +01:00
Willy Tarreau
4b962a4179 MEDIUM: stream-int: fix the si_cant_put() calls used for buffer readiness
A number of calls to si_cant_put() were used in fact to request being
called back once a buffer is available. These ones are not needed anymore
since si_alloc_ibuf() already sets the SI_FL_RXBLK_BUFF flag when called
in appctx context. Those called with a foreign stream-int are simply turned
to si_rx_buff_blk().
2018-11-18 21:41:48 +01:00
Willy Tarreau
3367d4156d MEDIUM: stream-int: fix the si_cant_put() calls used for end point readiness
A number of si_cant_put() calls were still present to in fact indicate
that the end point is ready (thus should be turned to si_rx_endp_more()).

One other call in the Lua handler indicates that the endpoint wanted to
be blocked until some room is made in the Rx buffer in order to detect
that the connection happened, which is in fact an indication that it
wants to be called once the endpoint is ready, this is the default case
for an applet so this call was removed.

A useless call to si_cant_put() before appctx_wakeup() in the Lua
applet wakeup call was removed as well since the first thing that will
be done there will be to set end ENDP blocking flag.
2018-11-18 21:41:48 +01:00
Willy Tarreau
0cd3bd628a MINOR: stream-int: rename si_applet_{want|stop|cant}_{get|put}
It doesn't make sense to limit this code to applets, as any stream
interface can use it. Let's rename it by simply dropping the "applet_"
part of the name. No other change was made except updating the comments.
2018-11-11 10:18:37 +01:00
Willy Tarreau
581abd3f99 MEDIUM: stream-int: replace channel_alloc_buffer() with si_alloc_ibuf() everywhere
Well that's only 3 places (applet.c, stream_interface.c, hlua.c). This
ensures we always clear SI_FL_WAIT_ROOM before setting it on failure,
so that it is granted that SI_FL_WAIT_ROOM always indicates a lack of
room for doing an operation, including the inability to allocate a
buffer for this.
2018-10-28 13:47:00 +01:00
Willy Tarreau
4e7cc3381b BUILD: compiler: rename __unreachable() to my_unreachable()
Olivier reported that on FreeBSD __unreachable is already defined
and causes build warnings. Let's rename it then.
2018-10-20 17:45:48 +02:00
Willy Tarreau
b059b894cd BUILD: lua: silence some compiler warnings after WILL_LJMP
These ones are on error paths that are properly handled by luaL_error()
which does a longjmp() but the compiler cannot know it. By adding an
__unreachable() statement in WILL_LJMP(), there is no ambiguity anymore.

This may be backported to 1.8 but these previous patches are needed first :
  - BUILD: compiler: add a new statement "__unreachable()"
  - MINOR: lua: all functions calling lua_yieldk() may return
  - BUILD: lua: silence some compiler warnings about potential null derefs (#2)
2018-10-16 17:57:36 +02:00
Willy Tarreau
9635e03c41 MINOR: lua: all functions calling lua_yieldk() may return
There was a mistake when tagging functions which always use longjmp and
those which may use it in that all those supposed to call lua_yieldk()
may return without calling longjmp. Thus they must not use WILL_LJMP()
but MAY_LJMP(). It has zero impact on the code emitted as such, but
prevents other fixes from being properly implemented : this was the
cause of the previous failure with the __unreachable() calls.

This may be backported to older versions. It may or may not apply
well depending on the context, though the change simply consists in
replacing "WILL_LJMP(hlua_yieldk" with "MAY_LJMP(hlua_yieldk", and
same with the single call to lua_yieldk() in hlua_yieldk().
2018-10-16 17:56:20 +02:00
Willy Tarreau
e09101e8d9 BUILD: lua: silence some compiler warnings about potential null derefs (#2)
Here we make sure that appctx is always taken from the unchecked value
since we know it's an appctx, which explains why it's immediately
dereferenced. A missing test was added to ensure that task_new() does
not return a NULL.

This may be backported to 1.8.
2018-10-16 17:39:05 +02:00
Willy Tarreau
526aed219f Revert "BUILD: lua: silence some compiler warnings about potential null derefs"
This reverts commit f1ffb39b61.

It breaks Lua causing some timeouts. Removing the __unreachable() statement
from WILL_LJMP() fixes it. It's very strange and unclear whether it's an
issue with WILL_LJMP() not fullfilling its promise of not returning, if
the code emitted with __unreachable() gets broken, or anything else. Let's
revert this for now.
2018-10-16 17:32:55 +02:00
Willy Tarreau
f1ffb39b61 BUILD: lua: silence some compiler warnings about potential null derefs
These ones are on error paths that are properly handled by luaL_error()
which does a longjmp() but the compiler cannot know it. By adding an
__unreachable() statement in WILL_LJMP(), there is no ambiguity anymore.

This may be backported to 1.8 but the previous patch (BUILD: compiler:
add a new statement "__unreachable()") is needed for this.
2018-10-15 13:24:43 +02:00
Willy Tarreau
61c112aa5b REORG: http: move HTTP rules parsing to http_rules.c
These ones are mostly called from cfgparse.c for the parsing and do
not depend on the HTTP representation. The functions's prototypes
were moved to proto/http_rules.h, making this file work exactly like
tcp_rules. Ideally we should stop calling these functions directly
from cfgparse and register keywords, but there are a few cases where
that wouldn't work (stats http-request) so it's probably not worth
trying to go this far.
2018-10-02 18:28:05 +02:00
Willy Tarreau
79e57336b5 REORG: http: move the code to different files
The current proto_http.c file is huge and contains different processing
domains making it very difficult to work on an alternative representation.
This commit moves some parts to other files :

  - ACL registration code => http_acl.c
    This code only creates some ACL mappings and doesn't know anything
    about HTTP nor about the representation. This code could even have
    moved to acl.c but it was not worth polluting it again.

  - HTTP sample conversion => http_conv.c
    This code doesn't depend on the internal representation but definitely
    manipulates some HTTP elements, such as dates. It also has access to
    captures.

  - HTTP sample fetching => http_fetch.c
    This code does depend entirely on the internal representation but is
    totally independent on the analysers. Placing it into a different
    file will ease the transition to the new representation and the
    creation of a wrapper if required. An include file was created due
    to CHECK_HTTP_MESSAGE_FIRST() being used at various places.

  - HTTP action registration => http_act.c
    This code doesn't directly interact with the messages nor the
    transaction but it does so via some exported http functions like
    http_replace_req_line() or http_set_status() so it will be easier
    to change only this after the conversion.

  - a few very generic parts were found and moved to http.{c,h} as
    relevant.

It is worth noting that the functions moved to these new files are not
referenced anywhere outside of the files and are only called as registered
callbacks, so these files do not even require associated include files.
2018-10-02 18:26:59 +02:00
Willy Tarreau
04f1e2d202 REORG: http: move error codes production and processing to http.c
These error codes and messages are agnostic to the version, even if
they are represented as HTTP/1.0 messages. Ultimately they will have
to be transformed into internal HTTP messages to be used everywhere.

The HTTP/1.1 100 Continue message was turned to an IST and the local
copy in the Lua code was removed.
2018-09-11 10:30:25 +02:00
Willy Tarreau
6b952c8101 REORG: http: move http_get_path() to http.c
This function is purely HTTP once http_txn is put aside. So the original
one was renamed to http_txn_get_path() and it extracts the relevant offsets
from the txn to pass them to http_get_path(). One benefit of the new version
is that it returns the length at the same time so that allowed to slightly
simplify http_get_path_from_string() which had to look up the end pointer
previously and which is not needed anymore.
2018-09-11 10:30:25 +02:00
Olivier Houchard
9e643ea172 BUG/MEDIUM: hlua: Don't call RESET_SAFE_LJMP if SET_SAFE_LJMP returns 0.
If SET_SAFE_LJMP returns 0, the spinlock is already unlocked, and lua_atpanic
is already set back to hlua_panic_safe, so there's no need to call
RESET_SAFE_LJMP.

This should be MFC'd into 1.8.
2018-08-31 16:14:58 +02:00
Frdric Lcaille
54f2bcf22b BUG/MAJOR: thread: lua: Wrong SSL context initialization.
When calling ->prepare_srv() callback for SSL server which
depends on global "nbthread" value, this latter was not already parsed,
so equal to 1 default value. This lead to bad memory accesses.

Thank you to Pieter (PiBa-NL) for having reported this issue and
for having provided a very helpful reg testing file to reproduce
this issue (reg-test/lua/b00002.*).

Must be backported to 1.8.
2018-08-30 10:06:45 +02:00
Olivier Houchard
594c8c5015 BUG/MEDIUM: hlua: Make sure we drain the output buffer when done.
In hlua_applet_tcp_fct(), drain the output buffer when the applet is done
running, every time we're called.
Overwise, there's a race condition, and the output buffer could be filled
after the applet ran, and as it is never cleared, the stream interface
will never be destroyed.

This should be backported to 1.8 and 1.7.
2018-08-28 16:18:34 +02:00
Frdric Lcaille
83ed5d58d2 BUG/MINOR: lua: Bad HTTP client request duration.
HTTP LUA applet callback should not update the date on which the HTTP client requests
arrive. This was done just after the LUA applet has completed its job.

This patch simply removes the affected statement. The same fixe has been applied
to TCP LUA applet callback.

To reproduce this issue, as reported by Patrick Hemmer, implement an HTTP LUA applet
which sleeps a bit before replying:

  core.register_service("foo", "http", function(applet)
      core.msleep(100)
      applet:set_status(200)
      applet:start_response()
  end)

This had as a consequence to log %TR field with approximatively the same value as
the LUA sleep time.

Thank you to Patrick Hemmer for having reported this issue.

Must be backported to 1.8, 1.7 and 1.6.
2018-08-24 14:49:30 +02:00
Cyril Bont
7ee465f1ad BUG/MINOR: lua: fix extra 500ms added to socket timeouts
Since commit #56cc12509, haproxy accepts double values for timeouts. The
value is then converted to  milliseconds before being rounded up and cast
to int. The issue is that to round up the value, a constant value of 0.5
is added to it, but too early in the conversion, resulting in an
additional 500ms to the value. We are talking about a precision of 1ms,
so we can safely get rid of this rounding trick and adjust resulting
timeouts equal to 0 to a minimum of 1ms.

This patch is specific to the 1.9 branch and doesn't require to be
backported.
2018-08-19 22:11:28 +02:00
Cyril Bont
7bb6345497 BUG/MEDIUM: lua: socket timeouts are not applied
Sachin Shetty reported that socket timeouts set in LUA code have no effect.
Indeed, connect timeout is never modified and is always set to its default,
set to 5 seconds. Currently, this patch will apply the specified timeout
value to the connect timeout.
For the read and write timeouts, the issue is that the timeout is updated but
the expiration dates were not updated.

This patch should be backported up to the 1.6 branch.
2018-08-18 00:23:52 +02:00
Patrick Hemmer
268a707a3d MEDIUM: add set-priority-class and set-priority-offset
This adds the set-priority-class and set-priority-offset actions to
http-request and tcp-request content. At this point they are not used
yet, which is the purpose of the next commit, but all the logic to
set and clear the values is there.
2018-08-10 15:06:31 +02:00
Patrick Hemmer
0355dabd7c MINOR: queue: replace the linked list with a tree
We'll need trees to manage the queues by priorities. This change replaces
the list with a tree based on a single key. It's effectively a list but
allows us to get rid of the list management right now.
2018-08-10 15:06:27 +02:00
Willy Tarreau
83061a820e MAJOR: chunks: replace struct chunk with struct buffer
Now all the code used to manipulate chunks uses a struct buffer instead.
The functions are still called "chunk*", and some of them will progressively
move to the generic buffer handling code as they are cleaned up.
2018-07-19 16:23:43 +02:00
Willy Tarreau
843b7cbe9d MEDIUM: chunks: make the chunk struct's fields match the buffer struct
Chunks are only a subset of a buffer (a non-wrapping version with no head
offset). Despite this we still carry a lot of duplicated code between
buffers and chunks. Replacing chunks with buffers would significantly
reduce the maintenance efforts. This first patch renames the chunk's
fields to match the name and types used by struct buffers, with the goal
of isolating the code changes from the declaration changes.

Most of the changes were made with spatch using this coccinelle script :

  @rule_d1@
  typedef chunk;
  struct chunk chunk;
  @@
  - chunk.str
  + chunk.area

  @rule_d2@
  typedef chunk;
  struct chunk chunk;
  @@
  - chunk.len
  + chunk.data

  @rule_i1@
  typedef chunk;
  struct chunk *chunk;
  @@
  - chunk->str
  + chunk->area

  @rule_i2@
  typedef chunk;
  struct chunk *chunk;
  @@
  - chunk->len
  + chunk->data

Some minor updates to 3 http functions had to be performed to take size_t
ints instead of ints in order to match the unsigned length here.
2018-07-19 16:23:43 +02:00
Willy Tarreau
c9fa0480af MAJOR: buffer: finalize buffer detachment
Now the buffers only contain the header and a pointer to the storage
area which can be anywhere. This will significantly simplify buffer
swapping and will make it possible to map chunks on buffers as well.

The buf_empty variable was removed, as now it's enough to have size==0
and area==NULL to designate the empty buffer (thus a non-allocated head
is the empty buffer by default). buf_wanted for now is indicated by
size==0 and area==(void *)1.

The channels and the checks now embed the buffer's head, and the only
pointer is to the storage area. This slightly increases the unallocated
buffer size (3 extra ints for the empty buffer) but considerably
simplifies dynamic buffer management. It will also later permit to
detach unused checks.

The way the struct buffer is arranged has proven quite efficient on a
number of tests, which makes sense given that size is always accessed
and often first, followed by the othe ones.
2018-07-19 16:23:43 +02:00
Willy Tarreau
e3128024bf MINOR: buffer: replace buffer_replace2() with b_rep_blk()
This one is more generic and designed to work on a random block. It
may later get a b_rep_ist() variant since many strings are already
available as (ptr,len).
2018-07-19 16:23:43 +02:00
Willy Tarreau
72a100b386 MINOR: buffer: replace bi_fast_delete() with b_del()
There's no distinction between in and out data now. The latter covers
the needs of the former and supports wrapping. The extra cost is
negligible given the locations where it's used.
2018-07-19 16:23:43 +02:00
Willy Tarreau
a79021af6f MINOR: lua: use the wrappers instead of directly manipulating buffer states
This replaces chn->buf->p with ci_head(chn), chn->buf->o with co_data(chn)
and chn->buf->i with ci_data(chn). This is in order to help porting to the
new buffer API.
2018-07-19 16:23:42 +02:00
Willy Tarreau
3f6799975f MINOR: buffer: replace bi_space_for_replace() with ci_space_for_replace()
This one computes the size that can be overwritten over the input part
of the buffer, so it's channel-specific.
2018-07-19 16:23:41 +02:00
Willy Tarreau
eac5259888 MINOR: buffer: use b_room() to determine available space in a buffer
We used to have variations around buffer_total_space() and
size-buffer_len() or size-b_data(). Let's simplify all this. buffer_len()
was also removed as not used anymore.
2018-07-19 16:23:41 +02:00
Willy Tarreau
55f3ce1c91 MINOR: buffer: make b_getblk_nc() take size_t for the block sizes
Till now we used to reimplement it using ints to limit external changes
but we must adjust it and the various users to switch to size_t.
2018-07-19 16:23:41 +02:00
Willy Tarreau
206ba834ef MINOR: buffer: make b_getblk_nc() take const pointers
Now that there are no more users requiring to modify the buffer anymore,
switch these ones to const char and const buffer. This will make it more
obvious next time send functions are tempted to modify the buffer's output
count. Minor adaptations were necessary at a few call places which were
using char due to the function's previous prototype.
2018-07-19 16:23:41 +02:00
Willy Tarreau
bcbd39370f MINOR: channel/buffer: replace b_{adv,rew} with c_{adv,rew}
These ones manipulate the output data count which will be specific to
the channel soon, so prepare the call points to use the channel only.
The b_* functions are now unused and were removed.
2018-07-19 16:23:40 +02:00
Willy Tarreau
fd8d42f496 MEDIUM: channel: make channel_slow_realign() take a swap buffer
The few call places where it's used can use the trash as a swap buffer,
which is made for this exact purpose. This way we can rely on the
generic b_slow_realign() call.
2018-07-19 16:23:40 +02:00
Willy Tarreau
4cf1300e6a MINOR: channel/buffer: replace buffer_slow_realign() with channel_slow_realign() and b_slow_realign()
Where relevant, the channel version is used instead. The buffer version
was ported to be more generic and now takes a swap buffer and the output
byte count to know where to set the alignment point. The H2 mux still
uses buffer_slow_realign() with buf->o but it will change later.
2018-07-19 16:23:40 +02:00
Thierry FOURNIER
70d318ccb7 BUG/MEDIUM: lua: possible CLOSE-WAIT state with '\n' headers
The Lua parser doesn't takes in account end-of-headers containing
only '\n'. It expects always '\r\n'. If a '\n' is processes the Lua
parser considers it miss 1 byte, and wait indefinitely for new data.

When the client reaches their timeout, it closes the connection.
This close is not detected and the connection keep in CLOSE-WAIT
state.

I guess that this patch fix only a visible part of the problem.
If the Lua HTTP parser wait for data, the timeout server or the
connectio closed by the client may stop the applet.

How reproduce the problem:

HAProxy conf:

   global
      lua-load bug38.lua
   frontend frt
      timeout client 2s
      timeout server 2s
      mode http
      bind *:8080
      http-request use-service lua.donothing

Lua conf

   core.register_service("donothing", "http", function(applet) end)

Client request:

   echo -ne 'GET / HTTP/1.1\n\n' | nc 127.0.0.1 8080

Look for CLOSE-WAIT in the connection with "netstat" or "ss". I
use this script:

   while sleep 1; do ss | grep CLOSE-WAIT; done

This patch must be backported in 1.6, 1.7 and 1.8

Workaround: enable the "hard-stop-after" directive, and perform
periodic reload.
2018-07-01 06:08:43 +02:00
Frdric Lcaille
f874a83b57 BUG/MINOR: lua: Segfaults with wrong usage of types.
Patrick reported that this simple configuration made haproxy segfaults:

    global
        lua-load /tmp/haproxy.lua

    frontend f1
        mode http
        bind :8000
        default_backend b1

        http-request lua.foo

    backend b1
        mode http
        server s1 127.0.0.1:8080

with this '/tmp/haproxy.lua' script:

    core.register_action("foo", { "http-req" }, function(txn)
        txn.sc:ipmask(txn.f:src(), 24, 112)
    end)

This is due to missing initialization of the array of arguments
passed to hlua_lua2arg_check() which makes it enter code with
corrupted arguments.

Thanks a lot to Patrick Hemmer for having reported this issue.

Must be backported to 1.8, 1.7 and 1.6.
2018-06-18 10:23:47 +02:00
Thierry FOURNIER
fc044c98e4 MINOR: lua: Increase debug information
When an unrecoverable error raises, the user receive poor information
for the trouble shooting. For example:

   [ALERT] 157/143755 (21212) : Lua function 'hello-world': runtime error: memory allocation error: block too big.

Unfortunately, the memory allocation error can be throwed by many
function, and we have no informatio to reach the original cause.
This patch add the list of function called from the entry point to
the function in error, like this:

   [ALERT] 157/143755 (21212) : Lua function 'hello-world': runtime error: memory allocation error: block too big from [C] method 'req_get_headers', bug35.lua:2 global 'ee', bug35.lua:6 global 'ff', bug35.lua:10 C function line 9.
2018-06-08 18:18:33 +02:00
Thierry FOURNIER
66b8919b10 BUG/MEDIUM: lua/socket: Buffer error, may segfault
The buffer pointer is already updated. It is again updated
when it is given to the function ci_putblk().

This patch must be backported in 1.6, 1.7 and 1.8
2018-05-31 10:58:41 +02:00
Thierry FOURNIER
101b97619a BUG/MEDIUM: lua/socket: Sheduling error on write: may dead-lock
When we write data, we risk to encounter a dead-loack. The
function "stream_int_notify()" cannot be called the the
cosocket because the caller acquire a lock and when the socket
is closed, the cleanup function try to acquire the same lock.,
so a dead-lock raises.

In other way, the function stream_int_update_applet() can't
be called because it schedumes the applet only if some activity
in the buffers were detected. It is not always the case. We
replace this function by appctx_wakeup() which wake up the
applet inconditionnaly.

The last part of the fix is setting right signals. the applet
call the stream_int_update() function if the output buffer si
not empty, and ask for put data if some rite signals are
registered.

This patch must be backported in 1.6, 1.7 and 1.8. Note that it requires
patch "MINOR: task/notification: Is notifications registered" to be
applied.
2018-05-31 10:58:41 +02:00
Thierry FOURNIER
ba42fcd064 BUG/MEDIUM: lua/socket: Notification error
Each time the send function yields, a notification must be registered.
Without this notification, the task is never wakeup when data arrives.

Today, the notification is registered only if the buffer is not available.
Other cases like the buffer is too small for all data are not processed.

This patch must be backported in 1.6, 1.7 and 1.8
2018-05-31 10:58:41 +02:00
Thierry FOURNIER
7e4ee47acc BUG/MAJOR: lua: Dead lock with sockets
In some cases, when we are waiting for data and the socket
timeout expires, we have a dead lock. The Lua socket locks
the applet socket, and call for a notify. The notify
immediately executes code and try to acquire the same lock,
so ... dead lock.

stream_int_notify() cant be used because it wakeup the applet
task only if the stream have changes. The changes are forces
by Lua, but not repported on the stream.

stream_int_update_applet() cant be used because the deadlock.

So, I inconditionnaly wakeup the applet. This wake is performed
asynchronously, and will call a stream_int_notify().

This patch must be backported in 1.6, 1.7 and 1.8
2018-05-31 10:58:41 +02:00
Thierry FOURNIER
af4bd0867a BUG/MEDIUM: lua/socket: wrong scheduling for sockets
The appctx pointer is given from any variable which are wrong.
This implies the wakeup of wrong applet, and the socket are no
longer responsive.

This behavior is hidden by another inherited error which is
fixed in the next patch.

This patch remove all wrong appctx affectations.

This patch must be backported in 1.6, 1.7 and 1.8
2018-05-31 10:58:41 +02:00
Olivier Houchard
9f6af33222 MINOR: tasks: Change the task API so that the callback takes 3 arguments.
In preparation for thread-specific runqueues, change the task API so that
the callback takes 3 arguments, the task itself, the context, and the state,
those were retrieved from the task before. This will allow these elements to
change atomically in the scheduler while the application uses the copied
value, and even to have NULL tasks later.
2018-05-26 19:23:57 +02:00
Thierry FOURNIER
8c126c7235 BUG/MEDIUM: lua/socket: Length required read doesn't work
The limit of data read works only if all the data is in the
input buffer. Otherwise (if the data arrive in chunks), the
total amount of data is not taken in acount.

Only the current read data are compared to the expected amout
of data.

This patch must be backported from 1.9 to 1.6
2018-05-26 08:51:05 +02:00
Thierry Fournier
d5b073cf1f MINOR: lua: Improve error message
The function hlua_ctx_resume return less text message and more error
code. These error code allow the caller to return appropriate
message to the user.
2018-05-22 18:57:46 +02:00
Willy Tarreau
cbe6da5eb0 BUG/MINOR: ssl/lua: prevent lua from affecting automatic maxconn computation
Since commit 36d1374 ("BUG/MINOR: lua: Fix SSL initialisation") in 1.6, the
Lua code always initializes an SSL server. It caused a small visible side
effect which is that by calling ssl_sock_prepare_srv_ctx(), it forces
global.ssl_used_backend to 1 and makes the initialization code believe that
there are some SSL servers in certain backends. This detection is used to
figure how to set the global maxconn value when only the memory usage is
limited. As such, even a configuration with no SSL at all will have a very
conservative maxconn.

The configuration below exhibits this :

   global
        ssl-server-verify none
        stats socket /tmp/sock1 mode 666 level admin
        tune.bufsize 16384

   listen  px
        timeout client  5s
        timeout server  5s
        timeout connect 5s
        bind :4445
        #bind :4443 ssl crt rsa+dh2048.pem
        #server s1 127.0.0.1:8003 ssl

Starting it with "-m 200" to limit it to 200 MB of RAM reports 1500 for
Maxconn, the same when uncommenting the "server" line, and 1300 when
uncommenting the "bind" line, regardless of the "server" line's status.

In practice it doesn't make sense to consider that Lua's server template
counts for one regular SSL server, because even if used for SSL, it will
not take large connection counts, compared to a backend relaying traffic.
Thus the solution consists in resetting the ssl_used_backend to its
previous value after creating the server_ctx from the Lua code. With the
fix, the same config with the same parameters now show :
  - maxconn=5700 when neither side uses SSL
  - maxconn=1500 when only one side uses SSL
  - maxconn=1300 when both sides use SSL

This fix can be backported to versions 1.6 and beyond.
2018-05-18 17:09:35 +02:00
sada
05ed330d72 BUG/MINOR: lua: Socket.send threw runtime error: 'close' needs 1 arguments.
Function `hlua_socket_close` expected exactly one argument on the Lua stack.
But when `hlua_socket_close` was called from `hlua_socket_write_yield`,
Lua stack had 3 arguments. So `hlua_socket_close` threw the exception with
message "'close' needs 1 arguments".

Introduced new helper function `hlua_socket_close_helper`, which removed the
Lua stack argument count check and only checked if the first argument was
a socket.

This fix should be backported to 1.8, 1.7 and 1.6.
2018-05-18 13:48:21 +02:00
PiBa-NL
706d5ee0c3 BUG/MINOR: lua: schedule socket task upon lua connect()
The parameters like server-address, port and timeout should be set before
process_stream task is called to avoid the stream being 'closed' before it
got initialized properly. This is most clearly visible when running with
tune.lua.forced-yield=1.. So scheduling the task should not be done when
creating the lua socket, but when connect is called. The error
"socket: not yet initialised, you can't set timeouts." would then appear.

Below code for example also shows this issue, as the sleep will
yield the lua code:
  local con = core.tcp()
  core.sleep(1)
  con:settimeout(10)
2018-05-06 14:36:41 +02:00
PiBa-NL
fe971b35ae BUG/MINOR, BUG/MINOR: lua: Put tasks to sleep when waiting for data
If a lua socket is waiting for data it currently spins at 100% cpu usage.
This because the TICK_ETERNITY returned by the socket is ignored when
setting the 'expire' time of the task.

Fixed by removing the check for yields that return TICK_ETERNITY.

This should be backported to at least 1.8.
2018-05-03 05:00:25 +02:00
Christopher Faulet
5bc9972ed8 BUG/MINOR: lua/threads: Make lua's tasks sticky to the current thread
PiBa-NL reported a bug with tasks registered in lua when HAProxy is started with
serveral threads. These tasks have not specific affinity with threads so they
can be woken up on any threads. So, it is impossbile for these tasks to handled
cosockets or applets, because cosockets and applets are sticky on the thread
which created them. It is forbbiden to manipulate a cosocket from another
thread.

So to fix the bug, tasks registered in lua are now sticky to the current
thread. Because these tasks can be registered before threads creation, the
affinity is set the first time a lua's task is processed.

This patch must be backported in HAProxy 1.8.
2018-04-26 22:58:16 +02:00
Aurlien Nephtali
abbf607105 MEDIUM: cli: Add payload support
In order to use arbitrary data in the CLI (multiple lines or group of words
that must be considered as a whole, for example), it is now possible to add a
payload to the commands. To do so, the first line needs to end with a special
pattern: <<\n. Everything that follows will be left untouched by the CLI parser
and will be passed to the commands parsers.

Per-command support will need to be added to take advantage of this
feature.

Signed-off-by: Aurlien Nephtali <aurelien.nephtali@corp.ovh.com>
2018-04-26 14:19:33 +02:00
Tim Duesterhus
cd235c6042 BUG/MEDIUM: lua: Fix segmentation fault if a Lua task exits
PiBa-NL reported that haproxy crashes with a segmentation fault
if a function registered using `core.register_task` returns.

An example Lua script that reproduces the bug is:

  mytask = function()
  	core.Info("Stopping task")
  end
  core.register_task(mytask)

The Valgrind output is as follows:

  ==6759== Process terminating with default action of signal 11 (SIGSEGV)
  ==6759==  Access not within mapped region at address 0x20
  ==6759==    at 0x5B60AA9: lua_sethook (in /usr/lib/x86_64-linux-gnu/liblua5.3.so.0.0.0)
  ==6759==    by 0x430264: hlua_ctx_resume (hlua.c:1009)
  ==6759==    by 0x43BB68: hlua_process_task (hlua.c:5525)
  ==6759==    by 0x4FED0A: process_runnable_tasks (task.c:231)
  ==6759==    by 0x4B2256: run_poll_loop (haproxy.c:2397)
  ==6759==    by 0x4B2256: run_thread_poll_loop (haproxy.c:2459)
  ==6759==    by 0x41A7E4: main (haproxy.c:3049)

Add the missing `task = NULL` for the `HLUA_E_OK` case. The error cases
have been fixed as of 253e53e661 which
first was included in haproxy v1.8-dev3. This bugfix should be backported
to haproxy 1.8.
2018-04-25 11:30:56 +02:00
Mark Lakes
56cc12509c MINOR: lua: allow socket api settimeout to accept integers, float, and doubles
Instead of hlua_socket_settimeout() accepting only integers, allow user
to specify float and double as well. Convert to milliseconds much like
cli_parse_set_timeout but also sanity check the value.

http://w3.impa.br/~diego/software/luasocket/tcp.html#settimeout

T. Fournier edit:

The main goal is to keep compatibility with the LuaSocket API. This
API only accept seconds, so using a float to specify milliseconds is
an acceptable way.

Update doc.
2018-03-27 14:17:02 +02:00
Mark Lakes
22154b437d CLEANUP: lua: typo fix in comments
Some typo fixes in comments.
2018-03-26 11:12:41 +02:00
Thierry Fournier
17a921b799 BUG/MINOR: lua funtion hlua_socket_settimeout don't check negative values
Negatives timeouts doesn't have sense. A negative timeout doesn't cause
a crash, but the connection expires before the system try to extablish it.

This patch should be backported in all versions from 1.6
2018-03-26 11:11:49 +02:00
Thierry Fournier
e9636f192a BUG/MINOR: lua: the function returns anything
The output of these function indicates that one element is pushed in
the stack, but no element is set in the stack. Actually, if anyone
read the value returned by this function, is gets "something"
present in the stack.

This patch is a complement of these one: 119a5f10e4

The LuaSocket documentation tell anything about the returned value,
but the effective code set an integer of value one.

   316a9455b9/src/timeout.c (L172)

Thanks to Tim for the bug report.

This patch should be backported in all version from 1.6
2018-03-26 11:11:23 +02:00
Thierry FOURNIER
2986c0db88 CLEANUP: lua/syntax: lua is a name and not an acronym
This patch fix some first letter upercase for Lua messages.
2018-03-19 12:59:26 +01:00
Thierry FOURNIER
fd1e955a56 BUG/MINOR: lua: return bad error messages
The returned type is the type of the top of stack value and
not the type of the checked argument.

[wt: this can be backported to 1.8, 1.7 and 1.6]
2018-03-19 12:59:19 +01:00
Tim Duesterhus
b814da6c5c MINOR: config: Add support for ARGT_MSK6
This commit adds support for ARGT_MSK6 to make_arg_list().
2018-01-25 22:25:40 +01:00
Tim Duesterhus
119a5f10e4 BUG/MINOR: lua: Fix return value of Socket.settimeout
The `socket.tcp.settimeout` method of Lua returns `1` in all cases,
while the `Socket.settimeout` method of haproxy returns `0` in all
cases. This breaks the `socket.http` module, because it validates
the return value of `settimeout`.

This bug was introduced in commit 7e7ac32dad
(which is the very first commit adding the Socket class to Lua). This
bugfix should be backported to every branch containing that commit:
- 1.6
- 1.7
- 1.8

A test case for this bug is as follows:

The 'Test' response header will contain an HTTP status code with the
patch applied and will be zero (nil) without the patch applied.

http.lua:
  http = require("socket.http")

  core.register_action("bug", { "http-req" }, function(txn)
  	local b, c, h = http.request {
  		url = "http://93.184.216.34",
  		headers = {
  			Host = "example.com"
  		},
  		create = core.tcp,
  		redirect = false
  	}

  	txn:set_var("txn.foo", c)
  end)

haproxy.cfg:
  global
  	lua-load /scratch/haproxy/http.lua

  frontend fe
  	bind 127.0.0.1:8080
  	http-request lua.bug
  	http-response set-header Test %[var(txn.foo)]

  	default_backend be

  backend be
  	server s example.com:80
2018-01-09 15:22:55 +01:00
Tim Duesterhus
6edab865f6 BUG/MEDIUM: lua: Fix IPv6 with separate port support for Socket.connect
The `socket.tcp.connect` method of Lua requires at least two parameters:
The host and the port. The `Socket.connect` method of haproxy requires
only one when a host with a combined port is provided. This stems from
the fact that `str2sa_range` is used internally in `hlua_socket_connect`.
This very fact unfortunately causes a diversion in the behaviour of
Lua's socket class and haproxy's for IPv6 addresses:

  sock:connect("::1", "80")

works fine with Lua, but fails with:

  connect: cannot parse destination address '::1'

in haproxy, because `str2sa_range` parses the trailing `:1` as the port.

This patch forcefully adds a `:` to the end of the address iff a port
number greater than `0` is given as the second parameter.

Technically this breaks backwards compatibility, because the docs state:

> The syntax "127.0.0.1:1234" is valid. in this case, the
> parameter *port* is ignored.

But: The connect() call can only succeed if the second parameter is left
out (which causes no breakage) or if the second parameter is an integer
or a numeric string.

It seems unlikely that someone would provide an address with a port number
and would also provide a second parameter containing a number other than
zero. Thus I feel this breakage is warranted to fix the mismatch between
haproxy's socket class and Lua's one.

This commit should be backported to haproxy 1.8 only, because of the
possible breakage of existing Lua scripts.
2018-01-09 15:22:55 +01:00
Tim Duesterhus
b33754ce86 DOC: lua: Fix typos in comments of hlua_socket_receive 2018-01-09 15:22:49 +01:00
Tim Duesterhus
c6e377e6bb BUG/MINOR: lua: Fix default value for pattern in Socket.receive
The default value of the pattern in `Socket.receive` is `*l` according
to the documentation and in the `socket.tcp.receive` method of Lua.

The default value of `wanted` in `int hlua_socket_receive(struct lua_State *)`
reflects this requirement, but the function fails to ensure this
nonetheless:

If no parameter is given the top of the Lua stack will have the index 1.
`lua_pushinteger(L, wanted);` then pushes the default value onto the stack
(with index 2).
The following `lua_replace(L, 2);` then pops the top index (2) and tries to
replace the index 2 with it.
I am not sure why exactly that happens (possibly, because one cannot replace
non-existent stack indicies), but this causes the stack index to be lost.

`hlua_socket_receive_yield` then tries to read the stack index 2, to
determine what to read and get the value `0`, instead of the correct
HLSR_READ_LINE, thus taking the wrong branch.

Fix this by ensuring that the top of the stack is not replaced by itself.

This bug was introduced in commit 7e7ac32dad
(which is the very first commit adding the Socket class to Lua). This
bugfix should be backported to every branch containing that commit:
- 1.6
- 1.7
- 1.8

A test case for this bug is as follows:

The 'Test' response header will contain an HTTP status line with the
patch applied and will be empty without the patch applied. Replacing
the `sock:receive()` with `sock:receive("*l")` will cause the status
line to appear with and without the patch

http.lua:
  core.register_action("bug", { "http-req" }, function(txn)
  	local sock = core.tcp()
  	sock:settimeout(60)
  	sock:connect("127.0.0.1:80")
  	sock:send("GET / HTTP/1.0\r\n\r\n")
  	response = sock:receive()
  	sock:close()
  	txn:set_var("txn.foo", response)
  end)

haproxy.cfg (bits omitted for brevity):
  global
  	lua-load /scratch/haproxy/http.lua

  frontend fe
  	bind 127.0.0.1:8080
  	http-request lua.bug
  	http-response set-header Test %[var(txn.foo)]

  	default_backend be

  backend be
  	server s 127.0.0.1:80
2018-01-09 15:22:46 +01:00
Eric Salama
fe7456f3b7 BUG/MEDIUM: lua: fix crash when using bogus mode in register_service()
When using an incorrect 'mode' as 2nd argument of core.register_service(),
HAProxy crashes while displaying the error message.

To be backported to 1.8, 1.7 and 1.6.
2017-12-22 14:34:54 +01:00
Thierry FOURNIER
cb14688496 BUG/MEDIUM: lua/notification: memory leak
The thread patches adds refcount for notifications. The notifications are
used with the Lua cosocket. These refcount free the notifications when
the session is cleared. In the Lua task case, it not have sessions, so
the nofications are never cleraed.

This patch adds a garbage collector for signals. The garbage collector
just clean the notifications for which the end point is disconnected.

This patch should be backported in 1.8
2017-12-10 19:38:58 +01:00
Willy Tarreau
bafbe01028 CLEANUP: pools: rename all pool functions and pointers to remove this "2"
During the migration to the second version of the pools, the new
functions and pool pointers were all called "pool_something2()" and
"pool2_something". Now there's no more pool v1 code and it's a real
pain to still have to deal with this. Let's clean this up now by
removing the "2" everywhere, and by renaming the pool heads
"pool_head_something".
2017-11-24 17:49:53 +01:00
Christopher Faulet
767a84bcc0 CLEANUP: log: Rename Alert/Warning in ha_alert/ha_warning 2017-11-24 17:19:12 +01:00
Christopher Faulet
9dcf9b6f03 MINOR: threads: Use __decl_hathreads to declare locks
This macro should be used to declare variables or struct members depending on
the USE_THREAD compile option. It avoids the encapsulation of such declarations
between #ifdef/#endif. It is used to declare all lock variables.
2017-11-13 11:38:17 +01:00
Christopher Faulet
2a944ee16b BUILD: threads: Rename SPIN/RWLOCK macros using HA_ prefix
This remove any name conflicts, especially on Solaris.
2017-11-07 11:10:24 +01:00
Olivier Houchard
9aaf778129 MAJOR: connection : Split struct connection into struct connection and struct conn_stream.
All the references to connections in the data path from streams and
stream_interfaces were changed to use conn_streams. Most functions named
"something_conn" were renamed to "something_cs" for this. Sometimes the
connection still is what matters (eg during a connection establishment)
and were not always renamed. The change is significant and minimal at the
same time, and was quite thoroughly tested now. As of this patch, all
accesses to the connection from upper layers go through the pass-through
mux.
2017-10-31 18:03:23 +01:00
Willy Tarreau
5f4a47b701 CLEANUP: threads: replace the last few 1UL<<tid with tid_bit
There were a few occurences left, better replace them now.
2017-10-31 15:59:32 +01:00
Thierry FOURNIER
952939d294 MEDIUM: threads/xref: Convert xref function to a thread safe model
Ensure that the unlink is done safely between thread and that
the peer struct will not destroy between the usage of the peer.
2017-10-31 13:58:32 +01:00
Thierry FOURNIER
94a6bfce9b MEDIUM: threads/lua: Cannot acces to the socket if we try to access from another thread.
We have two y for nsuring that the data is not concurently manipulated:
 - locks
 - running task on the same thread.
locks are expensives, it is better to avoid it.

This patch cecks that the Lua task run on the same thread that
the stream associated to the coprocess.

TODO: in a next version, the error should be replaced by a yield
and thread migration request.
2017-10-31 13:58:32 +01:00
Thierry FOURNIER
4325ab727c MEDIUM: threads/lua: Ensure that the launched tasks runs on the same threads than me
The applet manipulates the session and its buffers. We have two methods for
ensuring that the memory of the session will not change during its manipulation
by the task:
 1 - adding mutex
 2 - running on the same threads than the task.
The second point is smart because it cannot lock the execution of another thread.
2017-10-31 13:58:32 +01:00
Thierry FOURNIER
61ba0e2b6d MEDIUM: threads/lua: Add locks around the Lua execution parts.
Note that the Lua processing is not really thread safe. It provides
heavy system which consists to add our own lock function in the Lua
code and recompile the library. This system will probably not accepted
by maintainers of various distribs.

Our main excution point of the Lua is the function lua_resume(). A
quick looking on the Lua sources displays a lua_lock() a the start
of function and a lua_unlock() at the end of the function. So I
conclude that the Lua thread safe mode just perform a mutex around
all execution. So I prefer to do this in the HAProxy code, it will be
easier for distro maintainers.

Note that the HAProxy lua functions rounded by the macro SET_SAFE_LJMP
and RESET_SAFE_LJMP manipulates the Lua stack, so it will be careful
to set mutex around these functions.
2017-10-31 13:58:32 +01:00
Thierry FOURNIER
ffbad79027 MEDIUM: threads/lua: Makes the jmpbuf and some other buffers local to the current thread.
The jmpbuf contains pointer on the stack memory address currently use
when the jmpbuf is set. So the information is local to each thread.

The struct field is too big to put it in the stack, but it is used
as buffer for retriving stats values. So, this buffer si local to each
threads. Each function using this buffer, use it whithout break (yield)
so, the consistency of local buffer is ensured.
2017-10-31 13:58:32 +01:00
Emeric Brun
1138fd0c57 MAJOR: threads/applet: Handle multithreading for applets
A global lock has been added to protect accesses to the list of active
applets. A process mask has also been added on each applet. Like for FDs and
tasks, it is used to know which threads are allowed to process an
applet. Because applets are, most of time, linked to a session, it should be
sticky on the same thread. But in all cases, it is the responsibility of the
applet handler to lock what have to be protected in the applet context.
2017-10-31 13:58:31 +01:00
Christopher Faulet
40a007cf2a MEDIUM: threads/server: Make connection list (priv/idle/safe) thread-safe
For now, we have a list of each type per thread. So there is no need to lock
them. This is the easiest solution for now, but not the best one because there
is no sharing between threads. An idle connection on a thread will not be able
be used by a stream on another thread. So it could be a good idea to rework this
patch later.
2017-10-31 13:58:30 +01:00
Emeric Brun
c60def8368 MAJOR: threads/task: handle multithread on task scheduler
2 global locks have been added to protect, respectively, the run queue and the
wait queue. And a process mask has been added on each task. Like for FDs, this
mask is used to know which threads are allowed to process a task.

For many tasks, all threads are granted. And this must be your first intension
when you create a new task, else you have a good reason to make a task sticky on
some threads. This is then the responsibility to the process callback to lock
what have to be locked in the task context.

Nevertheless, all tasks linked to a session must be sticky on the thread
creating the session. It is important that I/O handlers processing session FDs
and these tasks run on the same thread to avoid conflicts.
2017-10-31 13:58:30 +01:00
Willy Tarreau
06d80a9a9c REORG: channel: finally rename the last bi_* / bo_* functions
For HTTP/2 we'll need some buffer-only equivalent functions to some of
the ones applying to channels and still squatting the bi_* / bo_*
namespace. Since these names have kept being misleading for quite some
time now and are really getting annoying, it's time to rename them. This
commit will use "ci/co" as the prefix (for "channel in", "channel out")
instead of "bi/bo". The following ones were renamed :

  bi_getblk_nc, bi_getline_nc, bi_putblk, bi_putchr,
  bo_getblk, bo_getblk_nc, bo_getline, bo_getline_nc, bo_inject,
  bi_putchk, bi_putstr, bo_getchr, bo_skip, bi_swpbuf
2017-10-19 15:01:08 +02:00
Emeric Brun
253e53e661 BUG/MAJOR: lua: scheduled task is freezing.
Since commit 'MAJOR: task: task scheduler rework'
0194897e54. LUA's
scheduling tasks are freezing.

A running task should not handle the scheduling itself
but let the task scheduler to handle it based on the
'expire' field.

[wt: no backport needed]
2017-10-18 19:23:33 +02:00
Willy Tarreau
0bf6fa5e40 MEDIUM: session: count the frontend's connections at a single place
There are several places where we see feconn++, feconn--, totalconn++ and
an increment on the frontend's number of connections and connection rate.
This is done exactly once per session in each direction, so better take
care of this counter in the session and simplify the callers. At least it
ensures a better symmetry. It also ensures consistency as till now the
lua/spoe/peers frontend didn't have these counters properly set, which can
be useful at least for troubleshooting.
2017-09-15 11:49:52 +02:00
Willy Tarreau
6f5e4b98df MEDIUM: session: take care of incrementing/decrementing jobs
Each user of a session increments/decrements the jobs variable at its
own place, resulting in a real mess and inconsistencies between them.
Let's have session_new() increment jobs and session_free() decrement
it.
2017-09-15 11:49:52 +02:00
Thierry FOURNIER
d697596c6c MINOR: tasks: Move Lua notification from Lua to tasks
These notification management function and structs are generic and
it will be better to move in common parts.

The notification management functions and structs have names
containing some "lua" references because it was written for
the Lua. This patch removes also these references.
2017-09-11 18:59:40 +02:00
Thierry FOURNIER
2da788e755 MEDIUM: xref/lua: Use xref for referencing cosocket relation between stream and lua
This relation will ensure that each was informed about death of another one.
2017-09-11 18:59:40 +02:00
Thierry FOURNIER
b01d28f976 BUG/MINOR: Lua: The socket may be destroyed when we try to access.
When we try to access to other proxy context, we must check
its existence because haproxy can kill it between the creation
and the usage.

This patch should be backported in 1.6 and 1.7
2017-09-11 18:59:40 +02:00
Emeric Brun
52a91d3d48 MEDIUM: check: server states and weight propagation re-work
The server state and weight was reworked to handle
"pending" values updated by checks/CLI/LUA/agent.
These values are commited to be propagated to the
LB stack.

In further dev related to multi-thread, the commit
will be handled into a sync point.

Pending values are named using the prefix 'next_'
Current values used by the LB stack are named 'cur_'
2017-09-05 15:23:16 +02:00
Willy Tarreau
87787acf72 MEDIUM: stream: make stream_new() allocate its own task
Currently a task is allocated in session_new() and serves two purposes :
  - either the handshake is complete and it is offered to the stream via
    the second arg of stream_new()

  - or the handshake is not complete and it's diverted to be used as a
    timeout handler for the embryonic session and repurposed once we land
    into conn_complete_session()

Furthermore, the task's process() function was taken from the listener's
handler in conn_complete_session() prior to being replaced by a call to
stream_new(). This will become a serious mess with the mux.

Since it's impossible to have a stream without a task, this patch removes
the second arg from stream_new() and make this function allocate its own
task. In session_accept_fd(), we now only allocate the task if needed for
the embryonic session and delete it later.
2017-08-30 07:05:04 +02:00
Willy Tarreau
585744bf2e REORG/MEDIUM: connection: introduce the notion of connection handle
Till now connections used to rely exclusively on file descriptors. It
was planned in the past that alternative solutions would be implemented,
leading to member "union t" presenting sock.fd only for now.

With QUIC, the connection will need to continue to exist but will not
rely on a file descriptor but a connection ID.

So this patch introduces a "connection handle" which is either a file
descriptor or a connection ID, to replace the existing "union t". We've
now removed the intermediate "struct sock" which was never used. There
is no functional change at all, though the struct connection was inflated
by 32 bits on 64-bit platforms due to alignment.
2017-08-24 19:30:04 +02:00
Willy Tarreau
ee1bdd5a03 OPTIM: lua: don't add "Connection: close" on the response
Haproxy doesn't need this anymore, we're wasting cycles checking for
a Connection header in order to add "Connection: close" only in the
1.1 case so that haproxy sees it and removes it. All tests were run
in 1.0 and 1.1, with/without the request header, and in the various
keep-alive/close modes, with/without compression, and everything works
fine. It's worth noting that this header was inherited from the stats
applet and that the same cleanup probably ought to be done there as
well.
2017-08-23 16:11:38 +02:00
Willy Tarreau
a329463655 OPTIM: lua: don't use expensive functions to parse headers in the HTTP applet
In the HTTP applet, we have to parse the response headers provided by
the application and to produce a response. strcasecmp() is expensive,
and chunk_append() even more as it uses a format string.

Here we check the string length before calling strcasecmp(), which
results in strcasecmp() being called only on the relevant header in
practise due to very few collisions on the name lengths, effectively
dividing the number of calls by 3, and we replace chunk_appendf()
with memcpy() as we already know the string lengths.

Doing just this makes the "hello-world" applet 5% faster, reaching
41400 requests/s on a core i5-3320M.
2017-08-23 16:11:38 +02:00
Willy Tarreau
c9f4ea0f61 MINOR: lua: properly process the contents of the content-length field
The header's value was parsed with atoi() then compared against -1,
meaning that all the unparsable stuff returning zero was not considered
and that all multiples of 2^32 + 0xFFFFFFFF would continue to emit a
chunk.

Now instead we parse the value using a long long, only accept positive
values and consider all unparsable values as incorrect and switch to
either close or chunked encoding. This is more in line with what a
client (including haproxy's parser) would expect.

This may be backported as a cleanup to stable versions, though it's
really unlikely that Lua applications are facing side effects of this.
2017-08-23 16:11:38 +02:00
Willy Tarreau
06c75fec17 BUG/MEDIUM: lua: HTTP services must take care of body-less status codes
The following Lua code causes emission of a final chunk after the body,
which is wrong :

core.register_service("send204", "http", function(applet)
   applet:set_status(204)
   applet:start_response()
end)

Indeed, responses with status codes 1xx, 204 and 304 do not contain any
body and the message ends immediately after the empty header (cf RFC7230)
so by emitting a 0<CR><LF> we're disturbing keep-alive responses. There's
a workaround against this for now which consists in always emitting
"Content-length: 0" but it may not be cool with 304 when clients use
the headers to update their cache.

This fix must be backported to stable versions back to 1.6.
2017-08-23 16:11:38 +02:00
Willy Tarreau
d958741886 BUG/MAJOR: lua: fix the impact of the scheduler changes again
Commit d1aa41f ("BUG/MAJOR: lua: properly dequeue hlua_applet_wakeup()
for new scheduler") tried to address the side effects of the scheduler
changes on Lua, but it was not enough. Having some Lua code send data
in chunks separated by one second each clearly shows busy polling being
done.

The issue was tracked down to hlua_applet_wakeup() being woken up on
timer expiration, and returning itself without clearing the timeout,
causing the task to be re-inserted with an expiration date in the past,
thus firing again. In the past it was not a problem, as returning NULL
was enough to clear the timer. Now we can't rely on this anymore so
it's important to clear this timeout.

No backport is needed, this issue is specific to 1.8-dev and results
from an incomplete fix in the commit above.
2017-08-23 16:07:33 +02:00
Willy Tarreau
d1aa41f83b BUG/MAJOR: lua: properly dequeue hlua_applet_wakeup() for new scheduler
The recent scheduler change broke the Lua co-sockets due to
hlua_applet_wakeup() returning NULL after waking the applet up. With the
previous scheduler, returning NULL was a way to do nothing on return.

With the new one it keeps TASK_RUNNING set, causing all new notifications
to end up into t->pending_state instead of t->state, and prevents the
task from being added into the run queue again, so and it's never woken
up anymore.

The applet keeps waking up, causing hlua_socket_handler() to do nothing
new, then si_applet_wake_cb() calling stream_int_notify() to try to wake
the task up, which it can't do due to the TASK_RUNNING flag, then decide
that since the associated task is not in the run queue, it needs to call
stream_int_update_applet() to propagate the update. This last one finds
that the applet needs to be woken up to deal with the last reported events
and calling appctx_wakeup() again. Previously, this situation didn't exist
because the task was always added in the run queue despite the TASK_RUNNING
flag.

By returning the task instead in hlua_applet_wakeup(), we can ensure its
flag is properly cleared and the task is requeued if needed or just sits
waiting for new events to happen.

This fix requires the previous ones ("BUG/MINOR: lua: always detach the
tcp/http tasks before freeing them") and MINOR: task: always preinitialize
the task's timeout in task_init().

Thanks to Thierry, Christopher and Emeric for the long head-scratching
session!

No backport is needed as the bug doesn't appear in older versions and
it's unsure whether we'll not break something by backporting it.
2017-07-24 18:14:49 +02:00
Willy Tarreau
bd7fc95edb BUG/MINOR: lua: always detach the tcp/http tasks before freeing them
In hlua_{http,tcp}_applet_release(), a call to task_free() is performed
to release the task, but no task_delete() is made on these tasks. Till
now it wasn't much of a problem because this was normally not done with
the task in the run queue, and the task was never put into the wait queue
since it doesn't have any timer. But with threading it will become an
issue. And not having this already prevents another bug from being fixed.

Thanks to Christopher for spotting this one. A backport to 1.7 and 1.6 is
preferred for safety.
2017-07-24 17:35:27 +02:00
Thierry FOURNIER
6b546a6048 BUG/MINOR: Lua: variable already initialized
The variable strm->hlua is already initilized by the function stream_new().
2017-07-18 06:41:58 +02:00
Thierry FOURNIER
7bd10d58d3 BUG/MEDIUM: lua: bad memory access
We cannot perform garbage collection on unreferenced thread.
This memory is now free and another Lua process can use it for
other things.

HAProxy is monothread, so this bug doesn't cause crash.

This patch must be backported in 1.6 and 1.7
2017-07-18 06:41:38 +02:00
Thierry FOURNIER
b13b20a19a BUG/MAJOR: lua/socket: resources not detroyed when the socket is aborted
In some cases, the socket is misused. The user can open socket and never
close it, or open the socket and close it without sending data. This
causes resources leak on all resources associated to the stream (buffer,
spoe, ...)

This is caused by the stream_shutdown function which is called outside
of the stream execution process. Sometimes, the shtudown is required
while the stream is not started, so the cleanup is ignored.

This patch change the shutdown mode of the session. Now if the session is
no longer used and the Lua want to destroy it, it just set a destroy flag
and the session kill itself.

This patch should be backported in 1.6 and 1.7
2017-07-18 06:41:33 +02:00
Thierry FOURNIER
75d0208009 BUG/MINOR: lua: executes the function destroying the Lua session in safe mode
When we destroy the Lua session, we manipulates Lua stack,
so errors can raises. It will be better to catch these errors.

This patch should be backported in 1.6 and 1.7
2017-07-18 06:41:28 +02:00
Thierry FOURNIER
0a97620c08 BUG/MINOR: lua: In error case, the safe mode is not removed
Just forgot of reset the safe mode. This have not consequences
the safe mode just set a pointer on fucntion which is called only
and initialises a longjmp.

Out of lua execution, this longjmp is never executed and the
function is never called.

This patch should be backported in 1.6 and 1.7
2017-07-18 06:41:19 +02:00
Emeric Brun
5f77fef34e MINOR: task/stream: tasks related to a stream must be init by the caller.
The task_wakeup was called on stream_new, but the task/stream
wasn't fully initialized yet. The task_wakeup must be called
explicitly by the caller once the task/stream is initialized.
2017-06-27 14:38:02 +02:00
Thierry FOURNIER
fd80df11c3 BUG/MEDIUM: lua: segfault if a converter or a sample doesn't return anything
In the case of a Lua sample-fetch or converter doesn't return any
value, an acces outside the Lua stack can be performed. This patch
check the stack size before converting the top value to a HAProxy
internal sample.

A workaround consist to check that a value value is always returned
with sample fetches and converters.

This patch should be backported in the version 1.6 and 1.7
2017-05-12 16:46:26 +02:00
Thierry FOURNIER
e068b60605 CLEANUP: lua: remove test
The man of "luaL_unref" says "If ref is LUA_NOREF or LUA_REFNIL,
luaL_unref does nothing.", so I remove the check.
2017-04-26 15:13:18 +02:00
Thierry FOURNIER
f326767711 BUG/MEDIUM: lua: memory leak
The priv context is not cleaned when we set a new priv context.
This is caused by a stupid swap between two parameter of the
luaL_unref() function.

workaround: use set_priv only once when we process a stream.

This patch should be backported in version 1.7 and 1.6
2017-04-26 15:13:18 +02:00
Willy Tarreau
42ef75fb84 MINOR: lua: ensure the memory allocator is used all the time
luaL_setstate() uses malloc() to initialize the first objects, and only
after this we replace the allocator. This creates trouble when replacing
the standard memory allocators during debugging sessions since the new
allocator is used to realloc() an area previously allocated using the
default malloc().

Lua provides lua_newstate() in addition to luaL_newstate(), which takes
an allocator for the initial malloc. This is exactly what we need, and
this patch does this and fixes the problem. The now useless call to
lua_setallocf() could be removed.

This has no impact outside of debugging sessions and there's no need to
backport this.
2017-04-13 17:10:15 +02:00
Thierry FOURNIER
7d38863552 BUG/MAJOR: lua segmentation fault when the request is like 'GET ?arg=val HTTP/1.1'
Error in the HTTP parser. The function http_get_path() can
return NULL and this case is not catched in the code. So, we
try to dereference NULL pointer, and a segfault occurs.

These two lines are useful to prevent the bug.

   acl prevent_bug path_beg /
	http-request deny if !prevent_bug

This bug fix should be backported in 1.6 and 1.7
2017-02-23 21:52:18 +01:00
Thierry FOURNIER
4dc7197338 BUG/MINOR: lua: Map.end are not reliable because "end" is a reserved keyword
This patch change the names prefixing it by a "_". So "end" becomes "_end".
The backward compatibility with names without the prefix "_" is assured.
In other way, another the keyword "end" can be used like this: Map['end'].

Thanks Robin H. Johnson for the bug repport

This should be backported in version 1.6 and 1.7
2017-01-30 20:29:10 +01:00
Jarno Huuskonen
16ad94adf6 MINOR: Use "500 Internal Server Error" for 500 error/status code message.
Internal Server Error is what is in RFC 2616/7231.
2017-01-11 12:44:40 +01:00
Willy Tarreau
48ef4c95b6 MINOR: tools: make str2sa_range() return the port in a separate argument
This will be needed so that we're don't have to extract it from the
returned address where it will not always be anymore (eg: for unresolved
servers).
2017-01-06 19:29:34 +01:00
Robin H. Johnson
52f5db2a44 MINOR: http: custom status reason.
The older 'rsprep' directive allows modification of the status reason.

Extend 'http-response set-status' to take an optional string of the new
status reason.

  http-response set-status 418 reason "I'm a coffeepot"

Matching updates in Lua code:
- AppletHTTP.set_status
- HTTP.res_set_status

Signed-off-by: Robin H. Johnson <robbat2@gentoo.org>
2017-01-06 11:57:44 +01:00
Willy Tarreau
17d4538044 MINOR: ssl_sock: implement and use prepare_srv()/destroy_srv()
Now we can simply check the transport layer at run time and decide
whether or not to initialize or destroy these entries. This removes
other ifdefs and includes from cfgparse.c, haproxy.c and hlua.c.
2016-12-22 23:26:38 +01:00
Willy Tarreau
a261e9b094 CLEANUP: connection: remove all direct references to raw_sock and ssl_sock
Now we exclusively use xprt_get(XPRT_RAW) instead of &raw_sock or
xprt_get(XPRT_SSL) for &ssl_sock. This removes a bunch of #ifdef and
include spread over a number of location including backend, cfgparse,
checks, cli, hlua, log, server and session.
2016-12-22 23:26:38 +01:00
Willy Tarreau
0320934f7e MEDIUM: ssl: remote the proxy argument from most functions
Most of the SSL functions used to have a proxy argument which was mostly
used to be able to emit clean errors using Alert(). First, many of them
were converted to memprintf() and don't require this pointer anymore.
Second, the rare which still need it also have either a bind_conf argument
or a server argument, both of which carry a pointer to the relevant proxy.

So let's now get rid of it, it needlessly complicates the API and certain
functions already have many arguments.
2016-12-22 23:26:38 +01:00
Willy Tarreau
bb57d94a96 CLEANUP: lua: use the build options list to report it
This removes 1 #ifdef from haproxy.c. The "build without" version
is not reported anymore now.
2016-12-21 21:30:54 +01:00
Thierry FOURNIER
2c8b54e7be MEDIUM: lua: remove Lua struct from session, and allocate it with memory pools
This patch use memory pools for allocating the Lua struct. This
save 128B of memory in the session if the Lua is unused.
2016-12-21 15:24:56 +01:00
Thierry FOURNIER
1be34152da BUG/MINOR: lua: memleak when Lua/cli fails
If the memory allocator fails, it return a bad code, and the execution
continue. If the Lua/cli initializer fails, the allocated struct is not
released.
2016-12-21 15:24:35 +01:00
Thierry FOURNIER
33558c4a3f BUG/MINOR: lua: bad return code
If the lua/cli fails during initialization, it returns an ok
status, an the execution continue. This will probably occur a
segfault.

Thiw patch should be backported in 1.7
2016-12-21 15:24:24 +01:00
Thierry FOURNIER
4e7c708612 BUG/MINOR: lua: memory leak executing tasks
The struct hlua isn't freed when the task is complete.

This patch should be backported in 1.6 and 1.7
2016-12-21 15:24:09 +01:00
Christopher Faulet
33834b15dc BUG/MINOR: Fix the sending function in Lua's cosocket
This is a regression from the commit a73e59b690.

When data are sent from a cosocket, the action is done in the context of the
applet running a lua stack and not in the context of the applet owning the
cosocket. So we must take care, explicitly, that this last applet have a buffer
(the req buffer of the cosocket).

This patch must be backported in 1.7
2016-12-21 15:22:08 +01:00
Thierry FOURNIER
3b0a6d480b MINOR/DOC: lua: just precise one thing
In the case of applet, the Lua context is taken from session
when we get the private values. This patch just update comments
associated to this action because it is not obvious.
2016-12-17 14:27:30 +01:00
Thierry FOURNIER
847ca66815 MINOR: lua/signals: Remove Lua part from signals.
The signals system embedded in Lua can be tranformed in general purpose
signals code. To reach this goal, this path removes the Lua part of the
signals.

This is an easy job, because Lua is useles with signal. I change just two
prototypes.
2016-12-16 16:46:57 +01:00
Thierry FOURNIER
ebed6e908a MEDIUM: lua: use memory pool for hlua struct in applets
The struct hlua size is 128 bytes. The size is the biggest of all the elements
of the union embedded in the appctx struct. With HTTP2, it is possible that this
appctx struct will be use many times for each connection, so the 128 bytes are
a little bit heavy for the global memory consomation.

This patch replace the embbeded hlua struct by a pointer and an associated memory
pool. Now, the memory for lua is allocated only if it is required.

[wt: the appctx is now down to 160 bytes]
2016-12-16 16:31:45 +01:00
Thierry FOURNIER
ffbf569edb BUG/MINOR: lua/cli: bad error message
Error message inherited from lua_appelet_tcp copy/paste.

Should be backported in 1.7
2016-12-16 16:25:51 +01:00
Thierry FOURNIER
18d0990a5d CLEANUP: lua: rename one of the lua appctx union
It is named hlua, which does not represent the usage of this variable.
this patch renames this one to "hlua_cosocket".
2016-12-16 12:59:00 +01:00
Willy Tarreau
8ae4f7533d CLEANUP: applet/lua: create a dedicated ->fcn entry in hlua_cli context
We have very few users of the appctx's private field which was introduced
prior to the split of the CLI. Unfortunately it was not removed after the
end. This commit simply introduces hlua_cli->fcn which is the pointer to
the Lua function that the Lua code used to store in this private pointer.
2016-12-14 16:48:16 +01:00
Thierry FOURNIER
11cfb3daec BUG/MEDIUM: lua: In some case, the return of sample-fetches is ignored (2)
This problem is already detected here:

   8dc7316a6f

Another case raises. Now HAProxy sends a final message (typically
with "http-request deny"). Once the the message is sent, the response
channel flags are not modified.

HAProxy executes a Lua sample-fecthes for building logs, and the
result is ignored because the response flag remains set to the value
HTTP_MSG_RPBEFORE. So the Lua function hlua_check_proto() want to
guarantee the valid state of the buffer and ask for aborting the
request.

The function check_proto() is not the good way to ensure request
consistency. The real question is not "Are the message valid ?", but
"Are the validity of message unchanged ?"

This patch memorize the parser state before entering int the Lua
code, and perform a check when it go out of the Lua code. If the parser
state change for down, the request is aborted because the HTTP message
is degraded.

This patch should be backported in version 1.6 and 1.7
2016-12-14 12:52:47 +01:00
Christopher Faulet
a73e59b690 BUG/MAJOR: Fix how the list of entities waiting for a buffer is handled
When an entity tries to get a buffer, if it cannot be allocted, for example
because the number of buffers which may be allocated per process is limited,
this entity is added in a list (called <buffer_wq>) and wait for an available
buffer.

Historically, the <buffer_wq> list was logically attached to streams because it
were the only entities likely to be added in it. Now, applets can also be
waiting for a free buffer. And with filters, we could imagine to have more other
entities waiting for a buffer. So it make sense to have a generic list.

Anyway, with the current design there is a bug. When an applet failed to get a
buffer, it will wait. But we add the stream attached to the applet in
<buffer_wq>, instead of the applet itself. So when a buffer is available, we
wake up the stream and not the waiting applet. So, it is possible to have
waiting applets and never awakened.

So, now, <buffer_wq> is independant from streams. And we really add the waiting
entity in <buffer_wq>. To be generic, the entity is responsible to define the
callback used to awaken it.

In addition, applets will still request an input buffer when they become
active. But they will not be sleeped anymore if no buffer are available. So this
is the responsibility to the applet I/O handler to check if this buffer is
allocated or not. This way, an applet can decide if this buffer is required or
not and can do additional processing if not.

[wt: backport to 1.7 and 1.6]
2016-12-12 19:11:04 +01:00
Thierry FOURNIER / OZON.IO
4394a2cc87 MINOR: lua: give HAProxy variable access to the applets
This patch give function for manipulating variables inside the
applet HTTP and applet TCP functions.
2016-12-12 14:34:56 +01:00
Thierry FOURNIER / OZON.IO
3e1d791a4a CLEANUP: hlua: just indent functions
Function indentation. The code is not modified. This is done in
the goal of better integration of the next patch
2016-12-12 14:34:56 +01:00
Thierry FOURNIER / OZON.IO
4b123bebe4 MINOR: lua: Allow argument for actions
(http|tcp)-(request|response) action cannot take arguments from the
configuration file. Arguments are useful for executing the action with
a special context.

This patch adds the possibility of passing arguments to an action. It
runs exactly like sample fetches and other Lua wrappers.

Note that this patch implements a 'TODO'.
2016-12-12 14:34:56 +01:00
Willy Tarreau
397131093f REORG: tcp-rules: move tcp rules processing to their own file
There's no more reason to keep tcp rules processing inside proto_tcp.c
given that there is nothing in common there except these 3 letters : tcp.
The tcp rules are in fact connection, session and content processing rules.
Let's move them to "tcp-rules" and let them live their life there.
2016-11-25 15:57:38 +01:00
William Lallemand
9ed6203aef REORG: cli: split dumpstats.h in stats.h and cli.h
proto/dumpstats.h has been split in 4 files:

  * proto/cli.h  contains protypes for the CLI
  * proto/stats.h contains prototypes for the stats
  * types/cli.h contains definition for the CLI
  * types/stats.h contains definition for the stats
2016-11-24 16:59:27 +01:00
Thierry FOURNIER / OZON.IO
8dc7316a6f BUG/MEDIUM: lua: In some case, the return of sample-fetche is ignored
When:

 - A Lua action return data and close the channel. The request status
   is set to HTTP_MSG_CLOSED for the request and HTTP_MSG_DONE for the
   response.

 - HAProxy sets the state HTTP_MSG_ERROR. I don't known why, because
   there are many line which sets this state.

 - A Lua sample-fetch is executed, typically for building the log
   line.

 - When the Lua sample fetch exits, a control of the data is
   executed. If HAProxy is currently parsing the request, the request
   is aborted in order to prevent a segfault or sending corrupted
   data.

This ast control is executed comparing the state HTTP_MSG_BODY. When
this state is reached, the request is parsed and no error are
possible. When the state is < than HTTP_MSG_BODY, the parser is
running.

Unfortunately, the code HTTP_MSG_ERROR is just < HTTP_MSG_BODY. When
we are in error, we want to terminate the execution of Lua without
error.

This patch changes the comparaison level.

This patch must be backported in 1.6
2016-11-19 00:29:19 +01:00
Thierry FOURNIER / OZON.IO
a44fdd95f9 MEDIUM: lua: Add cli handler for Lua
Now, HAProxy allows to register some keys in the "cli". This patch allows
to handle these keys with Lua code.
2016-11-18 14:32:03 +01:00
Willy Tarreau
a71f642b62 CLEANUP: lua: avoid directly calling getsockname/getpeername()
We already have per-protocol functions for this, and they already
take care of properly setting the CO_FL_ADDR_*_SET flags.
2016-11-16 17:32:57 +01:00
Thierry FOURNIER / OZON.IO
b41f22f59c CLEANUP: lua: control executed twice
The availaible size in the stack is check two times. This patch removes
this double check.

Must be backported in 1.6
2016-11-14 15:23:17 +01:00
Thierry FOURNIER / OZON.IO
02564fd153 CLEANUP: lua: move comment
Old comment is misplaced. Certainly due to a bad copy/paste

Must be backported in 1.6
2016-11-14 15:23:17 +01:00
Thierry FOURNIER / OZON.IO
65192f35d2 MINOR: lua: add function which return true if the channel is full.
Add function which return true if the channel is full. It is
useful for triggering some process when the buffer is full.
2016-11-12 10:42:25 +01:00
Christopher Faulet
85d79c94a9 MINOR: vars: Add 'unset-var' action/converter
It does the opposite of 'set-var' action/converter. It is really useful for
per-process variables. But, it can be used for any scope.

The lua function 'unset_var' has also been added.
2016-11-09 22:57:01 +01:00
Thierry FOURNIER / OZON.IO
b84ae92615 BUG/MEDIUM: lua: somme HTTP manipulation functions are called without valid requests
Somme HTTP manipulation functions are executed without valid and parsed
requests or responses. This causes a segmentation fault when the executed
code tries to change an empty buffer.

This patch must be backported in the 1.6 version
2016-08-03 00:06:13 +02:00
Thierry FOURNIER
9bd52d478b BUG/MEDIUM: lua: the function txn_done() from action wrapper can crash
If an action wrapper stops the processing of the transaction
with a txn_done() function, the return code of the action is
"continue". So the continue can implies the processing of other
like adding headers. However, the HTTP content is flushed and
a segfault occurs.

This patchs add a flag indicating that the Lua code want to
stop the processing, ths flags is forwarded to the haproxy core,
and other actions are ignored.

Must be backported in 1.6
2016-07-14 16:14:32 +02:00
Thierry FOURNIER
ab00df6cf6 BUG/MEDIUM: lua: the function txn_done() from sample fetches can crash
The function txn_done() ends a transaction. It does not make
sense to call this function from a lua sample-fetch wrapper,
because the role of a sample-fetch is not to terminate a
transaction.

This patch modify the role of the fucntion txn_done() if it
is called from a sample-fetch wrapper, now it just ends the
execution of the Lua code like the done() function.

Must be backported in 1.6
2016-07-14 16:14:24 +02:00
Thierry Fournier
4a53bfdc1d BUG/MEDIUM: lua: converters doesn't work
The number of arguments pushed in the stack are false, so we try to execute a
function out of the stack. This function is always a nil pointer, so the
following message is displayed.

   Lua converter 'testconv': runtime error: attempt to call a nil value.

Thanks Michael Ezzell for the repporting.

This patch must be backported in the 1.6 version.
2016-06-08 10:33:27 +02:00
Vincent Bernat
6e61589573 BUG/MAJOR: fix listening IP address storage for frontends
When compiled with GCC 6, the IP address specified for a frontend was
ignored and HAProxy was listening on all addresses instead. This is
caused by an incomplete copy of a "struct sockaddr_storage".

With the GNU Libc, "struct sockaddr_storage" is defined as this:

    struct sockaddr_storage
      {
        sa_family_t ss_family;
        unsigned long int __ss_align;
        char __ss_padding[(128 - (2 * sizeof (unsigned long int)))];
      };

Doing an aggregate copy (ss1 = ss2) is different than using memcpy():
only members of the aggregate have to be copied. Notably, padding can be
or not be copied. In GCC 6, some optimizations use this fact and if a
"struct sockaddr_storage" contains a "struct sockaddr_in", the port and
the address are part of the padding (between sa_family and __ss_align)
and can be not copied over.

Therefore, we replace any aggregate copy by a memcpy(). There is another
place using the same pattern. We also fix a function receiving a "struct
sockaddr_storage" by copy instead of by reference. Since it only needs a
read-only copy, the function is converted to request a reference.
2016-05-19 10:43:24 +02:00
David Carlier
0c437f4d35 MINOR: lua: migrate the argument mask to 64 bits type.
Recently the maximum number of arguments were ported to 12
due to the migration to 64 bits. So we allow lua to extend for
both converters and fetches.
2016-04-29 07:17:42 +02:00
David Carlier
abdb00fbc0 BUG/MEDIUM: lua: protects the upper boundary of the argument list for converters/fetches.
When a converter or sample is called from within a Lua code, there is a risk
of invalid argument string data usage when the upper boundary is reached.
Would be kind to port to 1.6 if possible.
2016-04-29 07:17:42 +02:00
Vincent Bernat
3c2f2f207f CLEANUP: remove unneeded casts
In C89, "void *" is automatically promoted to any pointer type. Casting
the result of malloc/calloc to the type of the LHS variable is therefore
unneeded.

Most of this patch was built using this Coccinelle patch:

@@
type T;
@@

- (T *)
  (\(lua_touserdata\|malloc\|calloc\|SSL_get_app_data\|hlua_checkudata\|lua_newuserdata\)(...))

@@
type T;
T *x;
void *data;
@@

  x =
- (T *)
  data

@@
type T;
T *x;
T *data;
@@

  x =
- (T *)
  data

Unfortunately, either Coccinelle or I is too limited to detect situation
where a complex RHS expression is of type "void *" and therefore casting
is not needed. Those cases were manually examined and corrected.
2016-04-03 14:17:42 +02:00
Thierry Fournier
3d4a675f24 MINOR: lua: post initialization
This patch adds a Lua post initialisation wrapper. It already exists for
pure Lua function, now it executes also C. It is useful for doing things
when the configuration is ready to use. For example we can can browse and
register all the proxies.
2016-03-30 15:44:58 +02:00
Thierry Fournier
fd107a2b1c MINOR: lua: precise message when a critical error is catched
This patch try to find error message when the safe execution wrapper
function catch a critical error.
2016-03-30 15:44:44 +02:00
Thierry Fournier
45e78d7aa9 MINOR: lua: refactor the Lua object registration
All the HAProxy Lua object are declared with the same pattern:
 - Add the function __tosting which dumps the object name
 - Register the name in the Lua REGISTRY
 - Register the reference ID

These action are refactored in on function. This remove some
lines of code.
2016-03-30 15:43:52 +02:00
Thierry Fournier
ddd8988fe5 MINOR: lua: move class registration facilities
The functions
 - hlua_class_const_int()
 - hlua_class_const_str()
 - hlua_class_function()
are use for common class registration actions.

The function 'hlua_dump_object()' is generic dump name function.

These functions can be used by all the HAProxy objects, so I move
it into the safe functions file.
2016-03-30 15:42:20 +02:00
Willy Tarreau
6204cd9f27 BUG/MAJOR: vars: always retrieve the stream and session from the sample
This is the continuation of previous patch called "BUG/MAJOR: samples:
check smp->strm before using it".

It happens that variables may have a session-wide scope, and that their
session is retrieved by dereferencing the stream. But nothing prevents them
from being used from a streamless context such as tcp-request connection,
thus crashing the process. Example :

    tcp-request connection accept if { src,set-var(sess.foo) -m found }

In order to fix this, we have to always ensure that variable manipulation
only happens via the sample, which contains the correct owner and context,
and that we never use one from a different source. This results in quite a
large change since a lot of functions are inderctly involved in the call
chain, but the change is easy to follow.

This fix must be backported to 1.6, and requires the last two patches.
2016-03-10 17:28:04 +01:00
Willy Tarreau
7560dd4b6a MINOR: sample: always set a new sample's owner before evaluating it
Some functions like sample_conv_var2smp(), var_get_byname(), and
var_set_byname() directly or indirectly need to access the current
stream and/or session and must find it in the sample itself and not
as a distinct argument. Thus we first need to call smp_set_owner()
prior to each such calls.
2016-03-10 16:42:58 +01:00
Willy Tarreau
1777ea63e0 MINOR: sample: add a new helper to initialize the owner of a sample
Since commit 6879ad3 ("MEDIUM: sample: fill the struct sample with the
session, proxy and stream pointers") merged in 1.6-dev2, the sample
contains the pointer to the stream and sample fetch functions as well
as converters use it heavily. This requires from a lot of call places
to initialize 4 fields, and it was even forgotten at a few places.

This patch provides a convenient helper to initialize all these fields
at once, making it easy to prepare a new sample from a previous one for
example.

A few call places were cleaned up to make use of it. It will be needed
by further fixes.

At one place in the Lua code, it was moved earlier because we used to
call sample casts with a non completely initialized sample, which is
not clean eventhough at the moment there are no consequences.
2016-03-10 16:42:58 +01:00
Willy Tarreau
be508f1580 BUG/MAJOR: samples: check smp->strm before using it
Since commit 6879ad3 ("MEDIUM: sample: fill the struct sample with the
session, proxy and stream pointers") merged in 1.6-dev2, the sample
contains the pointer to the stream and sample fetch functions as well
as converters use it heavily.

The problem is that earlier commit 87b0966 ("REORG/MAJOR: session:
rename the "session" entity to "stream"") had split the session and
stream resulting in the possibility for smp->strm to be NULL before
the stream was initialized. This is what happens in tcp-request
connection rulesets, as discovered by Baptiste.

The sample fetch functions must now check that smp->strm is valid
before using it. An alternative could consist in using a dummy stream
with nothing in it to avoid some checks but it would only result in
deferring them to the next step anyway, and making it harder to detect
that a stream is valid or the dummy one.

There is still an issue with variables which requires a complete
independant fix. They use strm->sess to find the session with strm
possibly NULL and passed as an argument. All call places indirectly
use smp->strm to build strm. So the problem is there but the API needs
to be changed to remove this duplicate argument that makes it much
harder to know what pointer to use.

This fix must be backported to 1.6, as well as the next one fixing
variables.
2016-03-10 16:42:58 +01:00
Thierry Fournier
9d5fb6d6a0 BUG/MINOR: lua: Useless copy
A value is copied two time in teh stack, but only one is usefull. The
second copy leaves unused in the stack and take some room for noting.

This path removes the second copy.

Must be backported in 1.6
2016-02-23 22:42:47 +01:00
Thierry Fournier
0164f200ab BUG/MAJOR: lua: applets can't sleep.
This patch must be backported in 1.6

hlua_yield() function returns the required sleep time. The Lua core must
be resume the execution after the required time. The core dedicated to
the http and tcp applet doesn't implement the wake up function. It is a
miss.

This patch fix this.
2016-02-20 18:55:33 +01:00
Thierry Fournier
e726b14d23 DOC: lua: copyrights 2016-02-19 13:24:21 +01:00
Thierry Fournier
9e7e3ea991 MINOR: lua: move common function
This patch moves the function hlua_checkudata which check that
an object contains the expected class_reference as metatable.
This function is commonly used by all the lua functions.
The function hlua_metatype is also moved.
2016-02-12 11:08:53 +01:00
Thierry Fournier
fb0b5467ca MINOR: lua: file dedicated to unsafe functions
When Lua executes functions from its API, these can throws an error.
These function must be executed in a special environment which catch
these error, otherwise a critical error (like segfault) can raise.

This patch add a c file called "hlua_fcn.c" which collect all the
Lua/c function needing safe environment for its execution.
2016-02-12 11:08:53 +01:00
Thierry Fournier
75933d48fe BUG/MINOR: lua: unsafe initialization
During the Lua HAProxy initialisation, C functions using Lua calls
can throws an error. This error was not catched. This patch fix
this behaviour.
2016-02-11 19:30:19 +01:00
Thierry FOURNIER
8db004cbf4 MINOR: lua: add set/get priv for applets
The applet can't have access to the session private data. This patch
fix this problem. Now an applet can use private data stored by actions
and fecthes.
2015-12-25 10:34:28 +01:00
Thierry FOURNIER
ed0bdaa623 CLEANUP: lua: bad error messages
An error message reference "register_service" in place of
"register_action".

This one should be backported to 1.6.
2015-12-20 23:13:01 +01:00
Thierry FOURNIER
52e2606188 BUG/MAJOR: lua: Do not force the HTTP analysers in use-services
INNER and XFERBODY analyzer were set in order to support HTTP applets
from TCP rulesets, but this does not work (cf previous patch).

Other cases already provides theses analyzers, so their addition is
not needed. Furthermore if INNER was set it could cause some headers
to be rewritten (ex: connection) after headers were already forwarded,
resulting in a crash in buffer_insert_line2().

Special thanks to Bernd Helm for providing very detailed information,
captures and stack traces making it possible to spot the root cause
here.

This fix must be backported to 1.6.
2015-12-20 23:13:01 +01:00
Thierry FOURNIER
718e2a73a2 BUG/MEDIUM: lua: Forbid HTTP applets from being called from tcp rulesets
HTTP applets request requires everything initilized by
"http_process_request" (analyzer flag AN_REQ_HTTP_INNER).
The applet will be immediately initilized, but its before
the call of this analyzer.

Due to this problem HTTP applets could be called with uncompletely
initialized http_txn.

This fix must be backported to 1.6.
2015-12-20 23:13:01 +01:00
Thierry FOURNIER
d93ea2b603 BUG/MINOR: lua: Lua applets must not use http_txn
In certain circumstances (eg: Lua HTTP applet called from a
TCP ruleset before http_process_request()), the HTTP TXN is not
yet fully initialized so some information it contains cannot be
relied on. Such information include the HTTP version, the state
of the expect: 100-continue header, the connection header and
the transfer-encoding header.

Here the bug only turns something which already doesn't work
into something wrong, but better avoid any references to the
http_txn from the Lua code to avoid future mistakes.

This patch should be backported into 1.6 for code consistency.
2015-12-20 23:13:00 +01:00
Thierry FOURNIER
ca98866bcf BUG/MEDIUM: lua: Lua applets must not fetch samples using http_txn
If a sample fetch needing http_txn is called from an HTTP Lua applet,
the result will be invalid and may even cause a crash because some HTTP
data can be forwarded and the HTTP txn is no longer valid.

Here the solution is to ensure that a fetch called from Lua never
needs http_txn. This is done thanks to a new flag HLUA_F_MAY_USE_HTTP
which indicates whether or not it is safe to call a fetch which needs
HTTP.

This fix needs to be backported to 1.6.
2015-12-20 23:13:00 +01:00
Thierry FOURNIER
7fa0549a2b REORG/MINOR: lua: convert boolean "int" to bitfield
This patch converts a boolean "int" to a bitfiled. The main
reason is to save space in the struct if another flag may will
be require.

Note that this patch is required for next fix and will need to be
backported to 1.6.
2015-12-20 23:13:00 +01:00
Thierry FOURNIER
841475e304 MINOR: lua: service/applet can have access to the HTTP headers when a POST is received
When a POST is processed by a Lua service, the HTTP header are
potentially gone. So, we cannot retrieve their content using
the standard "hdr" sample fetchs (which will soon become invalid
anyway) from an applet.

This patch add an entry "headers" to the object applet_http. This
entry is an array containing all the headers. It permits to use the
HTTP headers during the processing of the service.

Many thanks to Jan Bruder for reporting this issue with enough
details to reproduce it.

This patch will have to be backported to 1.6 since it will be the
only way to access headers from Lua applets.
2015-12-20 23:12:12 +01:00
Lukas Tribus
d334a2c843 BUG/MINOR: lua: don't force-sslv3 LUA's SSL socket
Sander Klein reported an error messages about SSLv3 not
being supported on Debian 8, although he didn't force-sslv3.

Vincent Bernat tracked this down to the LUA initialization, which
actually does force-sslv3.

This patch removes force-sslv3 from the LUA initialization, so
the LUA SSL socket can actually use TLS and doesn't trigger
warnings when SSLv3 is not supported by libssl (such as in
Debian 8).

This should be backported to 1.6.
2015-11-26 07:30:22 +01:00
Thierry FOURNIER
a3308fd8c1 BUG/MEDIUM: lua: clean output buffer
When the txn.done() fiunction is called, the ouput buffer is cleaned,
but the associated relative pointer on the HTTP requests elements
is not reseted.

This patch remove this cleanup, because the output buffer may contain
data to forward.
2015-11-06 01:15:34 +01:00
Thierry FOURNIER
c4eebc8157 BUG/MEDIUM: lua: sample fetches based on response doesn't work
The direction (request or response) is not propagated in the
sample fecthes called throught Lua. This patch adds the direction
status in some structs (hlua_txn and hlua_smp) to make sure that
the sample fetches will be called with all the information.

The converters can not access to a TXN object, so there are not
impacted the direction. However, the samples used as input of the
Lua converter wrapper are initiliazed with the direction. Thereby,
the struct smp stay consistent.
[wt: needs to be backported to 1.6]
2015-11-03 10:50:14 +01:00
Thierry FOURNIER
6e01f38e73 CLEANUP: use direction names in place of numeric values
This patch cleanups the direction names. It replaces numeric values,
by the associated defines. It ensure the compliance with values found
somwhere else in HAProxy.

It is required by the bugfix patch which is following.
[wt: needs to be backported to 1.6]
2015-11-03 10:48:00 +01:00
Thierry FOURNIER
26a7aacaff BUG/MEDIUM: lua: direction test failed
Lua needs to known the direction of the http data processed (request or
response). It checks the flag SMP_OPT_DIR_REQ, buf this flag is 0. This patch
correctly checks the flags after applying the SMP_OPT_DIR mask.
2015-10-13 15:49:31 +02:00
Vincent Bernat
a72db18243 MINOR: lua: fix a spelling error in some error messages
"unknown" was spelled "unkown".
2015-10-10 08:13:37 +02:00
Willy Tarreau
0078bfcb43 BUG/MEDIUM: lua: force server-close mode on Lua services
Thierry reported that keep-alive still didn't cope well with Lua
services. The reason is that for now applets have to be closed at
the end of a transaction so we want to work in server-close mode,
which isn't noticeable by the client since it still sees keep-alive.
Additionally we want to enable the request body transfer analyser
which will be needed to synchronize with the response analyser to
indicate the end of the transfer.
2015-10-07 20:24:05 +02:00
Thierry FOURNIER
56da1012d2 MINOR: lua: rename the tune.lua.applet-timeout
The name of applet is "service", so this patch renames the
tune.lua.applet-timeout to tune.lua.service-timeout
2015-10-02 22:56:10 +02:00
Thierry FOURNIER
10770faf8e MEDIUM: lua: change the timeout execution
Now, the Lua timeout is relative to the effective run time.
When the Lua is waiting for I/O, this time is not took in
lua run time account.
2015-09-29 19:13:49 +02:00
Thierry FOURNIER
bee90aeda1 MINOR: lua: remove the run flag
Only the main execution function can set the run flag, because it is
the last function before the execution time.

This patch removes the flag set by another function. It will be used
by the new lua timeout counter.
2015-09-29 18:57:03 +02:00
Thierry FOURNIER
a30b5dbf85 MINOR: lua: add AppletHTTP class and service
This class is used by Lua code for running as an applet called in HTTP mode
It defines also the associated lua service
2015-09-28 01:03:48 +02:00
Thierry FOURNIER
f0a64b676f MINOR: lua: add AppletTCP class and service
This class is used by Lua code for running as an applet called in TCP mode.
It defines also the lua service.
2015-09-28 01:03:48 +02:00
Thierry FOURNIER
2f3867f429 BUG/MEDIUM: lua: don't reset undesired flags in hlua_ctx_resume
Some flags like HLUA_MUST_GC must not be cleared otherwise sessions are
not properly cleaned.
2015-09-28 01:03:43 +02:00
Thierry FOURNIER
7c39ab4ac2 OPTIM/MEDIUM: lua: executes the garbage collector only when using cosocket
The garbage collector is a little bit heavy to run, and it was added
only for cosockets. This patch prevent useless executions when no
cosockets are used.
2015-09-27 22:56:40 +02:00
Thierry FOURNIER
6ab4d8ec0e MEDIUM: lua: change the GC policy
The GC is run each times that an Lua function exit with an error or with a success.
2015-09-27 22:22:37 +02:00
Thierry FOURNIER
6d695e6314 BUG/MEDIUM: lua: socket destroy before reading pending data
When the channel is down, the applet is waked up. Before this patch,
the applet closes the stream and the unread data are discarded.

After this patch, the stream is not closed except if the buffers are
empty.

It will be closed later by the close function, or by the garbage collector.
2015-09-27 21:50:26 +02:00
Thierry FOURNIER
8c8fbbe103 MINOR: lua/applet: the cosocket applet should use appctx_wakeup in place of task_wakeup
It seems that in the new applet system, the applet me be wakeup with the
function appctx_wakeup() in place of the function task_wakeup().
2015-09-27 19:30:26 +02:00
Thierry FOURNIER
c2f5653452 MINOR: lua: extend socket address to support non-IP families
The HAProxy Lua socket respects the Lua Socket tcp specs. these specs
are a little bit limited, it not permits to connect to unix socket.

this patch extends a little it the specs. It permit to accept a
syntax that begin with "unix@", "ipv4@", "ipv6@", "fd@" or "abns@".
2015-09-27 15:04:32 +02:00
Willy Tarreau
528192d310 MEDIUM: lua: only allow actions to yield if not in a final call
Actions may yield but must not do it during the final call from a ruleset
because it indicates there will be no more opportunity to complete or
clean up. This is indicated by ACT_FLAG_FINAL in the action's flags,
which must be passed to hlua_resume().

Thanks to this, an action called from a TCP ruleset is properly woken
up and possibly finished when the client disconnects.
2015-09-27 11:04:19 +02:00
Willy Tarreau
658b85b68d MEDIUM: actions: pass a new "flags" argument to custom actions
Since commit bc4c1ac ("MEDIUM: http/tcp: permit to resume http and tcp
custom actions"), some actions may yield and be called back when new
information are available. Unfortunately some of them may continue to
yield because they simply don't know that it's the last call from the
rule set. For this reason we'll need to pass a flag to the custom
action to pass such information and possibly other at the same time.
2015-09-27 11:04:06 +02:00
Thierry FOURNIER
eba6f64a5f BUG/MEDIUM: lua: wakeup task on bad conditions
the condition was :
 * wakeup for read if the output channel contains data
 * wakeup for write if the input channel have some room.
2015-09-27 11:03:19 +02:00
Thierry FOURNIER
5a50a85f4f BUG/MEDIUM: lua: forces a garbage collection
When a thread stops this patch forces a garbage collection which
cleanup and free the memory.

The HAProxy Lua Socket class contains an HAProxy session, so it
uses a big amount of memory, in other this Socket class uses a
filedescriptor and maintain a connection open.

If the class Socket is stored in a global variable, the Socket stay
alive along of the life of the process (except if it is closed by the
other size, or if a timeout is reached). If the class Socket is stored
in a local variable, it must die with this variable.

The socket is closed by a call from the garbage collector. And the
portability and use of a variable is known by the same garbage collector.

so, running the GC just after the end of all Lua code ensure that the
heavy resources like the socket class are freed quickly.
2015-09-27 11:03:08 +02:00
Willy Tarreau
3adac08849 BUG/MEDIUM: lua: properly set the target on the connection
Not having the target set on the connection causes it to be released
at the last moment, and the destination address to randomly be valid
depending on the data found in the memory at this moment. In practice
it works as long as memory poisonning is disabled. The deep reason is
that connect_server() doesn't expect to be called with SF_ADDR_SET and
an existing connection with !reuse. This causes the release of the
connection, its reallocation (!reuse), and taking the address from the
newly allocated connection. This should certainly be improved.
2015-09-26 17:56:23 +02:00
Willy Tarreau
9af89f7905 BUG/MEDIUM: lua: better fix for the protocol check
Commit d75cb0f ("BUG/MAJOR: lua: segfault after the channel data is
modified by some Lua action.") introduced a regression causing an
action run from a TCP rule in an HTTP proxy to end in HTTP error
if it terminated cleanly, because it didn't parse the HTTP request!

Relax the test so that it takes into account the opportunity for the
analysers to parse the message.
2015-09-26 11:50:08 +02:00
Willy Tarreau
de70fa17a9 MINOR: lua: use the proper applet wakeup mechanism
The lua code must the the appropriate wakeup mechanism for cosockets.
It wakes them up from outside the stream and outside the applet, so it
shouldn't use the applet's wakeup callback which is designed only for
use from within the applet itself. For now it didn't cause any trouble
(yet).
2015-09-26 11:25:05 +02:00
Thierry FOURNIER
10e5bc76c7 BUG/MEDIUM: lua: longjmp function must be unregistered
the longjmp function must be unregistered when we leaves the function
who install it.
2015-09-26 01:34:29 +02:00
Willy Tarreau
7a4501757f CLEANUP: lua: remove unneeded memset(0) after calloc()
No need for these memset() anymore, since calloc() was put there
to avoid them.
2015-09-26 01:33:24 +02:00
Thierry FOURNIER
3c7a77c0e7 CLEANUP: lua: use calloc in place of malloc
calloc is safer because it fills the allocated memory zone with zeros.
2015-09-26 01:32:06 +02:00
Thierry FOURNIER
d75cb0fce6 BUG/MAJOR: lua: segfault after the channel data is modified by some Lua action.
When an action or a fetch modify the channel data, the http request parser
pointer become inconsistent. This patch detects the modification and call
again the parser.
2015-09-26 00:37:55 +02:00
Thierry FOURNIER
84e73c8882 MEDIUM: lua: use the function lua_rawset in place of lua_settable
The function lua_settable uses the metatable for acessing data,
so in the C part, we want to index value in the real table and
not throught the meta-methods. It's much faster this way.
2015-09-26 00:37:35 +02:00
Thierry FOURNIER
d2a3dcc8bd MINOR: lua: identify userdata objects
This patch adds lua primitives for identifying lua class
associated with userdata.
2015-09-25 23:40:20 +02:00
Thierry FOURNIER
a7b536b53b MINOR: lua: reset pointer after use
After releasing the Lua environment, this patch set the only one pointer to
the Lua stack to NULL. This prevents an accidental re-use.
2015-09-25 23:40:02 +02:00
Willy Tarreau
aa977ba205 MINOR: stream-int: rename si_applet_done() to si_applet_wake_cb()
This function is a callback made only for calls from the applet handler.
Rename it to remove confusion. It's currently called from the Lua code
but that's not correct, we should call the notify and update functions
instead otherwise it will not enable the applet again.
2015-09-25 21:16:02 +02:00
Thierry FOURNIER
8255a75e08 MINOR: lua: change actions registration
The current Lua action are not registered. The executed function is
selected according with a function name writed in the HAProxy configuration.

This patch add an action registration function. The configuration mode
described above disappear.

This change make some incompatibilities with existing configuration files for
HAProxy 1.6-dev.
2015-09-23 21:44:23 +02:00
Thierry FOURNIER
ccf0063896 BUG/MINOR: lua: breaks the log message if his size exceed one buffer
Previously, the log was ignored if the log message exceed one buffer.
This patch doens't ignore the log, but trancate the message.
2015-09-17 17:51:51 +02:00
Thierry FOURNIER
babae28c87 BUG/MAJOR: lua: potential unexpected aborts()
This couple of function executes securely some Lua calls outside of
the lua runtime environment. Each Lua call can return a longjmp
if it encounter a memory error.

Lua documentation extract:

   If an error happens outside any protected environment, Lua calls
   a panic function (see lua_atpanic) and then calls abort, thus
   exiting the host application. Your panic function can avoid this
   exit by never returning (e.g., doing a long jump to your own
   recovery point outside Lua).

   The panic function runs as if it were a message handler (see
   2.3); in particular, the error message is at the top of the
   stack. However, there is no guarantee about stack space. To push
   anything on the stack, the panic function must first check the
   available space (see 4.2).

We must check all the Lua entry point. This includes:
 - The include/proto/hlua.h exported functions
 - the task wrapper function
 - The action wrapper function
 - The converters wrapper function
 - The sample-fetch wrapper functions

It is tolerated that the initilisation function returns an abort.
Before each Lua abort, an error message is writed on stderr.

The macro SET_SAFE_LJMP initialise the longjmp. The Macro
RESET_SAFE_LJMP reset the longjmp. These function must be macro
because they must be exists in the program stack when the longjmp
is called
2015-09-17 17:51:29 +02:00
Thierry FOURNIER
23bc375c59 CLEANUP: lua: Merge log functions
All the code which emits error log have the same pattern. Its:
Send log with syslog system, and if it is allowed, display error
log on screen.

This patch replace this pattern by a macro. This reduces the number
of lines.
2015-09-11 20:58:04 +02:00
Thierry FOURNIER
5554e2983d BUG/MINOR: lua: last log character truncated.
The send_log function needs a final \n.

This bug is repported by Michael Ezzell.

Minor bug: when writing to syslog from Lua scripts, the last character from
each log entry is truncated.

core.Alert("this is truncated");

Sep  7 15:07:56 localhost haproxy[7055]: this is truncate

This issue appears to be related to the fact that send_log() (in src/log.c)
is expecting a newline at the end of the message's format string:

/*
 * This function adds a header to the message and sends the syslog message
 * using a printf format string. It expects an LF-terminated message.
 */
void send_log(struct proxy *p, int level, const char *format, ...)

I believe the fix would be in in src/hlua.c at line 760
<http://git.haproxy.org/?p=haproxy.git;a=blob;f=src/hlua.c;h=1e4d47c31e66c16c837ff2aa5ef577f6cafdc7e7;hb=316e3196285b89a917c7d84794ced59a6a5b4eba#l760>,
where this...

   send_log(px, level, "%s", trash.str);

...should be adding a newline into the format string to accommodate what
the code expects.

    send_log(px, level, "%s\n", trash.str);

This change provides what seems to be the correct behavior:

Sep  7 15:08:30 localhost haproxy[7150]: this is truncated

All other uses of send_log() in hlua.c have a trailing dot "." in the
message that is masking the truncation issue because the output message
stops on a clean word boundary.  I suspect these would also benefit from
"\n" appended to their format strings as well, since this appears to be the
pattern seen throughout the rest of the code base.

Reported-by: Michael Ezzell <michael@ezzell.net>
2015-09-09 22:12:27 +02:00
Thierry FOURNIER
316e319628 BUG/MEDIUM: lua: outgoing connection was broken since 1.6-dev2 (bis)
See commit id bdc97a8795

Michael Ezzell reported that the following Lua code fails in
dev4 when the TCP is not established immediately (due to a little
bit of latency):

   function tricky_socket()
        local sock = core.tcp();
        sock:settimeout(3);
        core.log(core.alert,"calling connect()\n");
        local connected, con_err = sock:connect("x.x.x.x",80);
        core.log(core.alert,"returned from connect()\n");
        if con_err ~= nil then
          core.log(core.alert,"connect() failed with error: '" .. con_err .. "'\n");
        end

The problem is that the flags who want to wake up the applet are
resetted before each applet call, so the applet must set again the
flags if the connection is not established.
2015-09-06 08:22:49 +02:00
Thierry FOURNIER
42148735bc MEDIUM: actions: remove ACTION_STOP
Before this patch, two type of custom actions exists: ACT_ACTION_CONT and
ACT_ACTION_STOP. ACT_ACTION_CONT is a non terminal action and ACT_ACTION_STOP is
a terminal action.

Note that ACT_ACTION_STOP is not used in HAProxy.

This patch remove this behavior. Only type type of custom action exists, and it
is called ACT_CUSTOM. Now, the custion action can return a code indicating the
required behavior. ACT_RET_CONT wants that HAProxy continue the current rule
list evaluation, and ACT_RET_STOP wants that HAPRoxy stops the the current rule
list evaluation.
2015-09-02 18:36:38 +02:00
Willy Tarreau
630ef4585a BUG/MEDIUM: lua: fix a segfault in txn:done() if called twice
When called from an http ruleset, txn:done() can still crash the process
because it closes the stream without consuming pending data resulting in
the transaction's buffer representation to differ from the real buffer.

This patch also adjusts the transaction's state to indicate that it's
closed to be consistent with what's already done in redirect rules.
2015-08-28 10:28:24 +02:00
Willy Tarreau
a678b43119 CLEANUP: lua: fix some indent issues
Just the result from a few copy-pastes with different tab sizes.
2015-08-28 10:16:23 +02:00
Thierry FOURNIER
e1587b3314 BUG/MEDIUM: lua: cannot process more Lua hooks after a "done()" function call
When the Lua execution flow endswith the command done (core.done or txn.done())
an error is detourned, and the stack is no longer usable. This patch juste
reinitilize the stack if this case is detected.
2015-08-28 10:12:49 +02:00
Willy Tarreau
0458b08a5a BUG/MEDIUM: lua: txn:done() still causes a segfault in TCP mode
We must not dereference s->txn to get the channel, as it doesn't
exist in TCP mode.
2015-08-28 09:40:04 +02:00
Thierry FOURNIER
4bb375ca18 MEDIUM: lua: turns txn:close into txn:done
The function txn:close() must be terminal because it demands the session
destruction. This patch renames this function to "done()" to be much
clearer about the fact that it is a final operation.
2015-08-27 14:33:52 +02:00
Thierry FOURNIER
35d70efc33 MINOR: http: Action for manipulating the returned status code.
This patch is inspired by Bowen Ni's proposal and it is based on his first
implementation:

   With Lua integration in HAProxy 1.6, one can change the request method,
   path, uri, header, response header etc except response line.
   I'd like to contribute the following methods to allow modification of the
   response line.

   [...]

   There are two new keywords in 'http-response' that allows you to rewrite
   them in the native HAProxy config. There are also two new APIs in Lua that
   allows you to do the same rewriting in your Lua script.

   Example:
   Use it in HAProxy config:
   *http-response set-code 404*
   Or use it in Lua script:
   *txn.http:res_set_reason("Redirect")*

I dont take the full patch because the manipulation of the "reason" is useless.
standard reason are associated with each returned code, and unknown code can
take generic reason.

So, this patch can set the status code, and the reason is automatically adapted.
2015-08-27 14:29:44 +02:00
Thierry FOURNIER
93405e1fde BUG/MINOR: lua: in some case a sample may remain undefined
When we transform a top stack entry in sample, the empty stack case
is not handled. This patch fix this behavior.
2015-08-27 11:31:02 +02:00
Thierry FOURNIER
0a99b89531 MINOR: lua: add core.done() function
This function immediately give back the control to HAProxy core.
2015-08-27 11:27:29 +02:00
Thierry FOURNIER
10ec214f41 BUG/MEDIUM: lua: the lua fucntion Channel:close() causes a segfault
The function dont remove remaineing analysers and dont update response
channel timeout.

The fix is a copy of the behavior of the functions http_apply_redirect_rule()
and stream_int_retnclose().
2015-08-25 18:24:11 +02:00
Willy Tarreau
bdc97a8795 BUG/MEDIUM: lua: outgoing connection was broken since 1.6-dev2
Tsvetan Tsvetanov reported that the following Lua code fails in
dev2 and dev3 :

	function hello(txn)
	    local request_msg = txn.req:dup()
	    local tsm_sock = core.tcp()
	    tsm_sock:connect("127.0.0.1", 7777)
	    local res = tsm_sock:send(request_msg)
	    local response = tsm_sock:receive('*l')
	    txn.res:send(response)
	    txn:close()
	end

Thierry diagnosed that it was caused by commit 563cc37 ("MAJOR: stream:
use a regular ->update for all stream interfaces"). It broke lua's
ability to establish outgoing connections.

The reason is that the applet used to be notified about established
connections just after the stream analyser loop, and that's not the
case anymore. In peers, this issue didn't happen because peers use
a handshake so after sending data, the response is received and wakes
the applet up again. Here we have to indicate that we want to send or
receive data, this will cause the notification to happen as soon as
the connection is ready. This is similar to pretending that we're
working on a full buffer after all. In theory subscribing for reads
is not needed, but it's added here for completeness.

Reported-By: Tsvetan Tsvetanov <cpi.cecko@gmail.com>
2015-08-25 16:58:00 +02:00
Thierry FOURNIER
4dc15d1a2d MINOR: actions: Remove wrappers
Now the prototype for each action from each section are the same, and
a discriminant for determining for each section we are called are added.
So, this patch removes the wrappers for the action functions called from
more than one section.

This patch removes 132 lines of useless code.
2015-08-20 17:13:47 +02:00
Thierry FOURNIER
afa80496db MEDIUM: actions: Normalize the return code of the configuration parsers
This patch normalize the return code of the configuration parsers. Before
these changes, the tcp action parser returned -1 if fail and 0 for the
succes. The http action returned 0 if fail and 1 if succes.

The normalisation does:
 - ACT_RET_PRS_OK for succes
 - ACT_RET_PRS_ERR for failure
2015-08-20 17:13:47 +02:00
Thierry FOURNIER
c2bb050f7f MINOR: proto_tcp: proto_tcp.h is now useles
After removing the keyword register from types/proto_tcp.h, the header
file remains empty. This patch remove it
2015-08-20 17:13:47 +02:00
Thierry FOURNIER
36481b8667 MEDIUM: actions: Merge (http|tcp)-(request|reponse) keywords structs
This patch merges the conguration keyword struct. Each declared configuration
keyword struct are similar with the others. This patch simplify the code.
2015-08-20 17:13:47 +02:00
Thierry FOURNIER
24ff6c6fce MEDIUM: actions: Add standard return code for the action API
Action function can return 3 status:
 - error if the action encounter fatal error (like out of memory)
 - yield if the action must terminate his work later
 - continue in other cases
2015-08-20 17:13:47 +02:00
Thierry FOURNIER
0ea5c7fafa MINOR: actions: change actions names
For performances considerations, some actions are not processed by remote
function. They are directly processed by the function. Some of these actions
does the same things but for different processing part (request / response).

This patch give the same name for the same actions, and change the normalization
of the other actions names.

This patch is ONLY a rename, it doesn't modify the code.
2015-08-20 17:13:47 +02:00
Thierry FOURNIER
91f6ba0f2c MINOR: actions: Declare all the embedded actions in the same header file
This patch group the action name in one file. Some action are called
many times and need an action embedded in the action caller. The main
goal is to have only one header file grouping all definitions.
2015-08-20 17:13:47 +02:00
Thierry FOURNIER
231ef1d99c MINOR: lua: use the hlua_rule type in place of opaque type
The (http|tcp)-(request|response) action rules use common
opaque type. For the HAProxy embbedded feature, types are know,
it better to add this types in the action union and use it.
2015-08-20 17:13:46 +02:00
Thierry FOURNIER
7677f400f5 MINOR: actions: Remove the data opaque pointer
This patch removes the "data" opaque pointer and replace it by the generic
opaque pointer "p[0]".
2015-08-20 17:13:46 +02:00
Thierry FOURNIER
a28a9429b2 MEDIUM: actions: Merge (http|tcp)-(request|reponse) action structs
This patch is the first of a serie which merge all the action structs. The
function "tcp-request content", "tcp-response-content", "http-request" and
"http-response" have the same values and the same process for some defined
actions, but the struct and the prototype of the declared function are
different.

This patch try to unify all of these entries.
2015-08-20 17:13:46 +02:00
Thierry FOURNIER
136f9d34a9 MINOR: samples: rename union from "data" to "u"
The union name "data" is a little bit heavy while we read the source
code because we can read "data.data.sint". The rename from "data" to "u"
makes the read easiest like "data.u.sint".
2015-08-20 17:13:46 +02:00
Thierry FOURNIER
8c542cac07 MEDIUM: samples: Use the "struct sample_data" in the "struct sample"
This patch remove the struct information stored both in the struct
sample_data and in the striuct sample. Now, only thestruct sample_data
contains data, and the struct sample use the struct sample_data for storing
his own data.
2015-08-20 17:13:46 +02:00
Thierry FOURNIER
503bb09873 MINOR: samples: rename some struct member from "smp" to "data"
This members contains data and not sample.
2015-08-20 17:13:46 +02:00
Thierry FOURNIER
c7d7607351 BUG/MEDIUM: lua: bad error processing
When the lua actions (http|tcp)-(request|rersponse) fails a yield is
returned. this patch fix the behavior and returns a continue.
2015-08-19 10:54:06 +02:00
Thierry FOURNIER
422a3af4ce MINOR: proto_tcp: add session in the action prototype
Some actions require the "struct session" while the "struct stream" is not
avalaible. This patch adds a pointer to the session.
2015-08-11 14:08:29 +02:00
Thierry FOURNIER
a6b6343cff CLEANUP: http/tcp actions: remove the scope member
The scope member is not used. This patch removes this entry.
2015-08-11 13:44:53 +02:00
Thierry FOURNIER
61e96c68b9 BUG/MEDIUM: lua: timeout error with converters, wrapper and actions.
test conf:

   global
      tune.lua.session-timeout 0
      lua-load lol.lua
      debug
      maxconn 4096

   listen test
	   bind 0.0.0.0:10010
		mode tcp
		tcp-request content lua act_test
		balance roundrobin
		server test 127.0.0.1:3304

lua test:

   function act_test(txn)
      while true do
         core.Alert("TEST")
      end
   end

The function "act_test()" is not executed because a zero timeout is not
considered as TICK_ETERNITY, but is considered as 0.

This path fix this behavior. This is the same problem than the bugfix
685c014e99.
2015-08-10 06:18:30 +02:00
Camilo Lopez
685c014e99 BUG/MEDIUM: lua: Lua tasks fail to start.
I've been trying out 1.6 dev3 with lua support, and trying to start
lua tasks seems to not be working.

Using this configuration

global
  lua-load /lua/lol.lua
  debug
  maxconn 4096

backend shard_b
  server db01 mysql_shard_b:3306

backend shard_a
  server db01 mysql_shard_a:3306

listen mysql-cluster
  bind 0.0.0.0:8001
  mode tcp
  balance roundrobin
  use_backend shard_b

And this lua function

  core.register_task(function()
    while true do
      core.Alert("LOLOLOLOLOL")
    end
  end)

I'd always get a timeout error starting the registered function.

The problem lies as far as I can tell in the fact that is possible for
now_ms to not change (is this maybe a problem on my config/system?)
until the expiration check happens, in the resume function that
actually kickstarts the lua task, making HAProxy think that expiration
time for the task is up, if I understand correctly tasks are meant to
never really timeout.
2015-08-09 10:22:34 +02:00
Willy Tarreau
7017cb040c MINOR: server: add a list of safe, already reused idle connections
These ones are considered safe as they have already been reused.
They will be useful in "aggressive" and "always" http-reuse modes
in order to place the first request of a connection with the least
risk.
2015-08-06 16:29:01 +02:00
Willy Tarreau
173a1c6b43 MINOR: server: add a list of already used idle connections
There's a difference with the other idle conns in that these new
ones have already been used and may be reused by other streams.
2015-08-06 11:13:47 +02:00
Willy Tarreau
600802aef0 MINOR: server: add a list of private idle connections
For now it's not populated but we have the list entry. It will carry
all idle connections that sessions don't want to share. They may be
used later to reclaim connections upon socket shortage for example.
2015-08-06 10:59:08 +02:00
Willy Tarreau
973a54235f MEDIUM: stream-int: simplify si_alloc_conn()
Since we now always call this function with the reuse parameter cleared,
let's simplify the function's logic as it cannot return the existing
connection anymore. The savings on this inline function are appreciable
(240 bytes) :

$ size haproxy.old haproxy.new
   text    data     bss     dec     hex filename
1020383   40816   36928 1098127  10c18f haproxy.old
1020143   40816   36928 1097887  10c09f haproxy.new
2015-08-05 21:51:09 +02:00
Thierry FOURNIER
bf65cd4d77 MAJOR: arg: converts uint and sint in sint
This patch removes the 32 bits unsigned integer and the 32 bit signed
integer. It replaces these types by a unique type 64 bit signed.
2015-07-22 00:48:23 +02:00
Thierry FOURNIER
07ee64ef4d MAJOR: sample: converts uint and sint in 64 bits signed integer
This patch removes the 32 bits unsigned integer and the 32 bit signed
integer. It replaces these types by a unique type 64 bit signed.

This makes easy the usage of integer and clarify signed and unsigned use.
With the previous version, signed and unsigned are used ones in place of
others, and sometimes the converter loose the sign. For example, divisions
are processed with "unsigned", if one entry is negative, the result is
wrong.

Note that the integer pattern matching and dotted version pattern matching
are already working with signed 64 bits integer values.

There is one user-visible change : the "uint()" and "sint()" sample fetch
functions which used to return a constant integer have been replaced with
a new more natural, unified "int()" function. These functions were only
introduced in the latest 1.6-dev2 so there's no impact on regular
deployments.
2015-07-22 00:48:23 +02:00
Thierry FOURNIER
29176f3ebb BUG/MINOR: lua: type error in the arguments wrapper
The expected arguments time and size are returned as int. This patch
fix this bug and returns the expected type.
2015-07-10 16:29:31 +02:00