blob: 975176c3e7c38ae9a8513ccb06342d9656804b01 [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 Tarreau7c669d72008-06-20 15:04:11 +020018#include <common/debug.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020019#include <common/memory.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020020
Willy Tarreaubaaee002006-06-26 02:48:02 +020021#include <types/capture.h>
Willy Tarreau55a8d0e2008-11-30 18:47:21 +010022#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020023
Willy Tarreau1d0dfb12009-07-07 15:10:31 +020024#include <proto/acl.h>
Willy Tarreau61612d42012-04-19 18:42:05 +020025#include <proto/arg.h>
Willy Tarreau55a8d0e2008-11-30 18:47:21 +010026#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <proto/channel.h>
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +010028#include <proto/checks.h>
Willy Tarreaud2274c62012-07-06 14:29:45 +020029#include <proto/connection.h>
Willy Tarreau5ca791d2009-08-16 19:06:42 +020030#include <proto/dumpstats.h>
Willy Tarreaudd2f85e2012-09-02 22:34:23 +020031#include <proto/fd.h>
Willy Tarreau91c43d72010-06-20 11:19:22 +020032#include <proto/freq_ctr.h>
Willy Tarreau3041b9f2010-10-15 23:25:20 +020033#include <proto/frontend.h>
Willy Tarreau8d5d7f22007-01-21 19:16:41 +010034#include <proto/hdr_idx.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020035#include <proto/listener.h>
Willy Tarreau332f8bf2007-05-13 21:36:56 +020036#include <proto/log.h>
Willy Tarreaucbaaec42012-09-06 11:32:07 +020037#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038#include <proto/session.h>
Willy Tarreau3eba98a2009-01-25 13:56:13 +010039#include <proto/pipe.h>
Willy Tarreau55a8d0e2008-11-30 18:47:21 +010040#include <proto/proto_http.h>
41#include <proto/proto_tcp.h>
Willy Tarreau1d0dfb12009-07-07 15:10:31 +020042#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/queue.h>
Willy Tarreau7f062c42009-03-05 18:43:00 +010044#include <proto/server.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020045#include <proto/sample.h>
Emeric Brun1d33b292010-01-04 15:47:17 +010046#include <proto/stick_table.h>
Willy Tarreau55a8d0e2008-11-30 18:47:21 +010047#include <proto/stream_interface.h>
Willy Tarreau55a8d0e2008-11-30 18:47:21 +010048#include <proto/task.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049
Willy Tarreauc6ca1a02007-05-13 19:43:47 +020050struct pool_head *pool2_session;
Willy Tarreauf54f8bd2008-11-23 19:53:55 +010051struct list sessions;
Willy Tarreaubaaee002006-06-26 02:48:02 +020052
Willy Tarreau2542b532012-08-31 16:01:23 +020053static struct task *expire_mini_session(struct task *t);
54int session_complete(struct session *s);
55
56/* This function is called from the protocol layer accept() in order to
57 * instanciate a new embryonic session on behalf of a given listener and
58 * frontend. It returns a positive value upon success, 0 if the connection
59 * can be ignored, or a negative value upon critical failure. The accepted
60 * file descriptor is closed if we return <= 0.
Willy Tarreau81f9aa32010-06-01 17:45:26 +020061 */
62int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
63{
64 struct proxy *p = l->frontend;
65 struct session *s;
Willy Tarreau81f9aa32010-06-01 17:45:26 +020066 struct task *t;
Willy Tarreauabe8ea52010-11-11 10:56:04 +010067 int ret;
68
69
70 ret = -1; /* assume unrecoverable error by default */
Willy Tarreau81f9aa32010-06-01 17:45:26 +020071
Willy Tarreaufffe1322010-11-11 09:48:16 +010072 if (unlikely((s = pool_alloc2(pool2_session)) == NULL))
Willy Tarreau81f9aa32010-06-01 17:45:26 +020073 goto out_close;
Willy Tarreau81f9aa32010-06-01 17:45:26 +020074
Willy Tarreau2542b532012-08-31 16:01:23 +020075 /* minimum session initialization required for an embryonic session is
76 * fairly low. We need very little to execute L4 ACLs, then we need a
77 * task to make the client-side connection live on its own.
78 * - flags
79 * - stick-entry tracking
80 */
Willy Tarreau81f9aa32010-06-01 17:45:26 +020081 s->flags = 0;
82 s->logs.logwait = p->to_log;
Willy Tarreau56123282010-08-06 19:06:56 +020083 s->stkctr1_entry = NULL;
84 s->stkctr2_entry = NULL;
85 s->stkctr1_table = NULL;
86 s->stkctr2_table = NULL;
Willy Tarreau81f9aa32010-06-01 17:45:26 +020087
Willy Tarreau2542b532012-08-31 16:01:23 +020088 s->listener = l;
89 s->fe = p;
Willy Tarreauabe8ea52010-11-11 10:56:04 +010090
Willy Tarreau81f9aa32010-06-01 17:45:26 +020091 /* OK, we're keeping the session, so let's properly initialize the session */
Willy Tarreau96596ae2012-06-08 22:57:36 +020092 s->si[0].conn.t.sock.fd = cfd;
93 s->si[0].conn.ctrl = l->proto;
Willy Tarreau2542b532012-08-31 16:01:23 +020094 s->si[0].conn.flags = CO_FL_NONE;
Willy Tarreau986a9d22012-08-30 21:11:38 +020095 s->si[0].conn.addr.from = *addr;
Willy Tarreau2542b532012-08-31 16:01:23 +020096 set_target_client(&s->si[0].conn.target, l);
97
Willy Tarreau81f9aa32010-06-01 17:45:26 +020098 s->logs.accept_date = date; /* user-visible date for logging */
99 s->logs.tv_accept = now; /* corrected date for internal use */
100 s->uniq_id = totalconn;
Willy Tarreau2542b532012-08-31 16:01:23 +0200101 p->feconn++;
102 /* This session was accepted, count it now */
103 if (p->feconn > p->fe_counters.conn_max)
104 p->fe_counters.conn_max = p->feconn;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200105
Willy Tarreau2542b532012-08-31 16:01:23 +0200106 proxy_inc_fe_conn_ctr(l, p);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200107
108 /* now evaluate the tcp-request layer4 rules. Since we expect to be able
109 * to abort right here as soon as possible, we check the rules before
110 * even initializing the stream interfaces.
111 */
112 if ((l->options & LI_O_TCP_RULES) && !tcp_exec_req_rules(s)) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200113 /* let's do a no-linger now to close with a single RST. */
114 setsockopt(cfd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100115 ret = 0; /* successful termination */
Willy Tarreau2542b532012-08-31 16:01:23 +0200116 goto out_free_session;
117 }
118
Willy Tarreau82569f92012-09-27 23:48:56 +0200119 /* Adjust some socket options */
120 if (unlikely(fcntl(cfd, F_SETFL, O_NONBLOCK) == -1))
121 goto out_free_session;
122
123 /* monitor-net and health mode are processed immediately after TCP
124 * connection rules. This way it's possible to block them, but they
125 * never use the lower data layers, they send directly over the socket,
126 * as they were designed for. We first flush the socket receive buffer
127 * in order to avoid emission of an RST by the system. We ignore any
128 * error.
129 */
130 if (unlikely((p->mode == PR_MODE_HEALTH) ||
131 ((l->options & LI_O_CHK_MONNET) &&
132 addr->ss_family == AF_INET &&
133 (((struct sockaddr_in *)addr)->sin_addr.s_addr & p->mon_mask.s_addr) == p->mon_net.s_addr))) {
134 /* we have 4 possibilities here :
135 * - HTTP mode, from monitoring address => send "HTTP/1.0 200 OK"
136 * - HEALTH mode with HTTP check => send "HTTP/1.0 200 OK"
137 * - HEALTH mode without HTTP check => just send "OK"
138 * - TCP mode from monitoring address => just close
139 */
140 recv(cfd, trash, trashlen, 0&MSG_DONTWAIT);
141 if (p->mode == PR_MODE_HTTP ||
142 (p->mode == PR_MODE_HEALTH && (p->options2 & PR_O2_CHK_ANY) == PR_O2_HTTP_CHK))
143 send(cfd, "HTTP/1.0 200 OK\r\n\r\n", 19, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_MORE);
144 else if (p->mode == PR_MODE_HEALTH)
145 send(cfd, "OK\n", 3, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_MORE);
146 ret = 0;
147 goto out_free_session;
148 }
149
150
Willy Tarreau22cda212012-08-31 17:43:29 +0200151 /* wait for a PROXY protocol header */
152 if (l->options & LI_O_ACC_PROXY) {
153 s->si[0].conn.flags |= CO_FL_ACCEPT_PROXY;
154 conn_sock_want_recv(&s->si[0].conn);
155 }
156
Willy Tarreau2542b532012-08-31 16:01:23 +0200157 if (unlikely((t = task_new()) == NULL))
158 goto out_free_session;
159
160 t->context = s;
161 t->nice = l->nice;
162 s->task = t;
163
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200164 /* Add the various callbacks. Right now the transport layer is present
165 * but not initialized. Also note we need to be careful as the stream
166 * int is not initialized yet.
Willy Tarreau2542b532012-08-31 16:01:23 +0200167 */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200168 si_prepare_conn(&s->si[0], l->proto, l->xprt);
Willy Tarreau2542b532012-08-31 16:01:23 +0200169
170 /* finish initialization of the accepted file descriptor */
171 fd_insert(cfd);
172 fdtab[cfd].owner = &s->si[0].conn;
Willy Tarreau2542b532012-08-31 16:01:23 +0200173 fdtab[cfd].iocb = conn_fd_handler;
174 conn_data_want_recv(&s->si[0].conn);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200175 if (conn_xprt_init(&s->si[0].conn) < 0)
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100176 goto out_free_task;
Willy Tarreau2542b532012-08-31 16:01:23 +0200177
178 /* OK, now either we have a pending handshake to execute with and
179 * then we must return to the I/O layer, or we can proceed with the
180 * end of the session initialization. In case of handshake, we also
181 * set the I/O timeout to the frontend's client timeout.
182 */
183
184 if (s->si[0].conn.flags & CO_FL_HANDSHAKE) {
185 t->process = expire_mini_session;
186 t->expire = tick_add_ifset(now_ms, p->timeout.client);
187 task_queue(t);
188 s->si[0].conn.flags |= CO_FL_INIT_SESS;
189 return 1;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200190 }
191
Willy Tarreau2542b532012-08-31 16:01:23 +0200192 /* OK let's complete session initialization */
193 ret = session_complete(s);
194 if (ret > 0)
195 return ret;
196
197 /* Error unrolling */
198 out_free_task:
199 task_free(t);
200 out_free_session:
201 p->feconn--;
202 if (s->stkctr1_entry || s->stkctr2_entry)
203 session_store_counters(s);
204 pool_free2(pool2_session, s);
205 out_close:
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200206 if (ret < 0 && l->xprt == &raw_sock && p->mode == PR_MODE_HTTP) {
Willy Tarreau2542b532012-08-31 16:01:23 +0200207 /* critical error, no more memory, try to emit a 500 response */
Willy Tarreau783f2582012-09-04 12:19:04 +0200208 struct chunk *err_msg = http_error_message(s, HTTP_ERR_500);
Willy Tarreau2542b532012-08-31 16:01:23 +0200209 send(cfd, err_msg->str, err_msg->len, MSG_DONTWAIT|MSG_NOSIGNAL);
210 }
211
212 if (fdtab[cfd].owner)
213 fd_delete(cfd);
214 else
215 close(cfd);
216 return ret;
217}
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100218
Willy Tarreau2542b532012-08-31 16:01:23 +0200219/* This function kills an existing embryonic session. It stops the connection's
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200220 * transport layer, releases assigned resources, resumes the listener if it was
Willy Tarreau2542b532012-08-31 16:01:23 +0200221 * disabled and finally kills the file descriptor.
222 */
223static void kill_mini_session(struct session *s)
224{
225 /* kill the connection now */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200226 conn_xprt_close(&s->si[0].conn);
Willy Tarreau2542b532012-08-31 16:01:23 +0200227
228 s->fe->feconn--;
229 if (s->stkctr1_entry || s->stkctr2_entry)
230 session_store_counters(s);
231
232 if (!(s->listener->options & LI_O_UNLIMITED))
233 actconn--;
234 jobs--;
235 s->listener->nbconn--;
236 if (s->listener->state == LI_FULL)
237 resume_listener(s->listener);
238
239 /* Dequeues all of the listeners waiting for a resource */
240 if (!LIST_ISEMPTY(&global_listener_queue))
241 dequeue_all_listeners(&global_listener_queue);
242
243 if (!LIST_ISEMPTY(&s->fe->listener_queue) &&
244 (!s->fe->fe_sps_lim || freq_ctr_remain(&s->fe->fe_sess_per_sec, s->fe->fe_sps_lim, 0) > 0))
245 dequeue_all_listeners(&s->fe->listener_queue);
246
247 task_delete(s->task);
248 task_free(s->task);
249
250 if (fdtab[s->si[0].conn.t.sock.fd].owner)
251 fd_delete(s->si[0].conn.t.sock.fd);
252 else
253 close(s->si[0].conn.t.sock.fd);
254
255 pool_free2(pool2_session, s);
256}
257
Willy Tarreau22cda212012-08-31 17:43:29 +0200258/* Finish initializing a session from a connection, or kills it if the
259 * connection shows and error. Returns <0 if the connection was killed.
Willy Tarreau2542b532012-08-31 16:01:23 +0200260 */
Willy Tarreau22cda212012-08-31 17:43:29 +0200261int conn_session_complete(struct connection *conn, int flag)
Willy Tarreau2542b532012-08-31 16:01:23 +0200262{
Willy Tarreaue603e692012-09-27 22:20:41 +0200263 struct session *s = container_of(conn->owner, struct session, si[0]);
Willy Tarreau2542b532012-08-31 16:01:23 +0200264
Willy Tarreau22cda212012-08-31 17:43:29 +0200265 if (!(conn->flags & CO_FL_ERROR) && (session_complete(s) > 0)) {
Willy Tarreau2542b532012-08-31 16:01:23 +0200266 conn->flags &= ~flag;
267 return 0;
268 }
269
270 /* kill the connection now */
271 kill_mini_session(s);
272 return -1;
273}
274
275/* Manages embryonic sessions timeout. It is only called when the timeout
276 * strikes and performs the required cleanup.
277 */
278static struct task *expire_mini_session(struct task *t)
279{
280 struct session *s = t->context;
281
282 if (!(t->state & TASK_WOKEN_TIMER))
283 return t;
284
285 kill_mini_session(s);
286 return NULL;
287}
288
289/* This function is called from the I/O handler which detects the end of
290 * handshake, in order to complete initialization of a valid session. It must
291 * be called with an embryonic session. It returns a positive value upon
292 * success, 0 if the connection can be ignored, or a negative value upon
293 * critical failure. The accepted file descriptor is closed if we return <= 0.
294 */
295int session_complete(struct session *s)
296{
297 struct listener *l = s->listener;
298 struct proxy *p = s->fe;
299 struct http_txn *txn;
300 struct task *t = s->task;
301 int ret;
302
303 ret = -1; /* assume unrecoverable error by default */
304
305 /* OK, we're keeping the session, so let's properly initialize the session */
306 LIST_ADDQ(&sessions, &s->list);
307 LIST_INIT(&s->back_refs);
308 s->flags |= SN_INITIALIZED;
309
310 s->unique_id = NULL;
311 s->term_trace = 0;
312
313 t->process = l->handler;
314 t->context = s;
315 t->expire = TICK_ETERNITY;
316
317 /* Note: initially, the session's backend points to the frontend.
318 * This changes later when switching rules are executed or
319 * when the default backend is assigned.
320 */
321 s->be = s->fe;
322 s->req = s->rep = NULL; /* will be allocated later */
323
324 /* Let's count a session now */
Willy Tarreaub36b4242010-06-04 20:59:39 +0200325 proxy_inc_fe_sess_ctr(l, p);
Willy Tarreau56123282010-08-06 19:06:56 +0200326 if (s->stkctr1_entry) {
Willy Tarreau91c43d72010-06-20 11:19:22 +0200327 void *ptr;
328
Willy Tarreau56123282010-08-06 19:06:56 +0200329 ptr = stktable_data_ptr(s->stkctr1_table, s->stkctr1_entry, STKTABLE_DT_SESS_CNT);
Willy Tarreauf4d17d92010-06-18 22:10:12 +0200330 if (ptr)
331 stktable_data_cast(ptr, sess_cnt)++;
Willy Tarreau91c43d72010-06-20 11:19:22 +0200332
Willy Tarreau56123282010-08-06 19:06:56 +0200333 ptr = stktable_data_ptr(s->stkctr1_table, s->stkctr1_entry, STKTABLE_DT_SESS_RATE);
Willy Tarreau91c43d72010-06-20 11:19:22 +0200334 if (ptr)
335 update_freq_ctr_period(&stktable_data_cast(ptr, sess_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200336 s->stkctr1_table->data_arg[STKTABLE_DT_SESS_RATE].u, 1);
Willy Tarreauf4d17d92010-06-18 22:10:12 +0200337 }
Willy Tarreaub36b4242010-06-04 20:59:39 +0200338
Willy Tarreau56123282010-08-06 19:06:56 +0200339 if (s->stkctr2_entry) {
Willy Tarreau9e9879a2010-08-06 15:25:22 +0200340 void *ptr;
341
Willy Tarreau56123282010-08-06 19:06:56 +0200342 ptr = stktable_data_ptr(s->stkctr2_table, s->stkctr2_entry, STKTABLE_DT_SESS_CNT);
Willy Tarreau9e9879a2010-08-06 15:25:22 +0200343 if (ptr)
344 stktable_data_cast(ptr, sess_cnt)++;
345
Willy Tarreau56123282010-08-06 19:06:56 +0200346 ptr = stktable_data_ptr(s->stkctr2_table, s->stkctr2_entry, STKTABLE_DT_SESS_RATE);
Willy Tarreau9e9879a2010-08-06 15:25:22 +0200347 if (ptr)
348 update_freq_ctr_period(&stktable_data_cast(ptr, sess_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200349 s->stkctr2_table->data_arg[STKTABLE_DT_SESS_RATE].u, 1);
Willy Tarreau9e9879a2010-08-06 15:25:22 +0200350 }
351
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200352 /* this part should be common with other protocols */
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200353 s->si[0].owner = t;
354 s->si[0].state = s->si[0].prev_state = SI_ST_EST;
355 s->si[0].err_type = SI_ET_NONE;
356 s->si[0].err_loc = NULL;
Willy Tarreau0bd05ea2010-07-02 11:18:03 +0200357 s->si[0].release = NULL;
Willy Tarreau63e7fe32012-05-08 15:20:43 +0200358 s->si[0].send_proxy_ofs = 0;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200359 s->si[0].exp = TICK_ETERNITY;
360 s->si[0].flags = SI_FL_NONE;
361
362 if (likely(s->fe->options2 & PR_O2_INDEPSTR))
363 s->si[0].flags |= SI_FL_INDEP_STR;
364
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200365 /* pre-initialize the other side's stream interface to an INIT state. The
366 * callbacks will be initialized before attempting to connect.
367 */
Willy Tarreaufb7508a2012-05-21 16:47:54 +0200368 s->si[1].conn.t.sock.fd = -1; /* just to help with debugging */
Willy Tarreau505e34a2012-07-06 10:17:53 +0200369 s->si[1].conn.flags = CO_FL_NONE;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200370 s->si[1].owner = t;
371 s->si[1].state = s->si[1].prev_state = SI_ST_INI;
372 s->si[1].err_type = SI_ET_NONE;
Willy Tarreau0b3a4112011-03-27 19:16:56 +0200373 s->si[1].conn_retries = 0; /* used for logging too */
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200374 s->si[1].err_loc = NULL;
Willy Tarreau0bd05ea2010-07-02 11:18:03 +0200375 s->si[1].release = NULL;
Willy Tarreau63e7fe32012-05-08 15:20:43 +0200376 s->si[1].send_proxy_ofs = 0;
Willy Tarreau3cefd522012-08-30 15:49:18 +0200377 clear_target(&s->si[1].conn.target);
Willy Tarreauc5788912012-08-24 18:12:41 +0200378 si_prepare_embedded(&s->si[1]);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200379 s->si[1].exp = TICK_ETERNITY;
380 s->si[1].flags = SI_FL_NONE;
381
382 if (likely(s->fe->options2 & PR_O2_INDEPSTR))
383 s->si[1].flags |= SI_FL_INDEP_STR;
384
Willy Tarreau9bd0d742011-07-20 00:17:39 +0200385 session_init_srv_conn(s);
Willy Tarreau9e000c62011-03-10 14:03:36 +0100386 clear_target(&s->target);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200387 s->pend_pos = NULL;
388
389 /* init store persistence */
390 s->store_count = 0;
391
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200392 if (unlikely((s->req = pool_alloc2(pool2_channel)) == NULL))
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200393 goto out_free_task; /* no memory */
394
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200395 if (unlikely((s->rep = pool_alloc2(pool2_channel)) == NULL))
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200396 goto out_free_req; /* no memory */
397
398 /* initialize the request buffer */
Willy Tarreau572bf902012-07-02 17:01:20 +0200399 s->req->buf.size = global.tune.bufsize;
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200400 channel_init(s->req);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200401 s->req->prod = &s->si[0];
402 s->req->cons = &s->si[1];
403 s->si[0].ib = s->si[1].ob = s->req;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200404 s->req->flags |= CF_READ_ATTACHED; /* the producer is already connected */
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200405
406 /* activate default analysers enabled for this listener */
407 s->req->analysers = l->analysers;
408
409 s->req->wto = TICK_ETERNITY;
410 s->req->rto = TICK_ETERNITY;
411 s->req->rex = TICK_ETERNITY;
412 s->req->wex = TICK_ETERNITY;
413 s->req->analyse_exp = TICK_ETERNITY;
414
415 /* initialize response buffer */
Willy Tarreau572bf902012-07-02 17:01:20 +0200416 s->rep->buf.size = global.tune.bufsize;
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200417 channel_init(s->rep);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200418 s->rep->prod = &s->si[1];
419 s->rep->cons = &s->si[0];
420 s->si[0].ob = s->si[1].ib = s->rep;
421 s->rep->analysers = 0;
422
Willy Tarreau96e31212011-05-30 18:10:30 +0200423 if (s->fe->options2 & PR_O2_NODELAY) {
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200424 s->req->flags |= CF_NEVER_WAIT;
425 s->rep->flags |= CF_NEVER_WAIT;
Willy Tarreau96e31212011-05-30 18:10:30 +0200426 }
427
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200428 s->rep->rto = TICK_ETERNITY;
429 s->rep->wto = TICK_ETERNITY;
430 s->rep->rex = TICK_ETERNITY;
431 s->rep->wex = TICK_ETERNITY;
432 s->rep->analyse_exp = TICK_ETERNITY;
433
Willy Tarreau62f791e2012-03-09 11:32:30 +0100434 txn = &s->txn;
435 /* Those variables will be checked and freed if non-NULL in
436 * session.c:session_free(). It is important that they are
437 * properly initialized.
438 */
439 txn->sessid = NULL;
440 txn->srv_cookie = NULL;
441 txn->cli_cookie = NULL;
442 txn->uri = NULL;
443 txn->req.cap = NULL;
444 txn->rsp.cap = NULL;
445 txn->hdr_idx.v = NULL;
446 txn->hdr_idx.size = txn->hdr_idx.used = 0;
447 txn->req.flags = 0;
448 txn->rsp.flags = 0;
449 /* the HTTP messages need to know what buffer they're associated with */
450 txn->req.buf = s->req;
451 txn->rsp.buf = s->rep;
452
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200453 /* finish initialization of the accepted file descriptor */
Willy Tarreauf9dabec2012-08-17 17:33:53 +0200454 conn_data_want_recv(&s->si[0].conn);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200455
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100456 if (p->accept && (ret = p->accept(s)) <= 0) {
457 /* Either we had an unrecoverable error (<0) or work is
458 * finished (=0, eg: monitoring), in both situations,
459 * we can release everything and close.
460 */
461 goto out_free_rep;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200462 }
463
Willy Tarreau2542b532012-08-31 16:01:23 +0200464 /* we want the connection handler to notify the stream interface about updates. */
465 s->si[0].conn.flags |= CO_FL_NOTIFY_SI;
466
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200467 /* it is important not to call the wakeup function directly but to
468 * pass through task_wakeup(), because this one knows how to apply
469 * priorities to tasks.
470 */
471 task_wakeup(t, TASK_WOKEN_INIT);
472 return 1;
473
474 /* Error unrolling */
475 out_free_rep:
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200476 pool_free2(pool2_channel, s->rep);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200477 out_free_req:
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200478 pool_free2(pool2_channel, s->req);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200479 out_free_task:
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100480 return ret;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200481}
482
Willy Tarreaubaaee002006-06-26 02:48:02 +0200483/*
484 * frees the context associated to a session. It must have been removed first.
485 */
Simon Hormandec5be42011-06-08 09:19:07 +0900486static void session_free(struct session *s)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200487{
Willy Tarreau4dbc4a22007-03-03 16:23:22 +0100488 struct http_txn *txn = &s->txn;
Willy Tarreau632f5a72007-07-11 10:42:35 +0200489 struct proxy *fe = s->fe;
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100490 struct bref *bref, *back;
Willy Tarreaua4cda672010-06-06 18:28:49 +0200491 int i;
Willy Tarreau0f7562b2007-01-07 15:46:13 +0100492
Willy Tarreaubaaee002006-06-26 02:48:02 +0200493 if (s->pend_pos)
494 pendconn_free(s->pend_pos);
Willy Tarreau922a8062008-12-04 09:33:58 +0100495
Willy Tarreau827aee92011-03-10 16:55:02 +0100496 if (target_srv(&s->target)) { /* there may be requests left pending in queue */
Willy Tarreau1e62de62008-11-11 20:20:02 +0100497 if (s->flags & SN_CURR_SESS) {
498 s->flags &= ~SN_CURR_SESS;
Willy Tarreau827aee92011-03-10 16:55:02 +0100499 target_srv(&s->target)->cur_sess--;
Willy Tarreau1e62de62008-11-11 20:20:02 +0100500 }
Willy Tarreau827aee92011-03-10 16:55:02 +0100501 if (may_dequeue_tasks(target_srv(&s->target), s->be))
502 process_srv_queue(target_srv(&s->target));
Willy Tarreau1e62de62008-11-11 20:20:02 +0100503 }
Willy Tarreau922a8062008-12-04 09:33:58 +0100504
Willy Tarreau7c669d72008-06-20 15:04:11 +0200505 if (unlikely(s->srv_conn)) {
506 /* the session still has a reserved slot on a server, but
507 * it should normally be only the same as the one above,
508 * so this should not happen in fact.
509 */
510 sess_change_server(s, NULL);
511 }
512
Willy Tarreau3eba98a2009-01-25 13:56:13 +0100513 if (s->req->pipe)
514 put_pipe(s->req->pipe);
Willy Tarreau259de1b2009-01-18 21:56:21 +0100515
Willy Tarreau3eba98a2009-01-25 13:56:13 +0100516 if (s->rep->pipe)
517 put_pipe(s->rep->pipe);
Willy Tarreau259de1b2009-01-18 21:56:21 +0100518
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200519 pool_free2(pool2_channel, s->req);
520 pool_free2(pool2_channel, s->rep);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200521
Willy Tarreau46023632010-01-07 22:51:47 +0100522 http_end_txn(s);
523
Willy Tarreaua4cda672010-06-06 18:28:49 +0200524 for (i = 0; i < s->store_count; i++) {
525 if (!s->store[i].ts)
526 continue;
527 stksess_free(s->store[i].table, s->store[i].ts);
528 s->store[i].ts = NULL;
529 }
530
Willy Tarreau34eb6712011-10-24 18:15:04 +0200531 pool_free2(pool2_hdr_idx, txn->hdr_idx.v);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200532 if (fe) {
Willy Tarreau46023632010-01-07 22:51:47 +0100533 pool_free2(fe->rsp_cap_pool, txn->rsp.cap);
534 pool_free2(fe->req_cap_pool, txn->req.cap);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200535 }
Willy Tarreau0937bc42009-12-22 15:03:09 +0100536
Willy Tarreau56123282010-08-06 19:06:56 +0200537 if (s->stkctr1_entry || s->stkctr2_entry)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +0200538 session_store_counters(s);
539
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100540 list_for_each_entry_safe(bref, back, &s->back_refs, users) {
Willy Tarreaufd3828e2009-02-22 15:17:24 +0100541 /* we have to unlink all watchers. We must not relink them if
542 * this session was the last one in the list.
543 */
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100544 LIST_DEL(&bref->users);
Willy Tarreaufd3828e2009-02-22 15:17:24 +0100545 LIST_INIT(&bref->users);
546 if (s->list.n != &sessions)
547 LIST_ADDQ(&LIST_ELEM(s->list.n, struct session *, list)->back_refs, &bref->users);
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100548 bref->ref = s->list.n;
549 }
Willy Tarreauf54f8bd2008-11-23 19:53:55 +0100550 LIST_DEL(&s->list);
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200551 pool_free2(pool2_session, s);
Willy Tarreau632f5a72007-07-11 10:42:35 +0200552
553 /* We may want to free the maximum amount of pools if the proxy is stopping */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200554 if (fe && unlikely(fe->state == PR_STSTOPPED)) {
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200555 pool_flush2(pool2_channel);
Willy Tarreau34eb6712011-10-24 18:15:04 +0200556 pool_flush2(pool2_hdr_idx);
Willy Tarreau48d63db2008-08-03 17:41:33 +0200557 pool_flush2(pool2_requri);
558 pool_flush2(pool2_capture);
559 pool_flush2(pool2_session);
560 pool_flush2(fe->req_cap_pool);
561 pool_flush2(fe->rsp_cap_pool);
Willy Tarreau632f5a72007-07-11 10:42:35 +0200562 }
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200563}
564
565
566/* perform minimal intializations, report 0 in case of error, 1 if OK. */
567int init_session()
568{
Willy Tarreauf54f8bd2008-11-23 19:53:55 +0100569 LIST_INIT(&sessions);
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200570 pool2_session = create_pool("session", sizeof(struct session), MEM_F_SHARED);
571 return pool2_session != NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200572}
573
Willy Tarreau30e71012007-11-26 20:15:35 +0100574void session_process_counters(struct session *s)
575{
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100576 unsigned long long bytes;
577
Willy Tarreau30e71012007-11-26 20:15:35 +0100578 if (s->req) {
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100579 bytes = s->req->total - s->logs.bytes_in;
Willy Tarreau30e71012007-11-26 20:15:35 +0100580 s->logs.bytes_in = s->req->total;
581 if (bytes) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100582 s->fe->fe_counters.bytes_in += bytes;
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100583
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100584 s->be->be_counters.bytes_in += bytes;
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100585
Willy Tarreau827aee92011-03-10 16:55:02 +0100586 if (target_srv(&s->target))
587 target_srv(&s->target)->counters.bytes_in += bytes;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200588
589 if (s->listener->counters)
590 s->listener->counters->bytes_in += bytes;
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200591
Willy Tarreau56123282010-08-06 19:06:56 +0200592 if (s->stkctr2_entry) {
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200593 void *ptr;
594
Willy Tarreau56123282010-08-06 19:06:56 +0200595 ptr = stktable_data_ptr(s->stkctr2_table,
596 s->stkctr2_entry,
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200597 STKTABLE_DT_BYTES_IN_CNT);
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200598 if (ptr)
599 stktable_data_cast(ptr, bytes_in_cnt) += bytes;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200600
Willy Tarreau56123282010-08-06 19:06:56 +0200601 ptr = stktable_data_ptr(s->stkctr2_table,
602 s->stkctr2_entry,
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200603 STKTABLE_DT_BYTES_IN_RATE);
604 if (ptr)
605 update_freq_ctr_period(&stktable_data_cast(ptr, bytes_in_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200606 s->stkctr2_table->data_arg[STKTABLE_DT_BYTES_IN_RATE].u, bytes);
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200607 }
608
Willy Tarreau56123282010-08-06 19:06:56 +0200609 if (s->stkctr1_entry) {
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200610 void *ptr;
611
Willy Tarreau56123282010-08-06 19:06:56 +0200612 ptr = stktable_data_ptr(s->stkctr1_table,
613 s->stkctr1_entry,
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200614 STKTABLE_DT_BYTES_IN_CNT);
615 if (ptr)
616 stktable_data_cast(ptr, bytes_in_cnt) += bytes;
617
Willy Tarreau56123282010-08-06 19:06:56 +0200618 ptr = stktable_data_ptr(s->stkctr1_table,
619 s->stkctr1_entry,
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200620 STKTABLE_DT_BYTES_IN_RATE);
621 if (ptr)
622 update_freq_ctr_period(&stktable_data_cast(ptr, bytes_in_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200623 s->stkctr1_table->data_arg[STKTABLE_DT_BYTES_IN_RATE].u, bytes);
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200624 }
Willy Tarreau30e71012007-11-26 20:15:35 +0100625 }
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100626 }
627
Willy Tarreau30e71012007-11-26 20:15:35 +0100628 if (s->rep) {
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100629 bytes = s->rep->total - s->logs.bytes_out;
Willy Tarreau30e71012007-11-26 20:15:35 +0100630 s->logs.bytes_out = s->rep->total;
631 if (bytes) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100632 s->fe->fe_counters.bytes_out += bytes;
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100633
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100634 s->be->be_counters.bytes_out += bytes;
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100635
Willy Tarreau827aee92011-03-10 16:55:02 +0100636 if (target_srv(&s->target))
637 target_srv(&s->target)->counters.bytes_out += bytes;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200638
639 if (s->listener->counters)
640 s->listener->counters->bytes_out += bytes;
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200641
Willy Tarreau56123282010-08-06 19:06:56 +0200642 if (s->stkctr2_entry) {
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200643 void *ptr;
644
Willy Tarreau56123282010-08-06 19:06:56 +0200645 ptr = stktable_data_ptr(s->stkctr2_table,
646 s->stkctr2_entry,
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200647 STKTABLE_DT_BYTES_OUT_CNT);
648 if (ptr)
649 stktable_data_cast(ptr, bytes_out_cnt) += bytes;
650
Willy Tarreau56123282010-08-06 19:06:56 +0200651 ptr = stktable_data_ptr(s->stkctr2_table,
652 s->stkctr2_entry,
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200653 STKTABLE_DT_BYTES_OUT_RATE);
654 if (ptr)
655 update_freq_ctr_period(&stktable_data_cast(ptr, bytes_out_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200656 s->stkctr2_table->data_arg[STKTABLE_DT_BYTES_OUT_RATE].u, bytes);
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200657 }
658
Willy Tarreau56123282010-08-06 19:06:56 +0200659 if (s->stkctr1_entry) {
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200660 void *ptr;
661
Willy Tarreau56123282010-08-06 19:06:56 +0200662 ptr = stktable_data_ptr(s->stkctr1_table,
663 s->stkctr1_entry,
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200664 STKTABLE_DT_BYTES_OUT_CNT);
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200665 if (ptr)
666 stktable_data_cast(ptr, bytes_out_cnt) += bytes;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200667
Willy Tarreau56123282010-08-06 19:06:56 +0200668 ptr = stktable_data_ptr(s->stkctr1_table,
669 s->stkctr1_entry,
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200670 STKTABLE_DT_BYTES_OUT_RATE);
671 if (ptr)
672 update_freq_ctr_period(&stktable_data_cast(ptr, bytes_out_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200673 s->stkctr1_table->data_arg[STKTABLE_DT_BYTES_OUT_RATE].u, bytes);
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200674 }
Willy Tarreau30e71012007-11-26 20:15:35 +0100675 }
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100676 }
677}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200678
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100679/* This function is called with (si->state == SI_ST_CON) meaning that a
680 * connection was attempted and that the file descriptor is already allocated.
681 * We must check for establishment, error and abort. Possible output states
682 * are SI_ST_EST (established), SI_ST_CER (error), SI_ST_DIS (abort), and
683 * SI_ST_CON (no change). The function returns 0 if it switches to SI_ST_CER,
684 * otherwise 1.
685 */
Simon Hormandec5be42011-06-08 09:19:07 +0900686static int sess_update_st_con_tcp(struct session *s, struct stream_interface *si)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100687{
Willy Tarreau7421efb2012-07-02 15:11:27 +0200688 struct channel *req = si->ob;
689 struct channel *rep = si->ib;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100690
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100691 /* If we got an error, or if nothing happened and the connection timed
692 * out, we must give up. The CER state handler will take care of retry
693 * attempts and error reports.
694 */
695 if (unlikely(si->flags & (SI_FL_EXP|SI_FL_ERR))) {
Willy Tarreau127334e2009-03-28 10:47:26 +0100696 si->exp = TICK_ETERNITY;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100697 si->state = SI_ST_CER;
Willy Tarreaufb7508a2012-05-21 16:47:54 +0200698 fd_delete(si_fd(si));
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100699
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200700 conn_xprt_close(&si->conn);
Willy Tarreau0bd05ea2010-07-02 11:18:03 +0200701 if (si->release)
702 si->release(si);
703
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100704 if (si->err_type)
705 return 0;
706
Willy Tarreau827aee92011-03-10 16:55:02 +0100707 si->err_loc = target_srv(&s->target);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100708 if (si->flags & SI_FL_ERR)
709 si->err_type = SI_ET_CONN_ERR;
710 else
711 si->err_type = SI_ET_CONN_TO;
712 return 0;
713 }
714
715 /* OK, maybe we want to abort */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200716 if (unlikely((rep->flags & CF_SHUTW) ||
717 ((req->flags & CF_SHUTW_NOW) && /* FIXME: this should not prevent a connection from establishing */
718 ((!(req->flags & CF_WRITE_ACTIVITY) && channel_is_empty(req)) ||
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100719 s->be->options & PR_O_ABRT_CLOSE)))) {
720 /* give up */
Willy Tarreau73b013b2012-05-21 16:31:45 +0200721 si_shutw(si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100722 si->err_type |= SI_ET_CONN_ABRT;
Willy Tarreau827aee92011-03-10 16:55:02 +0100723 si->err_loc = target_srv(&s->target);
Willy Tarreau84455332009-03-15 22:34:05 +0100724 if (s->srv_error)
725 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100726 return 1;
727 }
728
729 /* we need to wait a bit more if there was no activity either */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200730 if (!(req->flags & CF_WRITE_ACTIVITY))
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100731 return 1;
732
733 /* OK, this means that a connection succeeded. The caller will be
734 * responsible for handling the transition from CON to EST.
735 */
736 s->logs.t_connect = tv_ms_elapsed(&s->logs.tv_accept, &now);
Willy Tarreau127334e2009-03-28 10:47:26 +0100737 si->exp = TICK_ETERNITY;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100738 si->state = SI_ST_EST;
739 si->err_type = SI_ET_NONE;
740 si->err_loc = NULL;
741 return 1;
742}
743
744/* This function is called with (si->state == SI_ST_CER) meaning that a
745 * previous connection attempt has failed and that the file descriptor
746 * has already been released. Possible causes include asynchronous error
747 * notification and time out. Possible output states are SI_ST_CLO when
748 * retries are exhausted, SI_ST_TAR when a delay is wanted before a new
749 * connection attempt, SI_ST_ASS when it's wise to retry on the same server,
750 * and SI_ST_REQ when an immediate redispatch is wanted. The buffers are
751 * marked as in error state. It returns 0.
752 */
Simon Hormandec5be42011-06-08 09:19:07 +0900753static int sess_update_st_cer(struct session *s, struct stream_interface *si)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100754{
755 /* we probably have to release last session from the server */
Willy Tarreau827aee92011-03-10 16:55:02 +0100756 if (target_srv(&s->target)) {
757 health_adjust(target_srv(&s->target), HANA_STATUS_L4_ERR);
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +0100758
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100759 if (s->flags & SN_CURR_SESS) {
760 s->flags &= ~SN_CURR_SESS;
Willy Tarreau827aee92011-03-10 16:55:02 +0100761 target_srv(&s->target)->cur_sess--;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100762 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100763 }
764
765 /* ensure that we have enough retries left */
Willy Tarreauee28de02010-06-01 09:51:00 +0200766 si->conn_retries--;
767 if (si->conn_retries < 0) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100768 if (!si->err_type) {
769 si->err_type = SI_ET_CONN_ERR;
Willy Tarreau827aee92011-03-10 16:55:02 +0100770 si->err_loc = target_srv(&s->target);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100771 }
772
Willy Tarreau827aee92011-03-10 16:55:02 +0100773 if (target_srv(&s->target))
774 target_srv(&s->target)->counters.failed_conns++;
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100775 s->be->be_counters.failed_conns++;
Willy Tarreaub89cfca2010-12-29 14:32:28 +0100776 sess_change_server(s, NULL);
Willy Tarreau827aee92011-03-10 16:55:02 +0100777 if (may_dequeue_tasks(target_srv(&s->target), s->be))
778 process_srv_queue(target_srv(&s->target));
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100779
780 /* shutw is enough so stop a connecting socket */
Willy Tarreau73b013b2012-05-21 16:31:45 +0200781 si_shutw(si);
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200782 si->ob->flags |= CF_WRITE_ERROR;
783 si->ib->flags |= CF_READ_ERROR;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100784
785 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +0100786 if (s->srv_error)
787 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100788 return 0;
789 }
790
791 /* If the "redispatch" option is set on the backend, we are allowed to
792 * retry on another server for the last retry. In order to achieve this,
793 * we must mark the session unassigned, and eventually clear the DIRECT
794 * bit to ignore any persistence cookie. We won't count a retry nor a
795 * redispatch yet, because this will depend on what server is selected.
796 */
Willy Tarreau827aee92011-03-10 16:55:02 +0100797 if (target_srv(&s->target) && si->conn_retries == 0 &&
Willy Tarreau4de91492010-01-22 19:10:05 +0100798 s->be->options & PR_O_REDISP && !(s->flags & SN_FORCE_PRST)) {
Willy Tarreaub89cfca2010-12-29 14:32:28 +0100799 sess_change_server(s, NULL);
Willy Tarreau827aee92011-03-10 16:55:02 +0100800 if (may_dequeue_tasks(target_srv(&s->target), s->be))
801 process_srv_queue(target_srv(&s->target));
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100802
803 s->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100804 si->state = SI_ST_REQ;
805 } else {
Willy Tarreau827aee92011-03-10 16:55:02 +0100806 if (target_srv(&s->target))
807 target_srv(&s->target)->counters.retries++;
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100808 s->be->be_counters.retries++;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100809 si->state = SI_ST_ASS;
810 }
811
812 if (si->flags & SI_FL_ERR) {
813 /* The error was an asynchronous connection error, and we will
814 * likely have to retry connecting to the same server, most
815 * likely leading to the same result. To avoid this, we wait
816 * one second before retrying.
817 */
818
819 if (!si->err_type)
820 si->err_type = SI_ET_CONN_ERR;
821
822 si->state = SI_ST_TAR;
823 si->exp = tick_add(now_ms, MS_TO_TICKS(1000));
824 return 0;
825 }
826 return 0;
827}
828
829/*
830 * This function handles the transition between the SI_ST_CON state and the
Willy Tarreau85e7d002010-05-31 11:57:51 +0200831 * SI_ST_EST state. It must only be called after switching from SI_ST_CON (or
Willy Tarreau26d8c592012-05-07 18:12:14 +0200832 * SI_ST_INI) to SI_ST_EST, but only when a ->proto is defined.
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100833 */
Simon Hormandec5be42011-06-08 09:19:07 +0900834static void sess_establish(struct session *s, struct stream_interface *si)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100835{
Willy Tarreau7421efb2012-07-02 15:11:27 +0200836 struct channel *req = si->ob;
837 struct channel *rep = si->ib;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100838
Willy Tarreau827aee92011-03-10 16:55:02 +0100839 if (target_srv(&s->target))
840 health_adjust(target_srv(&s->target), HANA_STATUS_L4_OK);
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +0100841
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100842 if (s->be->mode == PR_MODE_TCP) { /* let's allow immediate data connection in this case */
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100843 /* if the user wants to log as soon as possible, without counting
844 * bytes from the server, then this is the right moment. */
845 if (s->fe->to_log && !(s->logs.logwait & LW_BYTES)) {
846 s->logs.t_close = s->logs.t_connect; /* to get a valid end date */
Willy Tarreaua5555ec2008-11-30 19:02:32 +0100847 s->do_log(s);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100848 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100849 }
850 else {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100851 s->txn.rsp.msg_state = HTTP_MSG_RPBEFORE;
852 /* reset hdr_idx which was already initialized by the request.
853 * right now, the http parser does it.
854 * hdr_idx_init(&s->txn.hdr_idx);
855 */
856 }
857
Willy Tarreau4e5b8282009-08-16 22:57:50 +0200858 rep->analysers |= s->fe->fe_rsp_ana | s->be->be_rsp_ana;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200859 rep->flags |= CF_READ_ATTACHED; /* producer is now attached */
Willy Tarreau73b013b2012-05-21 16:31:45 +0200860 if (si_ctrl(si)) {
Willy Tarreaud04e8582010-05-31 12:31:35 +0200861 /* real connections have timeouts */
862 req->wto = s->be->timeout.server;
863 rep->rto = s->be->timeout.server;
864 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100865 req->wex = TICK_ETERNITY;
866}
867
868/* Update stream interface status for input states SI_ST_ASS, SI_ST_QUE, SI_ST_TAR.
869 * Other input states are simply ignored.
870 * Possible output states are SI_ST_CLO, SI_ST_TAR, SI_ST_ASS, SI_ST_REQ, SI_ST_CON.
871 * Flags must have previously been updated for timeouts and other conditions.
872 */
Simon Hormandec5be42011-06-08 09:19:07 +0900873static void sess_update_stream_int(struct session *s, struct stream_interface *si)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100874{
Willy Tarreau827aee92011-03-10 16:55:02 +0100875 struct server *srv = target_srv(&s->target);
876
Willy Tarreau02d6cfc2012-03-01 18:19:58 +0100877 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 +0100878 now_ms, __FUNCTION__,
879 s,
880 s->req, s->rep,
881 s->req->rex, s->rep->wex,
882 s->req->flags, s->rep->flags,
Cyril Bonté3aaba442012-09-23 14:19:12 +0200883 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 +0100884
885 if (si->state == SI_ST_ASS) {
886 /* Server assigned to connection request, we have to try to connect now */
887 int conn_err;
888
889 conn_err = connect_server(s);
Willy Tarreau827aee92011-03-10 16:55:02 +0100890 srv = target_srv(&s->target);
891
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100892 if (conn_err == SN_ERR_NONE) {
893 /* state = SI_ST_CON now */
Willy Tarreau827aee92011-03-10 16:55:02 +0100894 if (srv)
895 srv_inc_sess_ctr(srv);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100896 return;
897 }
898
899 /* We have received a synchronous error. We might have to
900 * abort, retry immediately or redispatch.
901 */
902 if (conn_err == SN_ERR_INTERNAL) {
903 if (!si->err_type) {
904 si->err_type = SI_ET_CONN_OTHER;
Willy Tarreau827aee92011-03-10 16:55:02 +0100905 si->err_loc = srv;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100906 }
907
Willy Tarreau827aee92011-03-10 16:55:02 +0100908 if (srv)
909 srv_inc_sess_ctr(srv);
910 if (srv)
911 srv->counters.failed_conns++;
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100912 s->be->be_counters.failed_conns++;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100913
914 /* release other sessions waiting for this server */
Willy Tarreaub89cfca2010-12-29 14:32:28 +0100915 sess_change_server(s, NULL);
Willy Tarreau827aee92011-03-10 16:55:02 +0100916 if (may_dequeue_tasks(srv, s->be))
917 process_srv_queue(srv);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100918
919 /* Failed and not retryable. */
Willy Tarreau73b013b2012-05-21 16:31:45 +0200920 si_shutr(si);
921 si_shutw(si);
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200922 si->ob->flags |= CF_WRITE_ERROR;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100923
924 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
925
926 /* no session was ever accounted for this server */
927 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +0100928 if (s->srv_error)
929 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100930 return;
931 }
932
933 /* We are facing a retryable error, but we don't want to run a
934 * turn-around now, as the problem is likely a source port
935 * allocation problem, so we want to retry now.
936 */
937 si->state = SI_ST_CER;
938 si->flags &= ~SI_FL_ERR;
939 sess_update_st_cer(s, si);
940 /* now si->state is one of SI_ST_CLO, SI_ST_TAR, SI_ST_ASS, SI_ST_REQ */
941 return;
942 }
943 else if (si->state == SI_ST_QUE) {
944 /* connection request was queued, check for any update */
945 if (!s->pend_pos) {
946 /* The connection is not in the queue anymore. Either
947 * we have a server connection slot available and we
948 * go directly to the assigned state, or we need to
949 * load-balance first and go to the INI state.
950 */
951 si->exp = TICK_ETERNITY;
952 if (unlikely(!(s->flags & SN_ASSIGNED)))
953 si->state = SI_ST_REQ;
954 else {
955 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
956 si->state = SI_ST_ASS;
957 }
958 return;
959 }
960
961 /* Connection request still in queue... */
962 if (si->flags & SI_FL_EXP) {
963 /* ... and timeout expired */
964 si->exp = TICK_ETERNITY;
965 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
Willy Tarreau827aee92011-03-10 16:55:02 +0100966 if (srv)
967 srv->counters.failed_conns++;
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100968 s->be->be_counters.failed_conns++;
Willy Tarreau73b013b2012-05-21 16:31:45 +0200969 si_shutr(si);
970 si_shutw(si);
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200971 si->ob->flags |= CF_WRITE_TIMEOUT;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100972 if (!si->err_type)
973 si->err_type = SI_ET_QUEUE_TO;
974 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +0100975 if (s->srv_error)
976 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100977 return;
978 }
979
980 /* Connection remains in queue, check if we have to abort it */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200981 if ((si->ob->flags & (CF_READ_ERROR)) ||
982 ((si->ob->flags & CF_SHUTW_NOW) && /* empty and client aborted */
Willy Tarreau8e21bb92012-08-24 22:40:29 +0200983 (channel_is_empty(si->ob) || s->be->options & PR_O_ABRT_CLOSE))) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100984 /* give up */
985 si->exp = TICK_ETERNITY;
986 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
Willy Tarreau73b013b2012-05-21 16:31:45 +0200987 si_shutr(si);
988 si_shutw(si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100989 si->err_type |= SI_ET_QUEUE_ABRT;
990 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +0100991 if (s->srv_error)
992 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100993 return;
994 }
995
996 /* Nothing changed */
997 return;
998 }
999 else if (si->state == SI_ST_TAR) {
1000 /* Connection request might be aborted */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001001 if ((si->ob->flags & (CF_READ_ERROR)) ||
1002 ((si->ob->flags & CF_SHUTW_NOW) && /* empty and client aborted */
Willy Tarreau8e21bb92012-08-24 22:40:29 +02001003 (channel_is_empty(si->ob) || s->be->options & PR_O_ABRT_CLOSE))) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001004 /* give up */
1005 si->exp = TICK_ETERNITY;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001006 si_shutr(si);
1007 si_shutw(si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001008 si->err_type |= SI_ET_CONN_ABRT;
1009 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +01001010 if (s->srv_error)
1011 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001012 return;
1013 }
1014
1015 if (!(si->flags & SI_FL_EXP))
1016 return; /* still in turn-around */
1017
1018 si->exp = TICK_ETERNITY;
1019
1020 /* we keep trying on the same server as long as the session is
1021 * marked "assigned".
1022 * FIXME: Should we force a redispatch attempt when the server is down ?
1023 */
1024 if (s->flags & SN_ASSIGNED)
1025 si->state = SI_ST_ASS;
1026 else
1027 si->state = SI_ST_REQ;
1028 return;
1029 }
1030}
1031
Simon Hormandec5be42011-06-08 09:19:07 +09001032/* Set correct session termination flags in case no analyser has done it. It
1033 * also counts a failed request if the server state has not reached the request
1034 * stage.
1035 */
1036static void sess_set_term_flags(struct session *s)
1037{
1038 if (!(s->flags & SN_FINST_MASK)) {
1039 if (s->si[1].state < SI_ST_REQ) {
1040
1041 s->fe->fe_counters.failed_req++;
1042 if (s->listener->counters)
1043 s->listener->counters->failed_req++;
1044
1045 s->flags |= SN_FINST_R;
1046 }
1047 else if (s->si[1].state == SI_ST_QUE)
1048 s->flags |= SN_FINST_Q;
1049 else if (s->si[1].state < SI_ST_EST)
1050 s->flags |= SN_FINST_C;
1051 else if (s->si[1].state == SI_ST_EST || s->si[1].prev_state == SI_ST_EST)
1052 s->flags |= SN_FINST_D;
1053 else
1054 s->flags |= SN_FINST_L;
1055 }
1056}
1057
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001058/* This function initiates a server connection request on a stream interface
1059 * already in SI_ST_REQ state. Upon success, the state goes to SI_ST_ASS,
1060 * indicating that a server has been assigned. It may also return SI_ST_QUE,
1061 * or SI_ST_CLO upon error.
1062 */
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001063static void sess_prepare_conn_req(struct session *s, struct stream_interface *si)
1064{
1065 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 +01001066 now_ms, __FUNCTION__,
1067 s,
1068 s->req, s->rep,
1069 s->req->rex, s->rep->wex,
1070 s->req->flags, s->rep->flags,
Cyril Bonté3aaba442012-09-23 14:19:12 +02001071 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 +01001072
1073 if (si->state != SI_ST_REQ)
1074 return;
1075
1076 /* Try to assign a server */
1077 if (srv_redispatch_connect(s) != 0) {
1078 /* We did not get a server. Either we queued the
1079 * connection request, or we encountered an error.
1080 */
1081 if (si->state == SI_ST_QUE)
1082 return;
1083
1084 /* we did not get any server, let's check the cause */
Willy Tarreau73b013b2012-05-21 16:31:45 +02001085 si_shutr(si);
1086 si_shutw(si);
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001087 si->ob->flags |= CF_WRITE_ERROR;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001088 if (!si->err_type)
1089 si->err_type = SI_ET_CONN_OTHER;
1090 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +01001091 if (s->srv_error)
1092 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001093 return;
1094 }
1095
1096 /* The server is assigned */
1097 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
1098 si->state = SI_ST_ASS;
1099}
1100
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001101/* This stream analyser checks the switching rules and changes the backend
Willy Tarreau4de91492010-01-22 19:10:05 +01001102 * if appropriate. The default_backend rule is also considered, then the
1103 * target backend's forced persistence rules are also evaluated last if any.
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001104 * It returns 1 if the processing can continue on next analysers, or zero if it
1105 * either needs more data or wants to immediately abort the request.
1106 */
Willy Tarreau7421efb2012-07-02 15:11:27 +02001107static int process_switching_rules(struct session *s, struct channel *req, int an_bit)
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001108{
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001109 struct persist_rule *prst_rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01001110
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001111 req->analysers &= ~an_bit;
1112 req->analyse_exp = TICK_ETERNITY;
1113
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001114 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 +02001115 now_ms, __FUNCTION__,
1116 s,
1117 req,
1118 req->rex, req->wex,
1119 req->flags,
Cyril Bonté3aaba442012-09-23 14:19:12 +02001120 req->buf.i,
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001121 req->analysers);
1122
1123 /* now check whether we have some switching rules for this request */
1124 if (!(s->flags & SN_BE_ASSIGNED)) {
1125 struct switching_rule *rule;
1126
1127 list_for_each_entry(rule, &s->fe->switching_rules, list) {
1128 int ret;
1129
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001130 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 +02001131 ret = acl_pass(ret);
1132 if (rule->cond->pol == ACL_COND_UNLESS)
1133 ret = !ret;
1134
1135 if (ret) {
Willy Tarreaubedb9ba2009-07-12 08:27:39 +02001136 if (!session_set_backend(s, rule->be.backend))
1137 goto sw_failed;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001138 break;
1139 }
1140 }
1141
1142 /* To ensure correct connection accounting on the backend, we
1143 * have to assign one if it was not set (eg: a listen). This
1144 * measure also takes care of correctly setting the default
1145 * backend if any.
1146 */
1147 if (!(s->flags & SN_BE_ASSIGNED))
Willy Tarreaubedb9ba2009-07-12 08:27:39 +02001148 if (!session_set_backend(s, s->fe->defbe.be ? s->fe->defbe.be : s->be))
1149 goto sw_failed;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001150 }
1151
Willy Tarreaufb356202010-08-03 14:02:05 +02001152 /* we don't want to run the TCP or HTTP filters again if the backend has not changed */
1153 if (s->fe == s->be) {
1154 s->req->analysers &= ~AN_REQ_INSPECT_BE;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001155 s->req->analysers &= ~AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaufb356202010-08-03 14:02:05 +02001156 }
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001157
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001158 /* 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 +01001159 * persistence rule, and report that in the session.
1160 */
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001161 list_for_each_entry(prst_rule, &s->be->persist_rules, list) {
Willy Tarreau4de91492010-01-22 19:10:05 +01001162 int ret = 1;
1163
1164 if (prst_rule->cond) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001165 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 +01001166 ret = acl_pass(ret);
1167 if (prst_rule->cond->pol == ACL_COND_UNLESS)
1168 ret = !ret;
1169 }
1170
1171 if (ret) {
1172 /* no rule, or the rule matches */
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001173 if (prst_rule->type == PERSIST_TYPE_FORCE) {
1174 s->flags |= SN_FORCE_PRST;
1175 } else {
1176 s->flags |= SN_IGNORE_PRST;
1177 }
Willy Tarreau4de91492010-01-22 19:10:05 +01001178 break;
1179 }
1180 }
1181
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001182 return 1;
Willy Tarreaubedb9ba2009-07-12 08:27:39 +02001183
1184 sw_failed:
1185 /* immediately abort this request in case of allocation failure */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001186 channel_abort(s->req);
1187 channel_abort(s->rep);
Willy Tarreaubedb9ba2009-07-12 08:27:39 +02001188
1189 if (!(s->flags & SN_ERR_MASK))
1190 s->flags |= SN_ERR_RESOURCE;
1191 if (!(s->flags & SN_FINST_MASK))
1192 s->flags |= SN_FINST_R;
1193
1194 s->txn.status = 500;
1195 s->req->analysers = 0;
1196 s->req->analyse_exp = TICK_ETERNITY;
1197 return 0;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001198}
1199
Willy Tarreau4a5cade2012-04-05 21:09:48 +02001200/* This stream analyser works on a request. It applies all use-server rules on
1201 * it then returns 1. The data must already be present in the buffer otherwise
1202 * they won't match. It always returns 1.
1203 */
Willy Tarreau7421efb2012-07-02 15:11:27 +02001204static int process_server_rules(struct session *s, struct channel *req, int an_bit)
Willy Tarreau4a5cade2012-04-05 21:09:48 +02001205{
1206 struct proxy *px = s->be;
1207 struct server_rule *rule;
1208
1209 DPRINTF(stderr,"[%u] %s: session=%p b=%p, exp(r,w)=%u,%u bf=%08x bl=%d analysers=%02x\n",
1210 now_ms, __FUNCTION__,
1211 s,
1212 req,
1213 req->rex, req->wex,
1214 req->flags,
Cyril Bonté3aaba442012-09-23 14:19:12 +02001215 req->buf.i + req->buf.o,
Willy Tarreau4a5cade2012-04-05 21:09:48 +02001216 req->analysers);
1217
1218 if (!(s->flags & SN_ASSIGNED)) {
1219 list_for_each_entry(rule, &px->server_rules, list) {
1220 int ret;
1221
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001222 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 +02001223 ret = acl_pass(ret);
1224 if (rule->cond->pol == ACL_COND_UNLESS)
1225 ret = !ret;
1226
1227 if (ret) {
1228 struct server *srv = rule->srv.ptr;
1229
1230 if ((srv->state & SRV_RUNNING) ||
1231 (px->options & PR_O_PERSIST) ||
1232 (s->flags & SN_FORCE_PRST)) {
1233 s->flags |= SN_DIRECT | SN_ASSIGNED;
1234 set_target_server(&s->target, srv);
1235 break;
1236 }
1237 /* if the server is not UP, let's go on with next rules
1238 * just in case another one is suited.
1239 */
1240 }
1241 }
1242 }
1243
1244 req->analysers &= ~an_bit;
1245 req->analyse_exp = TICK_ETERNITY;
1246 return 1;
1247}
1248
Emeric Brun1d33b292010-01-04 15:47:17 +01001249/* This stream analyser works on a request. It applies all sticking rules on
1250 * it then returns 1. The data must already be present in the buffer otherwise
1251 * they won't match. It always returns 1.
1252 */
Willy Tarreau7421efb2012-07-02 15:11:27 +02001253static int process_sticking_rules(struct session *s, struct channel *req, int an_bit)
Emeric Brun1d33b292010-01-04 15:47:17 +01001254{
1255 struct proxy *px = s->be;
1256 struct sticking_rule *rule;
1257
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001258 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 +01001259 now_ms, __FUNCTION__,
1260 s,
1261 req,
1262 req->rex, req->wex,
1263 req->flags,
Cyril Bonté3aaba442012-09-23 14:19:12 +02001264 req->buf.i,
Emeric Brun1d33b292010-01-04 15:47:17 +01001265 req->analysers);
1266
1267 list_for_each_entry(rule, &px->sticking_rules, list) {
1268 int ret = 1 ;
1269 int i;
1270
1271 for (i = 0; i < s->store_count; i++) {
1272 if (rule->table.t == s->store[i].table)
1273 break;
1274 }
1275
1276 if (i != s->store_count)
1277 continue;
1278
1279 if (rule->cond) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001280 ret = acl_exec_cond(rule->cond, px, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
Emeric Brun1d33b292010-01-04 15:47:17 +01001281 ret = acl_pass(ret);
1282 if (rule->cond->pol == ACL_COND_UNLESS)
1283 ret = !ret;
1284 }
1285
1286 if (ret) {
1287 struct stktable_key *key;
1288
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001289 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 +01001290 if (!key)
1291 continue;
1292
1293 if (rule->flags & STK_IS_MATCH) {
1294 struct stksess *ts;
1295
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001296 if ((ts = stktable_lookup_key(rule->table.t, key)) != NULL) {
Emeric Brun1d33b292010-01-04 15:47:17 +01001297 if (!(s->flags & SN_ASSIGNED)) {
1298 struct eb32_node *node;
Willy Tarreau13c29de2010-06-06 16:40:39 +02001299 void *ptr;
Emeric Brun1d33b292010-01-04 15:47:17 +01001300
1301 /* srv found in table */
Willy Tarreau13c29de2010-06-06 16:40:39 +02001302 ptr = stktable_data_ptr(rule->table.t, ts, STKTABLE_DT_SERVER_ID);
1303 node = eb32_lookup(&px->conf.used_server_id, stktable_data_cast(ptr, server_id));
Emeric Brun1d33b292010-01-04 15:47:17 +01001304 if (node) {
1305 struct server *srv;
1306
1307 srv = container_of(node, struct server, conf.id);
Willy Tarreau4de91492010-01-22 19:10:05 +01001308 if ((srv->state & SRV_RUNNING) ||
1309 (px->options & PR_O_PERSIST) ||
1310 (s->flags & SN_FORCE_PRST)) {
Emeric Brun1d33b292010-01-04 15:47:17 +01001311 s->flags |= SN_DIRECT | SN_ASSIGNED;
Willy Tarreau9e000c62011-03-10 14:03:36 +01001312 set_target_server(&s->target, srv);
Emeric Brun1d33b292010-01-04 15:47:17 +01001313 }
1314 }
1315 }
Emeric Brun85e77c72010-09-23 18:16:52 +02001316 stktable_touch(rule->table.t, ts, 1);
Emeric Brun1d33b292010-01-04 15:47:17 +01001317 }
1318 }
1319 if (rule->flags & STK_IS_STORE) {
1320 if (s->store_count < (sizeof(s->store) / sizeof(s->store[0]))) {
1321 struct stksess *ts;
1322
1323 ts = stksess_new(rule->table.t, key);
1324 if (ts) {
1325 s->store[s->store_count].table = rule->table.t;
1326 s->store[s->store_count++].ts = ts;
1327 }
1328 }
1329 }
1330 }
1331 }
1332
1333 req->analysers &= ~an_bit;
1334 req->analyse_exp = TICK_ETERNITY;
1335 return 1;
1336}
1337
1338/* This stream analyser works on a response. It applies all store rules on it
1339 * then returns 1. The data must already be present in the buffer otherwise
1340 * they won't match. It always returns 1.
1341 */
Willy Tarreau7421efb2012-07-02 15:11:27 +02001342static int process_store_rules(struct session *s, struct channel *rep, int an_bit)
Emeric Brun1d33b292010-01-04 15:47:17 +01001343{
1344 struct proxy *px = s->be;
1345 struct sticking_rule *rule;
1346 int i;
1347
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001348 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 +01001349 now_ms, __FUNCTION__,
1350 s,
Willy Tarreau2e2b3eb2010-02-09 20:55:44 +01001351 rep,
1352 rep->rex, rep->wex,
1353 rep->flags,
Cyril Bonté3aaba442012-09-23 14:19:12 +02001354 rep->buf.i,
Willy Tarreau2e2b3eb2010-02-09 20:55:44 +01001355 rep->analysers);
Emeric Brun1d33b292010-01-04 15:47:17 +01001356
1357 list_for_each_entry(rule, &px->storersp_rules, list) {
1358 int ret = 1 ;
1359 int storereqidx = -1;
1360
1361 for (i = 0; i < s->store_count; i++) {
1362 if (rule->table.t == s->store[i].table) {
1363 if (!(s->store[i].flags))
1364 storereqidx = i;
1365 break;
1366 }
1367 }
1368
1369 if ((i != s->store_count) && (storereqidx == -1))
1370 continue;
1371
1372 if (rule->cond) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001373 ret = acl_exec_cond(rule->cond, px, s, &s->txn, SMP_OPT_DIR_RES|SMP_OPT_FINAL);
Emeric Brun1d33b292010-01-04 15:47:17 +01001374 ret = acl_pass(ret);
1375 if (rule->cond->pol == ACL_COND_UNLESS)
1376 ret = !ret;
1377 }
1378
1379 if (ret) {
1380 struct stktable_key *key;
1381
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001382 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 +01001383 if (!key)
1384 continue;
1385
1386 if (storereqidx != -1) {
Willy Tarreau393379c2010-06-06 12:11:37 +02001387 stksess_setkey(s->store[storereqidx].table, s->store[storereqidx].ts, key);
Emeric Brun1d33b292010-01-04 15:47:17 +01001388 s->store[storereqidx].flags = 1;
1389 }
1390 else if (s->store_count < (sizeof(s->store) / sizeof(s->store[0]))) {
1391 struct stksess *ts;
1392
1393 ts = stksess_new(rule->table.t, key);
1394 if (ts) {
1395 s->store[s->store_count].table = rule->table.t;
1396 s->store[s->store_count].flags = 1;
1397 s->store[s->store_count++].ts = ts;
1398 }
1399 }
1400 }
1401 }
1402
1403 /* process store request and store response */
1404 for (i = 0; i < s->store_count; i++) {
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001405 struct stksess *ts;
Willy Tarreau13c29de2010-06-06 16:40:39 +02001406 void *ptr;
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001407
Simon Hormanfa461682011-06-25 09:39:49 +09001408 if (target_srv(&s->target) && target_srv(&s->target)->state & SRV_NON_STICK) {
1409 stksess_free(s->store[i].table, s->store[i].ts);
1410 s->store[i].ts = NULL;
1411 continue;
1412 }
1413
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001414 ts = stktable_lookup(s->store[i].table, s->store[i].ts);
1415 if (ts) {
1416 /* the entry already existed, we can free ours */
Emeric Brun85e77c72010-09-23 18:16:52 +02001417 stktable_touch(s->store[i].table, ts, 1);
Emeric Brun1d33b292010-01-04 15:47:17 +01001418 stksess_free(s->store[i].table, s->store[i].ts);
Emeric Brun1d33b292010-01-04 15:47:17 +01001419 }
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001420 else
Emeric Brun85e77c72010-09-23 18:16:52 +02001421 ts = stktable_store(s->store[i].table, s->store[i].ts, 1);
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001422
1423 s->store[i].ts = NULL;
Willy Tarreau13c29de2010-06-06 16:40:39 +02001424 ptr = stktable_data_ptr(s->store[i].table, ts, STKTABLE_DT_SERVER_ID);
Willy Tarreau827aee92011-03-10 16:55:02 +01001425 stktable_data_cast(ptr, server_id) = target_srv(&s->target)->puid;
Emeric Brun1d33b292010-01-04 15:47:17 +01001426 }
Willy Tarreau2a164ee2010-06-18 09:57:45 +02001427 s->store_count = 0; /* everything is stored */
Emeric Brun1d33b292010-01-04 15:47:17 +01001428
1429 rep->analysers &= ~an_bit;
1430 rep->analyse_exp = TICK_ETERNITY;
1431 return 1;
1432}
1433
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001434/* This macro is very specific to the function below. See the comments in
1435 * process_session() below to understand the logic and the tests.
1436 */
1437#define UPDATE_ANALYSERS(real, list, back, flag) { \
1438 list = (((list) & ~(flag)) | ~(back)) & (real); \
1439 back = real; \
1440 if (!(list)) \
1441 break; \
1442 if (((list) ^ ((list) & ((list) - 1))) < (flag)) \
1443 continue; \
1444}
1445
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001446/* Processes the client, server, request and response jobs of a session task,
1447 * then puts it back to the wait queue in a clean state, or cleans up its
1448 * resources if it must be deleted. Returns in <next> the date the task wants
1449 * to be woken up, or TICK_ETERNITY. In order not to call all functions for
1450 * nothing too many times, the request and response buffers flags are monitored
1451 * and each function is called only if at least another function has changed at
1452 * least one flag it is interested in.
1453 */
Willy Tarreau26c25062009-03-08 09:38:41 +01001454struct task *process_session(struct task *t)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001455{
Willy Tarreau827aee92011-03-10 16:55:02 +01001456 struct server *srv;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001457 struct session *s = t->context;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001458 unsigned int rqf_last, rpf_last;
Willy Tarreau815a9b22010-07-27 17:15:12 +02001459 unsigned int rq_prod_last, rq_cons_last;
1460 unsigned int rp_cons_last, rp_prod_last;
Willy Tarreau576507f2010-01-07 00:09:04 +01001461 unsigned int req_ana_back;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001462
1463 //DPRINTF(stderr, "%s:%d: cs=%d ss=%d(%d) rqf=0x%08x rpf=0x%08x\n", __FUNCTION__, __LINE__,
1464 // s->si[0].state, s->si[1].state, s->si[1].err_type, s->req->flags, s->rep->flags);
1465
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001466 /* this data may be no longer valid, clear it */
1467 memset(&s->txn.auth, 0, sizeof(s->txn.auth));
1468
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001469 /* This flag must explicitly be set every time */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001470 s->req->flags &= ~CF_READ_NOEXP;
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001471
1472 /* Keep a copy of req/rep flags so that we can detect shutdowns */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001473 rqf_last = s->req->flags & ~CF_MASK_ANALYSER;
1474 rpf_last = s->rep->flags & ~CF_MASK_ANALYSER;
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001475
Willy Tarreau89f7ef22009-09-05 20:57:35 +02001476 /* we don't want the stream interface functions to recursively wake us up */
1477 if (s->req->prod->owner == t)
1478 s->req->prod->flags |= SI_FL_DONT_WAKE;
1479 if (s->req->cons->owner == t)
1480 s->req->cons->flags |= SI_FL_DONT_WAKE;
1481
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001482 /* 1a: Check for low level timeouts if needed. We just set a flag on
1483 * stream interfaces when their timeouts have expired.
1484 */
1485 if (unlikely(t->state & TASK_WOKEN_TIMER)) {
1486 stream_int_check_timeouts(&s->si[0]);
1487 stream_int_check_timeouts(&s->si[1]);
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001488
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001489 /* check channel timeouts, and close the corresponding stream interfaces
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001490 * for future reads or writes. Note: this will also concern upper layers
1491 * but we do not touch any other flag. We must be careful and correctly
1492 * detect state changes when calling them.
1493 */
1494
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001495 channel_check_timeouts(s->req);
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001496
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001497 if (unlikely((s->req->flags & (CF_SHUTW|CF_WRITE_TIMEOUT)) == CF_WRITE_TIMEOUT)) {
Willy Tarreau14641402009-12-29 14:49:56 +01001498 s->req->cons->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001499 si_shutw(s->req->cons);
Willy Tarreau14641402009-12-29 14:49:56 +01001500 }
1501
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001502 if (unlikely((s->req->flags & (CF_SHUTR|CF_READ_TIMEOUT)) == CF_READ_TIMEOUT)) {
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02001503 if (s->req->prod->flags & SI_FL_NOHALF)
1504 s->req->prod->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001505 si_shutr(s->req->prod);
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02001506 }
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001507
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001508 channel_check_timeouts(s->rep);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001509
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001510 if (unlikely((s->rep->flags & (CF_SHUTW|CF_WRITE_TIMEOUT)) == CF_WRITE_TIMEOUT)) {
Willy Tarreau14641402009-12-29 14:49:56 +01001511 s->rep->cons->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001512 si_shutw(s->rep->cons);
Willy Tarreau14641402009-12-29 14:49:56 +01001513 }
1514
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001515 if (unlikely((s->rep->flags & (CF_SHUTR|CF_READ_TIMEOUT)) == CF_READ_TIMEOUT)) {
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02001516 if (s->rep->prod->flags & SI_FL_NOHALF)
1517 s->rep->prod->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001518 si_shutr(s->rep->prod);
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02001519 }
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001520 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001521
1522 /* 1b: check for low-level errors reported at the stream interface.
1523 * First we check if it's a retryable error (in which case we don't
1524 * want to tell the buffer). Otherwise we report the error one level
1525 * upper by setting flags into the buffers. Note that the side towards
1526 * the client cannot have connect (hence retryable) errors. Also, the
1527 * connection setup code must be able to deal with any type of abort.
1528 */
Willy Tarreau827aee92011-03-10 16:55:02 +01001529 srv = target_srv(&s->target);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001530 if (unlikely(s->si[0].flags & SI_FL_ERR)) {
1531 if (s->si[0].state == SI_ST_EST || s->si[0].state == SI_ST_DIS) {
Willy Tarreau73b013b2012-05-21 16:31:45 +02001532 si_shutr(&s->si[0]);
1533 si_shutw(&s->si[0]);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001534 stream_int_report_error(&s->si[0]);
Willy Tarreau05cb29b2008-12-14 11:44:04 +01001535 if (!(s->req->analysers) && !(s->rep->analysers)) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001536 s->be->be_counters.cli_aborts++;
1537 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001538 if (srv)
1539 srv->counters.cli_aborts++;
Willy Tarreau05cb29b2008-12-14 11:44:04 +01001540 if (!(s->flags & SN_ERR_MASK))
1541 s->flags |= SN_ERR_CLICL;
1542 if (!(s->flags & SN_FINST_MASK))
1543 s->flags |= SN_FINST_D;
1544 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001545 }
1546 }
1547
1548 if (unlikely(s->si[1].flags & SI_FL_ERR)) {
1549 if (s->si[1].state == SI_ST_EST || s->si[1].state == SI_ST_DIS) {
Willy Tarreau73b013b2012-05-21 16:31:45 +02001550 si_shutr(&s->si[1]);
1551 si_shutw(&s->si[1]);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001552 stream_int_report_error(&s->si[1]);
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001553 s->be->be_counters.failed_resp++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001554 if (srv)
1555 srv->counters.failed_resp++;
Willy Tarreau05cb29b2008-12-14 11:44:04 +01001556 if (!(s->req->analysers) && !(s->rep->analysers)) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001557 s->be->be_counters.srv_aborts++;
1558 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001559 if (srv)
1560 srv->counters.srv_aborts++;
Willy Tarreau05cb29b2008-12-14 11:44:04 +01001561 if (!(s->flags & SN_ERR_MASK))
1562 s->flags |= SN_ERR_SRVCL;
1563 if (!(s->flags & SN_FINST_MASK))
1564 s->flags |= SN_FINST_D;
1565 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001566 }
1567 /* note: maybe we should process connection errors here ? */
1568 }
1569
1570 if (s->si[1].state == SI_ST_CON) {
1571 /* we were trying to establish a connection on the server side,
1572 * maybe it succeeded, maybe it failed, maybe we timed out, ...
1573 */
1574 if (unlikely(!sess_update_st_con_tcp(s, &s->si[1])))
1575 sess_update_st_cer(s, &s->si[1]);
1576 else if (s->si[1].state == SI_ST_EST)
1577 sess_establish(s, &s->si[1]);
1578
1579 /* state is now one of SI_ST_CON (still in progress), SI_ST_EST
1580 * (established), SI_ST_DIS (abort), SI_ST_CLO (last error),
1581 * SI_ST_ASS/SI_ST_TAR/SI_ST_REQ for retryable errors.
1582 */
1583 }
1584
Willy Tarreau815a9b22010-07-27 17:15:12 +02001585 rq_prod_last = s->si[0].state;
1586 rq_cons_last = s->si[1].state;
1587 rp_cons_last = s->si[0].state;
1588 rp_prod_last = s->si[1].state;
1589
1590 resync_stream_interface:
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001591 /* Check for connection closure */
1592
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001593 DPRINTF(stderr,
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001594 "[%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 +01001595 now_ms, __FUNCTION__, __LINE__,
1596 t,
1597 s, s->flags,
1598 s->req, s->rep,
1599 s->req->rex, s->rep->wex,
1600 s->req->flags, s->rep->flags,
Cyril Bonté3aaba442012-09-23 14:19:12 +02001601 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 +01001602 s->rep->cons->err_type, s->req->cons->err_type,
Willy Tarreauee28de02010-06-01 09:51:00 +02001603 s->req->cons->conn_retries);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001604
1605 /* nothing special to be done on client side */
1606 if (unlikely(s->req->prod->state == SI_ST_DIS))
1607 s->req->prod->state = SI_ST_CLO;
1608
1609 /* When a server-side connection is released, we have to count it and
1610 * check for pending connections on this server.
1611 */
1612 if (unlikely(s->req->cons->state == SI_ST_DIS)) {
1613 s->req->cons->state = SI_ST_CLO;
Willy Tarreau827aee92011-03-10 16:55:02 +01001614 srv = target_srv(&s->target);
1615 if (srv) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001616 if (s->flags & SN_CURR_SESS) {
1617 s->flags &= ~SN_CURR_SESS;
Willy Tarreau827aee92011-03-10 16:55:02 +01001618 srv->cur_sess--;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001619 }
1620 sess_change_server(s, NULL);
Willy Tarreau827aee92011-03-10 16:55:02 +01001621 if (may_dequeue_tasks(srv, s->be))
1622 process_srv_queue(srv);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001623 }
1624 }
1625
1626 /*
1627 * Note: of the transient states (REQ, CER, DIS), only REQ may remain
1628 * at this point.
1629 */
1630
Willy Tarreau0be0ef92009-03-08 19:20:25 +01001631 resync_request:
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001632 /* Analyse request */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001633 if (((s->req->flags & ~rqf_last) & CF_MASK_ANALYSER) ||
1634 ((s->req->flags ^ rqf_last) & CF_MASK_STATIC) ||
Willy Tarreau815a9b22010-07-27 17:15:12 +02001635 s->si[0].state != rq_prod_last ||
1636 s->si[1].state != rq_cons_last) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001637 unsigned int flags = s->req->flags;
1638
1639 if (s->req->prod->state >= SI_ST_EST) {
Willy Tarreaue34070e2010-01-08 00:32:27 +01001640 int max_loops = global.tune.maxpollevents;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001641 unsigned int ana_list;
1642 unsigned int ana_back;
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001643
Willy Tarreau90deb182010-01-07 00:20:41 +01001644 /* it's up to the analysers to stop new connections,
1645 * disable reading or closing. Note: if an analyser
1646 * disables any of these bits, it is responsible for
1647 * enabling them again when it disables itself, so
1648 * that other analysers are called in similar conditions.
1649 */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001650 channel_auto_read(s->req);
1651 channel_auto_connect(s->req);
1652 channel_auto_close(s->req);
Willy Tarreauedcf6682008-11-30 23:15:34 +01001653
1654 /* We will call all analysers for which a bit is set in
1655 * s->req->analysers, following the bit order from LSB
1656 * to MSB. The analysers must remove themselves from
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001657 * the list when not needed. Any analyser may return 0
1658 * to break out of the loop, either because of missing
1659 * data to take a decision, or because it decides to
1660 * kill the session. We loop at least once through each
1661 * analyser, and we may loop again if other analysers
1662 * are added in the middle.
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001663 *
1664 * We build a list of analysers to run. We evaluate all
1665 * of these analysers in the order of the lower bit to
1666 * the higher bit. This ordering is very important.
1667 * An analyser will often add/remove other analysers,
1668 * including itself. Any changes to itself have no effect
1669 * on the loop. If it removes any other analysers, we
1670 * want those analysers not to be called anymore during
1671 * this loop. If it adds an analyser that is located
1672 * after itself, we want it to be scheduled for being
1673 * processed during the loop. If it adds an analyser
1674 * which is located before it, we want it to switch to
1675 * it immediately, even if it has already been called
1676 * once but removed since.
1677 *
1678 * In order to achieve this, we compare the analyser
1679 * list after the call with a copy of it before the
1680 * call. The work list is fed with analyser bits that
1681 * appeared during the call. Then we compare previous
1682 * work list with the new one, and check the bits that
1683 * appeared. If the lowest of these bits is lower than
1684 * the current bit, it means we have enabled a previous
1685 * analyser and must immediately loop again.
Willy Tarreauedcf6682008-11-30 23:15:34 +01001686 */
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001687
1688 ana_list = ana_back = s->req->analysers;
Willy Tarreaue34070e2010-01-08 00:32:27 +01001689 while (ana_list && max_loops--) {
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001690 /* Warning! ensure that analysers are always placed in ascending order! */
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001691
Willy Tarreaufb356202010-08-03 14:02:05 +02001692 if (ana_list & AN_REQ_INSPECT_FE) {
1693 if (!tcp_inspect_request(s, s->req, AN_REQ_INSPECT_FE))
Willy Tarreauedcf6682008-11-30 23:15:34 +01001694 break;
Willy Tarreaufb356202010-08-03 14:02:05 +02001695 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_INSPECT_FE);
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001696 }
Willy Tarreauedcf6682008-11-30 23:15:34 +01001697
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001698 if (ana_list & AN_REQ_WAIT_HTTP) {
Willy Tarreau3a816292009-07-07 10:55:49 +02001699 if (!http_wait_for_request(s, s->req, AN_REQ_WAIT_HTTP))
Willy Tarreaud787e662009-07-07 10:14:51 +02001700 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001701 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_WAIT_HTTP);
Willy Tarreaud787e662009-07-07 10:14:51 +02001702 }
1703
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001704 if (ana_list & AN_REQ_HTTP_PROCESS_FE) {
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001705 if (!http_process_req_common(s, s->req, AN_REQ_HTTP_PROCESS_FE, s->fe))
1706 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001707 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_PROCESS_FE);
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001708 }
1709
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001710 if (ana_list & AN_REQ_SWITCHING_RULES) {
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001711 if (!process_switching_rules(s, s->req, AN_REQ_SWITCHING_RULES))
1712 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001713 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_SWITCHING_RULES);
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001714 }
1715
Willy Tarreaufb356202010-08-03 14:02:05 +02001716 if (ana_list & AN_REQ_INSPECT_BE) {
1717 if (!tcp_inspect_request(s, s->req, AN_REQ_INSPECT_BE))
1718 break;
1719 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_INSPECT_BE);
1720 }
1721
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001722 if (ana_list & AN_REQ_HTTP_PROCESS_BE) {
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001723 if (!http_process_req_common(s, s->req, AN_REQ_HTTP_PROCESS_BE, s->be))
1724 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001725 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_PROCESS_BE);
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001726 }
1727
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001728 if (ana_list & AN_REQ_HTTP_TARPIT) {
Willy Tarreau3a816292009-07-07 10:55:49 +02001729 if (!http_process_tarpit(s, s->req, AN_REQ_HTTP_TARPIT))
Willy Tarreau60b85b02008-11-30 23:28:40 +01001730 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001731 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_TARPIT);
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001732 }
Willy Tarreau60b85b02008-11-30 23:28:40 +01001733
Willy Tarreau4a5cade2012-04-05 21:09:48 +02001734 if (ana_list & AN_REQ_SRV_RULES) {
1735 if (!process_server_rules(s, s->req, AN_REQ_SRV_RULES))
1736 break;
1737 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_SRV_RULES);
1738 }
1739
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001740 if (ana_list & AN_REQ_HTTP_INNER) {
Willy Tarreauc465fd72009-08-31 00:17:18 +02001741 if (!http_process_request(s, s->req, AN_REQ_HTTP_INNER))
1742 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001743 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_INNER);
Willy Tarreauc465fd72009-08-31 00:17:18 +02001744 }
1745
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001746 if (ana_list & AN_REQ_HTTP_BODY) {
Willy Tarreau3a816292009-07-07 10:55:49 +02001747 if (!http_process_request_body(s, s->req, AN_REQ_HTTP_BODY))
Willy Tarreaud34af782008-11-30 23:36:37 +01001748 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001749 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_BODY);
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001750 }
Emeric Brun647caf12009-06-30 17:57:00 +02001751
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001752 if (ana_list & AN_REQ_PRST_RDP_COOKIE) {
Emeric Brun647caf12009-06-30 17:57:00 +02001753 if (!tcp_persist_rdp_cookie(s, s->req, AN_REQ_PRST_RDP_COOKIE))
1754 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001755 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_PRST_RDP_COOKIE);
Emeric Brun647caf12009-06-30 17:57:00 +02001756 }
Willy Tarreaud98cf932009-12-27 22:54:55 +01001757
Emeric Brun1d33b292010-01-04 15:47:17 +01001758 if (ana_list & AN_REQ_STICKING_RULES) {
1759 if (!process_sticking_rules(s, s->req, AN_REQ_STICKING_RULES))
1760 break;
1761 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_STICKING_RULES);
1762 }
1763
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001764 if (ana_list & AN_REQ_HTTP_XFER_BODY) {
Willy Tarreaud98cf932009-12-27 22:54:55 +01001765 if (!http_request_forward_body(s, s->req, AN_REQ_HTTP_XFER_BODY))
1766 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001767 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_XFER_BODY);
Willy Tarreaud98cf932009-12-27 22:54:55 +01001768 }
Willy Tarreaue34070e2010-01-08 00:32:27 +01001769 break;
1770 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001771 }
Willy Tarreau84455332009-03-15 22:34:05 +01001772
Willy Tarreau815a9b22010-07-27 17:15:12 +02001773 rq_prod_last = s->si[0].state;
1774 rq_cons_last = s->si[1].state;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001775 s->req->flags &= ~CF_WAKE_ONCE;
Willy Tarreau815a9b22010-07-27 17:15:12 +02001776 rqf_last = s->req->flags;
1777
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001778 if ((s->req->flags ^ flags) & CF_MASK_STATIC)
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001779 goto resync_request;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001780 }
1781
Willy Tarreau576507f2010-01-07 00:09:04 +01001782 /* we'll monitor the request analysers while parsing the response,
1783 * because some response analysers may indirectly enable new request
1784 * analysers (eg: HTTP keep-alive).
1785 */
1786 req_ana_back = s->req->analysers;
1787
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001788 resync_response:
1789 /* Analyse response */
1790
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001791 if (unlikely(s->rep->flags & CF_HIJACK)) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001792 /* In inject mode, we wake up everytime something has
1793 * happened on the write side of the buffer.
1794 */
1795 unsigned int flags = s->rep->flags;
1796
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001797 if ((s->rep->flags & (CF_WRITE_PARTIAL|CF_WRITE_ERROR|CF_SHUTW)) &&
Willy Tarreau3bf1b2b2012-08-27 20:46:07 +02001798 !channel_full(s->rep)) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001799 s->rep->hijacker(s, s->rep);
1800 }
1801
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001802 if ((s->rep->flags ^ flags) & CF_MASK_STATIC) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001803 rpf_last = s->rep->flags;
1804 goto resync_response;
1805 }
1806 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001807 else if (((s->rep->flags & ~rpf_last) & CF_MASK_ANALYSER) ||
1808 (s->rep->flags ^ rpf_last) & CF_MASK_STATIC ||
Willy Tarreau815a9b22010-07-27 17:15:12 +02001809 s->si[0].state != rp_cons_last ||
1810 s->si[1].state != rp_prod_last) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001811 unsigned int flags = s->rep->flags;
1812
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001813 if ((s->rep->flags & CF_MASK_ANALYSER) &&
Willy Tarreau0499e352010-12-17 07:13:42 +01001814 (s->rep->analysers & AN_REQ_WAIT_HTTP)) {
1815 /* Due to HTTP pipelining, the HTTP request analyser might be waiting
1816 * for some free space in the response buffer, so we might need to call
1817 * it when something changes in the response buffer, but still we pass
1818 * it the request buffer. Note that the SI state might very well still
1819 * be zero due to us returning a flow of redirects!
1820 */
1821 s->rep->analysers &= ~AN_REQ_WAIT_HTTP;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001822 s->req->flags |= CF_WAKE_ONCE;
Willy Tarreau0499e352010-12-17 07:13:42 +01001823 }
1824
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001825 if (s->rep->prod->state >= SI_ST_EST) {
Willy Tarreaue34070e2010-01-08 00:32:27 +01001826 int max_loops = global.tune.maxpollevents;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001827 unsigned int ana_list;
1828 unsigned int ana_back;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001829
Willy Tarreau90deb182010-01-07 00:20:41 +01001830 /* it's up to the analysers to stop disable reading or
1831 * closing. Note: if an analyser disables any of these
1832 * bits, it is responsible for enabling them again when
1833 * it disables itself, so that other analysers are called
1834 * in similar conditions.
1835 */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001836 channel_auto_read(s->rep);
1837 channel_auto_close(s->rep);
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001838
1839 /* We will call all analysers for which a bit is set in
1840 * s->rep->analysers, following the bit order from LSB
1841 * to MSB. The analysers must remove themselves from
1842 * the list when not needed. Any analyser may return 0
1843 * to break out of the loop, either because of missing
1844 * data to take a decision, or because it decides to
1845 * kill the session. We loop at least once through each
1846 * analyser, and we may loop again if other analysers
1847 * are added in the middle.
1848 */
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001849
1850 ana_list = ana_back = s->rep->analysers;
Willy Tarreaue34070e2010-01-08 00:32:27 +01001851 while (ana_list && max_loops--) {
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001852 /* Warning! ensure that analysers are always placed in ascending order! */
1853
Emeric Brun97679e72010-09-23 17:56:44 +02001854 if (ana_list & AN_RES_INSPECT) {
1855 if (!tcp_inspect_response(s, s->rep, AN_RES_INSPECT))
1856 break;
1857 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_INSPECT);
1858 }
1859
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001860 if (ana_list & AN_RES_WAIT_HTTP) {
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001861 if (!http_wait_for_response(s, s->rep, AN_RES_WAIT_HTTP))
1862 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001863 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_WAIT_HTTP);
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001864 }
1865
Emeric Brun1d33b292010-01-04 15:47:17 +01001866 if (ana_list & AN_RES_STORE_RULES) {
1867 if (!process_store_rules(s, s->rep, AN_RES_STORE_RULES))
1868 break;
1869 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_STORE_RULES);
1870 }
1871
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001872 if (ana_list & AN_RES_HTTP_PROCESS_BE) {
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001873 if (!http_process_res_common(s, s->rep, AN_RES_HTTP_PROCESS_BE, s->be))
1874 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001875 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_HTTP_PROCESS_BE);
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001876 }
Willy Tarreaud98cf932009-12-27 22:54:55 +01001877
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001878 if (ana_list & AN_RES_HTTP_XFER_BODY) {
Willy Tarreaud98cf932009-12-27 22:54:55 +01001879 if (!http_response_forward_body(s, s->rep, AN_RES_HTTP_XFER_BODY))
1880 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001881 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_HTTP_XFER_BODY);
Willy Tarreaud98cf932009-12-27 22:54:55 +01001882 }
Willy Tarreaue34070e2010-01-08 00:32:27 +01001883 break;
1884 }
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001885 }
1886
Willy Tarreau815a9b22010-07-27 17:15:12 +02001887 rp_cons_last = s->si[0].state;
1888 rp_prod_last = s->si[1].state;
1889 rpf_last = s->rep->flags;
1890
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001891 if ((s->rep->flags ^ flags) & CF_MASK_STATIC)
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001892 goto resync_response;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001893 }
1894
Willy Tarreau576507f2010-01-07 00:09:04 +01001895 /* maybe someone has added some request analysers, so we must check and loop */
1896 if (s->req->analysers & ~req_ana_back)
1897 goto resync_request;
1898
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001899 if ((s->req->flags & ~rqf_last) & CF_MASK_ANALYSER)
Willy Tarreau0499e352010-12-17 07:13:42 +01001900 goto resync_request;
1901
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001902 /* FIXME: here we should call protocol handlers which rely on
1903 * both buffers.
1904 */
1905
1906
1907 /*
Willy Tarreauae526782010-03-04 20:34:23 +01001908 * Now we propagate unhandled errors to the session. Normally
1909 * we're just in a data phase here since it means we have not
1910 * seen any analyser who could set an error status.
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001911 */
Willy Tarreau827aee92011-03-10 16:55:02 +01001912 srv = target_srv(&s->target);
Willy Tarreau2f976e12010-11-11 14:28:47 +01001913 if (unlikely(!(s->flags & SN_ERR_MASK))) {
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001914 if (s->req->flags & (CF_READ_ERROR|CF_READ_TIMEOUT|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001915 /* Report it if the client got an error or a read timeout expired */
Willy Tarreau84455332009-03-15 22:34:05 +01001916 s->req->analysers = 0;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001917 if (s->req->flags & CF_READ_ERROR) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001918 s->be->be_counters.cli_aborts++;
1919 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001920 if (srv)
1921 srv->counters.cli_aborts++;
Willy Tarreau84455332009-03-15 22:34:05 +01001922 s->flags |= SN_ERR_CLICL;
Willy Tarreauae526782010-03-04 20:34:23 +01001923 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001924 else if (s->req->flags & CF_READ_TIMEOUT) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001925 s->be->be_counters.cli_aborts++;
1926 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001927 if (srv)
1928 srv->counters.cli_aborts++;
Willy Tarreau84455332009-03-15 22:34:05 +01001929 s->flags |= SN_ERR_CLITO;
Willy Tarreauae526782010-03-04 20:34:23 +01001930 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001931 else if (s->req->flags & CF_WRITE_ERROR) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001932 s->be->be_counters.srv_aborts++;
1933 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001934 if (srv)
1935 srv->counters.srv_aborts++;
Willy Tarreau84455332009-03-15 22:34:05 +01001936 s->flags |= SN_ERR_SRVCL;
Willy Tarreauae526782010-03-04 20:34:23 +01001937 }
1938 else {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001939 s->be->be_counters.srv_aborts++;
1940 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001941 if (srv)
1942 srv->counters.srv_aborts++;
Willy Tarreau84455332009-03-15 22:34:05 +01001943 s->flags |= SN_ERR_SRVTO;
Willy Tarreauae526782010-03-04 20:34:23 +01001944 }
Willy Tarreau84455332009-03-15 22:34:05 +01001945 sess_set_term_flags(s);
1946 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001947 else if (s->rep->flags & (CF_READ_ERROR|CF_READ_TIMEOUT|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001948 /* Report it if the server got an error or a read timeout expired */
1949 s->rep->analysers = 0;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001950 if (s->rep->flags & CF_READ_ERROR) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001951 s->be->be_counters.srv_aborts++;
1952 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001953 if (srv)
1954 srv->counters.srv_aborts++;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001955 s->flags |= SN_ERR_SRVCL;
Willy Tarreauae526782010-03-04 20:34:23 +01001956 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001957 else if (s->rep->flags & CF_READ_TIMEOUT) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001958 s->be->be_counters.srv_aborts++;
1959 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001960 if (srv)
1961 srv->counters.srv_aborts++;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001962 s->flags |= SN_ERR_SRVTO;
Willy Tarreauae526782010-03-04 20:34:23 +01001963 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001964 else if (s->rep->flags & CF_WRITE_ERROR) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001965 s->be->be_counters.cli_aborts++;
1966 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001967 if (srv)
1968 srv->counters.cli_aborts++;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001969 s->flags |= SN_ERR_CLICL;
Willy Tarreauae526782010-03-04 20:34:23 +01001970 }
1971 else {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001972 s->be->be_counters.cli_aborts++;
1973 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001974 if (srv)
1975 srv->counters.cli_aborts++;
Willy Tarreauae526782010-03-04 20:34:23 +01001976 s->flags |= SN_ERR_CLITO;
1977 }
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001978 sess_set_term_flags(s);
1979 }
Willy Tarreau84455332009-03-15 22:34:05 +01001980 }
1981
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001982 /*
1983 * Here we take care of forwarding unhandled data. This also includes
1984 * connection establishments and shutdown requests.
1985 */
1986
1987
Willy Tarreau7c84bab2009-03-08 21:38:23 +01001988 /* If noone is interested in analysing data, it's time to forward
Willy Tarreau31971e52009-09-20 12:07:52 +02001989 * everything. We configure the buffer to forward indefinitely.
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001990 * Note that we're checking CF_SHUTR_NOW as an indication of a possible
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001991 * recent call to channel_abort().
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01001992 */
Willy Tarreau7c84bab2009-03-08 21:38:23 +01001993 if (!s->req->analysers &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001994 !(s->req->flags & (CF_HIJACK|CF_SHUTW|CF_SHUTR_NOW)) &&
Willy Tarreau31971e52009-09-20 12:07:52 +02001995 (s->req->prod->state >= SI_ST_EST) &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001996 (s->req->to_forward != CHN_INFINITE_FORWARD)) {
Willy Tarreau7c84bab2009-03-08 21:38:23 +01001997 /* This buffer is freewheeling, there's no analyser nor hijacker
1998 * attached to it. If any data are left in, we'll permit them to
1999 * move.
2000 */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002001 channel_auto_read(s->req);
2002 channel_auto_connect(s->req);
2003 channel_auto_close(s->req);
Willy Tarreaua75bcef2012-08-24 22:56:11 +02002004 buffer_flush(&s->req->buf);
Willy Tarreau5bd8c372009-01-19 00:32:22 +01002005
Willy Tarreauda4d9fe2010-11-07 20:26:56 +01002006 /* We'll let data flow between the producer (if still connected)
2007 * to the consumer (which might possibly not be connected yet).
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002008 */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002009 if (!(s->req->flags & (CF_SHUTR|CF_SHUTW_NOW)))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002010 channel_forward(s->req, CHN_INFINITE_FORWARD);
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01002011 }
Willy Tarreauf890dc92008-12-13 21:12:26 +01002012
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002013 /* check if it is wise to enable kernel splicing to forward request data */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002014 if (!(s->req->flags & (CF_KERN_SPLICING|CF_SHUTR)) &&
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002015 s->req->to_forward &&
2016 (global.tune.options & GTUNE_USE_SPLICE) &&
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002017 (s->si[0].conn.xprt && s->si[0].conn.xprt->rcv_pipe && s->si[0].conn.xprt->snd_pipe) &&
2018 (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 +01002019 (pipes_used < global.maxpipes) &&
2020 (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_REQ) ||
2021 (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_AUT) &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002022 (s->req->flags & CF_STREAMER_FAST)))) {
2023 s->req->flags |= CF_KERN_SPLICING;
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002024 }
2025
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002026 /* reflect what the L7 analysers have seen last */
2027 rqf_last = s->req->flags;
2028
2029 /*
2030 * Now forward all shutdown requests between both sides of the buffer
2031 */
2032
Willy Tarreau520d95e2009-09-19 21:04:57 +02002033 /* first, let's check if the request buffer needs to shutdown(write), which may
2034 * happen either because the input is closed or because we want to force a close
Willy Tarreaue4599762010-03-21 23:25:09 +01002035 * once the server has begun to respond.
Willy Tarreau520d95e2009-09-19 21:04:57 +02002036 */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002037 if (unlikely((s->req->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_HIJACK|CF_AUTO_CLOSE|CF_SHUTR)) ==
2038 (CF_AUTO_CLOSE|CF_SHUTR)))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002039 channel_shutw_now(s->req);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002040
2041 /* shutdown(write) pending */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002042 if (unlikely((s->req->flags & (CF_SHUTW|CF_SHUTW_NOW)) == CF_SHUTW_NOW &&
Willy Tarreau8e21bb92012-08-24 22:40:29 +02002043 channel_is_empty(s->req)))
Willy Tarreau73b013b2012-05-21 16:31:45 +02002044 si_shutw(s->req->cons);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002045
2046 /* shutdown(write) done on server side, we must stop the client too */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002047 if (unlikely((s->req->flags & (CF_SHUTW|CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTW &&
Willy Tarreau3dbc6942008-12-07 13:05:04 +01002048 !s->req->analysers))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002049 channel_shutr_now(s->req);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002050
2051 /* shutdown(read) pending */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002052 if (unlikely((s->req->flags & (CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTR_NOW)) {
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02002053 if (s->req->prod->flags & SI_FL_NOHALF)
2054 s->req->prod->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02002055 si_shutr(s->req->prod);
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02002056 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002057
Willy Tarreau520d95e2009-09-19 21:04:57 +02002058 /* it's possible that an upper layer has requested a connection setup or abort.
2059 * There are 2 situations where we decide to establish a new connection :
2060 * - there are data scheduled for emission in the buffer
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002061 * - the CF_AUTO_CONNECT flag is set (active connection)
Willy Tarreau520d95e2009-09-19 21:04:57 +02002062 */
2063 if (s->req->cons->state == SI_ST_INI) {
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002064 if (!(s->req->flags & CF_SHUTW)) {
2065 if ((s->req->flags & CF_AUTO_CONNECT) || !channel_is_empty(s->req)) {
Willy Tarreaub24281b2011-02-13 13:16:36 +01002066 /* If we have an applet without a connect method, we immediately
Willy Tarreau85e7d002010-05-31 11:57:51 +02002067 * switch to the connected state, otherwise we perform a connection
2068 * request.
Willy Tarreau520d95e2009-09-19 21:04:57 +02002069 */
Willy Tarreau85e7d002010-05-31 11:57:51 +02002070 s->req->cons->state = SI_ST_REQ; /* new connection requested */
Willy Tarreau070ceb62010-06-01 10:36:43 +02002071 s->req->cons->conn_retries = s->be->conn_retries;
Willy Tarreau3cefd522012-08-30 15:49:18 +02002072 if (unlikely(s->req->cons->conn.target.type == TARG_TYPE_APPLET &&
Willy Tarreau73b013b2012-05-21 16:31:45 +02002073 !(si_ctrl(s->req->cons) && si_ctrl(s->req->cons)->connect))) {
Willy Tarreau520d95e2009-09-19 21:04:57 +02002074 s->req->cons->state = SI_ST_EST; /* connection established */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002075 s->rep->flags |= CF_READ_ATTACHED; /* producer is now attached */
Willy Tarreau85e7d002010-05-31 11:57:51 +02002076 s->req->wex = TICK_ETERNITY;
2077 }
Willy Tarreau520d95e2009-09-19 21:04:57 +02002078 }
Willy Tarreau73201222009-08-16 18:27:24 +02002079 }
Willy Tarreauf41ffdc2009-09-20 08:19:25 +02002080 else {
Willy Tarreau92795622009-03-06 12:51:23 +01002081 s->req->cons->state = SI_ST_CLO; /* shutw+ini = abort */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002082 channel_shutw_now(s->req); /* fix buffer flags upon abort */
2083 channel_shutr_now(s->rep);
Willy Tarreauf41ffdc2009-09-20 08:19:25 +02002084 }
Willy Tarreau92795622009-03-06 12:51:23 +01002085 }
2086
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002087
2088 /* we may have a pending connection request, or a connection waiting
2089 * for completion.
2090 */
2091 if (s->si[1].state >= SI_ST_REQ && s->si[1].state < SI_ST_CON) {
2092 do {
2093 /* nb: step 1 might switch from QUE to ASS, but we first want
2094 * to give a chance to step 2 to perform a redirect if needed.
2095 */
2096 if (s->si[1].state != SI_ST_REQ)
2097 sess_update_stream_int(s, &s->si[1]);
2098 if (s->si[1].state == SI_ST_REQ)
2099 sess_prepare_conn_req(s, &s->si[1]);
2100
Willy Tarreau827aee92011-03-10 16:55:02 +01002101 srv = target_srv(&s->target);
2102 if (s->si[1].state == SI_ST_ASS && srv && srv->rdr_len && (s->flags & SN_REDIRECTABLE))
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002103 perform_http_redirect(s, &s->si[1]);
2104 } while (s->si[1].state == SI_ST_ASS);
Mark Lamourinec2247f02012-01-04 13:02:01 -05002105
2106 /* Now we can add the server name to a header (if requested) */
2107 /* check for HTTP mode and proxy server_name_hdr_name != NULL */
Stathis Voukelatos09a030a2012-01-09 14:27:13 +01002108 if ((s->flags & SN_BE_ASSIGNED) &&
Willy Tarreau45c0d982012-03-09 12:11:57 +01002109 (s->be->mode == PR_MODE_HTTP) &&
2110 (s->be->server_id_hdr_name != NULL)) {
2111 http_send_name_header(&s->txn, s->be, target_srv(&s->target)->id);
Mark Lamourinec2247f02012-01-04 13:02:01 -05002112 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002113 }
2114
Willy Tarreau3deb3d02009-06-21 22:43:05 +02002115 /* Benchmarks have shown that it's optimal to do a full resync now */
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002116 if (s->req->prod->state == SI_ST_DIS || s->req->cons->state == SI_ST_DIS)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002117 goto resync_stream_interface;
2118
Willy Tarreau815a9b22010-07-27 17:15:12 +02002119 /* otherwise we want to check if we need to resync the req buffer or not */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002120 if ((s->req->flags ^ rqf_last) & CF_MASK_STATIC)
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002121 goto resync_request;
2122
Willy Tarreau3deb3d02009-06-21 22:43:05 +02002123 /* perform output updates to the response buffer */
Willy Tarreau84455332009-03-15 22:34:05 +01002124
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002125 /* If noone is interested in analysing data, it's time to forward
Willy Tarreau31971e52009-09-20 12:07:52 +02002126 * everything. We configure the buffer to forward indefinitely.
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002127 * Note that we're checking CF_SHUTR_NOW as an indication of a possible
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002128 * recent call to channel_abort().
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01002129 */
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002130 if (!s->rep->analysers &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002131 !(s->rep->flags & (CF_HIJACK|CF_SHUTW|CF_SHUTR_NOW)) &&
Willy Tarreau31971e52009-09-20 12:07:52 +02002132 (s->rep->prod->state >= SI_ST_EST) &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002133 (s->rep->to_forward != CHN_INFINITE_FORWARD)) {
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002134 /* This buffer is freewheeling, there's no analyser nor hijacker
2135 * attached to it. If any data are left in, we'll permit them to
2136 * move.
2137 */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002138 channel_auto_read(s->rep);
2139 channel_auto_close(s->rep);
Willy Tarreaua75bcef2012-08-24 22:56:11 +02002140 buffer_flush(&s->rep->buf);
Willy Tarreauda4d9fe2010-11-07 20:26:56 +01002141
2142 /* We'll let data flow between the producer (if still connected)
2143 * to the consumer.
2144 */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002145 if (!(s->rep->flags & (CF_SHUTR|CF_SHUTW_NOW)))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002146 channel_forward(s->rep, CHN_INFINITE_FORWARD);
Willy Tarreauce887fd2012-05-12 12:50:00 +02002147
2148 /* if we have no analyser anymore in any direction and have a
2149 * tunnel timeout set, use it now.
2150 */
2151 if (!s->req->analysers && s->be->timeout.tunnel) {
2152 s->req->rto = s->req->wto = s->rep->rto = s->rep->wto =
2153 s->be->timeout.tunnel;
2154 s->req->rex = s->req->wex = s->rep->rex = s->rep->wex =
2155 tick_add(now_ms, s->be->timeout.tunnel);
2156 }
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01002157 }
Willy Tarreauf890dc92008-12-13 21:12:26 +01002158
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002159 /* check if it is wise to enable kernel splicing to forward response data */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002160 if (!(s->rep->flags & (CF_KERN_SPLICING|CF_SHUTR)) &&
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002161 s->rep->to_forward &&
2162 (global.tune.options & GTUNE_USE_SPLICE) &&
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002163 (s->si[0].conn.xprt && s->si[0].conn.xprt->rcv_pipe && s->si[0].conn.xprt->snd_pipe) &&
2164 (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 +01002165 (pipes_used < global.maxpipes) &&
2166 (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_RTR) ||
2167 (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_AUT) &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002168 (s->rep->flags & CF_STREAMER_FAST)))) {
2169 s->rep->flags |= CF_KERN_SPLICING;
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002170 }
2171
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002172 /* reflect what the L7 analysers have seen last */
2173 rpf_last = s->rep->flags;
2174
2175 /*
2176 * Now forward all shutdown requests between both sides of the buffer
2177 */
2178
2179 /*
2180 * FIXME: this is probably where we should produce error responses.
2181 */
2182
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01002183 /* first, let's check if the response buffer needs to shutdown(write) */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002184 if (unlikely((s->rep->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_HIJACK|CF_AUTO_CLOSE|CF_SHUTR)) ==
2185 (CF_AUTO_CLOSE|CF_SHUTR)))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002186 channel_shutw_now(s->rep);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002187
2188 /* shutdown(write) pending */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002189 if (unlikely((s->rep->flags & (CF_SHUTW|CF_SHUTW_NOW)) == CF_SHUTW_NOW &&
Willy Tarreau8e21bb92012-08-24 22:40:29 +02002190 channel_is_empty(s->rep)))
Willy Tarreau73b013b2012-05-21 16:31:45 +02002191 si_shutw(s->rep->cons);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002192
2193 /* shutdown(write) done on the client side, we must stop the server too */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002194 if (unlikely((s->rep->flags & (CF_SHUTW|CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTW) &&
Willy Tarreau3dbc6942008-12-07 13:05:04 +01002195 !s->rep->analysers)
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002196 channel_shutr_now(s->rep);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002197
2198 /* shutdown(read) pending */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002199 if (unlikely((s->rep->flags & (CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTR_NOW)) {
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02002200 if (s->rep->prod->flags & SI_FL_NOHALF)
2201 s->rep->prod->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02002202 si_shutr(s->rep->prod);
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02002203 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002204
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002205 if (s->req->prod->state == SI_ST_DIS || s->req->cons->state == SI_ST_DIS)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002206 goto resync_stream_interface;
2207
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002208 if (s->req->flags != rqf_last)
2209 goto resync_request;
2210
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002211 if ((s->rep->flags ^ rpf_last) & CF_MASK_STATIC)
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002212 goto resync_response;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002213
Willy Tarreau89f7ef22009-09-05 20:57:35 +02002214 /* we're interested in getting wakeups again */
2215 s->req->prod->flags &= ~SI_FL_DONT_WAKE;
2216 s->req->cons->flags &= ~SI_FL_DONT_WAKE;
2217
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002218 /* This is needed only when debugging is enabled, to indicate
2219 * client-side or server-side close. Please note that in the unlikely
2220 * event where both sides would close at once, the sequence is reported
2221 * on the server side first.
2222 */
2223 if (unlikely((global.mode & MODE_DEBUG) &&
2224 (!(global.mode & MODE_QUIET) ||
2225 (global.mode & MODE_VERBOSE)))) {
2226 int len;
2227
2228 if (s->si[1].state == SI_ST_CLO &&
2229 s->si[1].prev_state == SI_ST_EST) {
2230 len = sprintf(trash, "%08x:%s.srvcls[%04x:%04x]\n",
2231 s->uniq_id, s->be->id,
Willy Tarreaufb7508a2012-05-21 16:47:54 +02002232 (unsigned short)si_fd(&s->si[0]),
2233 (unsigned short)si_fd(&s->si[1]));
Willy Tarreau21337822012-04-29 14:11:38 +02002234 if (write(1, trash, len) < 0) /* shut gcc warning */;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002235 }
2236
2237 if (s->si[0].state == SI_ST_CLO &&
2238 s->si[0].prev_state == SI_ST_EST) {
2239 len = sprintf(trash, "%08x:%s.clicls[%04x:%04x]\n",
2240 s->uniq_id, s->be->id,
Willy Tarreaufb7508a2012-05-21 16:47:54 +02002241 (unsigned short)si_fd(&s->si[0]),
2242 (unsigned short)si_fd(&s->si[1]));
Willy Tarreau21337822012-04-29 14:11:38 +02002243 if (write(1, trash, len) < 0) /* shut gcc warning */;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002244 }
2245 }
2246
2247 if (likely((s->rep->cons->state != SI_ST_CLO) ||
2248 (s->req->cons->state > SI_ST_INI && s->req->cons->state < SI_ST_CLO))) {
2249
2250 if ((s->fe->options & PR_O_CONTSTATS) && (s->flags & SN_BE_ASSIGNED))
2251 session_process_counters(s);
2252
Willy Tarreau3cefd522012-08-30 15:49:18 +02002253 if (s->rep->cons->state == SI_ST_EST && s->rep->cons->conn.target.type != TARG_TYPE_APPLET)
Willy Tarreau73b013b2012-05-21 16:31:45 +02002254 si_update(s->rep->cons);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002255
Willy Tarreau3cefd522012-08-30 15:49:18 +02002256 if (s->req->cons->state == SI_ST_EST && s->req->cons->conn.target.type != TARG_TYPE_APPLET)
Willy Tarreau73b013b2012-05-21 16:31:45 +02002257 si_update(s->req->cons);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002258
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002259 s->req->flags &= ~(CF_READ_NULL|CF_READ_PARTIAL|CF_WRITE_NULL|CF_WRITE_PARTIAL|CF_READ_ATTACHED);
2260 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 +01002261 s->si[0].prev_state = s->si[0].state;
2262 s->si[1].prev_state = s->si[1].state;
Willy Tarreaub0ef7352008-12-14 13:26:20 +01002263 s->si[0].flags &= ~(SI_FL_ERR|SI_FL_EXP);
2264 s->si[1].flags &= ~(SI_FL_ERR|SI_FL_EXP);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002265
2266 /* Trick: if a request is being waiting for the server to respond,
2267 * and if we know the server can timeout, we don't want the timeout
2268 * to expire on the client side first, but we're still interested
2269 * in passing data from the client to the server (eg: POST). Thus,
2270 * we can cancel the client's request timeout if the server's
2271 * request timeout is set and the server has not yet sent a response.
2272 */
2273
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002274 if ((s->rep->flags & (CF_AUTO_CLOSE|CF_SHUTR)) == 0 &&
Willy Tarreau86491c32008-12-14 09:04:47 +01002275 (tick_isset(s->req->wex) || tick_isset(s->rep->rex))) {
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002276 s->req->flags |= CF_READ_NOEXP;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002277 s->req->rex = TICK_ETERNITY;
Willy Tarreau86491c32008-12-14 09:04:47 +01002278 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002279
Willy Tarreau7a20aa62010-07-13 16:30:45 +02002280 /* Call the stream interfaces' I/O handlers when embedded.
Willy Tarreau1accfc02009-09-05 20:57:35 +02002281 * Note that this one may wake the task up again.
2282 */
Willy Tarreau3cefd522012-08-30 15:49:18 +02002283 if (s->req->cons->conn.target.type == TARG_TYPE_APPLET ||
2284 s->rep->cons->conn.target.type == TARG_TYPE_APPLET) {
2285 if (s->req->cons->conn.target.type == TARG_TYPE_APPLET)
2286 s->req->cons->conn.target.ptr.a->fct(s->req->cons);
2287 if (s->rep->cons->conn.target.type == TARG_TYPE_APPLET)
2288 s->rep->cons->conn.target.ptr.a->fct(s->rep->cons);
Willy Tarreau1accfc02009-09-05 20:57:35 +02002289 if (task_in_rq(t)) {
2290 /* If we woke up, we don't want to requeue the
2291 * task to the wait queue, but rather requeue
2292 * it into the runqueue ASAP.
2293 */
2294 t->expire = TICK_ETERNITY;
2295 return t;
2296 }
2297 }
2298
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002299 t->expire = tick_first(tick_first(s->req->rex, s->req->wex),
2300 tick_first(s->rep->rex, s->rep->wex));
2301 if (s->req->analysers)
2302 t->expire = tick_first(t->expire, s->req->analyse_exp);
2303
2304 if (s->si[0].exp)
2305 t->expire = tick_first(t->expire, s->si[0].exp);
2306
2307 if (s->si[1].exp)
2308 t->expire = tick_first(t->expire, s->si[1].exp);
2309
2310#ifdef DEBUG_FULL
Willy Tarreau127334e2009-03-28 10:47:26 +01002311 fprintf(stderr,
2312 "[%u] queuing with exp=%u req->rex=%u req->wex=%u req->ana_exp=%u"
2313 " rep->rex=%u rep->wex=%u, si[0].exp=%u, si[1].exp=%u, cs=%d, ss=%d\n",
2314 now_ms, t->expire, s->req->rex, s->req->wex, s->req->analyse_exp,
2315 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 +01002316#endif
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002317
2318#ifdef DEBUG_DEV
2319 /* this may only happen when no timeout is set or in case of an FSM bug */
Willy Tarreaud0a201b2009-03-08 15:53:06 +01002320 if (!tick_isset(t->expire))
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002321 ABORT_NOW();
2322#endif
Willy Tarreau26c25062009-03-08 09:38:41 +01002323 return t; /* nothing more to do */
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002324 }
2325
2326 s->fe->feconn--;
2327 if (s->flags & SN_BE_ASSIGNED)
2328 s->be->beconn--;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02002329 if (!(s->listener->options & LI_O_UNLIMITED))
2330 actconn--;
Willy Tarreauaf7ad002010-08-31 15:39:26 +02002331 jobs--;
Willy Tarreau6e6fb2b2009-08-16 18:20:44 +02002332 s->listener->nbconn--;
Willy Tarreau62793712011-07-24 19:23:38 +02002333 if (s->listener->state == LI_FULL)
2334 resume_listener(s->listener);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002335
Willy Tarreau08ceb102011-07-24 22:58:00 +02002336 /* Dequeues all of the listeners waiting for a resource */
2337 if (!LIST_ISEMPTY(&global_listener_queue))
2338 dequeue_all_listeners(&global_listener_queue);
2339
Willy Tarreaub32907b2011-07-25 08:37:44 +02002340 if (!LIST_ISEMPTY(&s->fe->listener_queue) &&
2341 (!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 +02002342 dequeue_all_listeners(&s->fe->listener_queue);
2343
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002344 if (unlikely((global.mode & MODE_DEBUG) &&
2345 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)))) {
2346 int len;
Willy Tarreauec22b2c2009-03-06 13:07:40 +01002347 len = sprintf(trash, "%08x:%s.closed[%04x:%04x]\n",
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002348 s->uniq_id, s->be->id,
Willy Tarreaufb7508a2012-05-21 16:47:54 +02002349 (unsigned short)si_fd(s->req->prod), (unsigned short)si_fd(s->req->cons));
Willy Tarreau21337822012-04-29 14:11:38 +02002350 if (write(1, trash, len) < 0) /* shut gcc warning */;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002351 }
2352
2353 s->logs.t_close = tv_ms_elapsed(&s->logs.tv_accept, &now);
2354 session_process_counters(s);
2355
Krzysztof Piotr Oledzkide71d162009-10-24 15:36:15 +02002356 if (s->txn.status) {
2357 int n;
2358
2359 n = s->txn.status / 100;
2360 if (n < 1 || n > 5)
2361 n = 0;
2362
2363 if (s->fe->mode == PR_MODE_HTTP)
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01002364 s->fe->fe_counters.p.http.rsp[n]++;
Krzysztof Piotr Oledzkide71d162009-10-24 15:36:15 +02002365
Willy Tarreau24657792010-02-26 10:30:28 +01002366 if ((s->flags & SN_BE_ASSIGNED) &&
Krzysztof Piotr Oledzkide71d162009-10-24 15:36:15 +02002367 (s->be->mode == PR_MODE_HTTP))
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01002368 s->be->be_counters.p.http.rsp[n]++;
Krzysztof Piotr Oledzkide71d162009-10-24 15:36:15 +02002369 }
2370
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002371 /* let's do a final log if we need it */
2372 if (s->logs.logwait &&
2373 !(s->flags & SN_MONITOR) &&
2374 (!(s->fe->options & PR_O_NULLNOLOG) || s->req->total)) {
Willy Tarreaua5555ec2008-11-30 19:02:32 +01002375 s->do_log(s);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002376 }
2377
2378 /* the task MUST not be in the run queue anymore */
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002379 session_free(s);
Willy Tarreau26c25062009-03-08 09:38:41 +01002380 task_delete(t);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002381 task_free(t);
Willy Tarreau26c25062009-03-08 09:38:41 +01002382 return NULL;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002383}
2384
Willy Tarreau7c669d72008-06-20 15:04:11 +02002385/*
2386 * This function adjusts sess->srv_conn and maintains the previous and new
2387 * server's served session counts. Setting newsrv to NULL is enough to release
2388 * current connection slot. This function also notifies any LB algo which might
2389 * expect to be informed about any change in the number of active sessions on a
2390 * server.
2391 */
2392void sess_change_server(struct session *sess, struct server *newsrv)
2393{
2394 if (sess->srv_conn == newsrv)
2395 return;
2396
2397 if (sess->srv_conn) {
2398 sess->srv_conn->served--;
2399 if (sess->srv_conn->proxy->lbprm.server_drop_conn)
2400 sess->srv_conn->proxy->lbprm.server_drop_conn(sess->srv_conn);
Simon Hormanaf514952011-06-21 14:34:57 +09002401 session_del_srv_conn(sess);
Willy Tarreau7c669d72008-06-20 15:04:11 +02002402 }
2403
2404 if (newsrv) {
2405 newsrv->served++;
2406 if (newsrv->proxy->lbprm.server_take_conn)
2407 newsrv->proxy->lbprm.server_take_conn(newsrv);
Simon Hormanaf514952011-06-21 14:34:57 +09002408 session_add_srv_conn(sess, newsrv);
Willy Tarreau7c669d72008-06-20 15:04:11 +02002409 }
2410}
2411
Willy Tarreau84455332009-03-15 22:34:05 +01002412/* Handle server-side errors for default protocols. It is called whenever a a
2413 * connection setup is aborted or a request is aborted in queue. It sets the
2414 * session termination flags so that the caller does not have to worry about
2415 * them. It's installed as ->srv_error for the server-side stream_interface.
2416 */
2417void default_srv_error(struct session *s, struct stream_interface *si)
2418{
2419 int err_type = si->err_type;
2420 int err = 0, fin = 0;
2421
2422 if (err_type & SI_ET_QUEUE_ABRT) {
2423 err = SN_ERR_CLICL;
2424 fin = SN_FINST_Q;
2425 }
2426 else if (err_type & SI_ET_CONN_ABRT) {
2427 err = SN_ERR_CLICL;
2428 fin = SN_FINST_C;
2429 }
2430 else if (err_type & SI_ET_QUEUE_TO) {
2431 err = SN_ERR_SRVTO;
2432 fin = SN_FINST_Q;
2433 }
2434 else if (err_type & SI_ET_QUEUE_ERR) {
2435 err = SN_ERR_SRVCL;
2436 fin = SN_FINST_Q;
2437 }
2438 else if (err_type & SI_ET_CONN_TO) {
2439 err = SN_ERR_SRVTO;
2440 fin = SN_FINST_C;
2441 }
2442 else if (err_type & SI_ET_CONN_ERR) {
2443 err = SN_ERR_SRVCL;
2444 fin = SN_FINST_C;
2445 }
2446 else /* SI_ET_CONN_OTHER and others */ {
2447 err = SN_ERR_INTERNAL;
2448 fin = SN_FINST_C;
2449 }
2450
2451 if (!(s->flags & SN_ERR_MASK))
2452 s->flags |= err;
2453 if (!(s->flags & SN_FINST_MASK))
2454 s->flags |= fin;
2455}
Willy Tarreau7c669d72008-06-20 15:04:11 +02002456
Willy Tarreaua2a64e92011-09-07 23:01:56 +02002457/* kill a session and set the termination flags to <why> (one of SN_ERR_*) */
2458void session_shutdown(struct session *session, int why)
2459{
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002460 if (session->req->flags & (CF_SHUTW|CF_SHUTW_NOW))
Willy Tarreaua2a64e92011-09-07 23:01:56 +02002461 return;
2462
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002463 channel_shutw_now(session->req);
2464 channel_shutr_now(session->rep);
Willy Tarreaua2a64e92011-09-07 23:01:56 +02002465 session->task->nice = 1024;
2466 if (!(session->flags & SN_ERR_MASK))
2467 session->flags |= why;
2468 task_wakeup(session->task, TASK_WOKEN_OTHER);
2469}
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02002470
Willy Tarreau8b22a712010-06-18 17:46:06 +02002471/************************************************************************/
2472/* All supported ACL keywords must be declared here. */
2473/************************************************************************/
2474
Willy Tarreaua5e37562011-12-16 17:06:15 +01002475/* set temp integer to the General Purpose Counter 0 value in the stksess entry <ts> */
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002476static int
Willy Tarreau37406352012-04-23 16:16:37 +02002477acl_fetch_get_gpc0(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002478{
Willy Tarreau37406352012-04-23 16:16:37 +02002479 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002480 smp->type = SMP_T_UINT;
2481 smp->data.uint = 0;
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002482 if (ts != NULL) {
2483 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_GPC0);
2484 if (!ptr)
2485 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002486 smp->data.uint = stktable_data_cast(ptr, gpc0);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002487 }
2488 return 1;
2489}
2490
Willy Tarreaua5e37562011-12-16 17:06:15 +01002491/* set temp integer to the General Purpose Counter 0 value from the session's tracked
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002492 * frontend counters.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002493 */
2494static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002495acl_fetch_sc1_get_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002496 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002497{
Willy Tarreau56123282010-08-06 19:06:56 +02002498 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002499 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002500 return acl_fetch_get_gpc0(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002501}
2502
Willy Tarreaua5e37562011-12-16 17:06:15 +01002503/* set temp integer to the General Purpose Counter 0 value from the session's tracked
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002504 * backend counters.
2505 */
2506static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002507acl_fetch_sc2_get_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002508 const struct arg *args, struct sample *smp)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002509{
Willy Tarreau56123282010-08-06 19:06:56 +02002510 if (!l4->stkctr2_entry)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002511 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002512 return acl_fetch_get_gpc0(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002513}
2514
Willy Tarreaua5e37562011-12-16 17:06:15 +01002515/* set temp integer to the General Purpose Counter 0 value from the session's source
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002516 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002517 * Accepts exactly 1 argument of type table.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002518 */
2519static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002520acl_fetch_src_get_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002521 const struct arg *args, struct sample *smp)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002522{
2523 struct stktable_key *key;
2524
Willy Tarreau64ee4912012-08-30 22:59:48 +02002525 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002526 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002527 return 0;
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002528
Willy Tarreau24e32d82012-04-23 23:55:44 +02002529 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002530 return acl_fetch_get_gpc0(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002531}
2532
2533/* Increment the General Purpose Counter 0 value in the stksess entry <ts> and
Willy Tarreaua5e37562011-12-16 17:06:15 +01002534 * return it into temp integer.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002535 */
2536static int
Willy Tarreau37406352012-04-23 16:16:37 +02002537acl_fetch_inc_gpc0(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002538{
Willy Tarreau37406352012-04-23 16:16:37 +02002539 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002540 smp->type = SMP_T_UINT;
2541 smp->data.uint = 0;
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002542 if (ts != NULL) {
2543 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_GPC0);
2544 if (!ptr)
2545 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002546 smp->data.uint = ++stktable_data_cast(ptr, gpc0);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002547 }
2548 return 1;
2549}
2550
2551/* Increment the General Purpose Counter 0 value from the session's tracked
Willy Tarreaua5e37562011-12-16 17:06:15 +01002552 * frontend counters and return it into temp integer.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002553 */
2554static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002555acl_fetch_sc1_inc_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002556 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002557{
Willy Tarreau56123282010-08-06 19:06:56 +02002558 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002559 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002560 return acl_fetch_inc_gpc0(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002561}
2562
2563/* Increment the General Purpose Counter 0 value from the session's tracked
Willy Tarreaua5e37562011-12-16 17:06:15 +01002564 * backend counters and return it into temp integer.
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002565 */
2566static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002567acl_fetch_sc2_inc_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002568 const struct arg *args, struct sample *smp)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002569{
Willy Tarreau56123282010-08-06 19:06:56 +02002570 if (!l4->stkctr2_entry)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002571 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002572 return acl_fetch_inc_gpc0(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002573}
2574
2575/* Increment the General Purpose Counter 0 value from the session's source
Willy Tarreaua5e37562011-12-16 17:06:15 +01002576 * address in the table pointed to by expr, and return it into temp integer.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002577 * Accepts exactly 1 argument of type table.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002578 */
2579static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002580acl_fetch_src_inc_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002581 const struct arg *args, struct sample *smp)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002582{
2583 struct stktable_key *key;
2584
Willy Tarreau64ee4912012-08-30 22:59:48 +02002585 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002586 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002587 return 0;
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002588
Willy Tarreau24e32d82012-04-23 23:55:44 +02002589 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002590 return acl_fetch_inc_gpc0(&px->table, smp, stktable_update_key(&px->table, key));
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002591}
2592
Willy Tarreauf73cd112011-08-13 01:45:16 +02002593/* Clear the General Purpose Counter 0 value in the stksess entry <ts> and
Willy Tarreaua5e37562011-12-16 17:06:15 +01002594 * return its previous value into temp integer.
Willy Tarreauf73cd112011-08-13 01:45:16 +02002595 */
2596static int
Willy Tarreau37406352012-04-23 16:16:37 +02002597acl_fetch_clr_gpc0(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauf73cd112011-08-13 01:45:16 +02002598{
Willy Tarreau37406352012-04-23 16:16:37 +02002599 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002600 smp->type = SMP_T_UINT;
2601 smp->data.uint = 0;
Willy Tarreauf73cd112011-08-13 01:45:16 +02002602 if (ts != NULL) {
2603 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_GPC0);
2604 if (!ptr)
2605 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002606 smp->data.uint = stktable_data_cast(ptr, gpc0);
Willy Tarreauf73cd112011-08-13 01:45:16 +02002607 stktable_data_cast(ptr, gpc0) = 0;
2608 }
2609 return 1;
2610}
2611
2612/* Clear the General Purpose Counter 0 value from the session's tracked
Willy Tarreaua5e37562011-12-16 17:06:15 +01002613 * frontend counters and return its previous value into temp integer.
Willy Tarreauf73cd112011-08-13 01:45:16 +02002614 */
2615static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002616acl_fetch_sc1_clr_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002617 const struct arg *args, struct sample *smp)
Willy Tarreauf73cd112011-08-13 01:45:16 +02002618{
2619 if (!l4->stkctr1_entry)
2620 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002621 return acl_fetch_clr_gpc0(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf73cd112011-08-13 01:45:16 +02002622}
2623
2624/* Clear the General Purpose Counter 0 value from the session's tracked
Willy Tarreaua5e37562011-12-16 17:06:15 +01002625 * backend counters and return its previous value into temp integer.
Willy Tarreauf73cd112011-08-13 01:45:16 +02002626 */
2627static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002628acl_fetch_sc2_clr_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002629 const struct arg *args, struct sample *smp)
Willy Tarreauf73cd112011-08-13 01:45:16 +02002630{
2631 if (!l4->stkctr2_entry)
2632 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002633 return acl_fetch_clr_gpc0(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauf73cd112011-08-13 01:45:16 +02002634}
2635
2636/* Clear the General Purpose Counter 0 value from the session's source address
Willy Tarreaua5e37562011-12-16 17:06:15 +01002637 * in the table pointed to by expr, and return its previous value into temp integer.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002638 * Accepts exactly 1 argument of type table.
Willy Tarreauf73cd112011-08-13 01:45:16 +02002639 */
2640static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002641acl_fetch_src_clr_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002642 const struct arg *args, struct sample *smp)
Willy Tarreauf73cd112011-08-13 01:45:16 +02002643{
2644 struct stktable_key *key;
2645
Willy Tarreau64ee4912012-08-30 22:59:48 +02002646 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauf73cd112011-08-13 01:45:16 +02002647 if (!key)
2648 return 0;
2649
Willy Tarreau24e32d82012-04-23 23:55:44 +02002650 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002651 return acl_fetch_clr_gpc0(&px->table, smp, stktable_update_key(&px->table, key));
Willy Tarreauf73cd112011-08-13 01:45:16 +02002652}
2653
Willy Tarreaua5e37562011-12-16 17:06:15 +01002654/* set temp integer to the cumulated number of connections in the stksess entry <ts> */
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002655static int
Willy Tarreau37406352012-04-23 16:16:37 +02002656acl_fetch_conn_cnt(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002657{
Willy Tarreau37406352012-04-23 16:16:37 +02002658 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002659 smp->type = SMP_T_UINT;
2660 smp->data.uint = 0;
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002661 if (ts != NULL) {
2662 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_CONN_CNT);
2663 if (!ptr)
2664 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002665 smp->data.uint = stktable_data_cast(ptr, conn_cnt);
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002666 }
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002667 return 1;
2668}
2669
Willy Tarreaua5e37562011-12-16 17:06:15 +01002670/* set temp integer to the cumulated number of connections from the session's tracked FE counters */
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002671static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002672acl_fetch_sc1_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002673 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002674{
Willy Tarreau56123282010-08-06 19:06:56 +02002675 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002676 return 0;
2677
Willy Tarreau37406352012-04-23 16:16:37 +02002678 return acl_fetch_conn_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002679}
2680
Willy Tarreaua5e37562011-12-16 17:06:15 +01002681/* set temp integer to the cumulated number of connections from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002682static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002683acl_fetch_sc2_conn_cnt(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 Tarreau9a3f8492010-06-18 19:53:25 +02002685{
Willy Tarreau56123282010-08-06 19:06:56 +02002686 if (!l4->stkctr2_entry)
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002687 return 0;
2688
Willy Tarreau37406352012-04-23 16:16:37 +02002689 return acl_fetch_conn_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002690}
2691
Willy Tarreaua5e37562011-12-16 17:06:15 +01002692/* set temp integer to the cumulated number of connections from the session's source
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002693 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002694 * Accepts exactly 1 argument of type table.
Willy Tarreau8b22a712010-06-18 17:46:06 +02002695 */
2696static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002697acl_fetch_src_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002698 const struct arg *args, struct sample *smp)
Willy Tarreau8b22a712010-06-18 17:46:06 +02002699{
Willy Tarreau8b22a712010-06-18 17:46:06 +02002700 struct stktable_key *key;
2701
Willy Tarreau64ee4912012-08-30 22:59:48 +02002702 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau8b22a712010-06-18 17:46:06 +02002703 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002704 return 0;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002705
Willy Tarreau24e32d82012-04-23 23:55:44 +02002706 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002707 return acl_fetch_conn_cnt(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau8b22a712010-06-18 17:46:06 +02002708}
2709
Willy Tarreaua5e37562011-12-16 17:06:15 +01002710/* set temp integer to the connection rate in the stksess entry <ts> over the configured period */
Willy Tarreau91c43d72010-06-20 11:19:22 +02002711static int
Willy Tarreau37406352012-04-23 16:16:37 +02002712acl_fetch_conn_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002713{
Willy Tarreau37406352012-04-23 16:16:37 +02002714 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002715 smp->type = SMP_T_UINT;
2716 smp->data.uint = 0;
Willy Tarreau91c43d72010-06-20 11:19:22 +02002717 if (ts != NULL) {
2718 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_CONN_RATE);
2719 if (!ptr)
2720 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002721 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, conn_rate),
Willy Tarreau91c43d72010-06-20 11:19:22 +02002722 table->data_arg[STKTABLE_DT_CONN_RATE].u);
2723 }
2724 return 1;
2725}
2726
Willy Tarreaua5e37562011-12-16 17:06:15 +01002727/* set temp integer to the connection rate from the session's tracked FE counters over
Willy Tarreau91c43d72010-06-20 11:19:22 +02002728 * the configured period.
2729 */
2730static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002731acl_fetch_sc1_conn_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002732 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002733{
Willy Tarreau56123282010-08-06 19:06:56 +02002734 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002735 return 0;
2736
Willy Tarreau37406352012-04-23 16:16:37 +02002737 return acl_fetch_conn_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002738}
2739
Willy Tarreaua5e37562011-12-16 17:06:15 +01002740/* set temp integer to the connection rate from the session's tracked BE counters over
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002741 * the configured period.
2742 */
2743static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002744acl_fetch_sc2_conn_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002745 const struct arg *args, struct sample *smp)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002746{
Willy Tarreau56123282010-08-06 19:06:56 +02002747 if (!l4->stkctr2_entry)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002748 return 0;
2749
Willy Tarreau37406352012-04-23 16:16:37 +02002750 return acl_fetch_conn_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau91c43d72010-06-20 11:19:22 +02002751}
2752
Willy Tarreaua5e37562011-12-16 17:06:15 +01002753/* set temp integer to the connection rate from the session's source address in the
Willy Tarreau91c43d72010-06-20 11:19:22 +02002754 * table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002755 * Accepts exactly 1 argument of type table.
Willy Tarreau91c43d72010-06-20 11:19:22 +02002756 */
2757static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002758acl_fetch_src_conn_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002759 const struct arg *args, struct sample *smp)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002760{
2761 struct stktable_key *key;
2762
Willy Tarreau64ee4912012-08-30 22:59:48 +02002763 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau91c43d72010-06-20 11:19:22 +02002764 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002765 return 0;
Willy Tarreau91c43d72010-06-20 11:19:22 +02002766
Willy Tarreau24e32d82012-04-23 23:55:44 +02002767 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002768 return acl_fetch_conn_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau91c43d72010-06-20 11:19:22 +02002769}
2770
Willy Tarreaua5e37562011-12-16 17:06:15 +01002771/* set temp integer to the number of connections from the session's source address
Willy Tarreau8b22a712010-06-18 17:46:06 +02002772 * in the table pointed to by expr, after updating it.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002773 * Accepts exactly 1 argument of type table.
Willy Tarreau8b22a712010-06-18 17:46:06 +02002774 */
2775static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002776acl_fetch_src_updt_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002777 const struct arg *args, struct sample *smp)
Willy Tarreau8b22a712010-06-18 17:46:06 +02002778{
2779 struct stksess *ts;
2780 struct stktable_key *key;
2781 void *ptr;
2782
Willy Tarreau64ee4912012-08-30 22:59:48 +02002783 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau8b22a712010-06-18 17:46:06 +02002784 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002785 return 0;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002786
Willy Tarreau24e32d82012-04-23 23:55:44 +02002787 px = args->data.prx;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002788
Willy Tarreau1f7e9252010-06-20 12:27:21 +02002789 if ((ts = stktable_update_key(&px->table, key)) == NULL)
2790 /* entry does not exist and could not be created */
2791 return 0;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002792
2793 ptr = stktable_data_ptr(&px->table, ts, STKTABLE_DT_CONN_CNT);
2794 if (!ptr)
2795 return 0; /* parameter not stored in this table */
2796
Willy Tarreauf853c462012-04-23 18:53:56 +02002797 smp->type = SMP_T_UINT;
2798 smp->data.uint = ++stktable_data_cast(ptr, conn_cnt);
Willy Tarreau37406352012-04-23 16:16:37 +02002799 smp->flags = SMP_F_VOL_TEST;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002800 return 1;
2801}
2802
Willy Tarreaua5e37562011-12-16 17:06:15 +01002803/* set temp integer to the number of concurrent connections in the stksess entry <ts> */
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002804static int
Willy Tarreau37406352012-04-23 16:16:37 +02002805acl_fetch_conn_cur(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002806{
Willy Tarreau37406352012-04-23 16:16:37 +02002807 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002808 smp->type = SMP_T_UINT;
2809 smp->data.uint = 0;
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002810
2811 if (ts != NULL) {
2812 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_CONN_CUR);
2813 if (!ptr)
2814 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002815 smp->data.uint = stktable_data_cast(ptr, conn_cur);
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002816 }
2817 return 1;
2818}
2819
Willy Tarreaua5e37562011-12-16 17:06:15 +01002820/* set temp integer to the number of concurrent connections from the session's tracked FE counters */
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002821static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002822acl_fetch_sc1_conn_cur(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002823 const struct arg *args, struct sample *smp)
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002824{
Willy Tarreau56123282010-08-06 19:06:56 +02002825 if (!l4->stkctr1_entry)
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002826 return 0;
2827
Willy Tarreau37406352012-04-23 16:16:37 +02002828 return acl_fetch_conn_cur(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002829}
2830
Willy Tarreaua5e37562011-12-16 17:06:15 +01002831/* set temp integer to the number of concurrent connections from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002832static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002833acl_fetch_sc2_conn_cur(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002834 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002835{
Willy Tarreau56123282010-08-06 19:06:56 +02002836 if (!l4->stkctr2_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002837 return 0;
2838
Willy Tarreau37406352012-04-23 16:16:37 +02002839 return acl_fetch_conn_cur(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002840}
2841
Willy Tarreaua5e37562011-12-16 17:06:15 +01002842/* set temp integer to the number of concurrent connections from the session's source
Willy Tarreau38285c12010-06-18 16:35:43 +02002843 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002844 * Accepts exactly 1 argument of type table.
Willy Tarreau38285c12010-06-18 16:35:43 +02002845 */
2846static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002847acl_fetch_src_conn_cur(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002848 const struct arg *args, struct sample *smp)
Willy Tarreau38285c12010-06-18 16:35:43 +02002849{
Willy Tarreau38285c12010-06-18 16:35:43 +02002850 struct stktable_key *key;
2851
Willy Tarreau64ee4912012-08-30 22:59:48 +02002852 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau38285c12010-06-18 16:35:43 +02002853 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002854 return 0;
Willy Tarreau38285c12010-06-18 16:35:43 +02002855
Willy Tarreau24e32d82012-04-23 23:55:44 +02002856 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002857 return acl_fetch_conn_cur(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau38285c12010-06-18 16:35:43 +02002858}
2859
Willy Tarreaua5e37562011-12-16 17:06:15 +01002860/* set temp integer to the cumulated number of sessions in the stksess entry <ts> */
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002861static int
Willy Tarreau37406352012-04-23 16:16:37 +02002862acl_fetch_sess_cnt(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002863{
Willy Tarreau37406352012-04-23 16:16:37 +02002864 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002865 smp->type = SMP_T_UINT;
2866 smp->data.uint = 0;
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002867 if (ts != NULL) {
2868 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_SESS_CNT);
2869 if (!ptr)
2870 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002871 smp->data.uint = stktable_data_cast(ptr, sess_cnt);
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002872 }
2873 return 1;
2874}
2875
Willy Tarreaua5e37562011-12-16 17:06:15 +01002876/* set temp integer to the cumulated number of sessions from the session's tracked FE counters */
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002877static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002878acl_fetch_sc1_sess_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002879 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002880{
Willy Tarreau56123282010-08-06 19:06:56 +02002881 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002882 return 0;
2883
Willy Tarreau37406352012-04-23 16:16:37 +02002884 return acl_fetch_sess_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002885}
2886
Willy Tarreaua5e37562011-12-16 17:06:15 +01002887/* set temp integer to the cumulated number of sessions from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002888static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002889acl_fetch_sc2_sess_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002890 const struct arg *args, struct sample *smp)
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002891{
Willy Tarreau56123282010-08-06 19:06:56 +02002892 if (!l4->stkctr2_entry)
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002893 return 0;
2894
Willy Tarreau37406352012-04-23 16:16:37 +02002895 return acl_fetch_sess_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002896}
2897
Willy Tarreaua5e37562011-12-16 17:06:15 +01002898/* set temp integer to the cumulated number of session from the session's source
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002899 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002900 * Accepts exactly 1 argument of type table.
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002901 */
2902static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002903acl_fetch_src_sess_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002904 const struct arg *args, struct sample *smp)
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002905{
2906 struct stktable_key *key;
2907
Willy Tarreau64ee4912012-08-30 22:59:48 +02002908 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002909 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002910 return 0;
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002911
Willy Tarreau24e32d82012-04-23 23:55:44 +02002912 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002913 return acl_fetch_sess_cnt(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002914}
2915
Willy Tarreaua5e37562011-12-16 17:06:15 +01002916/* set temp integer to the session rate in the stksess entry <ts> over the configured period */
Willy Tarreau91c43d72010-06-20 11:19:22 +02002917static int
Willy Tarreau37406352012-04-23 16:16:37 +02002918acl_fetch_sess_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002919{
Willy Tarreau37406352012-04-23 16:16:37 +02002920 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002921 smp->type = SMP_T_UINT;
2922 smp->data.uint = 0;
Willy Tarreau91c43d72010-06-20 11:19:22 +02002923 if (ts != NULL) {
2924 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_SESS_RATE);
2925 if (!ptr)
2926 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002927 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, sess_rate),
Willy Tarreau91c43d72010-06-20 11:19:22 +02002928 table->data_arg[STKTABLE_DT_SESS_RATE].u);
2929 }
2930 return 1;
2931}
2932
Willy Tarreaua5e37562011-12-16 17:06:15 +01002933/* set temp integer to the session rate from the session's tracked FE counters over
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002934 * the configured period.
2935 */
2936static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002937acl_fetch_sc1_sess_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002938 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002939{
Willy Tarreau56123282010-08-06 19:06:56 +02002940 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002941 return 0;
2942
Willy Tarreau37406352012-04-23 16:16:37 +02002943 return acl_fetch_sess_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002944}
2945
Willy Tarreaua5e37562011-12-16 17:06:15 +01002946/* set temp integer to the session rate from the session's tracked BE counters over
Willy Tarreau91c43d72010-06-20 11:19:22 +02002947 * the configured period.
2948 */
2949static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002950acl_fetch_sc2_sess_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002951 const struct arg *args, struct sample *smp)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002952{
Willy Tarreau56123282010-08-06 19:06:56 +02002953 if (!l4->stkctr2_entry)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002954 return 0;
2955
Willy Tarreau37406352012-04-23 16:16:37 +02002956 return acl_fetch_sess_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau91c43d72010-06-20 11:19:22 +02002957}
2958
Willy Tarreaua5e37562011-12-16 17:06:15 +01002959/* set temp integer to the session rate from the session's source address in the
Willy Tarreau91c43d72010-06-20 11:19:22 +02002960 * table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002961 * Accepts exactly 1 argument of type table.
Willy Tarreau91c43d72010-06-20 11:19:22 +02002962 */
2963static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002964acl_fetch_src_sess_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002965 const struct arg *args, struct sample *smp)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002966{
2967 struct stktable_key *key;
2968
Willy Tarreau64ee4912012-08-30 22:59:48 +02002969 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau91c43d72010-06-20 11:19:22 +02002970 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002971 return 0;
Willy Tarreau91c43d72010-06-20 11:19:22 +02002972
Willy Tarreau24e32d82012-04-23 23:55:44 +02002973 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002974 return acl_fetch_sess_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau91c43d72010-06-20 11:19:22 +02002975}
2976
Willy Tarreaua5e37562011-12-16 17:06:15 +01002977/* set temp integer to the cumulated number of sessions in the stksess entry <ts> */
Willy Tarreauda7ff642010-06-23 11:44:09 +02002978static int
Willy Tarreau37406352012-04-23 16:16:37 +02002979acl_fetch_http_req_cnt(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauda7ff642010-06-23 11:44:09 +02002980{
Willy Tarreau37406352012-04-23 16:16:37 +02002981 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002982 smp->type = SMP_T_UINT;
2983 smp->data.uint = 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02002984 if (ts != NULL) {
2985 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_HTTP_REQ_CNT);
2986 if (!ptr)
2987 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002988 smp->data.uint = stktable_data_cast(ptr, http_req_cnt);
Willy Tarreauda7ff642010-06-23 11:44:09 +02002989 }
2990 return 1;
2991}
2992
Willy Tarreaua5e37562011-12-16 17:06:15 +01002993/* set temp integer to the cumulated number of sessions from the session's tracked FE counters */
Willy Tarreauda7ff642010-06-23 11:44:09 +02002994static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002995acl_fetch_sc1_http_req_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002996 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002997{
Willy Tarreau56123282010-08-06 19:06:56 +02002998 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002999 return 0;
3000
Willy Tarreau37406352012-04-23 16:16:37 +02003001 return acl_fetch_http_req_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003002}
3003
Willy Tarreaua5e37562011-12-16 17:06:15 +01003004/* set temp integer to the cumulated number of sessions from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003005static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003006acl_fetch_sc2_http_req_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003007 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003008{
Willy Tarreau56123282010-08-06 19:06:56 +02003009 if (!l4->stkctr2_entry)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003010 return 0;
3011
Willy Tarreau37406352012-04-23 16:16:37 +02003012 return acl_fetch_http_req_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003013}
3014
Willy Tarreaua5e37562011-12-16 17:06:15 +01003015/* set temp integer to the cumulated number of session from the session's source
Willy Tarreauda7ff642010-06-23 11:44:09 +02003016 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003017 * Accepts exactly 1 argument of type table.
Willy Tarreauda7ff642010-06-23 11:44:09 +02003018 */
3019static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003020acl_fetch_src_http_req_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003021 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003022{
3023 struct stktable_key *key;
3024
Willy Tarreau64ee4912012-08-30 22:59:48 +02003025 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003026 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003027 return 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003028
Willy Tarreau24e32d82012-04-23 23:55:44 +02003029 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003030 return acl_fetch_http_req_cnt(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauda7ff642010-06-23 11:44:09 +02003031}
3032
Willy Tarreaua5e37562011-12-16 17:06:15 +01003033/* set temp integer to the session rate in the stksess entry <ts> over the configured period */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003034static int
Willy Tarreau37406352012-04-23 16:16:37 +02003035acl_fetch_http_req_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003036{
Willy Tarreau37406352012-04-23 16:16:37 +02003037 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003038 smp->type = SMP_T_UINT;
3039 smp->data.uint = 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003040 if (ts != NULL) {
3041 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_HTTP_REQ_RATE);
3042 if (!ptr)
3043 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003044 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, http_req_rate),
Willy Tarreauda7ff642010-06-23 11:44:09 +02003045 table->data_arg[STKTABLE_DT_HTTP_REQ_RATE].u);
3046 }
3047 return 1;
3048}
3049
Willy Tarreaua5e37562011-12-16 17:06:15 +01003050/* set temp integer to the session rate from the session's tracked FE counters over
Willy Tarreauda7ff642010-06-23 11:44:09 +02003051 * the configured period.
3052 */
3053static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003054acl_fetch_sc1_http_req_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003055 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003056{
Willy Tarreau56123282010-08-06 19:06:56 +02003057 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003058 return 0;
3059
Willy Tarreau37406352012-04-23 16:16:37 +02003060 return acl_fetch_http_req_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003061}
3062
Willy Tarreaua5e37562011-12-16 17:06:15 +01003063/* set temp integer to the session rate from the session's tracked BE counters over
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003064 * the configured period.
3065 */
3066static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003067acl_fetch_sc2_http_req_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003068 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003069{
Willy Tarreau56123282010-08-06 19:06:56 +02003070 if (!l4->stkctr2_entry)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003071 return 0;
3072
Willy Tarreau37406352012-04-23 16:16:37 +02003073 return acl_fetch_http_req_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003074}
3075
Willy Tarreaua5e37562011-12-16 17:06:15 +01003076/* set temp integer to the session rate from the session's source address in the
Willy Tarreauda7ff642010-06-23 11:44:09 +02003077 * table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003078 * Accepts exactly 1 argument of type table.
Willy Tarreauda7ff642010-06-23 11:44:09 +02003079 */
3080static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003081acl_fetch_src_http_req_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003082 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003083{
3084 struct stktable_key *key;
3085
Willy Tarreau64ee4912012-08-30 22:59:48 +02003086 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003087 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003088 return 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003089
Willy Tarreau24e32d82012-04-23 23:55:44 +02003090 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003091 return acl_fetch_http_req_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauda7ff642010-06-23 11:44:09 +02003092}
3093
Willy Tarreaua5e37562011-12-16 17:06:15 +01003094/* set temp integer to the cumulated number of sessions in the stksess entry <ts> */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003095static int
Willy Tarreau37406352012-04-23 16:16:37 +02003096acl_fetch_http_err_cnt(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003097{
Willy Tarreau37406352012-04-23 16:16:37 +02003098 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003099 smp->type = SMP_T_UINT;
3100 smp->data.uint = 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003101 if (ts != NULL) {
3102 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_HTTP_ERR_CNT);
3103 if (!ptr)
3104 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003105 smp->data.uint = stktable_data_cast(ptr, http_err_cnt);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003106 }
3107 return 1;
3108}
3109
Willy Tarreaua5e37562011-12-16 17:06:15 +01003110/* set temp integer to the cumulated number of sessions from the session's tracked FE counters */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003111static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003112acl_fetch_sc1_http_err_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003113 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003114{
Willy Tarreau56123282010-08-06 19:06:56 +02003115 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003116 return 0;
3117
Willy Tarreau37406352012-04-23 16:16:37 +02003118 return acl_fetch_http_err_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003119}
3120
Willy Tarreaua5e37562011-12-16 17:06:15 +01003121/* set temp integer to the cumulated number of sessions from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003122static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003123acl_fetch_sc2_http_err_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003124 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003125{
Willy Tarreau56123282010-08-06 19:06:56 +02003126 if (!l4->stkctr2_entry)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003127 return 0;
3128
Willy Tarreau37406352012-04-23 16:16:37 +02003129 return acl_fetch_http_err_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003130}
3131
Willy Tarreaua5e37562011-12-16 17:06:15 +01003132/* set temp integer to the cumulated number of session from the session's source
Willy Tarreauda7ff642010-06-23 11:44:09 +02003133 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003134 * Accepts exactly 1 argument of type table.
Willy Tarreauda7ff642010-06-23 11:44:09 +02003135 */
3136static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003137acl_fetch_src_http_err_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003138 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003139{
3140 struct stktable_key *key;
3141
Willy Tarreau64ee4912012-08-30 22:59:48 +02003142 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003143 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003144 return 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003145
Willy Tarreau24e32d82012-04-23 23:55:44 +02003146 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003147 return acl_fetch_http_err_cnt(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauda7ff642010-06-23 11:44:09 +02003148}
3149
Willy Tarreaua5e37562011-12-16 17:06:15 +01003150/* set temp integer to the session rate in the stksess entry <ts> over the configured period */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003151static int
Willy Tarreau37406352012-04-23 16:16:37 +02003152acl_fetch_http_err_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003153{
Willy Tarreau37406352012-04-23 16:16:37 +02003154 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003155 smp->type = SMP_T_UINT;
3156 smp->data.uint = 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003157 if (ts != NULL) {
3158 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_HTTP_ERR_RATE);
3159 if (!ptr)
3160 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003161 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, http_err_rate),
Willy Tarreauda7ff642010-06-23 11:44:09 +02003162 table->data_arg[STKTABLE_DT_HTTP_ERR_RATE].u);
3163 }
3164 return 1;
3165}
3166
Willy Tarreaua5e37562011-12-16 17:06:15 +01003167/* set temp integer to the session rate from the session's tracked FE counters over
Willy Tarreauda7ff642010-06-23 11:44:09 +02003168 * the configured period.
3169 */
3170static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003171acl_fetch_sc1_http_err_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003172 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003173{
Willy Tarreau56123282010-08-06 19:06:56 +02003174 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003175 return 0;
3176
Willy Tarreau37406352012-04-23 16:16:37 +02003177 return acl_fetch_http_err_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003178}
3179
Willy Tarreaua5e37562011-12-16 17:06:15 +01003180/* set temp integer to the session rate from the session's tracked BE counters over
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003181 * the configured period.
3182 */
3183static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003184acl_fetch_sc2_http_err_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003185 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003186{
Willy Tarreau56123282010-08-06 19:06:56 +02003187 if (!l4->stkctr2_entry)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003188 return 0;
3189
Willy Tarreau37406352012-04-23 16:16:37 +02003190 return acl_fetch_http_err_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003191}
3192
Willy Tarreaua5e37562011-12-16 17:06:15 +01003193/* set temp integer to the session rate from the session's source address in the
Willy Tarreauda7ff642010-06-23 11:44:09 +02003194 * table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003195 * Accepts exactly 1 argument of type table.
Willy Tarreauda7ff642010-06-23 11:44:09 +02003196 */
3197static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003198acl_fetch_src_http_err_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003199 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003200{
3201 struct stktable_key *key;
3202
Willy Tarreau64ee4912012-08-30 22:59:48 +02003203 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003204 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003205 return 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003206
Willy Tarreau24e32d82012-04-23 23:55:44 +02003207 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003208 return acl_fetch_http_err_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauda7ff642010-06-23 11:44:09 +02003209}
3210
Willy Tarreaua5e37562011-12-16 17:06:15 +01003211/* set temp integer to the number of kbytes received from clients matching the stksess entry <ts> */
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003212static int
Willy Tarreau37406352012-04-23 16:16:37 +02003213acl_fetch_kbytes_in(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003214{
Willy Tarreau37406352012-04-23 16:16:37 +02003215 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003216 smp->type = SMP_T_UINT;
3217 smp->data.uint = 0;
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003218
3219 if (ts != NULL) {
3220 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_BYTES_IN_CNT);
3221 if (!ptr)
3222 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003223 smp->data.uint = stktable_data_cast(ptr, bytes_in_cnt) >> 10;
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003224 }
3225 return 1;
3226}
3227
Willy Tarreaua5e37562011-12-16 17:06:15 +01003228/* set temp integer to the number of kbytes received from clients according to the
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003229 * session's tracked FE counters.
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003230 */
3231static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003232acl_fetch_sc1_kbytes_in(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003233 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003234{
Willy Tarreau56123282010-08-06 19:06:56 +02003235 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003236 return 0;
3237
Willy Tarreau37406352012-04-23 16:16:37 +02003238 return acl_fetch_kbytes_in(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003239}
3240
Willy Tarreaua5e37562011-12-16 17:06:15 +01003241/* set temp integer to the number of kbytes received from clients according to the
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003242 * session's tracked BE counters.
3243 */
3244static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003245acl_fetch_sc2_kbytes_in(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003246 const struct arg *args, struct sample *smp)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003247{
Willy Tarreau56123282010-08-06 19:06:56 +02003248 if (!l4->stkctr2_entry)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003249 return 0;
3250
Willy Tarreau37406352012-04-23 16:16:37 +02003251 return acl_fetch_kbytes_in(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003252}
3253
Willy Tarreaua5e37562011-12-16 17:06:15 +01003254/* set temp integer to the number of kbytes received from the session's source
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003255 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003256 * Accepts exactly 1 argument of type table.
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003257 */
3258static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003259acl_fetch_src_kbytes_in(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003260 const struct arg *args, struct sample *smp)
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003261{
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003262 struct stktable_key *key;
3263
Willy Tarreau64ee4912012-08-30 22:59:48 +02003264 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003265 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003266 return 0;
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003267
Willy Tarreau24e32d82012-04-23 23:55:44 +02003268 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003269 return acl_fetch_kbytes_in(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003270}
3271
Willy Tarreaua5e37562011-12-16 17:06:15 +01003272/* set temp integer to the bytes rate from clients in the stksess entry <ts> over the
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003273 * configured period.
3274 */
3275static int
Willy Tarreau37406352012-04-23 16:16:37 +02003276acl_fetch_bytes_in_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003277{
Willy Tarreau37406352012-04-23 16:16:37 +02003278 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003279 smp->type = SMP_T_UINT;
3280 smp->data.uint = 0;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003281 if (ts != NULL) {
3282 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_BYTES_IN_RATE);
3283 if (!ptr)
3284 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003285 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, bytes_in_rate),
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003286 table->data_arg[STKTABLE_DT_BYTES_IN_RATE].u);
3287 }
3288 return 1;
3289}
3290
Willy Tarreaua5e37562011-12-16 17:06:15 +01003291/* set temp integer to the bytes rate from clients from the session's tracked FE
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003292 * counters over the configured period.
3293 */
3294static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003295acl_fetch_sc1_bytes_in_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003296 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003297{
Willy Tarreau56123282010-08-06 19:06:56 +02003298 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003299 return 0;
3300
Willy Tarreau37406352012-04-23 16:16:37 +02003301 return acl_fetch_bytes_in_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003302}
3303
Willy Tarreaua5e37562011-12-16 17:06:15 +01003304/* set temp integer to the bytes rate from clients from the session's tracked BE
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003305 * counters over the configured period.
3306 */
3307static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003308acl_fetch_sc2_bytes_in_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003309 const struct arg *args, struct sample *smp)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003310{
Willy Tarreau56123282010-08-06 19:06:56 +02003311 if (!l4->stkctr2_entry)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003312 return 0;
3313
Willy Tarreau37406352012-04-23 16:16:37 +02003314 return acl_fetch_bytes_in_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003315}
3316
Willy Tarreaua5e37562011-12-16 17:06:15 +01003317/* set temp integer to the bytes rate from clients from the session's source address
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003318 * in the table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003319 * Accepts exactly 1 argument of type table.
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003320 */
3321static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003322acl_fetch_src_bytes_in_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003323 const struct arg *args, struct sample *smp)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003324{
3325 struct stktable_key *key;
3326
Willy Tarreau64ee4912012-08-30 22:59:48 +02003327 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003328 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003329 return 0;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003330
Willy Tarreau24e32d82012-04-23 23:55:44 +02003331 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003332 return acl_fetch_bytes_in_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003333}
3334
Willy Tarreaua5e37562011-12-16 17:06:15 +01003335/* set temp integer to the number of kbytes sent to clients matching the stksess entry <ts> */
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003336static int
Willy Tarreau37406352012-04-23 16:16:37 +02003337acl_fetch_kbytes_out(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003338{
Willy Tarreau37406352012-04-23 16:16:37 +02003339 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003340 smp->type = SMP_T_UINT;
3341 smp->data.uint = 0;
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003342
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003343 if (ts != NULL) {
3344 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_BYTES_OUT_CNT);
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003345 if (!ptr)
3346 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003347 smp->data.uint = stktable_data_cast(ptr, bytes_out_cnt) >> 10;
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003348 }
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003349 return 1;
3350}
3351
Willy Tarreaua5e37562011-12-16 17:06:15 +01003352/* set temp integer to the number of kbytes sent to clients according to the session's
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003353 * tracked FE counters.
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003354 */
3355static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003356acl_fetch_sc1_kbytes_out(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003357 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003358{
Willy Tarreau56123282010-08-06 19:06:56 +02003359 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003360 return 0;
3361
Willy Tarreau37406352012-04-23 16:16:37 +02003362 return acl_fetch_kbytes_out(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003363}
3364
Willy Tarreaua5e37562011-12-16 17:06:15 +01003365/* set temp integer to the number of kbytes sent to clients according to the session's
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003366 * tracked BE counters.
3367 */
3368static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003369acl_fetch_sc2_kbytes_out(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003370 const struct arg *args, struct sample *smp)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003371{
Willy Tarreau56123282010-08-06 19:06:56 +02003372 if (!l4->stkctr2_entry)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003373 return 0;
3374
Willy Tarreau37406352012-04-23 16:16:37 +02003375 return acl_fetch_kbytes_out(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003376}
3377
Willy Tarreaua5e37562011-12-16 17:06:15 +01003378/* set temp integer to the number of kbytes sent to the session's source address in
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003379 * the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003380 * Accepts exactly 1 argument of type table.
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003381 */
3382static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003383acl_fetch_src_kbytes_out(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003384 const struct arg *args, struct sample *smp)
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003385{
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003386 struct stktable_key *key;
3387
Willy Tarreau64ee4912012-08-30 22:59:48 +02003388 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003389 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003390 return 0;
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003391
Willy Tarreau24e32d82012-04-23 23:55:44 +02003392 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003393 return acl_fetch_kbytes_out(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003394}
3395
Willy Tarreaua5e37562011-12-16 17:06:15 +01003396/* set temp integer to the bytes rate to clients in the stksess entry <ts> over the
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003397 * configured period.
3398 */
3399static int
Willy Tarreau37406352012-04-23 16:16:37 +02003400acl_fetch_bytes_out_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003401{
Willy Tarreau37406352012-04-23 16:16:37 +02003402 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003403 smp->type = SMP_T_UINT;
3404 smp->data.uint = 0;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003405 if (ts != NULL) {
3406 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_BYTES_OUT_RATE);
3407 if (!ptr)
3408 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003409 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, bytes_out_rate),
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003410 table->data_arg[STKTABLE_DT_BYTES_OUT_RATE].u);
3411 }
3412 return 1;
3413}
3414
Willy Tarreaua5e37562011-12-16 17:06:15 +01003415/* set temp integer to the bytes rate to clients from the session's tracked FE counters
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003416 * over the configured period.
3417 */
3418static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003419acl_fetch_sc1_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003420 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003421{
Willy Tarreau56123282010-08-06 19:06:56 +02003422 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003423 return 0;
3424
Willy Tarreau37406352012-04-23 16:16:37 +02003425 return acl_fetch_bytes_out_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003426}
3427
Willy Tarreaua5e37562011-12-16 17:06:15 +01003428/* set temp integer to the bytes rate to clients from the session's tracked BE counters
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003429 * over the configured period.
3430 */
3431static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003432acl_fetch_sc2_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003433 const struct arg *args, struct sample *smp)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003434{
Willy Tarreau56123282010-08-06 19:06:56 +02003435 if (!l4->stkctr2_entry)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003436 return 0;
3437
Willy Tarreau37406352012-04-23 16:16:37 +02003438 return acl_fetch_bytes_out_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003439}
3440
Willy Tarreaua5e37562011-12-16 17:06:15 +01003441/* set temp integer to the bytes rate to client from the session's source address in
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003442 * the table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003443 * Accepts exactly 1 argument of type table.
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003444 */
3445static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003446acl_fetch_src_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003447 const struct arg *args, struct sample *smp)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003448{
3449 struct stktable_key *key;
3450
Willy Tarreau64ee4912012-08-30 22:59:48 +02003451 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003452 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003453 return 0;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003454
Willy Tarreau24e32d82012-04-23 23:55:44 +02003455 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003456 return acl_fetch_bytes_out_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003457}
3458
Willy Tarreau34db1082012-04-19 17:16:54 +02003459/* set temp integer to the number of used entries in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003460 * Accepts exactly 1 argument of type table.
Willy Tarreau34db1082012-04-19 17:16:54 +02003461 */
Willy Tarreauc735a072011-03-29 00:57:02 +02003462static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003463acl_fetch_table_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003464 const struct arg *args, struct sample *smp)
Willy Tarreauc735a072011-03-29 00:57:02 +02003465{
Willy Tarreau37406352012-04-23 16:16:37 +02003466 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003467 smp->type = SMP_T_UINT;
Willy Tarreau24e32d82012-04-23 23:55:44 +02003468 smp->data.uint = args->data.prx->table.current;
Willy Tarreauc735a072011-03-29 00:57:02 +02003469 return 1;
3470}
3471
Willy Tarreau34db1082012-04-19 17:16:54 +02003472/* set temp integer to the number of free entries in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003473 * Accepts exactly 1 argument of type table.
Willy Tarreau34db1082012-04-19 17:16:54 +02003474 */
Willy Tarreauc735a072011-03-29 00:57:02 +02003475static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003476acl_fetch_table_avl(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003477 const struct arg *args, struct sample *smp)
Willy Tarreauc735a072011-03-29 00:57:02 +02003478{
Willy Tarreau24e32d82012-04-23 23:55:44 +02003479 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003480 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003481 smp->type = SMP_T_UINT;
3482 smp->data.uint = px->table.size - px->table.current;
Willy Tarreauc735a072011-03-29 00:57:02 +02003483 return 1;
3484}
Willy Tarreau8b22a712010-06-18 17:46:06 +02003485
Willy Tarreau61612d42012-04-19 18:42:05 +02003486/* Note: must not be declared <const> as its list will be overwritten.
3487 * Please take care of keeping this list alphabetically sorted.
3488 */
Willy Tarreau8b22a712010-06-18 17:46:06 +02003489static struct acl_kw_list acl_kws = {{ },{
Willy Tarreau61612d42012-04-19 18:42:05 +02003490 { "sc1_bytes_in_rate", acl_parse_int, acl_fetch_sc1_bytes_in_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3491 { "sc1_bytes_out_rate", acl_parse_int, acl_fetch_sc1_bytes_out_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3492 { "sc1_clr_gpc0", acl_parse_int, acl_fetch_sc1_clr_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3493 { "sc1_conn_cnt", acl_parse_int, acl_fetch_sc1_conn_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3494 { "sc1_conn_cur", acl_parse_int, acl_fetch_sc1_conn_cur, acl_match_int, ACL_USE_NOTHING, 0 },
3495 { "sc1_conn_rate", acl_parse_int, acl_fetch_sc1_conn_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3496 { "sc1_get_gpc0", acl_parse_int, acl_fetch_sc1_get_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3497 { "sc1_http_err_cnt", acl_parse_int, acl_fetch_sc1_http_err_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3498 { "sc1_http_err_rate", acl_parse_int, acl_fetch_sc1_http_err_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3499 { "sc1_http_req_cnt", acl_parse_int, acl_fetch_sc1_http_req_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3500 { "sc1_http_req_rate", acl_parse_int, acl_fetch_sc1_http_req_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3501 { "sc1_inc_gpc0", acl_parse_int, acl_fetch_sc1_inc_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3502 { "sc1_kbytes_in", acl_parse_int, acl_fetch_sc1_kbytes_in, acl_match_int, ACL_USE_TCP4_VOLATILE, 0 },
3503 { "sc1_kbytes_out", acl_parse_int, acl_fetch_sc1_kbytes_out, acl_match_int, ACL_USE_TCP4_VOLATILE, 0 },
3504 { "sc1_sess_cnt", acl_parse_int, acl_fetch_sc1_sess_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3505 { "sc1_sess_rate", acl_parse_int, acl_fetch_sc1_sess_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3506 { "sc2_bytes_in_rate", acl_parse_int, acl_fetch_sc2_bytes_in_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3507 { "sc2_bytes_out_rate", acl_parse_int, acl_fetch_sc2_bytes_out_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3508 { "sc2_clr_gpc0", acl_parse_int, acl_fetch_sc2_clr_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3509 { "sc2_conn_cnt", acl_parse_int, acl_fetch_sc2_conn_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3510 { "sc2_conn_cur", acl_parse_int, acl_fetch_sc2_conn_cur, acl_match_int, ACL_USE_NOTHING, 0 },
3511 { "sc2_conn_rate", acl_parse_int, acl_fetch_sc2_conn_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3512 { "sc2_get_gpc0", acl_parse_int, acl_fetch_sc2_get_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3513 { "sc2_http_err_cnt", acl_parse_int, acl_fetch_sc2_http_err_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3514 { "sc2_http_err_rate", acl_parse_int, acl_fetch_sc2_http_err_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3515 { "sc2_http_req_cnt", acl_parse_int, acl_fetch_sc2_http_req_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3516 { "sc2_http_req_rate", acl_parse_int, acl_fetch_sc2_http_req_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3517 { "sc2_inc_gpc0", acl_parse_int, acl_fetch_sc2_inc_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3518 { "sc2_kbytes_in", acl_parse_int, acl_fetch_sc2_kbytes_in, acl_match_int, ACL_USE_TCP4_VOLATILE, 0 },
3519 { "sc2_kbytes_out", acl_parse_int, acl_fetch_sc2_kbytes_out, acl_match_int, ACL_USE_TCP4_VOLATILE, 0 },
3520 { "sc2_sess_cnt", acl_parse_int, acl_fetch_sc2_sess_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3521 { "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 +02003522 { "src_bytes_in_rate", acl_parse_int, acl_fetch_src_bytes_in_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3523 { "src_bytes_out_rate", acl_parse_int, acl_fetch_src_bytes_out_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3524 { "src_clr_gpc0", acl_parse_int, acl_fetch_src_clr_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3525 { "src_conn_cnt", acl_parse_int, acl_fetch_src_conn_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3526 { "src_conn_cur", acl_parse_int, acl_fetch_src_conn_cur, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3527 { "src_conn_rate", acl_parse_int, acl_fetch_src_conn_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3528 { "src_get_gpc0", acl_parse_int, acl_fetch_src_get_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3529 { "src_http_err_cnt", acl_parse_int, acl_fetch_src_http_err_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3530 { "src_http_err_rate", acl_parse_int, acl_fetch_src_http_err_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3531 { "src_http_req_cnt", acl_parse_int, acl_fetch_src_http_req_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3532 { "src_http_req_rate", acl_parse_int, acl_fetch_src_http_req_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3533 { "src_inc_gpc0", acl_parse_int, acl_fetch_src_inc_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3534 { "src_kbytes_in", acl_parse_int, acl_fetch_src_kbytes_in, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3535 { "src_kbytes_out", acl_parse_int, acl_fetch_src_kbytes_out, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3536 { "src_sess_cnt", acl_parse_int, acl_fetch_src_sess_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3537 { "src_sess_rate", acl_parse_int, acl_fetch_src_sess_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3538 { "src_updt_conn_cnt", acl_parse_int, acl_fetch_src_updt_conn_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3539 { "table_avl", acl_parse_int, acl_fetch_table_avl, acl_match_int, ACL_USE_NOTHING, ARG1(1,TAB) },
3540 { "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 +02003541 { NULL, NULL, NULL, NULL },
3542}};
3543
3544
Willy Tarreau56123282010-08-06 19:06:56 +02003545/* Parse a "track-sc[12]" line starting with "track-sc[12]" in args[arg-1].
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003546 * Returns the number of warnings emitted, or -1 in case of fatal errors. The
3547 * <prm> struct is fed with the table name if any. If unspecified, the caller
3548 * will assume that the current proxy's table is used.
3549 */
3550int parse_track_counters(char **args, int *arg,
3551 int section_type, struct proxy *curpx,
3552 struct track_ctr_prm *prm,
Willy Tarreau0a3dd742012-05-08 19:47:01 +02003553 struct proxy *defpx, char **err)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003554{
Willy Tarreau12785782012-04-27 21:37:17 +02003555 int sample_type = 0;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003556
Willy Tarreau56123282010-08-06 19:06:56 +02003557 /* parse the arguments of "track-sc[12]" before the condition in the
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003558 * following form :
Willy Tarreau56123282010-08-06 19:06:56 +02003559 * track-sc[12] src [ table xxx ] [ if|unless ... ]
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003560 */
3561 while (args[*arg]) {
3562 if (strcmp(args[*arg], "src") == 0) {
3563 prm->type = STKTABLE_TYPE_IP;
Willy Tarreau12785782012-04-27 21:37:17 +02003564 sample_type = 1;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003565 }
3566 else if (strcmp(args[*arg], "table") == 0) {
3567 if (!args[*arg + 1]) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02003568 memprintf(err, "missing table name");
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003569 return -1;
3570 }
3571 /* we copy the table name for now, it will be resolved later */
3572 prm->table.n = strdup(args[*arg + 1]);
3573 (*arg)++;
3574 }
3575 else {
3576 /* unhandled keywords are handled by the caller */
3577 break;
3578 }
3579 (*arg)++;
3580 }
3581
Willy Tarreau12785782012-04-27 21:37:17 +02003582 if (!sample_type) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02003583 memprintf(err,
3584 "tracking key not specified (found %s, only 'src' is supported)",
3585 quote_arg(args[*arg]));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003586 return -1;
3587 }
3588
3589 return 0;
3590}
3591
Willy Tarreau8b22a712010-06-18 17:46:06 +02003592__attribute__((constructor))
3593static void __session_init(void)
3594{
3595 acl_register_keywords(&acl_kws);
3596}
3597
Willy Tarreaubaaee002006-06-26 02:48:02 +02003598/*
3599 * Local variables:
3600 * c-indent-level: 8
3601 * c-basic-offset: 8
3602 * End:
3603 */