haproxy/include/proto
Christopher Faulet d7c9196ae5 MAJOR: filters: Add filters support
This patch adds the support of filters in HAProxy. The main idea is to have a
way to "easely" extend HAProxy by adding some "modules", called filters, that
will be able to change HAProxy behavior in a programmatic way.

To do so, many entry points has been added in code to let filters to hook up to
different steps of the processing. A filter must define a flt_ops sutrctures
(see include/types/filters.h for details). This structure contains all available
callbacks that a filter can define:

struct flt_ops {
       /*
        * Callbacks to manage the filter lifecycle
        */
       int  (*init)  (struct proxy *p);
       void (*deinit)(struct proxy *p);
       int  (*check) (struct proxy *p);

        /*
         * Stream callbacks
         */
        void (*stream_start)     (struct stream *s);
        void (*stream_accept)    (struct stream *s);
        void (*session_establish)(struct stream *s);
        void (*stream_stop)      (struct stream *s);

       /*
        * HTTP callbacks
        */
       int  (*http_start)         (struct stream *s, struct http_msg *msg);
       int  (*http_start_body)    (struct stream *s, struct http_msg *msg);
       int  (*http_start_chunk)   (struct stream *s, struct http_msg *msg);
       int  (*http_data)          (struct stream *s, struct http_msg *msg);
       int  (*http_last_chunk)    (struct stream *s, struct http_msg *msg);
       int  (*http_end_chunk)     (struct stream *s, struct http_msg *msg);
       int  (*http_chunk_trailers)(struct stream *s, struct http_msg *msg);
       int  (*http_end_body)      (struct stream *s, struct http_msg *msg);
       void (*http_end)           (struct stream *s, struct http_msg *msg);
       void (*http_reset)         (struct stream *s, struct http_msg *msg);
       int  (*http_pre_process)   (struct stream *s, struct http_msg *msg);
       int  (*http_post_process)  (struct stream *s, struct http_msg *msg);
       void (*http_reply)         (struct stream *s, short status,
                                   const struct chunk *msg);
};

To declare and use a filter, in the configuration, the "filter" keyword must be
used in a listener/frontend section:

  frontend test
    ...
    filter <FILTER-NAME> [OPTIONS...]

The filter referenced by the <FILTER-NAME> must declare a configuration parser
on its own name to fill flt_ops and filter_conf field in the proxy's
structure. An exemple will be provided later to make it perfectly clear.

For now, filters cannot be used in backend section. But this is only a matter of
time. Documentation will also be added later. This is the first commit of a long
list about filters.

It is possible to have several filters on the same listener/frontend. These
filters are stored in an array of at most MAX_FILTERS elements (define in
include/types/filters.h). Again, this will be replaced later by a list of
filters.

The filter API has been highly refactored. Main changes are:

* Now, HA supports an infinite number of filters per proxy. To do so, filters
  are stored in list.

* Because filters are stored in list, filters state has been moved from the
  channel structure to the filter structure. This is cleaner because there is no
  more info about filters in channel structure.

* It is possible to defined filters on backends only. For such filters,
  stream_start/stream_stop callbacks are not called. Of course, it is possible
  to mix frontend and backend filters.

* Now, TCP streams are also filtered. All callbacks without the 'http_' prefix
  are called for all kind of streams. In addition, 2 new callbacks were added to
  filter data exchanged through a TCP stream:

    - tcp_data: it is called when new data are available or when old unprocessed
      data are still waiting.

    - tcp_forward_data: it is called when some data can be consumed.

* New callbacks attached to channel were added:

    - channel_start_analyze: it is called when a filter is ready to process data
      exchanged through a channel. 2 new analyzers (a frontend and a backend)
      are attached to channels to call this callback. For a frontend filter, it
      is called before any other analyzer. For a backend filter, it is called
      when a backend is attached to a stream. So some processing cannot be
      filtered in that case.

    - channel_analyze: it is called before each analyzer attached to a channel,
      expects analyzers responsible for data sending.

    - channel_end_analyze: it is called when all other analyzers have finished
      their processing. A new analyzers is attached to channels to call this
      callback. For a TCP stream, this is always the last one called. For a HTTP
      one, the callback is called when a request/response ends, so it is called
      one time for each request/response.

