blob: f148cb8c20a5752bb50affd4da7a08476569ecee [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
Willy Tarreau81f9aa32010-06-01 17:45:26 +02002 * Session management functions.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003 *
Willy Tarreaud28c3532012-04-19 19:28:33 +02004 * Copyright 2000-2012 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdlib.h>
Willy Tarreau81f9aa32010-06-01 17:45:26 +020014#include <unistd.h>
15#include <fcntl.h>
Willy Tarreaue3ba5f02006-06-29 18:54:54 +020016
17#include <common/config.h>
Willy Tarreau9b28e032012-10-12 23:49:43 +020018#include <common/buffer.h>
Willy Tarreau7c669d72008-06-20 15:04:11 +020019#include <common/debug.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020020#include <common/memory.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020021
Willy Tarreaubaaee002006-06-26 02:48:02 +020022#include <types/capture.h>
Willy Tarreau55a8d0e2008-11-30 18:47:21 +010023#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020024
Willy Tarreau1d0dfb12009-07-07 15:10:31 +020025#include <proto/acl.h>
Willy Tarreau61612d42012-04-19 18:42:05 +020026#include <proto/arg.h>
Willy Tarreau55a8d0e2008-11-30 18:47:21 +010027#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020028#include <proto/channel.h>
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +010029#include <proto/checks.h>
Willy Tarreaud2274c62012-07-06 14:29:45 +020030#include <proto/connection.h>
Willy Tarreau5ca791d2009-08-16 19:06:42 +020031#include <proto/dumpstats.h>
Willy Tarreaudd2f85e2012-09-02 22:34:23 +020032#include <proto/fd.h>
Willy Tarreau91c43d72010-06-20 11:19:22 +020033#include <proto/freq_ctr.h>
Willy Tarreau3041b9f2010-10-15 23:25:20 +020034#include <proto/frontend.h>
Willy Tarreau8d5d7f22007-01-21 19:16:41 +010035#include <proto/hdr_idx.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020036#include <proto/listener.h>
Willy Tarreau332f8bf2007-05-13 21:36:56 +020037#include <proto/log.h>
Willy Tarreaucbaaec42012-09-06 11:32:07 +020038#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039#include <proto/session.h>
Willy Tarreau3eba98a2009-01-25 13:56:13 +010040#include <proto/pipe.h>
Willy Tarreau55a8d0e2008-11-30 18:47:21 +010041#include <proto/proto_http.h>
42#include <proto/proto_tcp.h>
Willy Tarreau1d0dfb12009-07-07 15:10:31 +020043#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/queue.h>
Willy Tarreau7f062c42009-03-05 18:43:00 +010045#include <proto/server.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020046#include <proto/sample.h>
Emeric Brun1d33b292010-01-04 15:47:17 +010047#include <proto/stick_table.h>
Willy Tarreau55a8d0e2008-11-30 18:47:21 +010048#include <proto/stream_interface.h>
Willy Tarreau55a8d0e2008-11-30 18:47:21 +010049#include <proto/task.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050
Willy Tarreauc6ca1a02007-05-13 19:43:47 +020051struct pool_head *pool2_session;
Willy Tarreauf54f8bd2008-11-23 19:53:55 +010052struct list sessions;
Willy Tarreaubaaee002006-06-26 02:48:02 +020053
Willy Tarreau071e1372012-10-03 01:39:48 +020054static int conn_session_complete(struct connection *conn);
Willy Tarreau9683e9a2012-10-03 21:17:23 +020055static int conn_session_update(struct connection *conn);
Willy Tarreau2542b532012-08-31 16:01:23 +020056static struct task *expire_mini_session(struct task *t);
57int session_complete(struct session *s);
58
Willy Tarreau5e75e272012-10-02 21:21:20 +020059/* data layer callbacks for an embryonic session */
60struct data_cb sess_conn_cb = {
61 .recv = NULL,
62 .send = NULL,
Willy Tarreau9683e9a2012-10-03 21:17:23 +020063 .wake = conn_session_update,
Willy Tarreau071e1372012-10-03 01:39:48 +020064 .init = conn_session_complete,
Willy Tarreau5e75e272012-10-02 21:21:20 +020065};
66
Willy Tarreau2542b532012-08-31 16:01:23 +020067/* This function is called from the protocol layer accept() in order to
68 * instanciate a new embryonic session on behalf of a given listener and
69 * frontend. It returns a positive value upon success, 0 if the connection
70 * can be ignored, or a negative value upon critical failure. The accepted
71 * file descriptor is closed if we return <= 0.
Willy Tarreau81f9aa32010-06-01 17:45:26 +020072 */
73int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
74{
75 struct proxy *p = l->frontend;
76 struct session *s;
Willy Tarreau81f9aa32010-06-01 17:45:26 +020077 struct task *t;
Willy Tarreauabe8ea52010-11-11 10:56:04 +010078 int ret;
79
80
81 ret = -1; /* assume unrecoverable error by default */
Willy Tarreau81f9aa32010-06-01 17:45:26 +020082
Willy Tarreaufffe1322010-11-11 09:48:16 +010083 if (unlikely((s = pool_alloc2(pool2_session)) == NULL))
Willy Tarreau81f9aa32010-06-01 17:45:26 +020084 goto out_close;
Willy Tarreau81f9aa32010-06-01 17:45:26 +020085
Willy Tarreau2542b532012-08-31 16:01:23 +020086 /* minimum session initialization required for an embryonic session is
87 * fairly low. We need very little to execute L4 ACLs, then we need a
88 * task to make the client-side connection live on its own.
89 * - flags
90 * - stick-entry tracking
91 */
Willy Tarreau81f9aa32010-06-01 17:45:26 +020092 s->flags = 0;
93 s->logs.logwait = p->to_log;
Willy Tarreau56123282010-08-06 19:06:56 +020094 s->stkctr1_entry = NULL;
95 s->stkctr2_entry = NULL;
96 s->stkctr1_table = NULL;
97 s->stkctr2_table = NULL;
Willy Tarreau81f9aa32010-06-01 17:45:26 +020098
Willy Tarreau2542b532012-08-31 16:01:23 +020099 s->listener = l;
100 s->fe = p;
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100101
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200102 /* OK, we're keeping the session, so let's properly initialize the session */
Willy Tarreau96596ae2012-06-08 22:57:36 +0200103 s->si[0].conn.t.sock.fd = cfd;
104 s->si[0].conn.ctrl = l->proto;
Willy Tarreau2542b532012-08-31 16:01:23 +0200105 s->si[0].conn.flags = CO_FL_NONE;
Willy Tarreau986a9d22012-08-30 21:11:38 +0200106 s->si[0].conn.addr.from = *addr;
Willy Tarreau2542b532012-08-31 16:01:23 +0200107 set_target_client(&s->si[0].conn.target, l);
108
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200109 s->logs.accept_date = date; /* user-visible date for logging */
110 s->logs.tv_accept = now; /* corrected date for internal use */
111 s->uniq_id = totalconn;
Willy Tarreau2542b532012-08-31 16:01:23 +0200112 p->feconn++;
113 /* This session was accepted, count it now */
114 if (p->feconn > p->fe_counters.conn_max)
115 p->fe_counters.conn_max = p->feconn;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200116
Willy Tarreau2542b532012-08-31 16:01:23 +0200117 proxy_inc_fe_conn_ctr(l, p);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200118
119 /* now evaluate the tcp-request layer4 rules. Since we expect to be able
120 * to abort right here as soon as possible, we check the rules before
121 * even initializing the stream interfaces.
122 */
123 if ((l->options & LI_O_TCP_RULES) && !tcp_exec_req_rules(s)) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200124 /* let's do a no-linger now to close with a single RST. */
125 setsockopt(cfd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100126 ret = 0; /* successful termination */
Willy Tarreau2542b532012-08-31 16:01:23 +0200127 goto out_free_session;
128 }
129
Willy Tarreau1bc4aab2012-10-08 20:11:03 +0200130#ifndef USE_ACCEPT4
131 /* Adjust some socket options if the connection was accepted by a plain
132 * accept() syscall.
133 */
Willy Tarreau82569f92012-09-27 23:48:56 +0200134 if (unlikely(fcntl(cfd, F_SETFL, O_NONBLOCK) == -1))
135 goto out_free_session;
Willy Tarreau1bc4aab2012-10-08 20:11:03 +0200136#endif
Willy Tarreau82569f92012-09-27 23:48:56 +0200137
138 /* monitor-net and health mode are processed immediately after TCP
139 * connection rules. This way it's possible to block them, but they
140 * never use the lower data layers, they send directly over the socket,
141 * as they were designed for. We first flush the socket receive buffer
142 * in order to avoid emission of an RST by the system. We ignore any
143 * error.
144 */
145 if (unlikely((p->mode == PR_MODE_HEALTH) ||
146 ((l->options & LI_O_CHK_MONNET) &&
147 addr->ss_family == AF_INET &&
148 (((struct sockaddr_in *)addr)->sin_addr.s_addr & p->mon_mask.s_addr) == p->mon_net.s_addr))) {
149 /* we have 4 possibilities here :
150 * - HTTP mode, from monitoring address => send "HTTP/1.0 200 OK"
151 * - HEALTH mode with HTTP check => send "HTTP/1.0 200 OK"
152 * - HEALTH mode without HTTP check => just send "OK"
153 * - TCP mode from monitoring address => just close
154 */
Willy Tarreaue9909f42012-10-12 17:36:40 +0200155 recv(cfd, trash, trashlen, MSG_DONTWAIT);
Willy Tarreau82569f92012-09-27 23:48:56 +0200156 if (p->mode == PR_MODE_HTTP ||
157 (p->mode == PR_MODE_HEALTH && (p->options2 & PR_O2_CHK_ANY) == PR_O2_HTTP_CHK))
158 send(cfd, "HTTP/1.0 200 OK\r\n\r\n", 19, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_MORE);
159 else if (p->mode == PR_MODE_HEALTH)
160 send(cfd, "OK\n", 3, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_MORE);
161 ret = 0;
162 goto out_free_session;
163 }
164
165
Willy Tarreau22cda212012-08-31 17:43:29 +0200166 /* wait for a PROXY protocol header */
167 if (l->options & LI_O_ACC_PROXY) {
168 s->si[0].conn.flags |= CO_FL_ACCEPT_PROXY;
169 conn_sock_want_recv(&s->si[0].conn);
170 }
171
Willy Tarreau2542b532012-08-31 16:01:23 +0200172 if (unlikely((t = task_new()) == NULL))
173 goto out_free_session;
174
175 t->context = s;
176 t->nice = l->nice;
177 s->task = t;
178
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200179 /* Add the various callbacks. Right now the transport layer is present
180 * but not initialized. Also note we need to be careful as the stream
181 * int is not initialized yet.
Willy Tarreau2542b532012-08-31 16:01:23 +0200182 */
Willy Tarreau5e75e272012-10-02 21:21:20 +0200183 conn_prepare(&s->si[0].conn, &sess_conn_cb, l->proto, l->xprt, s);
Willy Tarreau2542b532012-08-31 16:01:23 +0200184
185 /* finish initialization of the accepted file descriptor */
186 fd_insert(cfd);
187 fdtab[cfd].owner = &s->si[0].conn;
Willy Tarreau2542b532012-08-31 16:01:23 +0200188 fdtab[cfd].iocb = conn_fd_handler;
189 conn_data_want_recv(&s->si[0].conn);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200190 if (conn_xprt_init(&s->si[0].conn) < 0)
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100191 goto out_free_task;
Willy Tarreau2542b532012-08-31 16:01:23 +0200192
193 /* OK, now either we have a pending handshake to execute with and
194 * then we must return to the I/O layer, or we can proceed with the
195 * end of the session initialization. In case of handshake, we also
196 * set the I/O timeout to the frontend's client timeout.
197 */
198
199 if (s->si[0].conn.flags & CO_FL_HANDSHAKE) {
200 t->process = expire_mini_session;
201 t->expire = tick_add_ifset(now_ms, p->timeout.client);
202 task_queue(t);
Willy Tarreau91083f52012-10-12 17:42:13 +0200203 s->si[0].conn.flags |= CO_FL_INIT_DATA | CO_FL_WAKE_DATA;
Willy Tarreau2542b532012-08-31 16:01:23 +0200204 return 1;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200205 }
206
Willy Tarreau2542b532012-08-31 16:01:23 +0200207 /* OK let's complete session initialization */
208 ret = session_complete(s);
209 if (ret > 0)
210 return ret;
211
212 /* Error unrolling */
213 out_free_task:
214 task_free(t);
215 out_free_session:
216 p->feconn--;
217 if (s->stkctr1_entry || s->stkctr2_entry)
218 session_store_counters(s);
219 pool_free2(pool2_session, s);
220 out_close:
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200221 if (ret < 0 && l->xprt == &raw_sock && p->mode == PR_MODE_HTTP) {
Willy Tarreau2542b532012-08-31 16:01:23 +0200222 /* critical error, no more memory, try to emit a 500 response */
Willy Tarreau783f2582012-09-04 12:19:04 +0200223 struct chunk *err_msg = http_error_message(s, HTTP_ERR_500);
Willy Tarreau2542b532012-08-31 16:01:23 +0200224 send(cfd, err_msg->str, err_msg->len, MSG_DONTWAIT|MSG_NOSIGNAL);
225 }
226
227 if (fdtab[cfd].owner)
228 fd_delete(cfd);
229 else
230 close(cfd);
231 return ret;
232}
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100233
Willy Tarreau2542b532012-08-31 16:01:23 +0200234/* This function kills an existing embryonic session. It stops the connection's
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200235 * transport layer, releases assigned resources, resumes the listener if it was
Willy Tarreau2542b532012-08-31 16:01:23 +0200236 * disabled and finally kills the file descriptor.
237 */
238static void kill_mini_session(struct session *s)
239{
240 /* kill the connection now */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200241 conn_xprt_close(&s->si[0].conn);
Willy Tarreau2542b532012-08-31 16:01:23 +0200242
243 s->fe->feconn--;
244 if (s->stkctr1_entry || s->stkctr2_entry)
245 session_store_counters(s);
246
247 if (!(s->listener->options & LI_O_UNLIMITED))
248 actconn--;
249 jobs--;
250 s->listener->nbconn--;
251 if (s->listener->state == LI_FULL)
252 resume_listener(s->listener);
253
254 /* Dequeues all of the listeners waiting for a resource */
255 if (!LIST_ISEMPTY(&global_listener_queue))
256 dequeue_all_listeners(&global_listener_queue);
257
258 if (!LIST_ISEMPTY(&s->fe->listener_queue) &&
259 (!s->fe->fe_sps_lim || freq_ctr_remain(&s->fe->fe_sess_per_sec, s->fe->fe_sps_lim, 0) > 0))
260 dequeue_all_listeners(&s->fe->listener_queue);
261
262 task_delete(s->task);
263 task_free(s->task);
264
265 if (fdtab[s->si[0].conn.t.sock.fd].owner)
266 fd_delete(s->si[0].conn.t.sock.fd);
267 else
268 close(s->si[0].conn.t.sock.fd);
269
270 pool_free2(pool2_session, s);
271}
272
Willy Tarreau22cda212012-08-31 17:43:29 +0200273/* Finish initializing a session from a connection, or kills it if the
274 * connection shows and error. Returns <0 if the connection was killed.
Willy Tarreau2542b532012-08-31 16:01:23 +0200275 */
Willy Tarreau071e1372012-10-03 01:39:48 +0200276static int conn_session_complete(struct connection *conn)
Willy Tarreau2542b532012-08-31 16:01:23 +0200277{
Willy Tarreau5e75e272012-10-02 21:21:20 +0200278 struct session *s = conn->owner;
Willy Tarreau2542b532012-08-31 16:01:23 +0200279
Willy Tarreau22cda212012-08-31 17:43:29 +0200280 if (!(conn->flags & CO_FL_ERROR) && (session_complete(s) > 0)) {
Willy Tarreau071e1372012-10-03 01:39:48 +0200281 conn->flags &= ~CO_FL_INIT_DATA;
Willy Tarreau2542b532012-08-31 16:01:23 +0200282 return 0;
283 }
284
285 /* kill the connection now */
286 kill_mini_session(s);
287 return -1;
288}
289
Willy Tarreau9683e9a2012-10-03 21:17:23 +0200290/* Update an embryonic session status. The connection is killed in case of
291 * error, and <0 will be returned. Otherwise it does nothing.
292 */
293static int conn_session_update(struct connection *conn)
294{
295 if (conn->flags & CO_FL_ERROR) {
296 kill_mini_session(conn->owner);
297 return -1;
298 }
299 return 0;
300}
301
Willy Tarreau2542b532012-08-31 16:01:23 +0200302/* Manages embryonic sessions timeout. It is only called when the timeout
303 * strikes and performs the required cleanup.
304 */
305static struct task *expire_mini_session(struct task *t)
306{
307 struct session *s = t->context;
308
309 if (!(t->state & TASK_WOKEN_TIMER))
310 return t;
311
312 kill_mini_session(s);
313 return NULL;
314}
315
316/* This function is called from the I/O handler which detects the end of
317 * handshake, in order to complete initialization of a valid session. It must
318 * be called with an embryonic session. It returns a positive value upon
319 * success, 0 if the connection can be ignored, or a negative value upon
320 * critical failure. The accepted file descriptor is closed if we return <= 0.
321 */
322int session_complete(struct session *s)
323{
324 struct listener *l = s->listener;
325 struct proxy *p = s->fe;
326 struct http_txn *txn;
327 struct task *t = s->task;
328 int ret;
329
330 ret = -1; /* assume unrecoverable error by default */
331
332 /* OK, we're keeping the session, so let's properly initialize the session */
333 LIST_ADDQ(&sessions, &s->list);
334 LIST_INIT(&s->back_refs);
Willy Tarreau5e75e272012-10-02 21:21:20 +0200335 si_takeover_conn(&s->si[0], l->proto, l->xprt);
Willy Tarreau2542b532012-08-31 16:01:23 +0200336 s->flags |= SN_INITIALIZED;
337
338 s->unique_id = NULL;
Willy Tarreau2542b532012-08-31 16:01:23 +0200339
340 t->process = l->handler;
341 t->context = s;
342 t->expire = TICK_ETERNITY;
343
344 /* Note: initially, the session's backend points to the frontend.
345 * This changes later when switching rules are executed or
346 * when the default backend is assigned.
347 */
348 s->be = s->fe;
349 s->req = s->rep = NULL; /* will be allocated later */
William Lallemand82fe75c2012-10-23 10:25:10 +0200350 s->comp_algo = NULL;
Willy Tarreau2542b532012-08-31 16:01:23 +0200351
352 /* Let's count a session now */
Willy Tarreaub36b4242010-06-04 20:59:39 +0200353 proxy_inc_fe_sess_ctr(l, p);
Willy Tarreau56123282010-08-06 19:06:56 +0200354 if (s->stkctr1_entry) {
Willy Tarreau91c43d72010-06-20 11:19:22 +0200355 void *ptr;
356
Willy Tarreau56123282010-08-06 19:06:56 +0200357 ptr = stktable_data_ptr(s->stkctr1_table, s->stkctr1_entry, STKTABLE_DT_SESS_CNT);
Willy Tarreauf4d17d92010-06-18 22:10:12 +0200358 if (ptr)
359 stktable_data_cast(ptr, sess_cnt)++;
Willy Tarreau91c43d72010-06-20 11:19:22 +0200360
Willy Tarreau56123282010-08-06 19:06:56 +0200361 ptr = stktable_data_ptr(s->stkctr1_table, s->stkctr1_entry, STKTABLE_DT_SESS_RATE);
Willy Tarreau91c43d72010-06-20 11:19:22 +0200362 if (ptr)
363 update_freq_ctr_period(&stktable_data_cast(ptr, sess_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200364 s->stkctr1_table->data_arg[STKTABLE_DT_SESS_RATE].u, 1);
Willy Tarreauf4d17d92010-06-18 22:10:12 +0200365 }
Willy Tarreaub36b4242010-06-04 20:59:39 +0200366
Willy Tarreau56123282010-08-06 19:06:56 +0200367 if (s->stkctr2_entry) {
Willy Tarreau9e9879a2010-08-06 15:25:22 +0200368 void *ptr;
369
Willy Tarreau56123282010-08-06 19:06:56 +0200370 ptr = stktable_data_ptr(s->stkctr2_table, s->stkctr2_entry, STKTABLE_DT_SESS_CNT);
Willy Tarreau9e9879a2010-08-06 15:25:22 +0200371 if (ptr)
372 stktable_data_cast(ptr, sess_cnt)++;
373
Willy Tarreau56123282010-08-06 19:06:56 +0200374 ptr = stktable_data_ptr(s->stkctr2_table, s->stkctr2_entry, STKTABLE_DT_SESS_RATE);
Willy Tarreau9e9879a2010-08-06 15:25:22 +0200375 if (ptr)
376 update_freq_ctr_period(&stktable_data_cast(ptr, sess_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200377 s->stkctr2_table->data_arg[STKTABLE_DT_SESS_RATE].u, 1);
Willy Tarreau9e9879a2010-08-06 15:25:22 +0200378 }
379
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200380 /* this part should be common with other protocols */
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200381 s->si[0].owner = t;
382 s->si[0].state = s->si[0].prev_state = SI_ST_EST;
383 s->si[0].err_type = SI_ET_NONE;
384 s->si[0].err_loc = NULL;
Willy Tarreau0bd05ea2010-07-02 11:18:03 +0200385 s->si[0].release = NULL;
Willy Tarreau63e7fe32012-05-08 15:20:43 +0200386 s->si[0].send_proxy_ofs = 0;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200387 s->si[0].exp = TICK_ETERNITY;
388 s->si[0].flags = SI_FL_NONE;
389
390 if (likely(s->fe->options2 & PR_O2_INDEPSTR))
391 s->si[0].flags |= SI_FL_INDEP_STR;
392
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200393 /* pre-initialize the other side's stream interface to an INIT state. The
394 * callbacks will be initialized before attempting to connect.
395 */
Willy Tarreaufb7508a2012-05-21 16:47:54 +0200396 s->si[1].conn.t.sock.fd = -1; /* just to help with debugging */
Willy Tarreau505e34a2012-07-06 10:17:53 +0200397 s->si[1].conn.flags = CO_FL_NONE;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200398 s->si[1].owner = t;
399 s->si[1].state = s->si[1].prev_state = SI_ST_INI;
400 s->si[1].err_type = SI_ET_NONE;
Willy Tarreau0b3a4112011-03-27 19:16:56 +0200401 s->si[1].conn_retries = 0; /* used for logging too */
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200402 s->si[1].err_loc = NULL;
Willy Tarreau0bd05ea2010-07-02 11:18:03 +0200403 s->si[1].release = NULL;
Willy Tarreau63e7fe32012-05-08 15:20:43 +0200404 s->si[1].send_proxy_ofs = 0;
Willy Tarreau3cefd522012-08-30 15:49:18 +0200405 clear_target(&s->si[1].conn.target);
Willy Tarreauc5788912012-08-24 18:12:41 +0200406 si_prepare_embedded(&s->si[1]);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200407 s->si[1].exp = TICK_ETERNITY;
408 s->si[1].flags = SI_FL_NONE;
409
410 if (likely(s->fe->options2 & PR_O2_INDEPSTR))
411 s->si[1].flags |= SI_FL_INDEP_STR;
412
Willy Tarreau9bd0d742011-07-20 00:17:39 +0200413 session_init_srv_conn(s);
Willy Tarreau9e000c62011-03-10 14:03:36 +0100414 clear_target(&s->target);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200415 s->pend_pos = NULL;
416
417 /* init store persistence */
418 s->store_count = 0;
419
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200420 if (unlikely((s->req = pool_alloc2(pool2_channel)) == NULL))
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200421 goto out_free_task; /* no memory */
422
Willy Tarreau9b28e032012-10-12 23:49:43 +0200423 if (unlikely((s->req->buf = pool_alloc2(pool2_buffer)) == NULL))
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200424 goto out_free_req; /* no memory */
425
Willy Tarreau9b28e032012-10-12 23:49:43 +0200426 if (unlikely((s->rep = pool_alloc2(pool2_channel)) == NULL))
427 goto out_free_req_buf; /* no memory */
428
429 if (unlikely((s->rep->buf = pool_alloc2(pool2_buffer)) == NULL))
430 goto out_free_rep; /* no memory */
431
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200432 /* initialize the request buffer */
Willy Tarreau9b28e032012-10-12 23:49:43 +0200433 s->req->buf->size = global.tune.bufsize;
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200434 channel_init(s->req);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200435 s->req->prod = &s->si[0];
436 s->req->cons = &s->si[1];
437 s->si[0].ib = s->si[1].ob = s->req;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200438 s->req->flags |= CF_READ_ATTACHED; /* the producer is already connected */
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200439
440 /* activate default analysers enabled for this listener */
441 s->req->analysers = l->analysers;
442
443 s->req->wto = TICK_ETERNITY;
444 s->req->rto = TICK_ETERNITY;
445 s->req->rex = TICK_ETERNITY;
446 s->req->wex = TICK_ETERNITY;
447 s->req->analyse_exp = TICK_ETERNITY;
448
449 /* initialize response buffer */
Willy Tarreau9b28e032012-10-12 23:49:43 +0200450 s->rep->buf->size = global.tune.bufsize;
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200451 channel_init(s->rep);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200452 s->rep->prod = &s->si[1];
453 s->rep->cons = &s->si[0];
454 s->si[0].ob = s->si[1].ib = s->rep;
455 s->rep->analysers = 0;
456
Willy Tarreau96e31212011-05-30 18:10:30 +0200457 if (s->fe->options2 & PR_O2_NODELAY) {
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200458 s->req->flags |= CF_NEVER_WAIT;
459 s->rep->flags |= CF_NEVER_WAIT;
Willy Tarreau96e31212011-05-30 18:10:30 +0200460 }
461
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200462 s->rep->rto = TICK_ETERNITY;
463 s->rep->wto = TICK_ETERNITY;
464 s->rep->rex = TICK_ETERNITY;
465 s->rep->wex = TICK_ETERNITY;
466 s->rep->analyse_exp = TICK_ETERNITY;
467
Willy Tarreau62f791e2012-03-09 11:32:30 +0100468 txn = &s->txn;
469 /* Those variables will be checked and freed if non-NULL in
470 * session.c:session_free(). It is important that they are
471 * properly initialized.
472 */
473 txn->sessid = NULL;
474 txn->srv_cookie = NULL;
475 txn->cli_cookie = NULL;
476 txn->uri = NULL;
477 txn->req.cap = NULL;
478 txn->rsp.cap = NULL;
479 txn->hdr_idx.v = NULL;
480 txn->hdr_idx.size = txn->hdr_idx.used = 0;
481 txn->req.flags = 0;
482 txn->rsp.flags = 0;
483 /* the HTTP messages need to know what buffer they're associated with */
Willy Tarreau394db372012-10-12 22:40:39 +0200484 txn->req.chn = s->req;
485 txn->rsp.chn = s->rep;
Willy Tarreau62f791e2012-03-09 11:32:30 +0100486
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200487 /* finish initialization of the accepted file descriptor */
Willy Tarreauf9dabec2012-08-17 17:33:53 +0200488 conn_data_want_recv(&s->si[0].conn);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200489
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100490 if (p->accept && (ret = p->accept(s)) <= 0) {
491 /* Either we had an unrecoverable error (<0) or work is
492 * finished (=0, eg: monitoring), in both situations,
493 * we can release everything and close.
494 */
Willy Tarreau9b28e032012-10-12 23:49:43 +0200495 goto out_free_rep_buf;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200496 }
497
Willy Tarreau93dbc2b2012-10-12 18:01:49 +0200498 /* if logs require transport layer information, note it on the connection */
499 if (s->logs.logwait & LW_XPRT)
500 s->si[0].conn.flags |= CO_FL_XPRT_TRACKED;
501
Willy Tarreau2542b532012-08-31 16:01:23 +0200502 /* we want the connection handler to notify the stream interface about updates. */
Willy Tarreau4aa36832012-10-02 20:07:22 +0200503 s->si[0].conn.flags |= CO_FL_WAKE_DATA;
Willy Tarreau2542b532012-08-31 16:01:23 +0200504
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200505 /* it is important not to call the wakeup function directly but to
506 * pass through task_wakeup(), because this one knows how to apply
507 * priorities to tasks.
508 */
509 task_wakeup(t, TASK_WOKEN_INIT);
510 return 1;
511
512 /* Error unrolling */
Willy Tarreau9b28e032012-10-12 23:49:43 +0200513 out_free_rep_buf:
514 pool_free2(pool2_buffer, s->rep->buf);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200515 out_free_rep:
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200516 pool_free2(pool2_channel, s->rep);
Willy Tarreau9b28e032012-10-12 23:49:43 +0200517 out_free_req_buf:
518 pool_free2(pool2_buffer, s->req->buf);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200519 out_free_req:
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200520 pool_free2(pool2_channel, s->req);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200521 out_free_task:
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100522 return ret;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200523}
524
Willy Tarreaubaaee002006-06-26 02:48:02 +0200525/*
526 * frees the context associated to a session. It must have been removed first.
527 */
Simon Hormandec5be42011-06-08 09:19:07 +0900528static void session_free(struct session *s)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200529{
Willy Tarreau4dbc4a22007-03-03 16:23:22 +0100530 struct http_txn *txn = &s->txn;
Willy Tarreau632f5a72007-07-11 10:42:35 +0200531 struct proxy *fe = s->fe;
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100532 struct bref *bref, *back;
Willy Tarreaua4cda672010-06-06 18:28:49 +0200533 int i;
Willy Tarreau0f7562b2007-01-07 15:46:13 +0100534
Willy Tarreaubaaee002006-06-26 02:48:02 +0200535 if (s->pend_pos)
536 pendconn_free(s->pend_pos);
Willy Tarreau922a8062008-12-04 09:33:58 +0100537
Willy Tarreau827aee92011-03-10 16:55:02 +0100538 if (target_srv(&s->target)) { /* there may be requests left pending in queue */
Willy Tarreau1e62de62008-11-11 20:20:02 +0100539 if (s->flags & SN_CURR_SESS) {
540 s->flags &= ~SN_CURR_SESS;
Willy Tarreau827aee92011-03-10 16:55:02 +0100541 target_srv(&s->target)->cur_sess--;
Willy Tarreau1e62de62008-11-11 20:20:02 +0100542 }
Willy Tarreau827aee92011-03-10 16:55:02 +0100543 if (may_dequeue_tasks(target_srv(&s->target), s->be))
544 process_srv_queue(target_srv(&s->target));
Willy Tarreau1e62de62008-11-11 20:20:02 +0100545 }
Willy Tarreau922a8062008-12-04 09:33:58 +0100546
Willy Tarreau7c669d72008-06-20 15:04:11 +0200547 if (unlikely(s->srv_conn)) {
548 /* the session still has a reserved slot on a server, but
549 * it should normally be only the same as the one above,
550 * so this should not happen in fact.
551 */
552 sess_change_server(s, NULL);
553 }
554
William Lallemand82fe75c2012-10-23 10:25:10 +0200555 if (s->comp_algo) {
556 s->comp_algo->end(&s->comp_ctx.strm);
557 s->comp_algo = NULL;
558 }
559
Willy Tarreau3eba98a2009-01-25 13:56:13 +0100560 if (s->req->pipe)
561 put_pipe(s->req->pipe);
Willy Tarreau259de1b2009-01-18 21:56:21 +0100562
Willy Tarreau3eba98a2009-01-25 13:56:13 +0100563 if (s->rep->pipe)
564 put_pipe(s->rep->pipe);
Willy Tarreau259de1b2009-01-18 21:56:21 +0100565
Willy Tarreau9b28e032012-10-12 23:49:43 +0200566 pool_free2(pool2_buffer, s->req->buf);
567 pool_free2(pool2_buffer, s->rep->buf);
568
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200569 pool_free2(pool2_channel, s->req);
570 pool_free2(pool2_channel, s->rep);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200571
Willy Tarreau46023632010-01-07 22:51:47 +0100572 http_end_txn(s);
573
Willy Tarreau1e954912012-10-12 17:50:05 +0200574 /* ensure the client-side transport layer is destroyed */
575 s->si[0].conn.flags &= ~CO_FL_XPRT_TRACKED;
576 conn_xprt_close(&s->si[0].conn);
577
Willy Tarreaua4cda672010-06-06 18:28:49 +0200578 for (i = 0; i < s->store_count; i++) {
579 if (!s->store[i].ts)
580 continue;
581 stksess_free(s->store[i].table, s->store[i].ts);
582 s->store[i].ts = NULL;
583 }
584
Willy Tarreau34eb6712011-10-24 18:15:04 +0200585 pool_free2(pool2_hdr_idx, txn->hdr_idx.v);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200586 if (fe) {
Willy Tarreau46023632010-01-07 22:51:47 +0100587 pool_free2(fe->rsp_cap_pool, txn->rsp.cap);
588 pool_free2(fe->req_cap_pool, txn->req.cap);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589 }
Willy Tarreau0937bc42009-12-22 15:03:09 +0100590
Willy Tarreau56123282010-08-06 19:06:56 +0200591 if (s->stkctr1_entry || s->stkctr2_entry)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +0200592 session_store_counters(s);
593
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100594 list_for_each_entry_safe(bref, back, &s->back_refs, users) {
Willy Tarreaufd3828e2009-02-22 15:17:24 +0100595 /* we have to unlink all watchers. We must not relink them if
596 * this session was the last one in the list.
597 */
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100598 LIST_DEL(&bref->users);
Willy Tarreaufd3828e2009-02-22 15:17:24 +0100599 LIST_INIT(&bref->users);
600 if (s->list.n != &sessions)
601 LIST_ADDQ(&LIST_ELEM(s->list.n, struct session *, list)->back_refs, &bref->users);
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100602 bref->ref = s->list.n;
603 }
Willy Tarreauf54f8bd2008-11-23 19:53:55 +0100604 LIST_DEL(&s->list);
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200605 pool_free2(pool2_session, s);
Willy Tarreau632f5a72007-07-11 10:42:35 +0200606
607 /* We may want to free the maximum amount of pools if the proxy is stopping */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200608 if (fe && unlikely(fe->state == PR_STSTOPPED)) {
Willy Tarreau9b28e032012-10-12 23:49:43 +0200609 pool_flush2(pool2_buffer);
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200610 pool_flush2(pool2_channel);
Willy Tarreau34eb6712011-10-24 18:15:04 +0200611 pool_flush2(pool2_hdr_idx);
Willy Tarreau48d63db2008-08-03 17:41:33 +0200612 pool_flush2(pool2_requri);
613 pool_flush2(pool2_capture);
614 pool_flush2(pool2_session);
615 pool_flush2(fe->req_cap_pool);
616 pool_flush2(fe->rsp_cap_pool);
Willy Tarreau632f5a72007-07-11 10:42:35 +0200617 }
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200618}
619
620
621/* perform minimal intializations, report 0 in case of error, 1 if OK. */
622int init_session()
623{
Willy Tarreauf54f8bd2008-11-23 19:53:55 +0100624 LIST_INIT(&sessions);
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200625 pool2_session = create_pool("session", sizeof(struct session), MEM_F_SHARED);
626 return pool2_session != NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200627}
628
Willy Tarreau30e71012007-11-26 20:15:35 +0100629void session_process_counters(struct session *s)
630{
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100631 unsigned long long bytes;
632
Willy Tarreau30e71012007-11-26 20:15:35 +0100633 if (s->req) {
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100634 bytes = s->req->total - s->logs.bytes_in;
Willy Tarreau30e71012007-11-26 20:15:35 +0100635 s->logs.bytes_in = s->req->total;
636 if (bytes) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100637 s->fe->fe_counters.bytes_in += bytes;
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100638
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100639 s->be->be_counters.bytes_in += bytes;
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100640
Willy Tarreau827aee92011-03-10 16:55:02 +0100641 if (target_srv(&s->target))
642 target_srv(&s->target)->counters.bytes_in += bytes;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200643
644 if (s->listener->counters)
645 s->listener->counters->bytes_in += bytes;
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200646
Willy Tarreau56123282010-08-06 19:06:56 +0200647 if (s->stkctr2_entry) {
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200648 void *ptr;
649
Willy Tarreau56123282010-08-06 19:06:56 +0200650 ptr = stktable_data_ptr(s->stkctr2_table,
651 s->stkctr2_entry,
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200652 STKTABLE_DT_BYTES_IN_CNT);
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200653 if (ptr)
654 stktable_data_cast(ptr, bytes_in_cnt) += bytes;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200655
Willy Tarreau56123282010-08-06 19:06:56 +0200656 ptr = stktable_data_ptr(s->stkctr2_table,
657 s->stkctr2_entry,
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200658 STKTABLE_DT_BYTES_IN_RATE);
659 if (ptr)
660 update_freq_ctr_period(&stktable_data_cast(ptr, bytes_in_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200661 s->stkctr2_table->data_arg[STKTABLE_DT_BYTES_IN_RATE].u, bytes);
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200662 }
663
Willy Tarreau56123282010-08-06 19:06:56 +0200664 if (s->stkctr1_entry) {
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200665 void *ptr;
666
Willy Tarreau56123282010-08-06 19:06:56 +0200667 ptr = stktable_data_ptr(s->stkctr1_table,
668 s->stkctr1_entry,
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200669 STKTABLE_DT_BYTES_IN_CNT);
670 if (ptr)
671 stktable_data_cast(ptr, bytes_in_cnt) += bytes;
672
Willy Tarreau56123282010-08-06 19:06:56 +0200673 ptr = stktable_data_ptr(s->stkctr1_table,
674 s->stkctr1_entry,
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200675 STKTABLE_DT_BYTES_IN_RATE);
676 if (ptr)
677 update_freq_ctr_period(&stktable_data_cast(ptr, bytes_in_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200678 s->stkctr1_table->data_arg[STKTABLE_DT_BYTES_IN_RATE].u, bytes);
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200679 }
Willy Tarreau30e71012007-11-26 20:15:35 +0100680 }
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100681 }
682
Willy Tarreau30e71012007-11-26 20:15:35 +0100683 if (s->rep) {
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100684 bytes = s->rep->total - s->logs.bytes_out;
Willy Tarreau30e71012007-11-26 20:15:35 +0100685 s->logs.bytes_out = s->rep->total;
686 if (bytes) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100687 s->fe->fe_counters.bytes_out += bytes;
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100688
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100689 s->be->be_counters.bytes_out += bytes;
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100690
Willy Tarreau827aee92011-03-10 16:55:02 +0100691 if (target_srv(&s->target))
692 target_srv(&s->target)->counters.bytes_out += bytes;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200693
694 if (s->listener->counters)
695 s->listener->counters->bytes_out += bytes;
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200696
Willy Tarreau56123282010-08-06 19:06:56 +0200697 if (s->stkctr2_entry) {
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200698 void *ptr;
699
Willy Tarreau56123282010-08-06 19:06:56 +0200700 ptr = stktable_data_ptr(s->stkctr2_table,
701 s->stkctr2_entry,
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200702 STKTABLE_DT_BYTES_OUT_CNT);
703 if (ptr)
704 stktable_data_cast(ptr, bytes_out_cnt) += bytes;
705
Willy Tarreau56123282010-08-06 19:06:56 +0200706 ptr = stktable_data_ptr(s->stkctr2_table,
707 s->stkctr2_entry,
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200708 STKTABLE_DT_BYTES_OUT_RATE);
709 if (ptr)
710 update_freq_ctr_period(&stktable_data_cast(ptr, bytes_out_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200711 s->stkctr2_table->data_arg[STKTABLE_DT_BYTES_OUT_RATE].u, bytes);
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200712 }
713
Willy Tarreau56123282010-08-06 19:06:56 +0200714 if (s->stkctr1_entry) {
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200715 void *ptr;
716
Willy Tarreau56123282010-08-06 19:06:56 +0200717 ptr = stktable_data_ptr(s->stkctr1_table,
718 s->stkctr1_entry,
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200719 STKTABLE_DT_BYTES_OUT_CNT);
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200720 if (ptr)
721 stktable_data_cast(ptr, bytes_out_cnt) += bytes;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200722
Willy Tarreau56123282010-08-06 19:06:56 +0200723 ptr = stktable_data_ptr(s->stkctr1_table,
724 s->stkctr1_entry,
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200725 STKTABLE_DT_BYTES_OUT_RATE);
726 if (ptr)
727 update_freq_ctr_period(&stktable_data_cast(ptr, bytes_out_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200728 s->stkctr1_table->data_arg[STKTABLE_DT_BYTES_OUT_RATE].u, bytes);
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200729 }
Willy Tarreau30e71012007-11-26 20:15:35 +0100730 }
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100731 }
732}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200733
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100734/* This function is called with (si->state == SI_ST_CON) meaning that a
735 * connection was attempted and that the file descriptor is already allocated.
736 * We must check for establishment, error and abort. Possible output states
737 * are SI_ST_EST (established), SI_ST_CER (error), SI_ST_DIS (abort), and
738 * SI_ST_CON (no change). The function returns 0 if it switches to SI_ST_CER,
739 * otherwise 1.
740 */
Simon Hormandec5be42011-06-08 09:19:07 +0900741static int sess_update_st_con_tcp(struct session *s, struct stream_interface *si)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100742{
Willy Tarreau7421efb2012-07-02 15:11:27 +0200743 struct channel *req = si->ob;
744 struct channel *rep = si->ib;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100745
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100746 /* If we got an error, or if nothing happened and the connection timed
747 * out, we must give up. The CER state handler will take care of retry
748 * attempts and error reports.
749 */
750 if (unlikely(si->flags & (SI_FL_EXP|SI_FL_ERR))) {
Willy Tarreau127334e2009-03-28 10:47:26 +0100751 si->exp = TICK_ETERNITY;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100752 si->state = SI_ST_CER;
Willy Tarreaufb7508a2012-05-21 16:47:54 +0200753 fd_delete(si_fd(si));
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100754
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200755 conn_xprt_close(&si->conn);
Willy Tarreau0bd05ea2010-07-02 11:18:03 +0200756 if (si->release)
757 si->release(si);
758
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100759 if (si->err_type)
760 return 0;
761
Willy Tarreau827aee92011-03-10 16:55:02 +0100762 si->err_loc = target_srv(&s->target);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100763 if (si->flags & SI_FL_ERR)
764 si->err_type = SI_ET_CONN_ERR;
765 else
766 si->err_type = SI_ET_CONN_TO;
767 return 0;
768 }
769
770 /* OK, maybe we want to abort */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200771 if (unlikely((rep->flags & CF_SHUTW) ||
772 ((req->flags & CF_SHUTW_NOW) && /* FIXME: this should not prevent a connection from establishing */
773 ((!(req->flags & CF_WRITE_ACTIVITY) && channel_is_empty(req)) ||
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100774 s->be->options & PR_O_ABRT_CLOSE)))) {
775 /* give up */
Willy Tarreau73b013b2012-05-21 16:31:45 +0200776 si_shutw(si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100777 si->err_type |= SI_ET_CONN_ABRT;
Willy Tarreau827aee92011-03-10 16:55:02 +0100778 si->err_loc = target_srv(&s->target);
Willy Tarreau84455332009-03-15 22:34:05 +0100779 if (s->srv_error)
780 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100781 return 1;
782 }
783
784 /* we need to wait a bit more if there was no activity either */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200785 if (!(req->flags & CF_WRITE_ACTIVITY))
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100786 return 1;
787
788 /* OK, this means that a connection succeeded. The caller will be
789 * responsible for handling the transition from CON to EST.
790 */
791 s->logs.t_connect = tv_ms_elapsed(&s->logs.tv_accept, &now);
Willy Tarreau127334e2009-03-28 10:47:26 +0100792 si->exp = TICK_ETERNITY;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100793 si->state = SI_ST_EST;
794 si->err_type = SI_ET_NONE;
795 si->err_loc = NULL;
796 return 1;
797}
798
799/* This function is called with (si->state == SI_ST_CER) meaning that a
800 * previous connection attempt has failed and that the file descriptor
801 * has already been released. Possible causes include asynchronous error
802 * notification and time out. Possible output states are SI_ST_CLO when
803 * retries are exhausted, SI_ST_TAR when a delay is wanted before a new
804 * connection attempt, SI_ST_ASS when it's wise to retry on the same server,
805 * and SI_ST_REQ when an immediate redispatch is wanted. The buffers are
806 * marked as in error state. It returns 0.
807 */
Simon Hormandec5be42011-06-08 09:19:07 +0900808static int sess_update_st_cer(struct session *s, struct stream_interface *si)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100809{
810 /* we probably have to release last session from the server */
Willy Tarreau827aee92011-03-10 16:55:02 +0100811 if (target_srv(&s->target)) {
812 health_adjust(target_srv(&s->target), HANA_STATUS_L4_ERR);
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +0100813
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100814 if (s->flags & SN_CURR_SESS) {
815 s->flags &= ~SN_CURR_SESS;
Willy Tarreau827aee92011-03-10 16:55:02 +0100816 target_srv(&s->target)->cur_sess--;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100817 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100818 }
819
820 /* ensure that we have enough retries left */
Willy Tarreauee28de02010-06-01 09:51:00 +0200821 si->conn_retries--;
822 if (si->conn_retries < 0) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100823 if (!si->err_type) {
824 si->err_type = SI_ET_CONN_ERR;
Willy Tarreau827aee92011-03-10 16:55:02 +0100825 si->err_loc = target_srv(&s->target);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100826 }
827
Willy Tarreau827aee92011-03-10 16:55:02 +0100828 if (target_srv(&s->target))
829 target_srv(&s->target)->counters.failed_conns++;
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100830 s->be->be_counters.failed_conns++;
Willy Tarreaub89cfca2010-12-29 14:32:28 +0100831 sess_change_server(s, NULL);
Willy Tarreau827aee92011-03-10 16:55:02 +0100832 if (may_dequeue_tasks(target_srv(&s->target), s->be))
833 process_srv_queue(target_srv(&s->target));
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100834
835 /* shutw is enough so stop a connecting socket */
Willy Tarreau73b013b2012-05-21 16:31:45 +0200836 si_shutw(si);
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200837 si->ob->flags |= CF_WRITE_ERROR;
838 si->ib->flags |= CF_READ_ERROR;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100839
840 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +0100841 if (s->srv_error)
842 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100843 return 0;
844 }
845
846 /* If the "redispatch" option is set on the backend, we are allowed to
847 * retry on another server for the last retry. In order to achieve this,
848 * we must mark the session unassigned, and eventually clear the DIRECT
849 * bit to ignore any persistence cookie. We won't count a retry nor a
850 * redispatch yet, because this will depend on what server is selected.
851 */
Willy Tarreau827aee92011-03-10 16:55:02 +0100852 if (target_srv(&s->target) && si->conn_retries == 0 &&
Willy Tarreau4de91492010-01-22 19:10:05 +0100853 s->be->options & PR_O_REDISP && !(s->flags & SN_FORCE_PRST)) {
Willy Tarreaub89cfca2010-12-29 14:32:28 +0100854 sess_change_server(s, NULL);
Willy Tarreau827aee92011-03-10 16:55:02 +0100855 if (may_dequeue_tasks(target_srv(&s->target), s->be))
856 process_srv_queue(target_srv(&s->target));
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100857
858 s->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100859 si->state = SI_ST_REQ;
860 } else {
Willy Tarreau827aee92011-03-10 16:55:02 +0100861 if (target_srv(&s->target))
862 target_srv(&s->target)->counters.retries++;
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100863 s->be->be_counters.retries++;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100864 si->state = SI_ST_ASS;
865 }
866
867 if (si->flags & SI_FL_ERR) {
868 /* The error was an asynchronous connection error, and we will
869 * likely have to retry connecting to the same server, most
870 * likely leading to the same result. To avoid this, we wait
871 * one second before retrying.
872 */
873
874 if (!si->err_type)
875 si->err_type = SI_ET_CONN_ERR;
876
877 si->state = SI_ST_TAR;
878 si->exp = tick_add(now_ms, MS_TO_TICKS(1000));
879 return 0;
880 }
881 return 0;
882}
883
884/*
885 * This function handles the transition between the SI_ST_CON state and the
Willy Tarreau85e7d002010-05-31 11:57:51 +0200886 * SI_ST_EST state. It must only be called after switching from SI_ST_CON (or
Willy Tarreau26d8c592012-05-07 18:12:14 +0200887 * SI_ST_INI) to SI_ST_EST, but only when a ->proto is defined.
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100888 */
Simon Hormandec5be42011-06-08 09:19:07 +0900889static void sess_establish(struct session *s, struct stream_interface *si)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100890{
Willy Tarreau7421efb2012-07-02 15:11:27 +0200891 struct channel *req = si->ob;
892 struct channel *rep = si->ib;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100893
Willy Tarreau827aee92011-03-10 16:55:02 +0100894 if (target_srv(&s->target))
895 health_adjust(target_srv(&s->target), HANA_STATUS_L4_OK);
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +0100896
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100897 if (s->be->mode == PR_MODE_TCP) { /* let's allow immediate data connection in this case */
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100898 /* if the user wants to log as soon as possible, without counting
899 * bytes from the server, then this is the right moment. */
900 if (s->fe->to_log && !(s->logs.logwait & LW_BYTES)) {
901 s->logs.t_close = s->logs.t_connect; /* to get a valid end date */
Willy Tarreaua5555ec2008-11-30 19:02:32 +0100902 s->do_log(s);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100903 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100904 }
905 else {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100906 s->txn.rsp.msg_state = HTTP_MSG_RPBEFORE;
907 /* reset hdr_idx which was already initialized by the request.
908 * right now, the http parser does it.
909 * hdr_idx_init(&s->txn.hdr_idx);
910 */
911 }
912
Willy Tarreau4e5b8282009-08-16 22:57:50 +0200913 rep->analysers |= s->fe->fe_rsp_ana | s->be->be_rsp_ana;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200914 rep->flags |= CF_READ_ATTACHED; /* producer is now attached */
Willy Tarreau73b013b2012-05-21 16:31:45 +0200915 if (si_ctrl(si)) {
Willy Tarreaud04e8582010-05-31 12:31:35 +0200916 /* real connections have timeouts */
917 req->wto = s->be->timeout.server;
918 rep->rto = s->be->timeout.server;
919 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100920 req->wex = TICK_ETERNITY;
921}
922
923/* Update stream interface status for input states SI_ST_ASS, SI_ST_QUE, SI_ST_TAR.
924 * Other input states are simply ignored.
925 * Possible output states are SI_ST_CLO, SI_ST_TAR, SI_ST_ASS, SI_ST_REQ, SI_ST_CON.
926 * Flags must have previously been updated for timeouts and other conditions.
927 */
Simon Hormandec5be42011-06-08 09:19:07 +0900928static void sess_update_stream_int(struct session *s, struct stream_interface *si)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100929{
Willy Tarreau827aee92011-03-10 16:55:02 +0100930 struct server *srv = target_srv(&s->target);
931
Willy Tarreau02d6cfc2012-03-01 18:19:58 +0100932 DPRINTF(stderr,"[%u] %s: sess=%p rq=%p, rp=%p, exp(r,w)=%u,%u rqf=%08x rpf=%08x rqh=%d rqt=%d rph=%d rpt=%d cs=%d ss=%d\n",
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100933 now_ms, __FUNCTION__,
934 s,
935 s->req, s->rep,
936 s->req->rex, s->rep->wex,
937 s->req->flags, s->rep->flags,
Willy Tarreau9b28e032012-10-12 23:49:43 +0200938 s->req->buf->i, s->req->buf->o, s->rep->buf->i, s->rep->buf->o, s->rep->cons->state, s->req->cons->state);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100939
940 if (si->state == SI_ST_ASS) {
941 /* Server assigned to connection request, we have to try to connect now */
942 int conn_err;
943
944 conn_err = connect_server(s);
Willy Tarreau827aee92011-03-10 16:55:02 +0100945 srv = target_srv(&s->target);
946
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100947 if (conn_err == SN_ERR_NONE) {
948 /* state = SI_ST_CON now */
Willy Tarreau827aee92011-03-10 16:55:02 +0100949 if (srv)
950 srv_inc_sess_ctr(srv);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100951 return;
952 }
953
954 /* We have received a synchronous error. We might have to
955 * abort, retry immediately or redispatch.
956 */
957 if (conn_err == SN_ERR_INTERNAL) {
958 if (!si->err_type) {
959 si->err_type = SI_ET_CONN_OTHER;
Willy Tarreau827aee92011-03-10 16:55:02 +0100960 si->err_loc = srv;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100961 }
962
Willy Tarreau827aee92011-03-10 16:55:02 +0100963 if (srv)
964 srv_inc_sess_ctr(srv);
965 if (srv)
966 srv->counters.failed_conns++;
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100967 s->be->be_counters.failed_conns++;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100968
969 /* release other sessions waiting for this server */
Willy Tarreaub89cfca2010-12-29 14:32:28 +0100970 sess_change_server(s, NULL);
Willy Tarreau827aee92011-03-10 16:55:02 +0100971 if (may_dequeue_tasks(srv, s->be))
972 process_srv_queue(srv);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100973
974 /* Failed and not retryable. */
Willy Tarreau73b013b2012-05-21 16:31:45 +0200975 si_shutr(si);
976 si_shutw(si);
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200977 si->ob->flags |= CF_WRITE_ERROR;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100978
979 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
980
981 /* no session was ever accounted for this server */
982 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +0100983 if (s->srv_error)
984 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100985 return;
986 }
987
988 /* We are facing a retryable error, but we don't want to run a
989 * turn-around now, as the problem is likely a source port
990 * allocation problem, so we want to retry now.
991 */
992 si->state = SI_ST_CER;
993 si->flags &= ~SI_FL_ERR;
994 sess_update_st_cer(s, si);
995 /* now si->state is one of SI_ST_CLO, SI_ST_TAR, SI_ST_ASS, SI_ST_REQ */
996 return;
997 }
998 else if (si->state == SI_ST_QUE) {
999 /* connection request was queued, check for any update */
1000 if (!s->pend_pos) {
1001 /* The connection is not in the queue anymore. Either
1002 * we have a server connection slot available and we
1003 * go directly to the assigned state, or we need to
1004 * load-balance first and go to the INI state.
1005 */
1006 si->exp = TICK_ETERNITY;
1007 if (unlikely(!(s->flags & SN_ASSIGNED)))
1008 si->state = SI_ST_REQ;
1009 else {
1010 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
1011 si->state = SI_ST_ASS;
1012 }
1013 return;
1014 }
1015
1016 /* Connection request still in queue... */
1017 if (si->flags & SI_FL_EXP) {
1018 /* ... and timeout expired */
1019 si->exp = TICK_ETERNITY;
1020 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
Willy Tarreau827aee92011-03-10 16:55:02 +01001021 if (srv)
1022 srv->counters.failed_conns++;
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001023 s->be->be_counters.failed_conns++;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001024 si_shutr(si);
1025 si_shutw(si);
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001026 si->ob->flags |= CF_WRITE_TIMEOUT;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001027 if (!si->err_type)
1028 si->err_type = SI_ET_QUEUE_TO;
1029 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +01001030 if (s->srv_error)
1031 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001032 return;
1033 }
1034
1035 /* Connection remains in queue, check if we have to abort it */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001036 if ((si->ob->flags & (CF_READ_ERROR)) ||
1037 ((si->ob->flags & CF_SHUTW_NOW) && /* empty and client aborted */
Willy Tarreau8e21bb92012-08-24 22:40:29 +02001038 (channel_is_empty(si->ob) || s->be->options & PR_O_ABRT_CLOSE))) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001039 /* give up */
1040 si->exp = TICK_ETERNITY;
1041 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
Willy Tarreau73b013b2012-05-21 16:31:45 +02001042 si_shutr(si);
1043 si_shutw(si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001044 si->err_type |= SI_ET_QUEUE_ABRT;
1045 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +01001046 if (s->srv_error)
1047 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001048 return;
1049 }
1050
1051 /* Nothing changed */
1052 return;
1053 }
1054 else if (si->state == SI_ST_TAR) {
1055 /* Connection request might be aborted */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001056 if ((si->ob->flags & (CF_READ_ERROR)) ||
1057 ((si->ob->flags & CF_SHUTW_NOW) && /* empty and client aborted */
Willy Tarreau8e21bb92012-08-24 22:40:29 +02001058 (channel_is_empty(si->ob) || s->be->options & PR_O_ABRT_CLOSE))) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001059 /* give up */
1060 si->exp = TICK_ETERNITY;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001061 si_shutr(si);
1062 si_shutw(si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001063 si->err_type |= SI_ET_CONN_ABRT;
1064 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +01001065 if (s->srv_error)
1066 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001067 return;
1068 }
1069
1070 if (!(si->flags & SI_FL_EXP))
1071 return; /* still in turn-around */
1072
1073 si->exp = TICK_ETERNITY;
1074
1075 /* we keep trying on the same server as long as the session is
1076 * marked "assigned".
1077 * FIXME: Should we force a redispatch attempt when the server is down ?
1078 */
1079 if (s->flags & SN_ASSIGNED)
1080 si->state = SI_ST_ASS;
1081 else
1082 si->state = SI_ST_REQ;
1083 return;
1084 }
1085}
1086
Simon Hormandec5be42011-06-08 09:19:07 +09001087/* Set correct session termination flags in case no analyser has done it. It
1088 * also counts a failed request if the server state has not reached the request
1089 * stage.
1090 */
1091static void sess_set_term_flags(struct session *s)
1092{
1093 if (!(s->flags & SN_FINST_MASK)) {
1094 if (s->si[1].state < SI_ST_REQ) {
1095
1096 s->fe->fe_counters.failed_req++;
1097 if (s->listener->counters)
1098 s->listener->counters->failed_req++;
1099
1100 s->flags |= SN_FINST_R;
1101 }
1102 else if (s->si[1].state == SI_ST_QUE)
1103 s->flags |= SN_FINST_Q;
1104 else if (s->si[1].state < SI_ST_EST)
1105 s->flags |= SN_FINST_C;
1106 else if (s->si[1].state == SI_ST_EST || s->si[1].prev_state == SI_ST_EST)
1107 s->flags |= SN_FINST_D;
1108 else
1109 s->flags |= SN_FINST_L;
1110 }
1111}
1112
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001113/* This function initiates a server connection request on a stream interface
1114 * already in SI_ST_REQ state. Upon success, the state goes to SI_ST_ASS,
1115 * indicating that a server has been assigned. It may also return SI_ST_QUE,
1116 * or SI_ST_CLO upon error.
1117 */
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001118static void sess_prepare_conn_req(struct session *s, struct stream_interface *si)
1119{
1120 DPRINTF(stderr,"[%u] %s: sess=%p rq=%p, rp=%p, exp(r,w)=%u,%u rqf=%08x rpf=%08x rqh=%d rqt=%d rph=%d rpt=%d cs=%d ss=%d\n",
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001121 now_ms, __FUNCTION__,
1122 s,
1123 s->req, s->rep,
1124 s->req->rex, s->rep->wex,
1125 s->req->flags, s->rep->flags,
Willy Tarreau9b28e032012-10-12 23:49:43 +02001126 s->req->buf->i, s->req->buf->o, s->rep->buf->i, s->rep->buf->o, s->rep->cons->state, s->req->cons->state);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001127
1128 if (si->state != SI_ST_REQ)
1129 return;
1130
1131 /* Try to assign a server */
1132 if (srv_redispatch_connect(s) != 0) {
1133 /* We did not get a server. Either we queued the
1134 * connection request, or we encountered an error.
1135 */
1136 if (si->state == SI_ST_QUE)
1137 return;
1138
1139 /* we did not get any server, let's check the cause */
Willy Tarreau73b013b2012-05-21 16:31:45 +02001140 si_shutr(si);
1141 si_shutw(si);
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001142 si->ob->flags |= CF_WRITE_ERROR;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001143 if (!si->err_type)
1144 si->err_type = SI_ET_CONN_OTHER;
1145 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +01001146 if (s->srv_error)
1147 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001148 return;
1149 }
1150
1151 /* The server is assigned */
1152 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
1153 si->state = SI_ST_ASS;
1154}
1155
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001156/* This stream analyser checks the switching rules and changes the backend
Willy Tarreau4de91492010-01-22 19:10:05 +01001157 * if appropriate. The default_backend rule is also considered, then the
1158 * target backend's forced persistence rules are also evaluated last if any.
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001159 * It returns 1 if the processing can continue on next analysers, or zero if it
1160 * either needs more data or wants to immediately abort the request.
1161 */
Willy Tarreau7421efb2012-07-02 15:11:27 +02001162static int process_switching_rules(struct session *s, struct channel *req, int an_bit)
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001163{
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001164 struct persist_rule *prst_rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01001165
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001166 req->analysers &= ~an_bit;
1167 req->analyse_exp = TICK_ETERNITY;
1168
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001169 DPRINTF(stderr,"[%u] %s: session=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%d analysers=%02x\n",
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001170 now_ms, __FUNCTION__,
1171 s,
1172 req,
1173 req->rex, req->wex,
1174 req->flags,
Willy Tarreau9b28e032012-10-12 23:49:43 +02001175 req->buf->i,
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001176 req->analysers);
1177
1178 /* now check whether we have some switching rules for this request */
1179 if (!(s->flags & SN_BE_ASSIGNED)) {
1180 struct switching_rule *rule;
1181
1182 list_for_each_entry(rule, &s->fe->switching_rules, list) {
1183 int ret;
1184
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001185 ret = acl_exec_cond(rule->cond, s->fe, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001186 ret = acl_pass(ret);
1187 if (rule->cond->pol == ACL_COND_UNLESS)
1188 ret = !ret;
1189
1190 if (ret) {
Willy Tarreaubedb9ba2009-07-12 08:27:39 +02001191 if (!session_set_backend(s, rule->be.backend))
1192 goto sw_failed;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001193 break;
1194 }
1195 }
1196
1197 /* To ensure correct connection accounting on the backend, we
1198 * have to assign one if it was not set (eg: a listen). This
1199 * measure also takes care of correctly setting the default
1200 * backend if any.
1201 */
1202 if (!(s->flags & SN_BE_ASSIGNED))
Willy Tarreaubedb9ba2009-07-12 08:27:39 +02001203 if (!session_set_backend(s, s->fe->defbe.be ? s->fe->defbe.be : s->be))
1204 goto sw_failed;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001205 }
1206
Willy Tarreaufb356202010-08-03 14:02:05 +02001207 /* we don't want to run the TCP or HTTP filters again if the backend has not changed */
1208 if (s->fe == s->be) {
1209 s->req->analysers &= ~AN_REQ_INSPECT_BE;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001210 s->req->analysers &= ~AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaufb356202010-08-03 14:02:05 +02001211 }
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001212
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001213 /* as soon as we know the backend, we must check if we have a matching forced or ignored
Willy Tarreau4de91492010-01-22 19:10:05 +01001214 * persistence rule, and report that in the session.
1215 */
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001216 list_for_each_entry(prst_rule, &s->be->persist_rules, list) {
Willy Tarreau4de91492010-01-22 19:10:05 +01001217 int ret = 1;
1218
1219 if (prst_rule->cond) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001220 ret = acl_exec_cond(prst_rule->cond, s->be, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
Willy Tarreau4de91492010-01-22 19:10:05 +01001221 ret = acl_pass(ret);
1222 if (prst_rule->cond->pol == ACL_COND_UNLESS)
1223 ret = !ret;
1224 }
1225
1226 if (ret) {
1227 /* no rule, or the rule matches */
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001228 if (prst_rule->type == PERSIST_TYPE_FORCE) {
1229 s->flags |= SN_FORCE_PRST;
1230 } else {
1231 s->flags |= SN_IGNORE_PRST;
1232 }
Willy Tarreau4de91492010-01-22 19:10:05 +01001233 break;
1234 }
1235 }
1236
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001237 return 1;
Willy Tarreaubedb9ba2009-07-12 08:27:39 +02001238
1239 sw_failed:
1240 /* immediately abort this request in case of allocation failure */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001241 channel_abort(s->req);
1242 channel_abort(s->rep);
Willy Tarreaubedb9ba2009-07-12 08:27:39 +02001243
1244 if (!(s->flags & SN_ERR_MASK))
1245 s->flags |= SN_ERR_RESOURCE;
1246 if (!(s->flags & SN_FINST_MASK))
1247 s->flags |= SN_FINST_R;
1248
1249 s->txn.status = 500;
1250 s->req->analysers = 0;
1251 s->req->analyse_exp = TICK_ETERNITY;
1252 return 0;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001253}
1254
Willy Tarreau4a5cade2012-04-05 21:09:48 +02001255/* This stream analyser works on a request. It applies all use-server rules on
1256 * it then returns 1. The data must already be present in the buffer otherwise
1257 * they won't match. It always returns 1.
1258 */
Willy Tarreau7421efb2012-07-02 15:11:27 +02001259static int process_server_rules(struct session *s, struct channel *req, int an_bit)
Willy Tarreau4a5cade2012-04-05 21:09:48 +02001260{
1261 struct proxy *px = s->be;
1262 struct server_rule *rule;
1263
1264 DPRINTF(stderr,"[%u] %s: session=%p b=%p, exp(r,w)=%u,%u bf=%08x bl=%d analysers=%02x\n",
1265 now_ms, __FUNCTION__,
1266 s,
1267 req,
1268 req->rex, req->wex,
1269 req->flags,
Willy Tarreau9b28e032012-10-12 23:49:43 +02001270 req->buf->i + req->buf->o,
Willy Tarreau4a5cade2012-04-05 21:09:48 +02001271 req->analysers);
1272
1273 if (!(s->flags & SN_ASSIGNED)) {
1274 list_for_each_entry(rule, &px->server_rules, list) {
1275 int ret;
1276
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001277 ret = acl_exec_cond(rule->cond, s->be, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02001278 ret = acl_pass(ret);
1279 if (rule->cond->pol == ACL_COND_UNLESS)
1280 ret = !ret;
1281
1282 if (ret) {
1283 struct server *srv = rule->srv.ptr;
1284
1285 if ((srv->state & SRV_RUNNING) ||
1286 (px->options & PR_O_PERSIST) ||
1287 (s->flags & SN_FORCE_PRST)) {
1288 s->flags |= SN_DIRECT | SN_ASSIGNED;
1289 set_target_server(&s->target, srv);
1290 break;
1291 }
1292 /* if the server is not UP, let's go on with next rules
1293 * just in case another one is suited.
1294 */
1295 }
1296 }
1297 }
1298
1299 req->analysers &= ~an_bit;
1300 req->analyse_exp = TICK_ETERNITY;
1301 return 1;
1302}
1303
Emeric Brun1d33b292010-01-04 15:47:17 +01001304/* This stream analyser works on a request. It applies all sticking rules on
1305 * it then returns 1. The data must already be present in the buffer otherwise
1306 * they won't match. It always returns 1.
1307 */
Willy Tarreau7421efb2012-07-02 15:11:27 +02001308static int process_sticking_rules(struct session *s, struct channel *req, int an_bit)
Emeric Brun1d33b292010-01-04 15:47:17 +01001309{
1310 struct proxy *px = s->be;
1311 struct sticking_rule *rule;
1312
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001313 DPRINTF(stderr,"[%u] %s: session=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%d analysers=%02x\n",
Emeric Brun1d33b292010-01-04 15:47:17 +01001314 now_ms, __FUNCTION__,
1315 s,
1316 req,
1317 req->rex, req->wex,
1318 req->flags,
Willy Tarreau9b28e032012-10-12 23:49:43 +02001319 req->buf->i,
Emeric Brun1d33b292010-01-04 15:47:17 +01001320 req->analysers);
1321
1322 list_for_each_entry(rule, &px->sticking_rules, list) {
1323 int ret = 1 ;
1324 int i;
1325
1326 for (i = 0; i < s->store_count; i++) {
1327 if (rule->table.t == s->store[i].table)
1328 break;
1329 }
1330
1331 if (i != s->store_count)
1332 continue;
1333
1334 if (rule->cond) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001335 ret = acl_exec_cond(rule->cond, px, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
Emeric Brun1d33b292010-01-04 15:47:17 +01001336 ret = acl_pass(ret);
1337 if (rule->cond->pol == ACL_COND_UNLESS)
1338 ret = !ret;
1339 }
1340
1341 if (ret) {
1342 struct stktable_key *key;
1343
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001344 key = stktable_fetch_key(rule->table.t, px, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, rule->expr);
Emeric Brun1d33b292010-01-04 15:47:17 +01001345 if (!key)
1346 continue;
1347
1348 if (rule->flags & STK_IS_MATCH) {
1349 struct stksess *ts;
1350
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001351 if ((ts = stktable_lookup_key(rule->table.t, key)) != NULL) {
Emeric Brun1d33b292010-01-04 15:47:17 +01001352 if (!(s->flags & SN_ASSIGNED)) {
1353 struct eb32_node *node;
Willy Tarreau13c29de2010-06-06 16:40:39 +02001354 void *ptr;
Emeric Brun1d33b292010-01-04 15:47:17 +01001355
1356 /* srv found in table */
Willy Tarreau13c29de2010-06-06 16:40:39 +02001357 ptr = stktable_data_ptr(rule->table.t, ts, STKTABLE_DT_SERVER_ID);
1358 node = eb32_lookup(&px->conf.used_server_id, stktable_data_cast(ptr, server_id));
Emeric Brun1d33b292010-01-04 15:47:17 +01001359 if (node) {
1360 struct server *srv;
1361
1362 srv = container_of(node, struct server, conf.id);
Willy Tarreau4de91492010-01-22 19:10:05 +01001363 if ((srv->state & SRV_RUNNING) ||
1364 (px->options & PR_O_PERSIST) ||
1365 (s->flags & SN_FORCE_PRST)) {
Emeric Brun1d33b292010-01-04 15:47:17 +01001366 s->flags |= SN_DIRECT | SN_ASSIGNED;
Willy Tarreau9e000c62011-03-10 14:03:36 +01001367 set_target_server(&s->target, srv);
Emeric Brun1d33b292010-01-04 15:47:17 +01001368 }
1369 }
1370 }
Emeric Brun85e77c72010-09-23 18:16:52 +02001371 stktable_touch(rule->table.t, ts, 1);
Emeric Brun1d33b292010-01-04 15:47:17 +01001372 }
1373 }
1374 if (rule->flags & STK_IS_STORE) {
1375 if (s->store_count < (sizeof(s->store) / sizeof(s->store[0]))) {
1376 struct stksess *ts;
1377
1378 ts = stksess_new(rule->table.t, key);
1379 if (ts) {
1380 s->store[s->store_count].table = rule->table.t;
1381 s->store[s->store_count++].ts = ts;
1382 }
1383 }
1384 }
1385 }
1386 }
1387
1388 req->analysers &= ~an_bit;
1389 req->analyse_exp = TICK_ETERNITY;
1390 return 1;
1391}
1392
1393/* This stream analyser works on a response. It applies all store rules on it
1394 * then returns 1. The data must already be present in the buffer otherwise
1395 * they won't match. It always returns 1.
1396 */
Willy Tarreau7421efb2012-07-02 15:11:27 +02001397static int process_store_rules(struct session *s, struct channel *rep, int an_bit)
Emeric Brun1d33b292010-01-04 15:47:17 +01001398{
1399 struct proxy *px = s->be;
1400 struct sticking_rule *rule;
1401 int i;
1402
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001403 DPRINTF(stderr,"[%u] %s: session=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%d analysers=%02x\n",
Emeric Brun1d33b292010-01-04 15:47:17 +01001404 now_ms, __FUNCTION__,
1405 s,
Willy Tarreau2e2b3eb2010-02-09 20:55:44 +01001406 rep,
1407 rep->rex, rep->wex,
1408 rep->flags,
Willy Tarreau9b28e032012-10-12 23:49:43 +02001409 rep->buf->i,
Willy Tarreau2e2b3eb2010-02-09 20:55:44 +01001410 rep->analysers);
Emeric Brun1d33b292010-01-04 15:47:17 +01001411
1412 list_for_each_entry(rule, &px->storersp_rules, list) {
1413 int ret = 1 ;
1414 int storereqidx = -1;
1415
1416 for (i = 0; i < s->store_count; i++) {
1417 if (rule->table.t == s->store[i].table) {
1418 if (!(s->store[i].flags))
1419 storereqidx = i;
1420 break;
1421 }
1422 }
1423
1424 if ((i != s->store_count) && (storereqidx == -1))
1425 continue;
1426
1427 if (rule->cond) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001428 ret = acl_exec_cond(rule->cond, px, s, &s->txn, SMP_OPT_DIR_RES|SMP_OPT_FINAL);
Emeric Brun1d33b292010-01-04 15:47:17 +01001429 ret = acl_pass(ret);
1430 if (rule->cond->pol == ACL_COND_UNLESS)
1431 ret = !ret;
1432 }
1433
1434 if (ret) {
1435 struct stktable_key *key;
1436
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001437 key = stktable_fetch_key(rule->table.t, px, s, &s->txn, SMP_OPT_DIR_RES|SMP_OPT_FINAL, rule->expr);
Emeric Brun1d33b292010-01-04 15:47:17 +01001438 if (!key)
1439 continue;
1440
1441 if (storereqidx != -1) {
Willy Tarreau393379c2010-06-06 12:11:37 +02001442 stksess_setkey(s->store[storereqidx].table, s->store[storereqidx].ts, key);
Emeric Brun1d33b292010-01-04 15:47:17 +01001443 s->store[storereqidx].flags = 1;
1444 }
1445 else if (s->store_count < (sizeof(s->store) / sizeof(s->store[0]))) {
1446 struct stksess *ts;
1447
1448 ts = stksess_new(rule->table.t, key);
1449 if (ts) {
1450 s->store[s->store_count].table = rule->table.t;
1451 s->store[s->store_count].flags = 1;
1452 s->store[s->store_count++].ts = ts;
1453 }
1454 }
1455 }
1456 }
1457
1458 /* process store request and store response */
1459 for (i = 0; i < s->store_count; i++) {
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001460 struct stksess *ts;
Willy Tarreau13c29de2010-06-06 16:40:39 +02001461 void *ptr;
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001462
Simon Hormanfa461682011-06-25 09:39:49 +09001463 if (target_srv(&s->target) && target_srv(&s->target)->state & SRV_NON_STICK) {
1464 stksess_free(s->store[i].table, s->store[i].ts);
1465 s->store[i].ts = NULL;
1466 continue;
1467 }
1468
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001469 ts = stktable_lookup(s->store[i].table, s->store[i].ts);
1470 if (ts) {
1471 /* the entry already existed, we can free ours */
Emeric Brun85e77c72010-09-23 18:16:52 +02001472 stktable_touch(s->store[i].table, ts, 1);
Emeric Brun1d33b292010-01-04 15:47:17 +01001473 stksess_free(s->store[i].table, s->store[i].ts);
Emeric Brun1d33b292010-01-04 15:47:17 +01001474 }
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001475 else
Emeric Brun85e77c72010-09-23 18:16:52 +02001476 ts = stktable_store(s->store[i].table, s->store[i].ts, 1);
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001477
1478 s->store[i].ts = NULL;
Willy Tarreau13c29de2010-06-06 16:40:39 +02001479 ptr = stktable_data_ptr(s->store[i].table, ts, STKTABLE_DT_SERVER_ID);
Willy Tarreau827aee92011-03-10 16:55:02 +01001480 stktable_data_cast(ptr, server_id) = target_srv(&s->target)->puid;
Emeric Brun1d33b292010-01-04 15:47:17 +01001481 }
Willy Tarreau2a164ee2010-06-18 09:57:45 +02001482 s->store_count = 0; /* everything is stored */
Emeric Brun1d33b292010-01-04 15:47:17 +01001483
1484 rep->analysers &= ~an_bit;
1485 rep->analyse_exp = TICK_ETERNITY;
1486 return 1;
1487}
1488
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001489/* This macro is very specific to the function below. See the comments in
1490 * process_session() below to understand the logic and the tests.
1491 */
1492#define UPDATE_ANALYSERS(real, list, back, flag) { \
1493 list = (((list) & ~(flag)) | ~(back)) & (real); \
1494 back = real; \
1495 if (!(list)) \
1496 break; \
1497 if (((list) ^ ((list) & ((list) - 1))) < (flag)) \
1498 continue; \
1499}
1500
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001501/* Processes the client, server, request and response jobs of a session task,
1502 * then puts it back to the wait queue in a clean state, or cleans up its
1503 * resources if it must be deleted. Returns in <next> the date the task wants
1504 * to be woken up, or TICK_ETERNITY. In order not to call all functions for
1505 * nothing too many times, the request and response buffers flags are monitored
1506 * and each function is called only if at least another function has changed at
1507 * least one flag it is interested in.
1508 */
Willy Tarreau26c25062009-03-08 09:38:41 +01001509struct task *process_session(struct task *t)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001510{
Willy Tarreau827aee92011-03-10 16:55:02 +01001511 struct server *srv;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001512 struct session *s = t->context;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001513 unsigned int rqf_last, rpf_last;
Willy Tarreau815a9b22010-07-27 17:15:12 +02001514 unsigned int rq_prod_last, rq_cons_last;
1515 unsigned int rp_cons_last, rp_prod_last;
Willy Tarreau576507f2010-01-07 00:09:04 +01001516 unsigned int req_ana_back;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001517
1518 //DPRINTF(stderr, "%s:%d: cs=%d ss=%d(%d) rqf=0x%08x rpf=0x%08x\n", __FUNCTION__, __LINE__,
1519 // s->si[0].state, s->si[1].state, s->si[1].err_type, s->req->flags, s->rep->flags);
1520
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001521 /* this data may be no longer valid, clear it */
1522 memset(&s->txn.auth, 0, sizeof(s->txn.auth));
1523
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001524 /* This flag must explicitly be set every time */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001525 s->req->flags &= ~CF_READ_NOEXP;
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001526
1527 /* Keep a copy of req/rep flags so that we can detect shutdowns */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001528 rqf_last = s->req->flags & ~CF_MASK_ANALYSER;
1529 rpf_last = s->rep->flags & ~CF_MASK_ANALYSER;
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001530
Willy Tarreau89f7ef22009-09-05 20:57:35 +02001531 /* we don't want the stream interface functions to recursively wake us up */
1532 if (s->req->prod->owner == t)
1533 s->req->prod->flags |= SI_FL_DONT_WAKE;
1534 if (s->req->cons->owner == t)
1535 s->req->cons->flags |= SI_FL_DONT_WAKE;
1536
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001537 /* 1a: Check for low level timeouts if needed. We just set a flag on
1538 * stream interfaces when their timeouts have expired.
1539 */
1540 if (unlikely(t->state & TASK_WOKEN_TIMER)) {
1541 stream_int_check_timeouts(&s->si[0]);
1542 stream_int_check_timeouts(&s->si[1]);
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001543
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001544 /* check channel timeouts, and close the corresponding stream interfaces
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001545 * for future reads or writes. Note: this will also concern upper layers
1546 * but we do not touch any other flag. We must be careful and correctly
1547 * detect state changes when calling them.
1548 */
1549
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001550 channel_check_timeouts(s->req);
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001551
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001552 if (unlikely((s->req->flags & (CF_SHUTW|CF_WRITE_TIMEOUT)) == CF_WRITE_TIMEOUT)) {
Willy Tarreau14641402009-12-29 14:49:56 +01001553 s->req->cons->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001554 si_shutw(s->req->cons);
Willy Tarreau14641402009-12-29 14:49:56 +01001555 }
1556
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001557 if (unlikely((s->req->flags & (CF_SHUTR|CF_READ_TIMEOUT)) == CF_READ_TIMEOUT)) {
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02001558 if (s->req->prod->flags & SI_FL_NOHALF)
1559 s->req->prod->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001560 si_shutr(s->req->prod);
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02001561 }
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001562
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001563 channel_check_timeouts(s->rep);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001564
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001565 if (unlikely((s->rep->flags & (CF_SHUTW|CF_WRITE_TIMEOUT)) == CF_WRITE_TIMEOUT)) {
Willy Tarreau14641402009-12-29 14:49:56 +01001566 s->rep->cons->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001567 si_shutw(s->rep->cons);
Willy Tarreau14641402009-12-29 14:49:56 +01001568 }
1569
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001570 if (unlikely((s->rep->flags & (CF_SHUTR|CF_READ_TIMEOUT)) == CF_READ_TIMEOUT)) {
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02001571 if (s->rep->prod->flags & SI_FL_NOHALF)
1572 s->rep->prod->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001573 si_shutr(s->rep->prod);
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02001574 }
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001575 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001576
1577 /* 1b: check for low-level errors reported at the stream interface.
1578 * First we check if it's a retryable error (in which case we don't
1579 * want to tell the buffer). Otherwise we report the error one level
1580 * upper by setting flags into the buffers. Note that the side towards
1581 * the client cannot have connect (hence retryable) errors. Also, the
1582 * connection setup code must be able to deal with any type of abort.
1583 */
Willy Tarreau827aee92011-03-10 16:55:02 +01001584 srv = target_srv(&s->target);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001585 if (unlikely(s->si[0].flags & SI_FL_ERR)) {
1586 if (s->si[0].state == SI_ST_EST || s->si[0].state == SI_ST_DIS) {
Willy Tarreau73b013b2012-05-21 16:31:45 +02001587 si_shutr(&s->si[0]);
1588 si_shutw(&s->si[0]);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001589 stream_int_report_error(&s->si[0]);
Willy Tarreau05cb29b2008-12-14 11:44:04 +01001590 if (!(s->req->analysers) && !(s->rep->analysers)) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001591 s->be->be_counters.cli_aborts++;
1592 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001593 if (srv)
1594 srv->counters.cli_aborts++;
Willy Tarreau05cb29b2008-12-14 11:44:04 +01001595 if (!(s->flags & SN_ERR_MASK))
1596 s->flags |= SN_ERR_CLICL;
1597 if (!(s->flags & SN_FINST_MASK))
1598 s->flags |= SN_FINST_D;
1599 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001600 }
1601 }
1602
1603 if (unlikely(s->si[1].flags & SI_FL_ERR)) {
1604 if (s->si[1].state == SI_ST_EST || s->si[1].state == SI_ST_DIS) {
Willy Tarreau73b013b2012-05-21 16:31:45 +02001605 si_shutr(&s->si[1]);
1606 si_shutw(&s->si[1]);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001607 stream_int_report_error(&s->si[1]);
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001608 s->be->be_counters.failed_resp++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001609 if (srv)
1610 srv->counters.failed_resp++;
Willy Tarreau05cb29b2008-12-14 11:44:04 +01001611 if (!(s->req->analysers) && !(s->rep->analysers)) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001612 s->be->be_counters.srv_aborts++;
1613 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001614 if (srv)
1615 srv->counters.srv_aborts++;
Willy Tarreau05cb29b2008-12-14 11:44:04 +01001616 if (!(s->flags & SN_ERR_MASK))
1617 s->flags |= SN_ERR_SRVCL;
1618 if (!(s->flags & SN_FINST_MASK))
1619 s->flags |= SN_FINST_D;
1620 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001621 }
1622 /* note: maybe we should process connection errors here ? */
1623 }
1624
1625 if (s->si[1].state == SI_ST_CON) {
1626 /* we were trying to establish a connection on the server side,
1627 * maybe it succeeded, maybe it failed, maybe we timed out, ...
1628 */
1629 if (unlikely(!sess_update_st_con_tcp(s, &s->si[1])))
1630 sess_update_st_cer(s, &s->si[1]);
1631 else if (s->si[1].state == SI_ST_EST)
1632 sess_establish(s, &s->si[1]);
1633
1634 /* state is now one of SI_ST_CON (still in progress), SI_ST_EST
1635 * (established), SI_ST_DIS (abort), SI_ST_CLO (last error),
1636 * SI_ST_ASS/SI_ST_TAR/SI_ST_REQ for retryable errors.
1637 */
1638 }
1639
Willy Tarreau815a9b22010-07-27 17:15:12 +02001640 rq_prod_last = s->si[0].state;
1641 rq_cons_last = s->si[1].state;
1642 rp_cons_last = s->si[0].state;
1643 rp_prod_last = s->si[1].state;
1644
1645 resync_stream_interface:
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001646 /* Check for connection closure */
1647
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001648 DPRINTF(stderr,
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001649 "[%u] %s:%d: task=%p s=%p, sfl=0x%08x, rq=%p, rp=%p, exp(r,w)=%u,%u rqf=%08x rpf=%08x rqh=%d rqt=%d rph=%d rpt=%d cs=%d ss=%d, cet=0x%x set=0x%x retr=%d\n",
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001650 now_ms, __FUNCTION__, __LINE__,
1651 t,
1652 s, s->flags,
1653 s->req, s->rep,
1654 s->req->rex, s->rep->wex,
1655 s->req->flags, s->rep->flags,
Willy Tarreau9b28e032012-10-12 23:49:43 +02001656 s->req->buf->i, s->req->buf->o, s->rep->buf->i, s->rep->buf->o, s->rep->cons->state, s->req->cons->state,
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001657 s->rep->cons->err_type, s->req->cons->err_type,
Willy Tarreauee28de02010-06-01 09:51:00 +02001658 s->req->cons->conn_retries);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001659
1660 /* nothing special to be done on client side */
1661 if (unlikely(s->req->prod->state == SI_ST_DIS))
1662 s->req->prod->state = SI_ST_CLO;
1663
1664 /* When a server-side connection is released, we have to count it and
1665 * check for pending connections on this server.
1666 */
1667 if (unlikely(s->req->cons->state == SI_ST_DIS)) {
1668 s->req->cons->state = SI_ST_CLO;
Willy Tarreau827aee92011-03-10 16:55:02 +01001669 srv = target_srv(&s->target);
1670 if (srv) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001671 if (s->flags & SN_CURR_SESS) {
1672 s->flags &= ~SN_CURR_SESS;
Willy Tarreau827aee92011-03-10 16:55:02 +01001673 srv->cur_sess--;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001674 }
1675 sess_change_server(s, NULL);
Willy Tarreau827aee92011-03-10 16:55:02 +01001676 if (may_dequeue_tasks(srv, s->be))
1677 process_srv_queue(srv);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001678 }
1679 }
1680
1681 /*
1682 * Note: of the transient states (REQ, CER, DIS), only REQ may remain
1683 * at this point.
1684 */
1685
Willy Tarreau0be0ef92009-03-08 19:20:25 +01001686 resync_request:
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001687 /* Analyse request */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001688 if (((s->req->flags & ~rqf_last) & CF_MASK_ANALYSER) ||
1689 ((s->req->flags ^ rqf_last) & CF_MASK_STATIC) ||
Willy Tarreau815a9b22010-07-27 17:15:12 +02001690 s->si[0].state != rq_prod_last ||
1691 s->si[1].state != rq_cons_last) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001692 unsigned int flags = s->req->flags;
1693
1694 if (s->req->prod->state >= SI_ST_EST) {
Willy Tarreaue34070e2010-01-08 00:32:27 +01001695 int max_loops = global.tune.maxpollevents;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001696 unsigned int ana_list;
1697 unsigned int ana_back;
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001698
Willy Tarreau90deb182010-01-07 00:20:41 +01001699 /* it's up to the analysers to stop new connections,
1700 * disable reading or closing. Note: if an analyser
1701 * disables any of these bits, it is responsible for
1702 * enabling them again when it disables itself, so
1703 * that other analysers are called in similar conditions.
1704 */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001705 channel_auto_read(s->req);
1706 channel_auto_connect(s->req);
1707 channel_auto_close(s->req);
Willy Tarreauedcf6682008-11-30 23:15:34 +01001708
1709 /* We will call all analysers for which a bit is set in
1710 * s->req->analysers, following the bit order from LSB
1711 * to MSB. The analysers must remove themselves from
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001712 * the list when not needed. Any analyser may return 0
1713 * to break out of the loop, either because of missing
1714 * data to take a decision, or because it decides to
1715 * kill the session. We loop at least once through each
1716 * analyser, and we may loop again if other analysers
1717 * are added in the middle.
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001718 *
1719 * We build a list of analysers to run. We evaluate all
1720 * of these analysers in the order of the lower bit to
1721 * the higher bit. This ordering is very important.
1722 * An analyser will often add/remove other analysers,
1723 * including itself. Any changes to itself have no effect
1724 * on the loop. If it removes any other analysers, we
1725 * want those analysers not to be called anymore during
1726 * this loop. If it adds an analyser that is located
1727 * after itself, we want it to be scheduled for being
1728 * processed during the loop. If it adds an analyser
1729 * which is located before it, we want it to switch to
1730 * it immediately, even if it has already been called
1731 * once but removed since.
1732 *
1733 * In order to achieve this, we compare the analyser
1734 * list after the call with a copy of it before the
1735 * call. The work list is fed with analyser bits that
1736 * appeared during the call. Then we compare previous
1737 * work list with the new one, and check the bits that
1738 * appeared. If the lowest of these bits is lower than
1739 * the current bit, it means we have enabled a previous
1740 * analyser and must immediately loop again.
Willy Tarreauedcf6682008-11-30 23:15:34 +01001741 */
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001742
1743 ana_list = ana_back = s->req->analysers;
Willy Tarreaue34070e2010-01-08 00:32:27 +01001744 while (ana_list && max_loops--) {
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001745 /* Warning! ensure that analysers are always placed in ascending order! */
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001746
Willy Tarreaufb356202010-08-03 14:02:05 +02001747 if (ana_list & AN_REQ_INSPECT_FE) {
1748 if (!tcp_inspect_request(s, s->req, AN_REQ_INSPECT_FE))
Willy Tarreauedcf6682008-11-30 23:15:34 +01001749 break;
Willy Tarreaufb356202010-08-03 14:02:05 +02001750 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_INSPECT_FE);
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001751 }
Willy Tarreauedcf6682008-11-30 23:15:34 +01001752
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001753 if (ana_list & AN_REQ_WAIT_HTTP) {
Willy Tarreau3a816292009-07-07 10:55:49 +02001754 if (!http_wait_for_request(s, s->req, AN_REQ_WAIT_HTTP))
Willy Tarreaud787e662009-07-07 10:14:51 +02001755 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001756 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_WAIT_HTTP);
Willy Tarreaud787e662009-07-07 10:14:51 +02001757 }
1758
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001759 if (ana_list & AN_REQ_HTTP_PROCESS_FE) {
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001760 if (!http_process_req_common(s, s->req, AN_REQ_HTTP_PROCESS_FE, s->fe))
1761 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001762 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_PROCESS_FE);
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001763 }
1764
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001765 if (ana_list & AN_REQ_SWITCHING_RULES) {
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001766 if (!process_switching_rules(s, s->req, AN_REQ_SWITCHING_RULES))
1767 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001768 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_SWITCHING_RULES);
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001769 }
1770
Willy Tarreaufb356202010-08-03 14:02:05 +02001771 if (ana_list & AN_REQ_INSPECT_BE) {
1772 if (!tcp_inspect_request(s, s->req, AN_REQ_INSPECT_BE))
1773 break;
1774 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_INSPECT_BE);
1775 }
1776
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001777 if (ana_list & AN_REQ_HTTP_PROCESS_BE) {
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001778 if (!http_process_req_common(s, s->req, AN_REQ_HTTP_PROCESS_BE, s->be))
1779 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001780 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_PROCESS_BE);
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001781 }
1782
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001783 if (ana_list & AN_REQ_HTTP_TARPIT) {
Willy Tarreau3a816292009-07-07 10:55:49 +02001784 if (!http_process_tarpit(s, s->req, AN_REQ_HTTP_TARPIT))
Willy Tarreau60b85b02008-11-30 23:28:40 +01001785 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001786 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_TARPIT);
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001787 }
Willy Tarreau60b85b02008-11-30 23:28:40 +01001788
Willy Tarreau4a5cade2012-04-05 21:09:48 +02001789 if (ana_list & AN_REQ_SRV_RULES) {
1790 if (!process_server_rules(s, s->req, AN_REQ_SRV_RULES))
1791 break;
1792 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_SRV_RULES);
1793 }
1794
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001795 if (ana_list & AN_REQ_HTTP_INNER) {
Willy Tarreauc465fd72009-08-31 00:17:18 +02001796 if (!http_process_request(s, s->req, AN_REQ_HTTP_INNER))
1797 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001798 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_INNER);
Willy Tarreauc465fd72009-08-31 00:17:18 +02001799 }
1800
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001801 if (ana_list & AN_REQ_HTTP_BODY) {
Willy Tarreau3a816292009-07-07 10:55:49 +02001802 if (!http_process_request_body(s, s->req, AN_REQ_HTTP_BODY))
Willy Tarreaud34af782008-11-30 23:36:37 +01001803 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001804 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_BODY);
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001805 }
Emeric Brun647caf12009-06-30 17:57:00 +02001806
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001807 if (ana_list & AN_REQ_PRST_RDP_COOKIE) {
Emeric Brun647caf12009-06-30 17:57:00 +02001808 if (!tcp_persist_rdp_cookie(s, s->req, AN_REQ_PRST_RDP_COOKIE))
1809 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001810 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_PRST_RDP_COOKIE);
Emeric Brun647caf12009-06-30 17:57:00 +02001811 }
Willy Tarreaud98cf932009-12-27 22:54:55 +01001812
Emeric Brun1d33b292010-01-04 15:47:17 +01001813 if (ana_list & AN_REQ_STICKING_RULES) {
1814 if (!process_sticking_rules(s, s->req, AN_REQ_STICKING_RULES))
1815 break;
1816 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_STICKING_RULES);
1817 }
1818
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001819 if (ana_list & AN_REQ_HTTP_XFER_BODY) {
Willy Tarreaud98cf932009-12-27 22:54:55 +01001820 if (!http_request_forward_body(s, s->req, AN_REQ_HTTP_XFER_BODY))
1821 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001822 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_XFER_BODY);
Willy Tarreaud98cf932009-12-27 22:54:55 +01001823 }
Willy Tarreaue34070e2010-01-08 00:32:27 +01001824 break;
1825 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001826 }
Willy Tarreau84455332009-03-15 22:34:05 +01001827
Willy Tarreau815a9b22010-07-27 17:15:12 +02001828 rq_prod_last = s->si[0].state;
1829 rq_cons_last = s->si[1].state;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001830 s->req->flags &= ~CF_WAKE_ONCE;
Willy Tarreau815a9b22010-07-27 17:15:12 +02001831 rqf_last = s->req->flags;
1832
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001833 if ((s->req->flags ^ flags) & CF_MASK_STATIC)
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001834 goto resync_request;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001835 }
1836
Willy Tarreau576507f2010-01-07 00:09:04 +01001837 /* we'll monitor the request analysers while parsing the response,
1838 * because some response analysers may indirectly enable new request
1839 * analysers (eg: HTTP keep-alive).
1840 */
1841 req_ana_back = s->req->analysers;
1842
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001843 resync_response:
1844 /* Analyse response */
1845
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001846 if (unlikely(s->rep->flags & CF_HIJACK)) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001847 /* In inject mode, we wake up everytime something has
1848 * happened on the write side of the buffer.
1849 */
1850 unsigned int flags = s->rep->flags;
1851
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001852 if ((s->rep->flags & (CF_WRITE_PARTIAL|CF_WRITE_ERROR|CF_SHUTW)) &&
Willy Tarreau3bf1b2b2012-08-27 20:46:07 +02001853 !channel_full(s->rep)) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001854 s->rep->hijacker(s, s->rep);
1855 }
1856
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001857 if ((s->rep->flags ^ flags) & CF_MASK_STATIC) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001858 rpf_last = s->rep->flags;
1859 goto resync_response;
1860 }
1861 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001862 else if (((s->rep->flags & ~rpf_last) & CF_MASK_ANALYSER) ||
1863 (s->rep->flags ^ rpf_last) & CF_MASK_STATIC ||
Willy Tarreau815a9b22010-07-27 17:15:12 +02001864 s->si[0].state != rp_cons_last ||
1865 s->si[1].state != rp_prod_last) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001866 unsigned int flags = s->rep->flags;
1867
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001868 if ((s->rep->flags & CF_MASK_ANALYSER) &&
Willy Tarreau0499e352010-12-17 07:13:42 +01001869 (s->rep->analysers & AN_REQ_WAIT_HTTP)) {
1870 /* Due to HTTP pipelining, the HTTP request analyser might be waiting
1871 * for some free space in the response buffer, so we might need to call
1872 * it when something changes in the response buffer, but still we pass
1873 * it the request buffer. Note that the SI state might very well still
1874 * be zero due to us returning a flow of redirects!
1875 */
1876 s->rep->analysers &= ~AN_REQ_WAIT_HTTP;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001877 s->req->flags |= CF_WAKE_ONCE;
Willy Tarreau0499e352010-12-17 07:13:42 +01001878 }
1879
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001880 if (s->rep->prod->state >= SI_ST_EST) {
Willy Tarreaue34070e2010-01-08 00:32:27 +01001881 int max_loops = global.tune.maxpollevents;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001882 unsigned int ana_list;
1883 unsigned int ana_back;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001884
Willy Tarreau90deb182010-01-07 00:20:41 +01001885 /* it's up to the analysers to stop disable reading or
1886 * closing. Note: if an analyser disables any of these
1887 * bits, it is responsible for enabling them again when
1888 * it disables itself, so that other analysers are called
1889 * in similar conditions.
1890 */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001891 channel_auto_read(s->rep);
1892 channel_auto_close(s->rep);
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001893
1894 /* We will call all analysers for which a bit is set in
1895 * s->rep->analysers, following the bit order from LSB
1896 * to MSB. The analysers must remove themselves from
1897 * the list when not needed. Any analyser may return 0
1898 * to break out of the loop, either because of missing
1899 * data to take a decision, or because it decides to
1900 * kill the session. We loop at least once through each
1901 * analyser, and we may loop again if other analysers
1902 * are added in the middle.
1903 */
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001904
1905 ana_list = ana_back = s->rep->analysers;
Willy Tarreaue34070e2010-01-08 00:32:27 +01001906 while (ana_list && max_loops--) {
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001907 /* Warning! ensure that analysers are always placed in ascending order! */
1908
Emeric Brun97679e72010-09-23 17:56:44 +02001909 if (ana_list & AN_RES_INSPECT) {
1910 if (!tcp_inspect_response(s, s->rep, AN_RES_INSPECT))
1911 break;
1912 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_INSPECT);
1913 }
1914
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001915 if (ana_list & AN_RES_WAIT_HTTP) {
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001916 if (!http_wait_for_response(s, s->rep, AN_RES_WAIT_HTTP))
1917 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001918 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_WAIT_HTTP);
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001919 }
1920
Emeric Brun1d33b292010-01-04 15:47:17 +01001921 if (ana_list & AN_RES_STORE_RULES) {
1922 if (!process_store_rules(s, s->rep, AN_RES_STORE_RULES))
1923 break;
1924 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_STORE_RULES);
1925 }
1926
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001927 if (ana_list & AN_RES_HTTP_PROCESS_BE) {
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001928 if (!http_process_res_common(s, s->rep, AN_RES_HTTP_PROCESS_BE, s->be))
1929 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001930 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_HTTP_PROCESS_BE);
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001931 }
Willy Tarreaud98cf932009-12-27 22:54:55 +01001932
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001933 if (ana_list & AN_RES_HTTP_XFER_BODY) {
Willy Tarreaud98cf932009-12-27 22:54:55 +01001934 if (!http_response_forward_body(s, s->rep, AN_RES_HTTP_XFER_BODY))
1935 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001936 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_HTTP_XFER_BODY);
Willy Tarreaud98cf932009-12-27 22:54:55 +01001937 }
Willy Tarreaue34070e2010-01-08 00:32:27 +01001938 break;
1939 }
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001940 }
1941
Willy Tarreau815a9b22010-07-27 17:15:12 +02001942 rp_cons_last = s->si[0].state;
1943 rp_prod_last = s->si[1].state;
1944 rpf_last = s->rep->flags;
1945
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001946 if ((s->rep->flags ^ flags) & CF_MASK_STATIC)
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001947 goto resync_response;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001948 }
1949
Willy Tarreau576507f2010-01-07 00:09:04 +01001950 /* maybe someone has added some request analysers, so we must check and loop */
1951 if (s->req->analysers & ~req_ana_back)
1952 goto resync_request;
1953
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001954 if ((s->req->flags & ~rqf_last) & CF_MASK_ANALYSER)
Willy Tarreau0499e352010-12-17 07:13:42 +01001955 goto resync_request;
1956
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001957 /* FIXME: here we should call protocol handlers which rely on
1958 * both buffers.
1959 */
1960
1961
1962 /*
Willy Tarreauae526782010-03-04 20:34:23 +01001963 * Now we propagate unhandled errors to the session. Normally
1964 * we're just in a data phase here since it means we have not
1965 * seen any analyser who could set an error status.
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001966 */
Willy Tarreau827aee92011-03-10 16:55:02 +01001967 srv = target_srv(&s->target);
Willy Tarreau2f976e12010-11-11 14:28:47 +01001968 if (unlikely(!(s->flags & SN_ERR_MASK))) {
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001969 if (s->req->flags & (CF_READ_ERROR|CF_READ_TIMEOUT|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001970 /* Report it if the client got an error or a read timeout expired */
Willy Tarreau84455332009-03-15 22:34:05 +01001971 s->req->analysers = 0;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001972 if (s->req->flags & CF_READ_ERROR) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001973 s->be->be_counters.cli_aborts++;
1974 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001975 if (srv)
1976 srv->counters.cli_aborts++;
Willy Tarreau84455332009-03-15 22:34:05 +01001977 s->flags |= SN_ERR_CLICL;
Willy Tarreauae526782010-03-04 20:34:23 +01001978 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001979 else if (s->req->flags & CF_READ_TIMEOUT) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001980 s->be->be_counters.cli_aborts++;
1981 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001982 if (srv)
1983 srv->counters.cli_aborts++;
Willy Tarreau84455332009-03-15 22:34:05 +01001984 s->flags |= SN_ERR_CLITO;
Willy Tarreauae526782010-03-04 20:34:23 +01001985 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001986 else if (s->req->flags & CF_WRITE_ERROR) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001987 s->be->be_counters.srv_aborts++;
1988 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001989 if (srv)
1990 srv->counters.srv_aborts++;
Willy Tarreau84455332009-03-15 22:34:05 +01001991 s->flags |= SN_ERR_SRVCL;
Willy Tarreauae526782010-03-04 20:34:23 +01001992 }
1993 else {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001994 s->be->be_counters.srv_aborts++;
1995 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001996 if (srv)
1997 srv->counters.srv_aborts++;
Willy Tarreau84455332009-03-15 22:34:05 +01001998 s->flags |= SN_ERR_SRVTO;
Willy Tarreauae526782010-03-04 20:34:23 +01001999 }
Willy Tarreau84455332009-03-15 22:34:05 +01002000 sess_set_term_flags(s);
2001 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002002 else if (s->rep->flags & (CF_READ_ERROR|CF_READ_TIMEOUT|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02002003 /* Report it if the server got an error or a read timeout expired */
2004 s->rep->analysers = 0;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002005 if (s->rep->flags & CF_READ_ERROR) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01002006 s->be->be_counters.srv_aborts++;
2007 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01002008 if (srv)
2009 srv->counters.srv_aborts++;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02002010 s->flags |= SN_ERR_SRVCL;
Willy Tarreauae526782010-03-04 20:34:23 +01002011 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002012 else if (s->rep->flags & CF_READ_TIMEOUT) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01002013 s->be->be_counters.srv_aborts++;
2014 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01002015 if (srv)
2016 srv->counters.srv_aborts++;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02002017 s->flags |= SN_ERR_SRVTO;
Willy Tarreauae526782010-03-04 20:34:23 +01002018 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002019 else if (s->rep->flags & CF_WRITE_ERROR) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01002020 s->be->be_counters.cli_aborts++;
2021 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01002022 if (srv)
2023 srv->counters.cli_aborts++;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02002024 s->flags |= SN_ERR_CLICL;
Willy Tarreauae526782010-03-04 20:34:23 +01002025 }
2026 else {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01002027 s->be->be_counters.cli_aborts++;
2028 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01002029 if (srv)
2030 srv->counters.cli_aborts++;
Willy Tarreauae526782010-03-04 20:34:23 +01002031 s->flags |= SN_ERR_CLITO;
2032 }
Willy Tarreau3deb3d02009-06-21 22:43:05 +02002033 sess_set_term_flags(s);
2034 }
Willy Tarreau84455332009-03-15 22:34:05 +01002035 }
2036
Willy Tarreau3deb3d02009-06-21 22:43:05 +02002037 /*
2038 * Here we take care of forwarding unhandled data. This also includes
2039 * connection establishments and shutdown requests.
2040 */
2041
2042
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002043 /* If noone is interested in analysing data, it's time to forward
Willy Tarreau31971e52009-09-20 12:07:52 +02002044 * everything. We configure the buffer to forward indefinitely.
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002045 * Note that we're checking CF_SHUTR_NOW as an indication of a possible
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002046 * recent call to channel_abort().
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01002047 */
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002048 if (!s->req->analysers &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002049 !(s->req->flags & (CF_HIJACK|CF_SHUTW|CF_SHUTR_NOW)) &&
Willy Tarreau31971e52009-09-20 12:07:52 +02002050 (s->req->prod->state >= SI_ST_EST) &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002051 (s->req->to_forward != CHN_INFINITE_FORWARD)) {
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002052 /* This buffer is freewheeling, there's no analyser nor hijacker
2053 * attached to it. If any data are left in, we'll permit them to
2054 * move.
2055 */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002056 channel_auto_read(s->req);
2057 channel_auto_connect(s->req);
2058 channel_auto_close(s->req);
Willy Tarreau9b28e032012-10-12 23:49:43 +02002059 buffer_flush(s->req->buf);
Willy Tarreau5bd8c372009-01-19 00:32:22 +01002060
Willy Tarreauda4d9fe2010-11-07 20:26:56 +01002061 /* We'll let data flow between the producer (if still connected)
2062 * to the consumer (which might possibly not be connected yet).
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002063 */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002064 if (!(s->req->flags & (CF_SHUTR|CF_SHUTW_NOW)))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002065 channel_forward(s->req, CHN_INFINITE_FORWARD);
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01002066 }
Willy Tarreauf890dc92008-12-13 21:12:26 +01002067
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002068 /* check if it is wise to enable kernel splicing to forward request data */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002069 if (!(s->req->flags & (CF_KERN_SPLICING|CF_SHUTR)) &&
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002070 s->req->to_forward &&
2071 (global.tune.options & GTUNE_USE_SPLICE) &&
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002072 (s->si[0].conn.xprt && s->si[0].conn.xprt->rcv_pipe && s->si[0].conn.xprt->snd_pipe) &&
2073 (s->si[1].conn.xprt && s->si[1].conn.xprt->rcv_pipe && s->si[1].conn.xprt->snd_pipe) &&
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002074 (pipes_used < global.maxpipes) &&
2075 (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_REQ) ||
2076 (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_AUT) &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002077 (s->req->flags & CF_STREAMER_FAST)))) {
2078 s->req->flags |= CF_KERN_SPLICING;
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002079 }
2080
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002081 /* reflect what the L7 analysers have seen last */
2082 rqf_last = s->req->flags;
2083
2084 /*
2085 * Now forward all shutdown requests between both sides of the buffer
2086 */
2087
Willy Tarreau520d95e2009-09-19 21:04:57 +02002088 /* first, let's check if the request buffer needs to shutdown(write), which may
2089 * happen either because the input is closed or because we want to force a close
Willy Tarreaue4599762010-03-21 23:25:09 +01002090 * once the server has begun to respond.
Willy Tarreau520d95e2009-09-19 21:04:57 +02002091 */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002092 if (unlikely((s->req->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_HIJACK|CF_AUTO_CLOSE|CF_SHUTR)) ==
2093 (CF_AUTO_CLOSE|CF_SHUTR)))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002094 channel_shutw_now(s->req);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002095
2096 /* shutdown(write) pending */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002097 if (unlikely((s->req->flags & (CF_SHUTW|CF_SHUTW_NOW)) == CF_SHUTW_NOW &&
Willy Tarreau8e21bb92012-08-24 22:40:29 +02002098 channel_is_empty(s->req)))
Willy Tarreau73b013b2012-05-21 16:31:45 +02002099 si_shutw(s->req->cons);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002100
2101 /* shutdown(write) done on server side, we must stop the client too */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002102 if (unlikely((s->req->flags & (CF_SHUTW|CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTW &&
Willy Tarreau3dbc6942008-12-07 13:05:04 +01002103 !s->req->analysers))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002104 channel_shutr_now(s->req);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002105
2106 /* shutdown(read) pending */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002107 if (unlikely((s->req->flags & (CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTR_NOW)) {
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02002108 if (s->req->prod->flags & SI_FL_NOHALF)
2109 s->req->prod->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02002110 si_shutr(s->req->prod);
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02002111 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002112
Willy Tarreau520d95e2009-09-19 21:04:57 +02002113 /* it's possible that an upper layer has requested a connection setup or abort.
2114 * There are 2 situations where we decide to establish a new connection :
2115 * - there are data scheduled for emission in the buffer
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002116 * - the CF_AUTO_CONNECT flag is set (active connection)
Willy Tarreau520d95e2009-09-19 21:04:57 +02002117 */
2118 if (s->req->cons->state == SI_ST_INI) {
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002119 if (!(s->req->flags & CF_SHUTW)) {
2120 if ((s->req->flags & CF_AUTO_CONNECT) || !channel_is_empty(s->req)) {
Willy Tarreaub24281b2011-02-13 13:16:36 +01002121 /* If we have an applet without a connect method, we immediately
Willy Tarreau85e7d002010-05-31 11:57:51 +02002122 * switch to the connected state, otherwise we perform a connection
2123 * request.
Willy Tarreau520d95e2009-09-19 21:04:57 +02002124 */
Willy Tarreau85e7d002010-05-31 11:57:51 +02002125 s->req->cons->state = SI_ST_REQ; /* new connection requested */
Willy Tarreau070ceb62010-06-01 10:36:43 +02002126 s->req->cons->conn_retries = s->be->conn_retries;
Willy Tarreau3cefd522012-08-30 15:49:18 +02002127 if (unlikely(s->req->cons->conn.target.type == TARG_TYPE_APPLET &&
Willy Tarreau73b013b2012-05-21 16:31:45 +02002128 !(si_ctrl(s->req->cons) && si_ctrl(s->req->cons)->connect))) {
Willy Tarreau520d95e2009-09-19 21:04:57 +02002129 s->req->cons->state = SI_ST_EST; /* connection established */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002130 s->rep->flags |= CF_READ_ATTACHED; /* producer is now attached */
Willy Tarreau85e7d002010-05-31 11:57:51 +02002131 s->req->wex = TICK_ETERNITY;
2132 }
Willy Tarreau520d95e2009-09-19 21:04:57 +02002133 }
Willy Tarreau73201222009-08-16 18:27:24 +02002134 }
Willy Tarreauf41ffdc2009-09-20 08:19:25 +02002135 else {
Willy Tarreau92795622009-03-06 12:51:23 +01002136 s->req->cons->state = SI_ST_CLO; /* shutw+ini = abort */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002137 channel_shutw_now(s->req); /* fix buffer flags upon abort */
2138 channel_shutr_now(s->rep);
Willy Tarreauf41ffdc2009-09-20 08:19:25 +02002139 }
Willy Tarreau92795622009-03-06 12:51:23 +01002140 }
2141
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002142
2143 /* we may have a pending connection request, or a connection waiting
2144 * for completion.
2145 */
2146 if (s->si[1].state >= SI_ST_REQ && s->si[1].state < SI_ST_CON) {
2147 do {
2148 /* nb: step 1 might switch from QUE to ASS, but we first want
2149 * to give a chance to step 2 to perform a redirect if needed.
2150 */
2151 if (s->si[1].state != SI_ST_REQ)
2152 sess_update_stream_int(s, &s->si[1]);
2153 if (s->si[1].state == SI_ST_REQ)
2154 sess_prepare_conn_req(s, &s->si[1]);
2155
Willy Tarreau827aee92011-03-10 16:55:02 +01002156 srv = target_srv(&s->target);
2157 if (s->si[1].state == SI_ST_ASS && srv && srv->rdr_len && (s->flags & SN_REDIRECTABLE))
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002158 perform_http_redirect(s, &s->si[1]);
2159 } while (s->si[1].state == SI_ST_ASS);
Mark Lamourinec2247f02012-01-04 13:02:01 -05002160
2161 /* Now we can add the server name to a header (if requested) */
2162 /* check for HTTP mode and proxy server_name_hdr_name != NULL */
Stathis Voukelatos09a030a2012-01-09 14:27:13 +01002163 if ((s->flags & SN_BE_ASSIGNED) &&
Willy Tarreau45c0d982012-03-09 12:11:57 +01002164 (s->be->mode == PR_MODE_HTTP) &&
2165 (s->be->server_id_hdr_name != NULL)) {
2166 http_send_name_header(&s->txn, s->be, target_srv(&s->target)->id);
Mark Lamourinec2247f02012-01-04 13:02:01 -05002167 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002168 }
2169
Willy Tarreau3deb3d02009-06-21 22:43:05 +02002170 /* Benchmarks have shown that it's optimal to do a full resync now */
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002171 if (s->req->prod->state == SI_ST_DIS || s->req->cons->state == SI_ST_DIS)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002172 goto resync_stream_interface;
2173
Willy Tarreau815a9b22010-07-27 17:15:12 +02002174 /* otherwise we want to check if we need to resync the req buffer or not */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002175 if ((s->req->flags ^ rqf_last) & CF_MASK_STATIC)
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002176 goto resync_request;
2177
Willy Tarreau3deb3d02009-06-21 22:43:05 +02002178 /* perform output updates to the response buffer */
Willy Tarreau84455332009-03-15 22:34:05 +01002179
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002180 /* If noone is interested in analysing data, it's time to forward
Willy Tarreau31971e52009-09-20 12:07:52 +02002181 * everything. We configure the buffer to forward indefinitely.
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002182 * Note that we're checking CF_SHUTR_NOW as an indication of a possible
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002183 * recent call to channel_abort().
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01002184 */
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002185 if (!s->rep->analysers &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002186 !(s->rep->flags & (CF_HIJACK|CF_SHUTW|CF_SHUTR_NOW)) &&
Willy Tarreau31971e52009-09-20 12:07:52 +02002187 (s->rep->prod->state >= SI_ST_EST) &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002188 (s->rep->to_forward != CHN_INFINITE_FORWARD)) {
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002189 /* This buffer is freewheeling, there's no analyser nor hijacker
2190 * attached to it. If any data are left in, we'll permit them to
2191 * move.
2192 */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002193 channel_auto_read(s->rep);
2194 channel_auto_close(s->rep);
Willy Tarreau9b28e032012-10-12 23:49:43 +02002195 buffer_flush(s->rep->buf);
Willy Tarreauda4d9fe2010-11-07 20:26:56 +01002196
2197 /* We'll let data flow between the producer (if still connected)
2198 * to the consumer.
2199 */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002200 if (!(s->rep->flags & (CF_SHUTR|CF_SHUTW_NOW)))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002201 channel_forward(s->rep, CHN_INFINITE_FORWARD);
Willy Tarreauce887fd2012-05-12 12:50:00 +02002202
2203 /* if we have no analyser anymore in any direction and have a
2204 * tunnel timeout set, use it now.
2205 */
2206 if (!s->req->analysers && s->be->timeout.tunnel) {
2207 s->req->rto = s->req->wto = s->rep->rto = s->rep->wto =
2208 s->be->timeout.tunnel;
2209 s->req->rex = s->req->wex = s->rep->rex = s->rep->wex =
2210 tick_add(now_ms, s->be->timeout.tunnel);
2211 }
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01002212 }
Willy Tarreauf890dc92008-12-13 21:12:26 +01002213
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002214 /* check if it is wise to enable kernel splicing to forward response data */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002215 if (!(s->rep->flags & (CF_KERN_SPLICING|CF_SHUTR)) &&
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002216 s->rep->to_forward &&
2217 (global.tune.options & GTUNE_USE_SPLICE) &&
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002218 (s->si[0].conn.xprt && s->si[0].conn.xprt->rcv_pipe && s->si[0].conn.xprt->snd_pipe) &&
2219 (s->si[1].conn.xprt && s->si[1].conn.xprt->rcv_pipe && s->si[1].conn.xprt->snd_pipe) &&
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002220 (pipes_used < global.maxpipes) &&
2221 (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_RTR) ||
2222 (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_AUT) &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002223 (s->rep->flags & CF_STREAMER_FAST)))) {
2224 s->rep->flags |= CF_KERN_SPLICING;
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002225 }
2226
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002227 /* reflect what the L7 analysers have seen last */
2228 rpf_last = s->rep->flags;
2229
2230 /*
2231 * Now forward all shutdown requests between both sides of the buffer
2232 */
2233
2234 /*
2235 * FIXME: this is probably where we should produce error responses.
2236 */
2237
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01002238 /* first, let's check if the response buffer needs to shutdown(write) */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002239 if (unlikely((s->rep->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_HIJACK|CF_AUTO_CLOSE|CF_SHUTR)) ==
2240 (CF_AUTO_CLOSE|CF_SHUTR)))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002241 channel_shutw_now(s->rep);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002242
2243 /* shutdown(write) pending */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002244 if (unlikely((s->rep->flags & (CF_SHUTW|CF_SHUTW_NOW)) == CF_SHUTW_NOW &&
Willy Tarreau8e21bb92012-08-24 22:40:29 +02002245 channel_is_empty(s->rep)))
Willy Tarreau73b013b2012-05-21 16:31:45 +02002246 si_shutw(s->rep->cons);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002247
2248 /* shutdown(write) done on the client side, we must stop the server too */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002249 if (unlikely((s->rep->flags & (CF_SHUTW|CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTW) &&
Willy Tarreau3dbc6942008-12-07 13:05:04 +01002250 !s->rep->analysers)
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002251 channel_shutr_now(s->rep);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002252
2253 /* shutdown(read) pending */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002254 if (unlikely((s->rep->flags & (CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTR_NOW)) {
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02002255 if (s->rep->prod->flags & SI_FL_NOHALF)
2256 s->rep->prod->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02002257 si_shutr(s->rep->prod);
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02002258 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002259
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002260 if (s->req->prod->state == SI_ST_DIS || s->req->cons->state == SI_ST_DIS)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002261 goto resync_stream_interface;
2262
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002263 if (s->req->flags != rqf_last)
2264 goto resync_request;
2265
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002266 if ((s->rep->flags ^ rpf_last) & CF_MASK_STATIC)
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002267 goto resync_response;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002268
Willy Tarreau89f7ef22009-09-05 20:57:35 +02002269 /* we're interested in getting wakeups again */
2270 s->req->prod->flags &= ~SI_FL_DONT_WAKE;
2271 s->req->cons->flags &= ~SI_FL_DONT_WAKE;
2272
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002273 /* This is needed only when debugging is enabled, to indicate
2274 * client-side or server-side close. Please note that in the unlikely
2275 * event where both sides would close at once, the sequence is reported
2276 * on the server side first.
2277 */
2278 if (unlikely((global.mode & MODE_DEBUG) &&
2279 (!(global.mode & MODE_QUIET) ||
2280 (global.mode & MODE_VERBOSE)))) {
2281 int len;
2282
2283 if (s->si[1].state == SI_ST_CLO &&
2284 s->si[1].prev_state == SI_ST_EST) {
2285 len = sprintf(trash, "%08x:%s.srvcls[%04x:%04x]\n",
2286 s->uniq_id, s->be->id,
Willy Tarreaufb7508a2012-05-21 16:47:54 +02002287 (unsigned short)si_fd(&s->si[0]),
2288 (unsigned short)si_fd(&s->si[1]));
Willy Tarreau21337822012-04-29 14:11:38 +02002289 if (write(1, trash, len) < 0) /* shut gcc warning */;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002290 }
2291
2292 if (s->si[0].state == SI_ST_CLO &&
2293 s->si[0].prev_state == SI_ST_EST) {
2294 len = sprintf(trash, "%08x:%s.clicls[%04x:%04x]\n",
2295 s->uniq_id, s->be->id,
Willy Tarreaufb7508a2012-05-21 16:47:54 +02002296 (unsigned short)si_fd(&s->si[0]),
2297 (unsigned short)si_fd(&s->si[1]));
Willy Tarreau21337822012-04-29 14:11:38 +02002298 if (write(1, trash, len) < 0) /* shut gcc warning */;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002299 }
2300 }
2301
2302 if (likely((s->rep->cons->state != SI_ST_CLO) ||
2303 (s->req->cons->state > SI_ST_INI && s->req->cons->state < SI_ST_CLO))) {
2304
2305 if ((s->fe->options & PR_O_CONTSTATS) && (s->flags & SN_BE_ASSIGNED))
2306 session_process_counters(s);
2307
Willy Tarreau3cefd522012-08-30 15:49:18 +02002308 if (s->rep->cons->state == SI_ST_EST && s->rep->cons->conn.target.type != TARG_TYPE_APPLET)
Willy Tarreau73b013b2012-05-21 16:31:45 +02002309 si_update(s->rep->cons);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002310
Willy Tarreau3cefd522012-08-30 15:49:18 +02002311 if (s->req->cons->state == SI_ST_EST && s->req->cons->conn.target.type != TARG_TYPE_APPLET)
Willy Tarreau73b013b2012-05-21 16:31:45 +02002312 si_update(s->req->cons);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002313
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002314 s->req->flags &= ~(CF_READ_NULL|CF_READ_PARTIAL|CF_WRITE_NULL|CF_WRITE_PARTIAL|CF_READ_ATTACHED);
2315 s->rep->flags &= ~(CF_READ_NULL|CF_READ_PARTIAL|CF_WRITE_NULL|CF_WRITE_PARTIAL|CF_READ_ATTACHED);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002316 s->si[0].prev_state = s->si[0].state;
2317 s->si[1].prev_state = s->si[1].state;
Willy Tarreaub0ef7352008-12-14 13:26:20 +01002318 s->si[0].flags &= ~(SI_FL_ERR|SI_FL_EXP);
2319 s->si[1].flags &= ~(SI_FL_ERR|SI_FL_EXP);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002320
2321 /* Trick: if a request is being waiting for the server to respond,
2322 * and if we know the server can timeout, we don't want the timeout
2323 * to expire on the client side first, but we're still interested
2324 * in passing data from the client to the server (eg: POST). Thus,
2325 * we can cancel the client's request timeout if the server's
2326 * request timeout is set and the server has not yet sent a response.
2327 */
2328
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002329 if ((s->rep->flags & (CF_AUTO_CLOSE|CF_SHUTR)) == 0 &&
Willy Tarreau86491c32008-12-14 09:04:47 +01002330 (tick_isset(s->req->wex) || tick_isset(s->rep->rex))) {
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002331 s->req->flags |= CF_READ_NOEXP;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002332 s->req->rex = TICK_ETERNITY;
Willy Tarreau86491c32008-12-14 09:04:47 +01002333 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002334
Willy Tarreau7a20aa62010-07-13 16:30:45 +02002335 /* Call the stream interfaces' I/O handlers when embedded.
Willy Tarreau1accfc02009-09-05 20:57:35 +02002336 * Note that this one may wake the task up again.
2337 */
Willy Tarreau3cefd522012-08-30 15:49:18 +02002338 if (s->req->cons->conn.target.type == TARG_TYPE_APPLET ||
2339 s->rep->cons->conn.target.type == TARG_TYPE_APPLET) {
2340 if (s->req->cons->conn.target.type == TARG_TYPE_APPLET)
2341 s->req->cons->conn.target.ptr.a->fct(s->req->cons);
2342 if (s->rep->cons->conn.target.type == TARG_TYPE_APPLET)
2343 s->rep->cons->conn.target.ptr.a->fct(s->rep->cons);
Willy Tarreau1accfc02009-09-05 20:57:35 +02002344 if (task_in_rq(t)) {
2345 /* If we woke up, we don't want to requeue the
2346 * task to the wait queue, but rather requeue
2347 * it into the runqueue ASAP.
2348 */
2349 t->expire = TICK_ETERNITY;
2350 return t;
2351 }
2352 }
2353
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002354 t->expire = tick_first(tick_first(s->req->rex, s->req->wex),
2355 tick_first(s->rep->rex, s->rep->wex));
2356 if (s->req->analysers)
2357 t->expire = tick_first(t->expire, s->req->analyse_exp);
2358
2359 if (s->si[0].exp)
2360 t->expire = tick_first(t->expire, s->si[0].exp);
2361
2362 if (s->si[1].exp)
2363 t->expire = tick_first(t->expire, s->si[1].exp);
2364
2365#ifdef DEBUG_FULL
Willy Tarreau127334e2009-03-28 10:47:26 +01002366 fprintf(stderr,
2367 "[%u] queuing with exp=%u req->rex=%u req->wex=%u req->ana_exp=%u"
2368 " rep->rex=%u rep->wex=%u, si[0].exp=%u, si[1].exp=%u, cs=%d, ss=%d\n",
2369 now_ms, t->expire, s->req->rex, s->req->wex, s->req->analyse_exp,
2370 s->rep->rex, s->rep->wex, s->si[0].exp, s->si[1].exp, s->si[0].state, s->si[1].state);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002371#endif
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002372
2373#ifdef DEBUG_DEV
2374 /* this may only happen when no timeout is set or in case of an FSM bug */
Willy Tarreaud0a201b2009-03-08 15:53:06 +01002375 if (!tick_isset(t->expire))
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002376 ABORT_NOW();
2377#endif
Willy Tarreau26c25062009-03-08 09:38:41 +01002378 return t; /* nothing more to do */
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002379 }
2380
2381 s->fe->feconn--;
2382 if (s->flags & SN_BE_ASSIGNED)
2383 s->be->beconn--;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02002384 if (!(s->listener->options & LI_O_UNLIMITED))
2385 actconn--;
Willy Tarreauaf7ad002010-08-31 15:39:26 +02002386 jobs--;
Willy Tarreau6e6fb2b2009-08-16 18:20:44 +02002387 s->listener->nbconn--;
Willy Tarreau62793712011-07-24 19:23:38 +02002388 if (s->listener->state == LI_FULL)
2389 resume_listener(s->listener);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002390
Willy Tarreau08ceb102011-07-24 22:58:00 +02002391 /* Dequeues all of the listeners waiting for a resource */
2392 if (!LIST_ISEMPTY(&global_listener_queue))
2393 dequeue_all_listeners(&global_listener_queue);
2394
Willy Tarreaub32907b2011-07-25 08:37:44 +02002395 if (!LIST_ISEMPTY(&s->fe->listener_queue) &&
2396 (!s->fe->fe_sps_lim || freq_ctr_remain(&s->fe->fe_sess_per_sec, s->fe->fe_sps_lim, 0) > 0))
Willy Tarreau07687c12011-07-24 23:55:06 +02002397 dequeue_all_listeners(&s->fe->listener_queue);
2398
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002399 if (unlikely((global.mode & MODE_DEBUG) &&
2400 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)))) {
2401 int len;
Willy Tarreauec22b2c2009-03-06 13:07:40 +01002402 len = sprintf(trash, "%08x:%s.closed[%04x:%04x]\n",
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002403 s->uniq_id, s->be->id,
Willy Tarreaufb7508a2012-05-21 16:47:54 +02002404 (unsigned short)si_fd(s->req->prod), (unsigned short)si_fd(s->req->cons));
Willy Tarreau21337822012-04-29 14:11:38 +02002405 if (write(1, trash, len) < 0) /* shut gcc warning */;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002406 }
2407
2408 s->logs.t_close = tv_ms_elapsed(&s->logs.tv_accept, &now);
2409 session_process_counters(s);
2410
Krzysztof Piotr Oledzkide71d162009-10-24 15:36:15 +02002411 if (s->txn.status) {
2412 int n;
2413
2414 n = s->txn.status / 100;
2415 if (n < 1 || n > 5)
2416 n = 0;
2417
2418 if (s->fe->mode == PR_MODE_HTTP)
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01002419 s->fe->fe_counters.p.http.rsp[n]++;
Krzysztof Piotr Oledzkide71d162009-10-24 15:36:15 +02002420
Willy Tarreau24657792010-02-26 10:30:28 +01002421 if ((s->flags & SN_BE_ASSIGNED) &&
Krzysztof Piotr Oledzkide71d162009-10-24 15:36:15 +02002422 (s->be->mode == PR_MODE_HTTP))
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01002423 s->be->be_counters.p.http.rsp[n]++;
Krzysztof Piotr Oledzkide71d162009-10-24 15:36:15 +02002424 }
2425
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002426 /* let's do a final log if we need it */
2427 if (s->logs.logwait &&
2428 !(s->flags & SN_MONITOR) &&
2429 (!(s->fe->options & PR_O_NULLNOLOG) || s->req->total)) {
Willy Tarreaua5555ec2008-11-30 19:02:32 +01002430 s->do_log(s);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002431 }
2432
2433 /* the task MUST not be in the run queue anymore */
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002434 session_free(s);
Willy Tarreau26c25062009-03-08 09:38:41 +01002435 task_delete(t);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002436 task_free(t);
Willy Tarreau26c25062009-03-08 09:38:41 +01002437 return NULL;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002438}
2439
Willy Tarreau7c669d72008-06-20 15:04:11 +02002440/*
2441 * This function adjusts sess->srv_conn and maintains the previous and new
2442 * server's served session counts. Setting newsrv to NULL is enough to release
2443 * current connection slot. This function also notifies any LB algo which might
2444 * expect to be informed about any change in the number of active sessions on a
2445 * server.
2446 */
2447void sess_change_server(struct session *sess, struct server *newsrv)
2448{
2449 if (sess->srv_conn == newsrv)
2450 return;
2451
2452 if (sess->srv_conn) {
2453 sess->srv_conn->served--;
2454 if (sess->srv_conn->proxy->lbprm.server_drop_conn)
2455 sess->srv_conn->proxy->lbprm.server_drop_conn(sess->srv_conn);
Simon Hormanaf514952011-06-21 14:34:57 +09002456 session_del_srv_conn(sess);
Willy Tarreau7c669d72008-06-20 15:04:11 +02002457 }
2458
2459 if (newsrv) {
2460 newsrv->served++;
2461 if (newsrv->proxy->lbprm.server_take_conn)
2462 newsrv->proxy->lbprm.server_take_conn(newsrv);
Simon Hormanaf514952011-06-21 14:34:57 +09002463 session_add_srv_conn(sess, newsrv);
Willy Tarreau7c669d72008-06-20 15:04:11 +02002464 }
2465}
2466
Willy Tarreau84455332009-03-15 22:34:05 +01002467/* Handle server-side errors for default protocols. It is called whenever a a
2468 * connection setup is aborted or a request is aborted in queue. It sets the
2469 * session termination flags so that the caller does not have to worry about
2470 * them. It's installed as ->srv_error for the server-side stream_interface.
2471 */
2472void default_srv_error(struct session *s, struct stream_interface *si)
2473{
2474 int err_type = si->err_type;
2475 int err = 0, fin = 0;
2476
2477 if (err_type & SI_ET_QUEUE_ABRT) {
2478 err = SN_ERR_CLICL;
2479 fin = SN_FINST_Q;
2480 }
2481 else if (err_type & SI_ET_CONN_ABRT) {
2482 err = SN_ERR_CLICL;
2483 fin = SN_FINST_C;
2484 }
2485 else if (err_type & SI_ET_QUEUE_TO) {
2486 err = SN_ERR_SRVTO;
2487 fin = SN_FINST_Q;
2488 }
2489 else if (err_type & SI_ET_QUEUE_ERR) {
2490 err = SN_ERR_SRVCL;
2491 fin = SN_FINST_Q;
2492 }
2493 else if (err_type & SI_ET_CONN_TO) {
2494 err = SN_ERR_SRVTO;
2495 fin = SN_FINST_C;
2496 }
2497 else if (err_type & SI_ET_CONN_ERR) {
2498 err = SN_ERR_SRVCL;
2499 fin = SN_FINST_C;
2500 }
2501 else /* SI_ET_CONN_OTHER and others */ {
2502 err = SN_ERR_INTERNAL;
2503 fin = SN_FINST_C;
2504 }
2505
2506 if (!(s->flags & SN_ERR_MASK))
2507 s->flags |= err;
2508 if (!(s->flags & SN_FINST_MASK))
2509 s->flags |= fin;
2510}
Willy Tarreau7c669d72008-06-20 15:04:11 +02002511
Willy Tarreaua2a64e92011-09-07 23:01:56 +02002512/* kill a session and set the termination flags to <why> (one of SN_ERR_*) */
2513void session_shutdown(struct session *session, int why)
2514{
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002515 if (session->req->flags & (CF_SHUTW|CF_SHUTW_NOW))
Willy Tarreaua2a64e92011-09-07 23:01:56 +02002516 return;
2517
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002518 channel_shutw_now(session->req);
2519 channel_shutr_now(session->rep);
Willy Tarreaua2a64e92011-09-07 23:01:56 +02002520 session->task->nice = 1024;
2521 if (!(session->flags & SN_ERR_MASK))
2522 session->flags |= why;
2523 task_wakeup(session->task, TASK_WOKEN_OTHER);
2524}
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02002525
Willy Tarreau8b22a712010-06-18 17:46:06 +02002526/************************************************************************/
2527/* All supported ACL keywords must be declared here. */
2528/************************************************************************/
2529
Willy Tarreaua5e37562011-12-16 17:06:15 +01002530/* set temp integer to the General Purpose Counter 0 value in the stksess entry <ts> */
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002531static int
Willy Tarreau37406352012-04-23 16:16:37 +02002532acl_fetch_get_gpc0(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002533{
Willy Tarreau37406352012-04-23 16:16:37 +02002534 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002535 smp->type = SMP_T_UINT;
2536 smp->data.uint = 0;
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002537 if (ts != NULL) {
2538 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_GPC0);
2539 if (!ptr)
2540 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002541 smp->data.uint = stktable_data_cast(ptr, gpc0);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002542 }
2543 return 1;
2544}
2545
Willy Tarreaua5e37562011-12-16 17:06:15 +01002546/* set temp integer to the General Purpose Counter 0 value from the session's tracked
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002547 * frontend counters.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002548 */
2549static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002550acl_fetch_sc1_get_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002551 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002552{
Willy Tarreau56123282010-08-06 19:06:56 +02002553 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002554 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002555 return acl_fetch_get_gpc0(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002556}
2557
Willy Tarreaua5e37562011-12-16 17:06:15 +01002558/* set temp integer to the General Purpose Counter 0 value from the session's tracked
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002559 * backend counters.
2560 */
2561static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002562acl_fetch_sc2_get_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002563 const struct arg *args, struct sample *smp)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002564{
Willy Tarreau56123282010-08-06 19:06:56 +02002565 if (!l4->stkctr2_entry)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002566 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002567 return acl_fetch_get_gpc0(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002568}
2569
Willy Tarreaua5e37562011-12-16 17:06:15 +01002570/* set temp integer to the General Purpose Counter 0 value from the session's source
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002571 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002572 * Accepts exactly 1 argument of type table.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002573 */
2574static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002575acl_fetch_src_get_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002576 const struct arg *args, struct sample *smp)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002577{
2578 struct stktable_key *key;
2579
Willy Tarreau64ee4912012-08-30 22:59:48 +02002580 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002581 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002582 return 0;
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002583
Willy Tarreau24e32d82012-04-23 23:55:44 +02002584 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002585 return acl_fetch_get_gpc0(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002586}
2587
2588/* Increment the General Purpose Counter 0 value in the stksess entry <ts> and
Willy Tarreaua5e37562011-12-16 17:06:15 +01002589 * return it into temp integer.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002590 */
2591static int
Willy Tarreau37406352012-04-23 16:16:37 +02002592acl_fetch_inc_gpc0(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002593{
Willy Tarreau37406352012-04-23 16:16:37 +02002594 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002595 smp->type = SMP_T_UINT;
2596 smp->data.uint = 0;
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002597 if (ts != NULL) {
2598 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_GPC0);
2599 if (!ptr)
2600 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002601 smp->data.uint = ++stktable_data_cast(ptr, gpc0);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002602 }
2603 return 1;
2604}
2605
2606/* Increment the General Purpose Counter 0 value from the session's tracked
Willy Tarreaua5e37562011-12-16 17:06:15 +01002607 * frontend counters and return it into temp integer.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002608 */
2609static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002610acl_fetch_sc1_inc_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002611 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002612{
Willy Tarreau56123282010-08-06 19:06:56 +02002613 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002614 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002615 return acl_fetch_inc_gpc0(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002616}
2617
2618/* Increment the General Purpose Counter 0 value from the session's tracked
Willy Tarreaua5e37562011-12-16 17:06:15 +01002619 * backend counters and return it into temp integer.
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002620 */
2621static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002622acl_fetch_sc2_inc_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002623 const struct arg *args, struct sample *smp)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002624{
Willy Tarreau56123282010-08-06 19:06:56 +02002625 if (!l4->stkctr2_entry)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002626 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002627 return acl_fetch_inc_gpc0(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002628}
2629
2630/* Increment the General Purpose Counter 0 value from the session's source
Willy Tarreaua5e37562011-12-16 17:06:15 +01002631 * address in the table pointed to by expr, and return it into temp integer.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002632 * Accepts exactly 1 argument of type table.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002633 */
2634static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002635acl_fetch_src_inc_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002636 const struct arg *args, struct sample *smp)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002637{
2638 struct stktable_key *key;
2639
Willy Tarreau64ee4912012-08-30 22:59:48 +02002640 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002641 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002642 return 0;
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002643
Willy Tarreau24e32d82012-04-23 23:55:44 +02002644 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002645 return acl_fetch_inc_gpc0(&px->table, smp, stktable_update_key(&px->table, key));
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002646}
2647
Willy Tarreauf73cd112011-08-13 01:45:16 +02002648/* Clear the General Purpose Counter 0 value in the stksess entry <ts> and
Willy Tarreaua5e37562011-12-16 17:06:15 +01002649 * return its previous value into temp integer.
Willy Tarreauf73cd112011-08-13 01:45:16 +02002650 */
2651static int
Willy Tarreau37406352012-04-23 16:16:37 +02002652acl_fetch_clr_gpc0(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauf73cd112011-08-13 01:45:16 +02002653{
Willy Tarreau37406352012-04-23 16:16:37 +02002654 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002655 smp->type = SMP_T_UINT;
2656 smp->data.uint = 0;
Willy Tarreauf73cd112011-08-13 01:45:16 +02002657 if (ts != NULL) {
2658 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_GPC0);
2659 if (!ptr)
2660 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002661 smp->data.uint = stktable_data_cast(ptr, gpc0);
Willy Tarreauf73cd112011-08-13 01:45:16 +02002662 stktable_data_cast(ptr, gpc0) = 0;
2663 }
2664 return 1;
2665}
2666
2667/* Clear the General Purpose Counter 0 value from the session's tracked
Willy Tarreaua5e37562011-12-16 17:06:15 +01002668 * frontend counters and return its previous value into temp integer.
Willy Tarreauf73cd112011-08-13 01:45:16 +02002669 */
2670static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002671acl_fetch_sc1_clr_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002672 const struct arg *args, struct sample *smp)
Willy Tarreauf73cd112011-08-13 01:45:16 +02002673{
2674 if (!l4->stkctr1_entry)
2675 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002676 return acl_fetch_clr_gpc0(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf73cd112011-08-13 01:45:16 +02002677}
2678
2679/* Clear the General Purpose Counter 0 value from the session's tracked
Willy Tarreaua5e37562011-12-16 17:06:15 +01002680 * backend counters and return its previous value into temp integer.
Willy Tarreauf73cd112011-08-13 01:45:16 +02002681 */
2682static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002683acl_fetch_sc2_clr_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002684 const struct arg *args, struct sample *smp)
Willy Tarreauf73cd112011-08-13 01:45:16 +02002685{
2686 if (!l4->stkctr2_entry)
2687 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002688 return acl_fetch_clr_gpc0(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauf73cd112011-08-13 01:45:16 +02002689}
2690
2691/* Clear the General Purpose Counter 0 value from the session's source address
Willy Tarreaua5e37562011-12-16 17:06:15 +01002692 * in the table pointed to by expr, and return its previous value into temp integer.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002693 * Accepts exactly 1 argument of type table.
Willy Tarreauf73cd112011-08-13 01:45:16 +02002694 */
2695static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002696acl_fetch_src_clr_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002697 const struct arg *args, struct sample *smp)
Willy Tarreauf73cd112011-08-13 01:45:16 +02002698{
2699 struct stktable_key *key;
2700
Willy Tarreau64ee4912012-08-30 22:59:48 +02002701 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauf73cd112011-08-13 01:45:16 +02002702 if (!key)
2703 return 0;
2704
Willy Tarreau24e32d82012-04-23 23:55:44 +02002705 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002706 return acl_fetch_clr_gpc0(&px->table, smp, stktable_update_key(&px->table, key));
Willy Tarreauf73cd112011-08-13 01:45:16 +02002707}
2708
Willy Tarreaua5e37562011-12-16 17:06:15 +01002709/* set temp integer to the cumulated number of connections in the stksess entry <ts> */
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002710static int
Willy Tarreau37406352012-04-23 16:16:37 +02002711acl_fetch_conn_cnt(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002712{
Willy Tarreau37406352012-04-23 16:16:37 +02002713 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002714 smp->type = SMP_T_UINT;
2715 smp->data.uint = 0;
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002716 if (ts != NULL) {
2717 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_CONN_CNT);
2718 if (!ptr)
2719 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002720 smp->data.uint = stktable_data_cast(ptr, conn_cnt);
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002721 }
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002722 return 1;
2723}
2724
Willy Tarreaua5e37562011-12-16 17:06:15 +01002725/* set temp integer to the cumulated number of connections from the session's tracked FE counters */
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002726static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002727acl_fetch_sc1_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002728 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002729{
Willy Tarreau56123282010-08-06 19:06:56 +02002730 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002731 return 0;
2732
Willy Tarreau37406352012-04-23 16:16:37 +02002733 return acl_fetch_conn_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002734}
2735
Willy Tarreaua5e37562011-12-16 17:06:15 +01002736/* set temp integer to the cumulated number of connections from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002737static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002738acl_fetch_sc2_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002739 const struct arg *args, struct sample *smp)
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002740{
Willy Tarreau56123282010-08-06 19:06:56 +02002741 if (!l4->stkctr2_entry)
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002742 return 0;
2743
Willy Tarreau37406352012-04-23 16:16:37 +02002744 return acl_fetch_conn_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002745}
2746
Willy Tarreaua5e37562011-12-16 17:06:15 +01002747/* set temp integer to the cumulated number of connections from the session's source
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002748 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002749 * Accepts exactly 1 argument of type table.
Willy Tarreau8b22a712010-06-18 17:46:06 +02002750 */
2751static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002752acl_fetch_src_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002753 const struct arg *args, struct sample *smp)
Willy Tarreau8b22a712010-06-18 17:46:06 +02002754{
Willy Tarreau8b22a712010-06-18 17:46:06 +02002755 struct stktable_key *key;
2756
Willy Tarreau64ee4912012-08-30 22:59:48 +02002757 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau8b22a712010-06-18 17:46:06 +02002758 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002759 return 0;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002760
Willy Tarreau24e32d82012-04-23 23:55:44 +02002761 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002762 return acl_fetch_conn_cnt(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau8b22a712010-06-18 17:46:06 +02002763}
2764
Willy Tarreaua5e37562011-12-16 17:06:15 +01002765/* set temp integer to the connection rate in the stksess entry <ts> over the configured period */
Willy Tarreau91c43d72010-06-20 11:19:22 +02002766static int
Willy Tarreau37406352012-04-23 16:16:37 +02002767acl_fetch_conn_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002768{
Willy Tarreau37406352012-04-23 16:16:37 +02002769 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002770 smp->type = SMP_T_UINT;
2771 smp->data.uint = 0;
Willy Tarreau91c43d72010-06-20 11:19:22 +02002772 if (ts != NULL) {
2773 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_CONN_RATE);
2774 if (!ptr)
2775 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002776 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, conn_rate),
Willy Tarreau91c43d72010-06-20 11:19:22 +02002777 table->data_arg[STKTABLE_DT_CONN_RATE].u);
2778 }
2779 return 1;
2780}
2781
Willy Tarreaua5e37562011-12-16 17:06:15 +01002782/* set temp integer to the connection rate from the session's tracked FE counters over
Willy Tarreau91c43d72010-06-20 11:19:22 +02002783 * the configured period.
2784 */
2785static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002786acl_fetch_sc1_conn_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002787 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002788{
Willy Tarreau56123282010-08-06 19:06:56 +02002789 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002790 return 0;
2791
Willy Tarreau37406352012-04-23 16:16:37 +02002792 return acl_fetch_conn_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002793}
2794
Willy Tarreaua5e37562011-12-16 17:06:15 +01002795/* set temp integer to the connection rate from the session's tracked BE counters over
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002796 * the configured period.
2797 */
2798static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002799acl_fetch_sc2_conn_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002800 const struct arg *args, struct sample *smp)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002801{
Willy Tarreau56123282010-08-06 19:06:56 +02002802 if (!l4->stkctr2_entry)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002803 return 0;
2804
Willy Tarreau37406352012-04-23 16:16:37 +02002805 return acl_fetch_conn_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau91c43d72010-06-20 11:19:22 +02002806}
2807
Willy Tarreaua5e37562011-12-16 17:06:15 +01002808/* set temp integer to the connection rate from the session's source address in the
Willy Tarreau91c43d72010-06-20 11:19:22 +02002809 * table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002810 * Accepts exactly 1 argument of type table.
Willy Tarreau91c43d72010-06-20 11:19:22 +02002811 */
2812static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002813acl_fetch_src_conn_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002814 const struct arg *args, struct sample *smp)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002815{
2816 struct stktable_key *key;
2817
Willy Tarreau64ee4912012-08-30 22:59:48 +02002818 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau91c43d72010-06-20 11:19:22 +02002819 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002820 return 0;
Willy Tarreau91c43d72010-06-20 11:19:22 +02002821
Willy Tarreau24e32d82012-04-23 23:55:44 +02002822 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002823 return acl_fetch_conn_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau91c43d72010-06-20 11:19:22 +02002824}
2825
Willy Tarreaua5e37562011-12-16 17:06:15 +01002826/* set temp integer to the number of connections from the session's source address
Willy Tarreau8b22a712010-06-18 17:46:06 +02002827 * in the table pointed to by expr, after updating it.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002828 * Accepts exactly 1 argument of type table.
Willy Tarreau8b22a712010-06-18 17:46:06 +02002829 */
2830static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002831acl_fetch_src_updt_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002832 const struct arg *args, struct sample *smp)
Willy Tarreau8b22a712010-06-18 17:46:06 +02002833{
2834 struct stksess *ts;
2835 struct stktable_key *key;
2836 void *ptr;
2837
Willy Tarreau64ee4912012-08-30 22:59:48 +02002838 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau8b22a712010-06-18 17:46:06 +02002839 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002840 return 0;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002841
Willy Tarreau24e32d82012-04-23 23:55:44 +02002842 px = args->data.prx;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002843
Willy Tarreau1f7e9252010-06-20 12:27:21 +02002844 if ((ts = stktable_update_key(&px->table, key)) == NULL)
2845 /* entry does not exist and could not be created */
2846 return 0;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002847
2848 ptr = stktable_data_ptr(&px->table, ts, STKTABLE_DT_CONN_CNT);
2849 if (!ptr)
2850 return 0; /* parameter not stored in this table */
2851
Willy Tarreauf853c462012-04-23 18:53:56 +02002852 smp->type = SMP_T_UINT;
2853 smp->data.uint = ++stktable_data_cast(ptr, conn_cnt);
Willy Tarreau37406352012-04-23 16:16:37 +02002854 smp->flags = SMP_F_VOL_TEST;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002855 return 1;
2856}
2857
Willy Tarreaua5e37562011-12-16 17:06:15 +01002858/* set temp integer to the number of concurrent connections in the stksess entry <ts> */
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002859static int
Willy Tarreau37406352012-04-23 16:16:37 +02002860acl_fetch_conn_cur(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002861{
Willy Tarreau37406352012-04-23 16:16:37 +02002862 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002863 smp->type = SMP_T_UINT;
2864 smp->data.uint = 0;
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002865
2866 if (ts != NULL) {
2867 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_CONN_CUR);
2868 if (!ptr)
2869 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002870 smp->data.uint = stktable_data_cast(ptr, conn_cur);
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002871 }
2872 return 1;
2873}
2874
Willy Tarreaua5e37562011-12-16 17:06:15 +01002875/* set temp integer to the number of concurrent connections from the session's tracked FE counters */
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002876static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002877acl_fetch_sc1_conn_cur(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002878 const struct arg *args, struct sample *smp)
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002879{
Willy Tarreau56123282010-08-06 19:06:56 +02002880 if (!l4->stkctr1_entry)
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002881 return 0;
2882
Willy Tarreau37406352012-04-23 16:16:37 +02002883 return acl_fetch_conn_cur(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002884}
2885
Willy Tarreaua5e37562011-12-16 17:06:15 +01002886/* set temp integer to the number of concurrent connections from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002887static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002888acl_fetch_sc2_conn_cur(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002889 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002890{
Willy Tarreau56123282010-08-06 19:06:56 +02002891 if (!l4->stkctr2_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002892 return 0;
2893
Willy Tarreau37406352012-04-23 16:16:37 +02002894 return acl_fetch_conn_cur(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002895}
2896
Willy Tarreaua5e37562011-12-16 17:06:15 +01002897/* set temp integer to the number of concurrent connections from the session's source
Willy Tarreau38285c12010-06-18 16:35:43 +02002898 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002899 * Accepts exactly 1 argument of type table.
Willy Tarreau38285c12010-06-18 16:35:43 +02002900 */
2901static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002902acl_fetch_src_conn_cur(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002903 const struct arg *args, struct sample *smp)
Willy Tarreau38285c12010-06-18 16:35:43 +02002904{
Willy Tarreau38285c12010-06-18 16:35:43 +02002905 struct stktable_key *key;
2906
Willy Tarreau64ee4912012-08-30 22:59:48 +02002907 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau38285c12010-06-18 16:35:43 +02002908 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002909 return 0;
Willy Tarreau38285c12010-06-18 16:35:43 +02002910
Willy Tarreau24e32d82012-04-23 23:55:44 +02002911 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002912 return acl_fetch_conn_cur(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau38285c12010-06-18 16:35:43 +02002913}
2914
Willy Tarreaua5e37562011-12-16 17:06:15 +01002915/* set temp integer to the cumulated number of sessions in the stksess entry <ts> */
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002916static int
Willy Tarreau37406352012-04-23 16:16:37 +02002917acl_fetch_sess_cnt(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002918{
Willy Tarreau37406352012-04-23 16:16:37 +02002919 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002920 smp->type = SMP_T_UINT;
2921 smp->data.uint = 0;
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002922 if (ts != NULL) {
2923 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_SESS_CNT);
2924 if (!ptr)
2925 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002926 smp->data.uint = stktable_data_cast(ptr, sess_cnt);
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002927 }
2928 return 1;
2929}
2930
Willy Tarreaua5e37562011-12-16 17:06:15 +01002931/* set temp integer to the cumulated number of sessions from the session's tracked FE counters */
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002932static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002933acl_fetch_sc1_sess_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002934 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002935{
Willy Tarreau56123282010-08-06 19:06:56 +02002936 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002937 return 0;
2938
Willy Tarreau37406352012-04-23 16:16:37 +02002939 return acl_fetch_sess_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002940}
2941
Willy Tarreaua5e37562011-12-16 17:06:15 +01002942/* set temp integer to the cumulated number of sessions from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002943static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002944acl_fetch_sc2_sess_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002945 const struct arg *args, struct sample *smp)
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002946{
Willy Tarreau56123282010-08-06 19:06:56 +02002947 if (!l4->stkctr2_entry)
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002948 return 0;
2949
Willy Tarreau37406352012-04-23 16:16:37 +02002950 return acl_fetch_sess_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002951}
2952
Willy Tarreaua5e37562011-12-16 17:06:15 +01002953/* set temp integer to the cumulated number of session from the session's source
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002954 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002955 * Accepts exactly 1 argument of type table.
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002956 */
2957static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002958acl_fetch_src_sess_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002959 const struct arg *args, struct sample *smp)
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002960{
2961 struct stktable_key *key;
2962
Willy Tarreau64ee4912012-08-30 22:59:48 +02002963 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002964 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002965 return 0;
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002966
Willy Tarreau24e32d82012-04-23 23:55:44 +02002967 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002968 return acl_fetch_sess_cnt(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002969}
2970
Willy Tarreaua5e37562011-12-16 17:06:15 +01002971/* set temp integer to the session rate in the stksess entry <ts> over the configured period */
Willy Tarreau91c43d72010-06-20 11:19:22 +02002972static int
Willy Tarreau37406352012-04-23 16:16:37 +02002973acl_fetch_sess_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002974{
Willy Tarreau37406352012-04-23 16:16:37 +02002975 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002976 smp->type = SMP_T_UINT;
2977 smp->data.uint = 0;
Willy Tarreau91c43d72010-06-20 11:19:22 +02002978 if (ts != NULL) {
2979 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_SESS_RATE);
2980 if (!ptr)
2981 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002982 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, sess_rate),
Willy Tarreau91c43d72010-06-20 11:19:22 +02002983 table->data_arg[STKTABLE_DT_SESS_RATE].u);
2984 }
2985 return 1;
2986}
2987
Willy Tarreaua5e37562011-12-16 17:06:15 +01002988/* set temp integer to the session rate from the session's tracked FE counters over
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002989 * the configured period.
2990 */
2991static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002992acl_fetch_sc1_sess_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002993 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002994{
Willy Tarreau56123282010-08-06 19:06:56 +02002995 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002996 return 0;
2997
Willy Tarreau37406352012-04-23 16:16:37 +02002998 return acl_fetch_sess_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002999}
3000
Willy Tarreaua5e37562011-12-16 17:06:15 +01003001/* set temp integer to the session rate from the session's tracked BE counters over
Willy Tarreau91c43d72010-06-20 11:19:22 +02003002 * the configured period.
3003 */
3004static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003005acl_fetch_sc2_sess_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003006 const struct arg *args, struct sample *smp)
Willy Tarreau91c43d72010-06-20 11:19:22 +02003007{
Willy Tarreau56123282010-08-06 19:06:56 +02003008 if (!l4->stkctr2_entry)
Willy Tarreau91c43d72010-06-20 11:19:22 +02003009 return 0;
3010
Willy Tarreau37406352012-04-23 16:16:37 +02003011 return acl_fetch_sess_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau91c43d72010-06-20 11:19:22 +02003012}
3013
Willy Tarreaua5e37562011-12-16 17:06:15 +01003014/* set temp integer to the session rate from the session's source address in the
Willy Tarreau91c43d72010-06-20 11:19:22 +02003015 * table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003016 * Accepts exactly 1 argument of type table.
Willy Tarreau91c43d72010-06-20 11:19:22 +02003017 */
3018static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003019acl_fetch_src_sess_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003020 const struct arg *args, struct sample *smp)
Willy Tarreau91c43d72010-06-20 11:19:22 +02003021{
3022 struct stktable_key *key;
3023
Willy Tarreau64ee4912012-08-30 22:59:48 +02003024 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau91c43d72010-06-20 11:19:22 +02003025 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003026 return 0;
Willy Tarreau91c43d72010-06-20 11:19:22 +02003027
Willy Tarreau24e32d82012-04-23 23:55:44 +02003028 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003029 return acl_fetch_sess_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau91c43d72010-06-20 11:19:22 +02003030}
3031
Willy Tarreaua5e37562011-12-16 17:06:15 +01003032/* set temp integer to the cumulated number of sessions in the stksess entry <ts> */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003033static int
Willy Tarreau37406352012-04-23 16:16:37 +02003034acl_fetch_http_req_cnt(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003035{
Willy Tarreau37406352012-04-23 16:16:37 +02003036 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003037 smp->type = SMP_T_UINT;
3038 smp->data.uint = 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003039 if (ts != NULL) {
3040 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_HTTP_REQ_CNT);
3041 if (!ptr)
3042 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003043 smp->data.uint = stktable_data_cast(ptr, http_req_cnt);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003044 }
3045 return 1;
3046}
3047
Willy Tarreaua5e37562011-12-16 17:06:15 +01003048/* set temp integer to the cumulated number of sessions from the session's tracked FE counters */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003049static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003050acl_fetch_sc1_http_req_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003051 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003052{
Willy Tarreau56123282010-08-06 19:06:56 +02003053 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003054 return 0;
3055
Willy Tarreau37406352012-04-23 16:16:37 +02003056 return acl_fetch_http_req_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003057}
3058
Willy Tarreaua5e37562011-12-16 17:06:15 +01003059/* set temp integer to the cumulated number of sessions from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003060static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003061acl_fetch_sc2_http_req_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003062 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003063{
Willy Tarreau56123282010-08-06 19:06:56 +02003064 if (!l4->stkctr2_entry)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003065 return 0;
3066
Willy Tarreau37406352012-04-23 16:16:37 +02003067 return acl_fetch_http_req_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003068}
3069
Willy Tarreaua5e37562011-12-16 17:06:15 +01003070/* set temp integer to the cumulated number of session from the session's source
Willy Tarreauda7ff642010-06-23 11:44:09 +02003071 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003072 * Accepts exactly 1 argument of type table.
Willy Tarreauda7ff642010-06-23 11:44:09 +02003073 */
3074static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003075acl_fetch_src_http_req_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003076 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003077{
3078 struct stktable_key *key;
3079
Willy Tarreau64ee4912012-08-30 22:59:48 +02003080 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003081 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003082 return 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003083
Willy Tarreau24e32d82012-04-23 23:55:44 +02003084 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003085 return acl_fetch_http_req_cnt(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauda7ff642010-06-23 11:44:09 +02003086}
3087
Willy Tarreaua5e37562011-12-16 17:06:15 +01003088/* set temp integer to the session rate in the stksess entry <ts> over the configured period */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003089static int
Willy Tarreau37406352012-04-23 16:16:37 +02003090acl_fetch_http_req_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003091{
Willy Tarreau37406352012-04-23 16:16:37 +02003092 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003093 smp->type = SMP_T_UINT;
3094 smp->data.uint = 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003095 if (ts != NULL) {
3096 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_HTTP_REQ_RATE);
3097 if (!ptr)
3098 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003099 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, http_req_rate),
Willy Tarreauda7ff642010-06-23 11:44:09 +02003100 table->data_arg[STKTABLE_DT_HTTP_REQ_RATE].u);
3101 }
3102 return 1;
3103}
3104
Willy Tarreaua5e37562011-12-16 17:06:15 +01003105/* set temp integer to the session rate from the session's tracked FE counters over
Willy Tarreauda7ff642010-06-23 11:44:09 +02003106 * the configured period.
3107 */
3108static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003109acl_fetch_sc1_http_req_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003110 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003111{
Willy Tarreau56123282010-08-06 19:06:56 +02003112 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003113 return 0;
3114
Willy Tarreau37406352012-04-23 16:16:37 +02003115 return acl_fetch_http_req_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003116}
3117
Willy Tarreaua5e37562011-12-16 17:06:15 +01003118/* set temp integer to the session rate from the session's tracked BE counters over
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003119 * the configured period.
3120 */
3121static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003122acl_fetch_sc2_http_req_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003123 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003124{
Willy Tarreau56123282010-08-06 19:06:56 +02003125 if (!l4->stkctr2_entry)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003126 return 0;
3127
Willy Tarreau37406352012-04-23 16:16:37 +02003128 return acl_fetch_http_req_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003129}
3130
Willy Tarreaua5e37562011-12-16 17:06:15 +01003131/* set temp integer to the session rate from the session's source address in the
Willy Tarreauda7ff642010-06-23 11:44:09 +02003132 * table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003133 * Accepts exactly 1 argument of type table.
Willy Tarreauda7ff642010-06-23 11:44:09 +02003134 */
3135static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003136acl_fetch_src_http_req_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003137 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003138{
3139 struct stktable_key *key;
3140
Willy Tarreau64ee4912012-08-30 22:59:48 +02003141 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003142 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003143 return 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003144
Willy Tarreau24e32d82012-04-23 23:55:44 +02003145 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003146 return acl_fetch_http_req_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauda7ff642010-06-23 11:44:09 +02003147}
3148
Willy Tarreaua5e37562011-12-16 17:06:15 +01003149/* set temp integer to the cumulated number of sessions in the stksess entry <ts> */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003150static int
Willy Tarreau37406352012-04-23 16:16:37 +02003151acl_fetch_http_err_cnt(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003152{
Willy Tarreau37406352012-04-23 16:16:37 +02003153 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003154 smp->type = SMP_T_UINT;
3155 smp->data.uint = 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003156 if (ts != NULL) {
3157 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_HTTP_ERR_CNT);
3158 if (!ptr)
3159 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003160 smp->data.uint = stktable_data_cast(ptr, http_err_cnt);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003161 }
3162 return 1;
3163}
3164
Willy Tarreaua5e37562011-12-16 17:06:15 +01003165/* set temp integer to the cumulated number of sessions from the session's tracked FE counters */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003166static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003167acl_fetch_sc1_http_err_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003168 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003169{
Willy Tarreau56123282010-08-06 19:06:56 +02003170 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003171 return 0;
3172
Willy Tarreau37406352012-04-23 16:16:37 +02003173 return acl_fetch_http_err_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003174}
3175
Willy Tarreaua5e37562011-12-16 17:06:15 +01003176/* set temp integer to the cumulated number of sessions from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003177static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003178acl_fetch_sc2_http_err_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003179 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003180{
Willy Tarreau56123282010-08-06 19:06:56 +02003181 if (!l4->stkctr2_entry)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003182 return 0;
3183
Willy Tarreau37406352012-04-23 16:16:37 +02003184 return acl_fetch_http_err_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003185}
3186
Willy Tarreaua5e37562011-12-16 17:06:15 +01003187/* set temp integer to the cumulated number of session from the session's source
Willy Tarreauda7ff642010-06-23 11:44:09 +02003188 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003189 * Accepts exactly 1 argument of type table.
Willy Tarreauda7ff642010-06-23 11:44:09 +02003190 */
3191static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003192acl_fetch_src_http_err_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003193 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003194{
3195 struct stktable_key *key;
3196
Willy Tarreau64ee4912012-08-30 22:59:48 +02003197 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003198 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003199 return 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003200
Willy Tarreau24e32d82012-04-23 23:55:44 +02003201 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003202 return acl_fetch_http_err_cnt(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauda7ff642010-06-23 11:44:09 +02003203}
3204
Willy Tarreaua5e37562011-12-16 17:06:15 +01003205/* set temp integer to the session rate in the stksess entry <ts> over the configured period */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003206static int
Willy Tarreau37406352012-04-23 16:16:37 +02003207acl_fetch_http_err_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003208{
Willy Tarreau37406352012-04-23 16:16:37 +02003209 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003210 smp->type = SMP_T_UINT;
3211 smp->data.uint = 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003212 if (ts != NULL) {
3213 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_HTTP_ERR_RATE);
3214 if (!ptr)
3215 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003216 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, http_err_rate),
Willy Tarreauda7ff642010-06-23 11:44:09 +02003217 table->data_arg[STKTABLE_DT_HTTP_ERR_RATE].u);
3218 }
3219 return 1;
3220}
3221
Willy Tarreaua5e37562011-12-16 17:06:15 +01003222/* set temp integer to the session rate from the session's tracked FE counters over
Willy Tarreauda7ff642010-06-23 11:44:09 +02003223 * the configured period.
3224 */
3225static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003226acl_fetch_sc1_http_err_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003227 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003228{
Willy Tarreau56123282010-08-06 19:06:56 +02003229 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003230 return 0;
3231
Willy Tarreau37406352012-04-23 16:16:37 +02003232 return acl_fetch_http_err_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003233}
3234
Willy Tarreaua5e37562011-12-16 17:06:15 +01003235/* set temp integer to the session rate from the session's tracked BE counters over
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003236 * the configured period.
3237 */
3238static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003239acl_fetch_sc2_http_err_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003240 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003241{
Willy Tarreau56123282010-08-06 19:06:56 +02003242 if (!l4->stkctr2_entry)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003243 return 0;
3244
Willy Tarreau37406352012-04-23 16:16:37 +02003245 return acl_fetch_http_err_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003246}
3247
Willy Tarreaua5e37562011-12-16 17:06:15 +01003248/* set temp integer to the session rate from the session's source address in the
Willy Tarreauda7ff642010-06-23 11:44:09 +02003249 * table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003250 * Accepts exactly 1 argument of type table.
Willy Tarreauda7ff642010-06-23 11:44:09 +02003251 */
3252static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003253acl_fetch_src_http_err_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003254 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003255{
3256 struct stktable_key *key;
3257
Willy Tarreau64ee4912012-08-30 22:59:48 +02003258 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003259 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003260 return 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003261
Willy Tarreau24e32d82012-04-23 23:55:44 +02003262 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003263 return acl_fetch_http_err_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauda7ff642010-06-23 11:44:09 +02003264}
3265
Willy Tarreaua5e37562011-12-16 17:06:15 +01003266/* set temp integer to the number of kbytes received from clients matching the stksess entry <ts> */
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003267static int
Willy Tarreau37406352012-04-23 16:16:37 +02003268acl_fetch_kbytes_in(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003269{
Willy Tarreau37406352012-04-23 16:16:37 +02003270 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003271 smp->type = SMP_T_UINT;
3272 smp->data.uint = 0;
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003273
3274 if (ts != NULL) {
3275 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_BYTES_IN_CNT);
3276 if (!ptr)
3277 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003278 smp->data.uint = stktable_data_cast(ptr, bytes_in_cnt) >> 10;
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003279 }
3280 return 1;
3281}
3282
Willy Tarreaua5e37562011-12-16 17:06:15 +01003283/* set temp integer to the number of kbytes received from clients according to the
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003284 * session's tracked FE counters.
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003285 */
3286static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003287acl_fetch_sc1_kbytes_in(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003288 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003289{
Willy Tarreau56123282010-08-06 19:06:56 +02003290 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003291 return 0;
3292
Willy Tarreau37406352012-04-23 16:16:37 +02003293 return acl_fetch_kbytes_in(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003294}
3295
Willy Tarreaua5e37562011-12-16 17:06:15 +01003296/* set temp integer to the number of kbytes received from clients according to the
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003297 * session's tracked BE counters.
3298 */
3299static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003300acl_fetch_sc2_kbytes_in(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003301 const struct arg *args, struct sample *smp)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003302{
Willy Tarreau56123282010-08-06 19:06:56 +02003303 if (!l4->stkctr2_entry)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003304 return 0;
3305
Willy Tarreau37406352012-04-23 16:16:37 +02003306 return acl_fetch_kbytes_in(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003307}
3308
Willy Tarreaua5e37562011-12-16 17:06:15 +01003309/* set temp integer to the number of kbytes received from the session's source
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003310 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003311 * Accepts exactly 1 argument of type table.
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003312 */
3313static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003314acl_fetch_src_kbytes_in(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003315 const struct arg *args, struct sample *smp)
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003316{
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003317 struct stktable_key *key;
3318
Willy Tarreau64ee4912012-08-30 22:59:48 +02003319 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003320 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003321 return 0;
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003322
Willy Tarreau24e32d82012-04-23 23:55:44 +02003323 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003324 return acl_fetch_kbytes_in(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003325}
3326
Willy Tarreaua5e37562011-12-16 17:06:15 +01003327/* set temp integer to the bytes rate from clients in the stksess entry <ts> over the
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003328 * configured period.
3329 */
3330static int
Willy Tarreau37406352012-04-23 16:16:37 +02003331acl_fetch_bytes_in_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003332{
Willy Tarreau37406352012-04-23 16:16:37 +02003333 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003334 smp->type = SMP_T_UINT;
3335 smp->data.uint = 0;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003336 if (ts != NULL) {
3337 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_BYTES_IN_RATE);
3338 if (!ptr)
3339 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003340 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, bytes_in_rate),
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003341 table->data_arg[STKTABLE_DT_BYTES_IN_RATE].u);
3342 }
3343 return 1;
3344}
3345
Willy Tarreaua5e37562011-12-16 17:06:15 +01003346/* set temp integer to the bytes rate from clients from the session's tracked FE
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003347 * counters over the configured period.
3348 */
3349static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003350acl_fetch_sc1_bytes_in_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003351 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003352{
Willy Tarreau56123282010-08-06 19:06:56 +02003353 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003354 return 0;
3355
Willy Tarreau37406352012-04-23 16:16:37 +02003356 return acl_fetch_bytes_in_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003357}
3358
Willy Tarreaua5e37562011-12-16 17:06:15 +01003359/* set temp integer to the bytes rate from clients from the session's tracked BE
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003360 * counters over the configured period.
3361 */
3362static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003363acl_fetch_sc2_bytes_in_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003364 const struct arg *args, struct sample *smp)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003365{
Willy Tarreau56123282010-08-06 19:06:56 +02003366 if (!l4->stkctr2_entry)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003367 return 0;
3368
Willy Tarreau37406352012-04-23 16:16:37 +02003369 return acl_fetch_bytes_in_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003370}
3371
Willy Tarreaua5e37562011-12-16 17:06:15 +01003372/* set temp integer to the bytes rate from clients from the session's source address
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003373 * in the table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003374 * Accepts exactly 1 argument of type table.
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003375 */
3376static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003377acl_fetch_src_bytes_in_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003378 const struct arg *args, struct sample *smp)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003379{
3380 struct stktable_key *key;
3381
Willy Tarreau64ee4912012-08-30 22:59:48 +02003382 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003383 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003384 return 0;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003385
Willy Tarreau24e32d82012-04-23 23:55:44 +02003386 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003387 return acl_fetch_bytes_in_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003388}
3389
Willy Tarreaua5e37562011-12-16 17:06:15 +01003390/* set temp integer to the number of kbytes sent to clients matching the stksess entry <ts> */
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003391static int
Willy Tarreau37406352012-04-23 16:16:37 +02003392acl_fetch_kbytes_out(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003393{
Willy Tarreau37406352012-04-23 16:16:37 +02003394 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003395 smp->type = SMP_T_UINT;
3396 smp->data.uint = 0;
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003397
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003398 if (ts != NULL) {
3399 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_BYTES_OUT_CNT);
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003400 if (!ptr)
3401 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003402 smp->data.uint = stktable_data_cast(ptr, bytes_out_cnt) >> 10;
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003403 }
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003404 return 1;
3405}
3406
Willy Tarreaua5e37562011-12-16 17:06:15 +01003407/* set temp integer to the number of kbytes sent to clients according to the session's
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003408 * tracked FE counters.
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003409 */
3410static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003411acl_fetch_sc1_kbytes_out(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003412 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003413{
Willy Tarreau56123282010-08-06 19:06:56 +02003414 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003415 return 0;
3416
Willy Tarreau37406352012-04-23 16:16:37 +02003417 return acl_fetch_kbytes_out(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003418}
3419
Willy Tarreaua5e37562011-12-16 17:06:15 +01003420/* set temp integer to the number of kbytes sent to clients according to the session's
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003421 * tracked BE counters.
3422 */
3423static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003424acl_fetch_sc2_kbytes_out(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003425 const struct arg *args, struct sample *smp)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003426{
Willy Tarreau56123282010-08-06 19:06:56 +02003427 if (!l4->stkctr2_entry)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003428 return 0;
3429
Willy Tarreau37406352012-04-23 16:16:37 +02003430 return acl_fetch_kbytes_out(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003431}
3432
Willy Tarreaua5e37562011-12-16 17:06:15 +01003433/* set temp integer to the number of kbytes sent to the session's source address in
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003434 * the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003435 * Accepts exactly 1 argument of type table.
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003436 */
3437static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003438acl_fetch_src_kbytes_out(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003439 const struct arg *args, struct sample *smp)
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003440{
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003441 struct stktable_key *key;
3442
Willy Tarreau64ee4912012-08-30 22:59:48 +02003443 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003444 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003445 return 0;
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003446
Willy Tarreau24e32d82012-04-23 23:55:44 +02003447 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003448 return acl_fetch_kbytes_out(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003449}
3450
Willy Tarreaua5e37562011-12-16 17:06:15 +01003451/* set temp integer to the bytes rate to clients in the stksess entry <ts> over the
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003452 * configured period.
3453 */
3454static int
Willy Tarreau37406352012-04-23 16:16:37 +02003455acl_fetch_bytes_out_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003456{
Willy Tarreau37406352012-04-23 16:16:37 +02003457 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003458 smp->type = SMP_T_UINT;
3459 smp->data.uint = 0;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003460 if (ts != NULL) {
3461 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_BYTES_OUT_RATE);
3462 if (!ptr)
3463 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003464 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, bytes_out_rate),
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003465 table->data_arg[STKTABLE_DT_BYTES_OUT_RATE].u);
3466 }
3467 return 1;
3468}
3469
Willy Tarreaua5e37562011-12-16 17:06:15 +01003470/* set temp integer to the bytes rate to clients from the session's tracked FE counters
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003471 * over the configured period.
3472 */
3473static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003474acl_fetch_sc1_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003475 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003476{
Willy Tarreau56123282010-08-06 19:06:56 +02003477 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003478 return 0;
3479
Willy Tarreau37406352012-04-23 16:16:37 +02003480 return acl_fetch_bytes_out_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003481}
3482
Willy Tarreaua5e37562011-12-16 17:06:15 +01003483/* set temp integer to the bytes rate to clients from the session's tracked BE counters
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003484 * over the configured period.
3485 */
3486static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003487acl_fetch_sc2_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003488 const struct arg *args, struct sample *smp)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003489{
Willy Tarreau56123282010-08-06 19:06:56 +02003490 if (!l4->stkctr2_entry)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003491 return 0;
3492
Willy Tarreau37406352012-04-23 16:16:37 +02003493 return acl_fetch_bytes_out_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003494}
3495
Willy Tarreaua5e37562011-12-16 17:06:15 +01003496/* set temp integer to the bytes rate to client from the session's source address in
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003497 * the table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003498 * Accepts exactly 1 argument of type table.
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003499 */
3500static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003501acl_fetch_src_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003502 const struct arg *args, struct sample *smp)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003503{
3504 struct stktable_key *key;
3505
Willy Tarreau64ee4912012-08-30 22:59:48 +02003506 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003507 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003508 return 0;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003509
Willy Tarreau24e32d82012-04-23 23:55:44 +02003510 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003511 return acl_fetch_bytes_out_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003512}
3513
Willy Tarreau34db1082012-04-19 17:16:54 +02003514/* set temp integer to the number of used entries in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003515 * Accepts exactly 1 argument of type table.
Willy Tarreau34db1082012-04-19 17:16:54 +02003516 */
Willy Tarreauc735a072011-03-29 00:57:02 +02003517static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003518acl_fetch_table_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003519 const struct arg *args, struct sample *smp)
Willy Tarreauc735a072011-03-29 00:57:02 +02003520{
Willy Tarreau37406352012-04-23 16:16:37 +02003521 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003522 smp->type = SMP_T_UINT;
Willy Tarreau24e32d82012-04-23 23:55:44 +02003523 smp->data.uint = args->data.prx->table.current;
Willy Tarreauc735a072011-03-29 00:57:02 +02003524 return 1;
3525}
3526
Willy Tarreau34db1082012-04-19 17:16:54 +02003527/* set temp integer to the number of free entries in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003528 * Accepts exactly 1 argument of type table.
Willy Tarreau34db1082012-04-19 17:16:54 +02003529 */
Willy Tarreauc735a072011-03-29 00:57:02 +02003530static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003531acl_fetch_table_avl(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003532 const struct arg *args, struct sample *smp)
Willy Tarreauc735a072011-03-29 00:57:02 +02003533{
Willy Tarreau24e32d82012-04-23 23:55:44 +02003534 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003535 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003536 smp->type = SMP_T_UINT;
3537 smp->data.uint = px->table.size - px->table.current;
Willy Tarreauc735a072011-03-29 00:57:02 +02003538 return 1;
3539}
Willy Tarreau8b22a712010-06-18 17:46:06 +02003540
Willy Tarreau61612d42012-04-19 18:42:05 +02003541/* Note: must not be declared <const> as its list will be overwritten.
3542 * Please take care of keeping this list alphabetically sorted.
3543 */
Willy Tarreau8b22a712010-06-18 17:46:06 +02003544static struct acl_kw_list acl_kws = {{ },{
Willy Tarreau61612d42012-04-19 18:42:05 +02003545 { "sc1_bytes_in_rate", acl_parse_int, acl_fetch_sc1_bytes_in_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3546 { "sc1_bytes_out_rate", acl_parse_int, acl_fetch_sc1_bytes_out_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3547 { "sc1_clr_gpc0", acl_parse_int, acl_fetch_sc1_clr_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3548 { "sc1_conn_cnt", acl_parse_int, acl_fetch_sc1_conn_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3549 { "sc1_conn_cur", acl_parse_int, acl_fetch_sc1_conn_cur, acl_match_int, ACL_USE_NOTHING, 0 },
3550 { "sc1_conn_rate", acl_parse_int, acl_fetch_sc1_conn_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3551 { "sc1_get_gpc0", acl_parse_int, acl_fetch_sc1_get_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3552 { "sc1_http_err_cnt", acl_parse_int, acl_fetch_sc1_http_err_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3553 { "sc1_http_err_rate", acl_parse_int, acl_fetch_sc1_http_err_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3554 { "sc1_http_req_cnt", acl_parse_int, acl_fetch_sc1_http_req_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3555 { "sc1_http_req_rate", acl_parse_int, acl_fetch_sc1_http_req_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3556 { "sc1_inc_gpc0", acl_parse_int, acl_fetch_sc1_inc_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3557 { "sc1_kbytes_in", acl_parse_int, acl_fetch_sc1_kbytes_in, acl_match_int, ACL_USE_TCP4_VOLATILE, 0 },
3558 { "sc1_kbytes_out", acl_parse_int, acl_fetch_sc1_kbytes_out, acl_match_int, ACL_USE_TCP4_VOLATILE, 0 },
3559 { "sc1_sess_cnt", acl_parse_int, acl_fetch_sc1_sess_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3560 { "sc1_sess_rate", acl_parse_int, acl_fetch_sc1_sess_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3561 { "sc2_bytes_in_rate", acl_parse_int, acl_fetch_sc2_bytes_in_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3562 { "sc2_bytes_out_rate", acl_parse_int, acl_fetch_sc2_bytes_out_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3563 { "sc2_clr_gpc0", acl_parse_int, acl_fetch_sc2_clr_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3564 { "sc2_conn_cnt", acl_parse_int, acl_fetch_sc2_conn_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3565 { "sc2_conn_cur", acl_parse_int, acl_fetch_sc2_conn_cur, acl_match_int, ACL_USE_NOTHING, 0 },
3566 { "sc2_conn_rate", acl_parse_int, acl_fetch_sc2_conn_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3567 { "sc2_get_gpc0", acl_parse_int, acl_fetch_sc2_get_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3568 { "sc2_http_err_cnt", acl_parse_int, acl_fetch_sc2_http_err_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3569 { "sc2_http_err_rate", acl_parse_int, acl_fetch_sc2_http_err_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3570 { "sc2_http_req_cnt", acl_parse_int, acl_fetch_sc2_http_req_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3571 { "sc2_http_req_rate", acl_parse_int, acl_fetch_sc2_http_req_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3572 { "sc2_inc_gpc0", acl_parse_int, acl_fetch_sc2_inc_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3573 { "sc2_kbytes_in", acl_parse_int, acl_fetch_sc2_kbytes_in, acl_match_int, ACL_USE_TCP4_VOLATILE, 0 },
3574 { "sc2_kbytes_out", acl_parse_int, acl_fetch_sc2_kbytes_out, acl_match_int, ACL_USE_TCP4_VOLATILE, 0 },
3575 { "sc2_sess_cnt", acl_parse_int, acl_fetch_sc2_sess_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3576 { "sc2_sess_rate", acl_parse_int, acl_fetch_sc2_sess_rate, acl_match_int, ACL_USE_NOTHING, 0 },
Willy Tarreaufc2c1fd2012-04-19 23:35:54 +02003577 { "src_bytes_in_rate", acl_parse_int, acl_fetch_src_bytes_in_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3578 { "src_bytes_out_rate", acl_parse_int, acl_fetch_src_bytes_out_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3579 { "src_clr_gpc0", acl_parse_int, acl_fetch_src_clr_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3580 { "src_conn_cnt", acl_parse_int, acl_fetch_src_conn_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3581 { "src_conn_cur", acl_parse_int, acl_fetch_src_conn_cur, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3582 { "src_conn_rate", acl_parse_int, acl_fetch_src_conn_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3583 { "src_get_gpc0", acl_parse_int, acl_fetch_src_get_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3584 { "src_http_err_cnt", acl_parse_int, acl_fetch_src_http_err_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3585 { "src_http_err_rate", acl_parse_int, acl_fetch_src_http_err_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3586 { "src_http_req_cnt", acl_parse_int, acl_fetch_src_http_req_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3587 { "src_http_req_rate", acl_parse_int, acl_fetch_src_http_req_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3588 { "src_inc_gpc0", acl_parse_int, acl_fetch_src_inc_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3589 { "src_kbytes_in", acl_parse_int, acl_fetch_src_kbytes_in, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3590 { "src_kbytes_out", acl_parse_int, acl_fetch_src_kbytes_out, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3591 { "src_sess_cnt", acl_parse_int, acl_fetch_src_sess_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3592 { "src_sess_rate", acl_parse_int, acl_fetch_src_sess_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3593 { "src_updt_conn_cnt", acl_parse_int, acl_fetch_src_updt_conn_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3594 { "table_avl", acl_parse_int, acl_fetch_table_avl, acl_match_int, ACL_USE_NOTHING, ARG1(1,TAB) },
3595 { "table_cnt", acl_parse_int, acl_fetch_table_cnt, acl_match_int, ACL_USE_NOTHING, ARG1(1,TAB) },
Willy Tarreau8b22a712010-06-18 17:46:06 +02003596 { NULL, NULL, NULL, NULL },
3597}};
3598
3599
Willy Tarreau56123282010-08-06 19:06:56 +02003600/* Parse a "track-sc[12]" line starting with "track-sc[12]" in args[arg-1].
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003601 * Returns the number of warnings emitted, or -1 in case of fatal errors. The
3602 * <prm> struct is fed with the table name if any. If unspecified, the caller
3603 * will assume that the current proxy's table is used.
3604 */
3605int parse_track_counters(char **args, int *arg,
3606 int section_type, struct proxy *curpx,
3607 struct track_ctr_prm *prm,
Willy Tarreau0a3dd742012-05-08 19:47:01 +02003608 struct proxy *defpx, char **err)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003609{
Willy Tarreau12785782012-04-27 21:37:17 +02003610 int sample_type = 0;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003611
Willy Tarreau56123282010-08-06 19:06:56 +02003612 /* parse the arguments of "track-sc[12]" before the condition in the
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003613 * following form :
Willy Tarreau56123282010-08-06 19:06:56 +02003614 * track-sc[12] src [ table xxx ] [ if|unless ... ]
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003615 */
3616 while (args[*arg]) {
3617 if (strcmp(args[*arg], "src") == 0) {
3618 prm->type = STKTABLE_TYPE_IP;
Willy Tarreau12785782012-04-27 21:37:17 +02003619 sample_type = 1;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003620 }
3621 else if (strcmp(args[*arg], "table") == 0) {
3622 if (!args[*arg + 1]) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02003623 memprintf(err, "missing table name");
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003624 return -1;
3625 }
3626 /* we copy the table name for now, it will be resolved later */
3627 prm->table.n = strdup(args[*arg + 1]);
3628 (*arg)++;
3629 }
3630 else {
3631 /* unhandled keywords are handled by the caller */
3632 break;
3633 }
3634 (*arg)++;
3635 }
3636
Willy Tarreau12785782012-04-27 21:37:17 +02003637 if (!sample_type) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02003638 memprintf(err,
3639 "tracking key not specified (found %s, only 'src' is supported)",
3640 quote_arg(args[*arg]));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003641 return -1;
3642 }
3643
3644 return 0;
3645}
3646
Willy Tarreau8b22a712010-06-18 17:46:06 +02003647__attribute__((constructor))
3648static void __session_init(void)
3649{
3650 acl_register_keywords(&acl_kws);
3651}
3652
Willy Tarreaubaaee002006-06-26 02:48:02 +02003653/*
3654 * Local variables:
3655 * c-indent-level: 8
3656 * c-basic-offset: 8
3657 * End:
3658 */