* 'session_established' callback has been removed. Everything that is done in
  this callback can be handled by 'channel_start_analyze' on the response
  channel.

* 'http_pre_process' and 'http_post_process' callbacks have been replaced by
  'channel_analyze'.

* 'http_start' callback has been replaced by 'http_headers'. This new one is
  called just before headers sending and parsing of the body.

* 'http_end' callback has been replaced by 'channel_end_analyze'.

* It is possible to set a forwarder for TCP channels. It was already possible to
  do it for HTTP ones.

* Forwarders can partially consumed forwardable data. For this reason a new
  HTTP message state was added before HTTP_MSG_DONE : HTTP_MSG_ENDING.

Now all filters can define corresponding callbacks (http_forward_data
and tcp_forward_data). Each filter owns 2 offsets relative to buf->p, next and
forward, to track, respectively, input data already parsed but not forwarded yet
by the filter and parsed data considered as forwarded by the filter. A any time,
we have the warranty that a filter cannot parse or forward more input than
previous ones. And, of course, it cannot forward more input than it has
parsed. 2 macros has been added to retrieve these offets: FLT_NXT and FLT_FWD.

In addition, 2 functions has been added to change the 'next size' and the
'forward size' of a filter. When a filter parses input data, it can alter these
data, so the size of these data can vary. This action has an effet on all
previous filters that must be handled. To do so, the function
'filter_change_next_size' must be called, passing the size variation. In the
same spirit, if a filter alter forwarded data, it must call the function
'filter_change_forward_size'. 'filter_change_next_size' can be called in
'http_data' and 'tcp_data' callbacks and only these ones. And
'filter_change_forward_size' can be called in 'http_forward_data' and
'tcp_forward_data' callbacks and only these ones. The data changes are the
filter responsability, but with some limitation. It must not change already
parsed/forwarded data or data that previous filters have not parsed/forwarded
yet.

Because filters can be used on backends, when we the backend is set for a
stream, we add filters defined for this backend in the filter list of the
stream. But we must only do that when the backend and the frontend of the stream
are not the same. Else same filters are added a second time leading to undefined
behavior.

The HTTP compression code had to be moved.

So it simplifies http_response_forward_body function. To do so, the way the data
are forwarded has changed. Now, a filter (and only one) can forward data. In a
commit to come, this limitation will be removed to let all filters take part to
data forwarding. There are 2 new functions that filters should use to deal with
this feature:

 * flt_set_http_data_forwarder: This function sets the filter (using its id)
   that will forward data for the specified HTTP message. It is possible if it
   was not already set by another filter _AND_ if no data was yet forwarded
   (msg->msg_state <= HTTP_MSG_BODY). It returns -1 if an error occurs.

 * flt_http_data_forwarder: This function returns the filter id that will
   forward data for the specified HTTP message. If there is no forwarder set, it
   returns -1.

When an HTTP data forwarder is set for the response, the HTTP compression is
disabled. Of course, this is not definitive.
2016-02-09 14:53:15 +01:00
..
acl.h MAJOR: sample: pass a pointer to the session to each sample fetch function 2015-04-06 11:37:25 +02:00
action.h MINOR: http/tcp: fill the avalaible actions 2015-10-02 22:56:11 +02:00
applet.h MINOR: applet: rename applet_runq to applet_active_queue 2015-09-25 18:02:44 +02:00
arg.h MINOR: global: export many symbols. 2015-02-28 23:12:32 +01:00
auth.h MEDIUM: pattern: The match function browse itself the list or the tree. 2014-03-17 18:06:07 +01:00
backend.h REORG/MAJOR: session: rename the "session" entity to "stream" 2015-04-06 11:23:56 +02:00
channel.h BUG/MEDIUM: channel: fix miscalculation of available buffer space. 2016-01-25 02:31:18 +01:00
checks.h MAJOR: server: add DNS-based server name resolution 2015-06-13 22:07:35 +02:00
compression.h REORG/MAJOR: session: rename the "session" entity to "stream" 2015-04-06 11:23:56 +02:00
connection.h MINOR: connection: add a new list member in the connection struct 2015-08-06 11:00:34 +02:00
dns.h MINOR: fix the return type for dns_response_get_query_id() function 2016-01-20 23:51:24 +01:00
dumpstats.h CLEANUP: applet: rename struct si_applet to applet 2015-04-23 17:56:16 +02:00
fd.h MAJOR: polling: centralize calls to I/O callbacks 2014-11-21 20:37:32 +01:00
filters.h MAJOR: filters: Add filters support 2016-02-09 14:53:15 +01:00
freq_ctr.h MINOR: freq_ctr: introduce a new averaging method 2014-06-17 17:15:51 +02:00
frontend.h REORG/MAJOR: session: rename the "session" entity to "stream" 2015-04-06 11:23:56 +02:00
hdr_idx.h
hlua.h BUILD/MINOR: lua: ensure that hlua_ctx_destroy is properly defined 2015-06-17 20:18:54 +02:00
lb_chash.h
lb_fas.h
lb_fwlc.h
lb_fwrr.h
lb_map.h
listener.h CLEANUP: fix missing include <string.h> in proto/listener.h 2013-06-14 19:52:17 +02:00
log.h BUG/MEDIUM: logs: segfault writing to log from Lua 2015-10-02 00:57:45 +02:00
map.h MINOR: samples: rename some struct member from "smp" to "data" 2015-08-20 17:13:46 +02:00
obj_type.h CLEANUP: applet: rename struct si_applet to applet 2015-04-23 17:56:16 +02:00
pattern.h MINOR: samples: rename a struct from sample_storage to sample_data 2015-08-20 17:13:46 +02:00
payload.h REORG/MAJOR: session: rename the "session" entity to "stream" 2015-04-06 11:23:56 +02:00
peers.h MAJOR: peers: peers protocol version 2.0 2015-05-29 15:50:33 +02:00
pipe.h
port_range.h
proto_http.h MAJOR: filters: Add filters support 2016-02-09 14:53:15 +01:00
proto_tcp.h CLEANUP: actions: missplaced includes 2015-09-10 21:17:04 +02:00
proto_udp.h MEDIUM: protocol: add minimalist UDP protocol client 2015-06-13 22:07:35 +02:00
proto_uxst.h REORG/MAJOR: session: rename the "session" entity to "stream" 2015-04-06 11:23:56 +02:00
protocol.h MEDIUM: protocol: use a family array to index the protocol handlers 2015-02-28 23:12:31 +01:00
proxy.h CLEANUP: proxy: remove last references to appsession 2015-08-10 19:42:30 +02:00
queue.h REORG/MAJOR: session: rename the "session" entity to "stream" 2015-04-06 11:23:56 +02:00
raw_sock.h REORG: connection: rename the data layer the "transport layer" 2012-10-04 22:26:09 +02:00
sample.h MEDIUM: samples: Use the "struct sample_data" in the "struct sample" 2015-08-20 17:13:46 +02:00
server.h MINOR: config: new backend directives: load-server-state-from-file and server-state-file-name 2015-09-19 17:05:28 +02:00
session.h MINOR: session: introduce session_new() 2015-04-06 11:37:33 +02:00
shctx.h BUG/MAJOR: ssl: Fallback to private session cache if current lock mode is not supported. 2014-05-08 22:46:32 +02:00
signal.h CLEANUP: includes: fix includes for a number of users of fd.h 2012-09-03 20:49:14 +02:00
ssl_sock.h BUG/MINOR: ssl: Be sure to use unique serial for regenerated certificates 2016-02-09 09:04:53 +01:00
stick_table.h MEDIUM: stick-table: remove the now duplicate find_stktable() function 2015-05-26 12:08:07 +02:00
stream_interface.h BUG: stream_interface: Reuse connection even if the output channel is empty 2016-02-03 14:22:55 +01:00
stream.h MINOR: stream/applet: add use-service action 2015-09-28 01:03:48 +02:00
task.h MAJOR: poll: only rely on wake_expired_tasks() to compute the wait delay 2015-02-28 23:12:30 +01:00
template.h
vars.h MINOR: vars: returns variable content 2015-07-22 00:48:24 +02:00