blob: a32ec6b09d738307a6383be020addd9a37877ccb [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 Tarreau071e1372012-10-03 01:39:48 +020053static int conn_session_complete(struct connection *conn);
Willy Tarreau2542b532012-08-31 16:01:23 +020054static struct task *expire_mini_session(struct task *t);
55int session_complete(struct session *s);
56
Willy Tarreau5e75e272012-10-02 21:21:20 +020057/* data layer callbacks for an embryonic session */
58struct data_cb sess_conn_cb = {
59 .recv = NULL,
60 .send = NULL,
61 .wake = NULL,
Willy Tarreau071e1372012-10-03 01:39:48 +020062 .init = conn_session_complete,
Willy Tarreau5e75e272012-10-02 21:21:20 +020063};
64
Willy Tarreau2542b532012-08-31 16:01:23 +020065/* This function is called from the protocol layer accept() in order to
66 * instanciate a new embryonic session on behalf of a given listener and
67 * frontend. It returns a positive value upon success, 0 if the connection
68 * can be ignored, or a negative value upon critical failure. The accepted
69 * file descriptor is closed if we return <= 0.
Willy Tarreau81f9aa32010-06-01 17:45:26 +020070 */
71int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
72{
73 struct proxy *p = l->frontend;
74 struct session *s;
Willy Tarreau81f9aa32010-06-01 17:45:26 +020075 struct task *t;
Willy Tarreauabe8ea52010-11-11 10:56:04 +010076 int ret;
77
78
79 ret = -1; /* assume unrecoverable error by default */
Willy Tarreau81f9aa32010-06-01 17:45:26 +020080
Willy Tarreaufffe1322010-11-11 09:48:16 +010081 if (unlikely((s = pool_alloc2(pool2_session)) == NULL))
Willy Tarreau81f9aa32010-06-01 17:45:26 +020082 goto out_close;
Willy Tarreau81f9aa32010-06-01 17:45:26 +020083
Willy Tarreau2542b532012-08-31 16:01:23 +020084 /* minimum session initialization required for an embryonic session is
85 * fairly low. We need very little to execute L4 ACLs, then we need a
86 * task to make the client-side connection live on its own.
87 * - flags
88 * - stick-entry tracking
89 */
Willy Tarreau81f9aa32010-06-01 17:45:26 +020090 s->flags = 0;
91 s->logs.logwait = p->to_log;
Willy Tarreau56123282010-08-06 19:06:56 +020092 s->stkctr1_entry = NULL;
93 s->stkctr2_entry = NULL;
94 s->stkctr1_table = NULL;
95 s->stkctr2_table = NULL;
Willy Tarreau81f9aa32010-06-01 17:45:26 +020096
Willy Tarreau2542b532012-08-31 16:01:23 +020097 s->listener = l;
98 s->fe = p;
Willy Tarreauabe8ea52010-11-11 10:56:04 +010099
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200100 /* OK, we're keeping the session, so let's properly initialize the session */
Willy Tarreau96596ae2012-06-08 22:57:36 +0200101 s->si[0].conn.t.sock.fd = cfd;
102 s->si[0].conn.ctrl = l->proto;
Willy Tarreau2542b532012-08-31 16:01:23 +0200103 s->si[0].conn.flags = CO_FL_NONE;
Willy Tarreau986a9d22012-08-30 21:11:38 +0200104 s->si[0].conn.addr.from = *addr;
Willy Tarreau2542b532012-08-31 16:01:23 +0200105 set_target_client(&s->si[0].conn.target, l);
106
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200107 s->logs.accept_date = date; /* user-visible date for logging */
108 s->logs.tv_accept = now; /* corrected date for internal use */
109 s->uniq_id = totalconn;
Willy Tarreau2542b532012-08-31 16:01:23 +0200110 p->feconn++;
111 /* This session was accepted, count it now */
112 if (p->feconn > p->fe_counters.conn_max)
113 p->fe_counters.conn_max = p->feconn;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200114
Willy Tarreau2542b532012-08-31 16:01:23 +0200115 proxy_inc_fe_conn_ctr(l, p);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200116
117 /* now evaluate the tcp-request layer4 rules. Since we expect to be able
118 * to abort right here as soon as possible, we check the rules before
119 * even initializing the stream interfaces.
120 */
121 if ((l->options & LI_O_TCP_RULES) && !tcp_exec_req_rules(s)) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200122 /* let's do a no-linger now to close with a single RST. */
123 setsockopt(cfd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100124 ret = 0; /* successful termination */
Willy Tarreau2542b532012-08-31 16:01:23 +0200125 goto out_free_session;
126 }
127
Willy Tarreau82569f92012-09-27 23:48:56 +0200128 /* Adjust some socket options */
129 if (unlikely(fcntl(cfd, F_SETFL, O_NONBLOCK) == -1))
130 goto out_free_session;
131
132 /* monitor-net and health mode are processed immediately after TCP
133 * connection rules. This way it's possible to block them, but they
134 * never use the lower data layers, they send directly over the socket,
135 * as they were designed for. We first flush the socket receive buffer
136 * in order to avoid emission of an RST by the system. We ignore any
137 * error.
138 */
139 if (unlikely((p->mode == PR_MODE_HEALTH) ||
140 ((l->options & LI_O_CHK_MONNET) &&
141 addr->ss_family == AF_INET &&
142 (((struct sockaddr_in *)addr)->sin_addr.s_addr & p->mon_mask.s_addr) == p->mon_net.s_addr))) {
143 /* we have 4 possibilities here :
144 * - HTTP mode, from monitoring address => send "HTTP/1.0 200 OK"
145 * - HEALTH mode with HTTP check => send "HTTP/1.0 200 OK"
146 * - HEALTH mode without HTTP check => just send "OK"
147 * - TCP mode from monitoring address => just close
148 */
149 recv(cfd, trash, trashlen, 0&MSG_DONTWAIT);
150 if (p->mode == PR_MODE_HTTP ||
151 (p->mode == PR_MODE_HEALTH && (p->options2 & PR_O2_CHK_ANY) == PR_O2_HTTP_CHK))
152 send(cfd, "HTTP/1.0 200 OK\r\n\r\n", 19, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_MORE);
153 else if (p->mode == PR_MODE_HEALTH)
154 send(cfd, "OK\n", 3, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_MORE);
155 ret = 0;
156 goto out_free_session;
157 }
158
159
Willy Tarreau22cda212012-08-31 17:43:29 +0200160 /* wait for a PROXY protocol header */
161 if (l->options & LI_O_ACC_PROXY) {
162 s->si[0].conn.flags |= CO_FL_ACCEPT_PROXY;
163 conn_sock_want_recv(&s->si[0].conn);
164 }
165
Willy Tarreau2542b532012-08-31 16:01:23 +0200166 if (unlikely((t = task_new()) == NULL))
167 goto out_free_session;
168
169 t->context = s;
170 t->nice = l->nice;
171 s->task = t;
172
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200173 /* Add the various callbacks. Right now the transport layer is present
174 * but not initialized. Also note we need to be careful as the stream
175 * int is not initialized yet.
Willy Tarreau2542b532012-08-31 16:01:23 +0200176 */
Willy Tarreau5e75e272012-10-02 21:21:20 +0200177 conn_prepare(&s->si[0].conn, &sess_conn_cb, l->proto, l->xprt, s);
Willy Tarreau2542b532012-08-31 16:01:23 +0200178
179 /* finish initialization of the accepted file descriptor */
180 fd_insert(cfd);
181 fdtab[cfd].owner = &s->si[0].conn;
Willy Tarreau2542b532012-08-31 16:01:23 +0200182 fdtab[cfd].iocb = conn_fd_handler;
183 conn_data_want_recv(&s->si[0].conn);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200184 if (conn_xprt_init(&s->si[0].conn) < 0)
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100185 goto out_free_task;
Willy Tarreau2542b532012-08-31 16:01:23 +0200186
187 /* OK, now either we have a pending handshake to execute with and
188 * then we must return to the I/O layer, or we can proceed with the
189 * end of the session initialization. In case of handshake, we also
190 * set the I/O timeout to the frontend's client timeout.
191 */
192
193 if (s->si[0].conn.flags & CO_FL_HANDSHAKE) {
194 t->process = expire_mini_session;
195 t->expire = tick_add_ifset(now_ms, p->timeout.client);
196 task_queue(t);
Willy Tarreau071e1372012-10-03 01:39:48 +0200197 s->si[0].conn.flags |= CO_FL_INIT_DATA;
Willy Tarreau2542b532012-08-31 16:01:23 +0200198 return 1;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200199 }
200
Willy Tarreau2542b532012-08-31 16:01:23 +0200201 /* OK let's complete session initialization */
202 ret = session_complete(s);
203 if (ret > 0)
204 return ret;
205
206 /* Error unrolling */
207 out_free_task:
208 task_free(t);
209 out_free_session:
210 p->feconn--;
211 if (s->stkctr1_entry || s->stkctr2_entry)
212 session_store_counters(s);
213 pool_free2(pool2_session, s);
214 out_close:
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200215 if (ret < 0 && l->xprt == &raw_sock && p->mode == PR_MODE_HTTP) {
Willy Tarreau2542b532012-08-31 16:01:23 +0200216 /* critical error, no more memory, try to emit a 500 response */
Willy Tarreau783f2582012-09-04 12:19:04 +0200217 struct chunk *err_msg = http_error_message(s, HTTP_ERR_500);
Willy Tarreau2542b532012-08-31 16:01:23 +0200218 send(cfd, err_msg->str, err_msg->len, MSG_DONTWAIT|MSG_NOSIGNAL);
219 }
220
221 if (fdtab[cfd].owner)
222 fd_delete(cfd);
223 else
224 close(cfd);
225 return ret;
226}
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100227
Willy Tarreau2542b532012-08-31 16:01:23 +0200228/* This function kills an existing embryonic session. It stops the connection's
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200229 * transport layer, releases assigned resources, resumes the listener if it was
Willy Tarreau2542b532012-08-31 16:01:23 +0200230 * disabled and finally kills the file descriptor.
231 */
232static void kill_mini_session(struct session *s)
233{
234 /* kill the connection now */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200235 conn_xprt_close(&s->si[0].conn);
Willy Tarreau2542b532012-08-31 16:01:23 +0200236
237 s->fe->feconn--;
238 if (s->stkctr1_entry || s->stkctr2_entry)
239 session_store_counters(s);
240
241 if (!(s->listener->options & LI_O_UNLIMITED))
242 actconn--;
243 jobs--;
244 s->listener->nbconn--;
245 if (s->listener->state == LI_FULL)
246 resume_listener(s->listener);
247
248 /* Dequeues all of the listeners waiting for a resource */
249 if (!LIST_ISEMPTY(&global_listener_queue))
250 dequeue_all_listeners(&global_listener_queue);
251
252 if (!LIST_ISEMPTY(&s->fe->listener_queue) &&
253 (!s->fe->fe_sps_lim || freq_ctr_remain(&s->fe->fe_sess_per_sec, s->fe->fe_sps_lim, 0) > 0))
254 dequeue_all_listeners(&s->fe->listener_queue);
255
256 task_delete(s->task);
257 task_free(s->task);
258
259 if (fdtab[s->si[0].conn.t.sock.fd].owner)
260 fd_delete(s->si[0].conn.t.sock.fd);
261 else
262 close(s->si[0].conn.t.sock.fd);
263
264 pool_free2(pool2_session, s);
265}
266
Willy Tarreau22cda212012-08-31 17:43:29 +0200267/* Finish initializing a session from a connection, or kills it if the
268 * connection shows and error. Returns <0 if the connection was killed.
Willy Tarreau2542b532012-08-31 16:01:23 +0200269 */
Willy Tarreau071e1372012-10-03 01:39:48 +0200270static int conn_session_complete(struct connection *conn)
Willy Tarreau2542b532012-08-31 16:01:23 +0200271{
Willy Tarreau5e75e272012-10-02 21:21:20 +0200272 struct session *s = conn->owner;
Willy Tarreau2542b532012-08-31 16:01:23 +0200273
Willy Tarreau22cda212012-08-31 17:43:29 +0200274 if (!(conn->flags & CO_FL_ERROR) && (session_complete(s) > 0)) {
Willy Tarreau071e1372012-10-03 01:39:48 +0200275 conn->flags &= ~CO_FL_INIT_DATA;
Willy Tarreau2542b532012-08-31 16:01:23 +0200276 return 0;
277 }
278
279 /* kill the connection now */
280 kill_mini_session(s);
281 return -1;
282}
283
284/* Manages embryonic sessions timeout. It is only called when the timeout
285 * strikes and performs the required cleanup.
286 */
287static struct task *expire_mini_session(struct task *t)
288{
289 struct session *s = t->context;
290
291 if (!(t->state & TASK_WOKEN_TIMER))
292 return t;
293
294 kill_mini_session(s);
295 return NULL;
296}
297
298/* This function is called from the I/O handler which detects the end of
299 * handshake, in order to complete initialization of a valid session. It must
300 * be called with an embryonic session. It returns a positive value upon
301 * success, 0 if the connection can be ignored, or a negative value upon
302 * critical failure. The accepted file descriptor is closed if we return <= 0.
303 */
304int session_complete(struct session *s)
305{
306 struct listener *l = s->listener;
307 struct proxy *p = s->fe;
308 struct http_txn *txn;
309 struct task *t = s->task;
310 int ret;
311
312 ret = -1; /* assume unrecoverable error by default */
313
314 /* OK, we're keeping the session, so let's properly initialize the session */
315 LIST_ADDQ(&sessions, &s->list);
316 LIST_INIT(&s->back_refs);
Willy Tarreau5e75e272012-10-02 21:21:20 +0200317 si_takeover_conn(&s->si[0], l->proto, l->xprt);
Willy Tarreau2542b532012-08-31 16:01:23 +0200318 s->flags |= SN_INITIALIZED;
319
320 s->unique_id = NULL;
321 s->term_trace = 0;
322
323 t->process = l->handler;
324 t->context = s;
325 t->expire = TICK_ETERNITY;
326
327 /* Note: initially, the session's backend points to the frontend.
328 * This changes later when switching rules are executed or
329 * when the default backend is assigned.
330 */
331 s->be = s->fe;
332 s->req = s->rep = NULL; /* will be allocated later */
333
334 /* Let's count a session now */
Willy Tarreaub36b4242010-06-04 20:59:39 +0200335 proxy_inc_fe_sess_ctr(l, p);
Willy Tarreau56123282010-08-06 19:06:56 +0200336 if (s->stkctr1_entry) {
Willy Tarreau91c43d72010-06-20 11:19:22 +0200337 void *ptr;
338
Willy Tarreau56123282010-08-06 19:06:56 +0200339 ptr = stktable_data_ptr(s->stkctr1_table, s->stkctr1_entry, STKTABLE_DT_SESS_CNT);
Willy Tarreauf4d17d92010-06-18 22:10:12 +0200340 if (ptr)
341 stktable_data_cast(ptr, sess_cnt)++;
Willy Tarreau91c43d72010-06-20 11:19:22 +0200342
Willy Tarreau56123282010-08-06 19:06:56 +0200343 ptr = stktable_data_ptr(s->stkctr1_table, s->stkctr1_entry, STKTABLE_DT_SESS_RATE);
Willy Tarreau91c43d72010-06-20 11:19:22 +0200344 if (ptr)
345 update_freq_ctr_period(&stktable_data_cast(ptr, sess_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200346 s->stkctr1_table->data_arg[STKTABLE_DT_SESS_RATE].u, 1);
Willy Tarreauf4d17d92010-06-18 22:10:12 +0200347 }
Willy Tarreaub36b4242010-06-04 20:59:39 +0200348
Willy Tarreau56123282010-08-06 19:06:56 +0200349 if (s->stkctr2_entry) {
Willy Tarreau9e9879a2010-08-06 15:25:22 +0200350 void *ptr;
351
Willy Tarreau56123282010-08-06 19:06:56 +0200352 ptr = stktable_data_ptr(s->stkctr2_table, s->stkctr2_entry, STKTABLE_DT_SESS_CNT);
Willy Tarreau9e9879a2010-08-06 15:25:22 +0200353 if (ptr)
354 stktable_data_cast(ptr, sess_cnt)++;
355
Willy Tarreau56123282010-08-06 19:06:56 +0200356 ptr = stktable_data_ptr(s->stkctr2_table, s->stkctr2_entry, STKTABLE_DT_SESS_RATE);
Willy Tarreau9e9879a2010-08-06 15:25:22 +0200357 if (ptr)
358 update_freq_ctr_period(&stktable_data_cast(ptr, sess_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200359 s->stkctr2_table->data_arg[STKTABLE_DT_SESS_RATE].u, 1);
Willy Tarreau9e9879a2010-08-06 15:25:22 +0200360 }
361
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200362 /* this part should be common with other protocols */
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200363 s->si[0].owner = t;
364 s->si[0].state = s->si[0].prev_state = SI_ST_EST;
365 s->si[0].err_type = SI_ET_NONE;
366 s->si[0].err_loc = NULL;
Willy Tarreau0bd05ea2010-07-02 11:18:03 +0200367 s->si[0].release = NULL;
Willy Tarreau63e7fe32012-05-08 15:20:43 +0200368 s->si[0].send_proxy_ofs = 0;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200369 s->si[0].exp = TICK_ETERNITY;
370 s->si[0].flags = SI_FL_NONE;
371
372 if (likely(s->fe->options2 & PR_O2_INDEPSTR))
373 s->si[0].flags |= SI_FL_INDEP_STR;
374
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200375 /* pre-initialize the other side's stream interface to an INIT state. The
376 * callbacks will be initialized before attempting to connect.
377 */
Willy Tarreaufb7508a2012-05-21 16:47:54 +0200378 s->si[1].conn.t.sock.fd = -1; /* just to help with debugging */
Willy Tarreau505e34a2012-07-06 10:17:53 +0200379 s->si[1].conn.flags = CO_FL_NONE;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200380 s->si[1].owner = t;
381 s->si[1].state = s->si[1].prev_state = SI_ST_INI;
382 s->si[1].err_type = SI_ET_NONE;
Willy Tarreau0b3a4112011-03-27 19:16:56 +0200383 s->si[1].conn_retries = 0; /* used for logging too */
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200384 s->si[1].err_loc = NULL;
Willy Tarreau0bd05ea2010-07-02 11:18:03 +0200385 s->si[1].release = NULL;
Willy Tarreau63e7fe32012-05-08 15:20:43 +0200386 s->si[1].send_proxy_ofs = 0;
Willy Tarreau3cefd522012-08-30 15:49:18 +0200387 clear_target(&s->si[1].conn.target);
Willy Tarreauc5788912012-08-24 18:12:41 +0200388 si_prepare_embedded(&s->si[1]);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200389 s->si[1].exp = TICK_ETERNITY;
390 s->si[1].flags = SI_FL_NONE;
391
392 if (likely(s->fe->options2 & PR_O2_INDEPSTR))
393 s->si[1].flags |= SI_FL_INDEP_STR;
394
Willy Tarreau9bd0d742011-07-20 00:17:39 +0200395 session_init_srv_conn(s);
Willy Tarreau9e000c62011-03-10 14:03:36 +0100396 clear_target(&s->target);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200397 s->pend_pos = NULL;
398
399 /* init store persistence */
400 s->store_count = 0;
401
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200402 if (unlikely((s->req = pool_alloc2(pool2_channel)) == NULL))
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200403 goto out_free_task; /* no memory */
404
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200405 if (unlikely((s->rep = pool_alloc2(pool2_channel)) == NULL))
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200406 goto out_free_req; /* no memory */
407
408 /* initialize the request buffer */
Willy Tarreau572bf902012-07-02 17:01:20 +0200409 s->req->buf.size = global.tune.bufsize;
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200410 channel_init(s->req);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200411 s->req->prod = &s->si[0];
412 s->req->cons = &s->si[1];
413 s->si[0].ib = s->si[1].ob = s->req;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200414 s->req->flags |= CF_READ_ATTACHED; /* the producer is already connected */
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200415
416 /* activate default analysers enabled for this listener */
417 s->req->analysers = l->analysers;
418
419 s->req->wto = TICK_ETERNITY;
420 s->req->rto = TICK_ETERNITY;
421 s->req->rex = TICK_ETERNITY;
422 s->req->wex = TICK_ETERNITY;
423 s->req->analyse_exp = TICK_ETERNITY;
424
425 /* initialize response buffer */
Willy Tarreau572bf902012-07-02 17:01:20 +0200426 s->rep->buf.size = global.tune.bufsize;
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200427 channel_init(s->rep);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200428 s->rep->prod = &s->si[1];
429 s->rep->cons = &s->si[0];
430 s->si[0].ob = s->si[1].ib = s->rep;
431 s->rep->analysers = 0;
432
Willy Tarreau96e31212011-05-30 18:10:30 +0200433 if (s->fe->options2 & PR_O2_NODELAY) {
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200434 s->req->flags |= CF_NEVER_WAIT;
435 s->rep->flags |= CF_NEVER_WAIT;
Willy Tarreau96e31212011-05-30 18:10:30 +0200436 }
437
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200438 s->rep->rto = TICK_ETERNITY;
439 s->rep->wto = TICK_ETERNITY;
440 s->rep->rex = TICK_ETERNITY;
441 s->rep->wex = TICK_ETERNITY;
442 s->rep->analyse_exp = TICK_ETERNITY;
443
Willy Tarreau62f791e2012-03-09 11:32:30 +0100444 txn = &s->txn;
445 /* Those variables will be checked and freed if non-NULL in
446 * session.c:session_free(). It is important that they are
447 * properly initialized.
448 */
449 txn->sessid = NULL;
450 txn->srv_cookie = NULL;
451 txn->cli_cookie = NULL;
452 txn->uri = NULL;
453 txn->req.cap = NULL;
454 txn->rsp.cap = NULL;
455 txn->hdr_idx.v = NULL;
456 txn->hdr_idx.size = txn->hdr_idx.used = 0;
457 txn->req.flags = 0;
458 txn->rsp.flags = 0;
459 /* the HTTP messages need to know what buffer they're associated with */
460 txn->req.buf = s->req;
461 txn->rsp.buf = s->rep;
462
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200463 /* finish initialization of the accepted file descriptor */
Willy Tarreauf9dabec2012-08-17 17:33:53 +0200464 conn_data_want_recv(&s->si[0].conn);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200465
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100466 if (p->accept && (ret = p->accept(s)) <= 0) {
467 /* Either we had an unrecoverable error (<0) or work is
468 * finished (=0, eg: monitoring), in both situations,
469 * we can release everything and close.
470 */
471 goto out_free_rep;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200472 }
473
Willy Tarreau2542b532012-08-31 16:01:23 +0200474 /* we want the connection handler to notify the stream interface about updates. */
Willy Tarreau4aa36832012-10-02 20:07:22 +0200475 s->si[0].conn.flags |= CO_FL_WAKE_DATA;
Willy Tarreau2542b532012-08-31 16:01:23 +0200476
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200477 /* it is important not to call the wakeup function directly but to
478 * pass through task_wakeup(), because this one knows how to apply
479 * priorities to tasks.
480 */
481 task_wakeup(t, TASK_WOKEN_INIT);
482 return 1;
483
484 /* Error unrolling */
485 out_free_rep:
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200486 pool_free2(pool2_channel, s->rep);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200487 out_free_req:
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200488 pool_free2(pool2_channel, s->req);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200489 out_free_task:
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100490 return ret;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200491}
492
Willy Tarreaubaaee002006-06-26 02:48:02 +0200493/*
494 * frees the context associated to a session. It must have been removed first.
495 */
Simon Hormandec5be42011-06-08 09:19:07 +0900496static void session_free(struct session *s)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200497{
Willy Tarreau4dbc4a22007-03-03 16:23:22 +0100498 struct http_txn *txn = &s->txn;
Willy Tarreau632f5a72007-07-11 10:42:35 +0200499 struct proxy *fe = s->fe;
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100500 struct bref *bref, *back;
Willy Tarreaua4cda672010-06-06 18:28:49 +0200501 int i;
Willy Tarreau0f7562b2007-01-07 15:46:13 +0100502
Willy Tarreaubaaee002006-06-26 02:48:02 +0200503 if (s->pend_pos)
504 pendconn_free(s->pend_pos);
Willy Tarreau922a8062008-12-04 09:33:58 +0100505
Willy Tarreau827aee92011-03-10 16:55:02 +0100506 if (target_srv(&s->target)) { /* there may be requests left pending in queue */
Willy Tarreau1e62de62008-11-11 20:20:02 +0100507 if (s->flags & SN_CURR_SESS) {
508 s->flags &= ~SN_CURR_SESS;
Willy Tarreau827aee92011-03-10 16:55:02 +0100509 target_srv(&s->target)->cur_sess--;
Willy Tarreau1e62de62008-11-11 20:20:02 +0100510 }
Willy Tarreau827aee92011-03-10 16:55:02 +0100511 if (may_dequeue_tasks(target_srv(&s->target), s->be))
512 process_srv_queue(target_srv(&s->target));
Willy Tarreau1e62de62008-11-11 20:20:02 +0100513 }
Willy Tarreau922a8062008-12-04 09:33:58 +0100514
Willy Tarreau7c669d72008-06-20 15:04:11 +0200515 if (unlikely(s->srv_conn)) {
516 /* the session still has a reserved slot on a server, but
517 * it should normally be only the same as the one above,
518 * so this should not happen in fact.
519 */
520 sess_change_server(s, NULL);
521 }
522
Willy Tarreau3eba98a2009-01-25 13:56:13 +0100523 if (s->req->pipe)
524 put_pipe(s->req->pipe);
Willy Tarreau259de1b2009-01-18 21:56:21 +0100525
Willy Tarreau3eba98a2009-01-25 13:56:13 +0100526 if (s->rep->pipe)
527 put_pipe(s->rep->pipe);
Willy Tarreau259de1b2009-01-18 21:56:21 +0100528
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200529 pool_free2(pool2_channel, s->req);
530 pool_free2(pool2_channel, s->rep);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200531
Willy Tarreau46023632010-01-07 22:51:47 +0100532 http_end_txn(s);
533
Willy Tarreaua4cda672010-06-06 18:28:49 +0200534 for (i = 0; i < s->store_count; i++) {
535 if (!s->store[i].ts)
536 continue;
537 stksess_free(s->store[i].table, s->store[i].ts);
538 s->store[i].ts = NULL;
539 }
540
Willy Tarreau34eb6712011-10-24 18:15:04 +0200541 pool_free2(pool2_hdr_idx, txn->hdr_idx.v);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200542 if (fe) {
Willy Tarreau46023632010-01-07 22:51:47 +0100543 pool_free2(fe->rsp_cap_pool, txn->rsp.cap);
544 pool_free2(fe->req_cap_pool, txn->req.cap);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200545 }
Willy Tarreau0937bc42009-12-22 15:03:09 +0100546
Willy Tarreau56123282010-08-06 19:06:56 +0200547 if (s->stkctr1_entry || s->stkctr2_entry)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +0200548 session_store_counters(s);
549
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100550 list_for_each_entry_safe(bref, back, &s->back_refs, users) {
Willy Tarreaufd3828e2009-02-22 15:17:24 +0100551 /* we have to unlink all watchers. We must not relink them if
552 * this session was the last one in the list.
553 */
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100554 LIST_DEL(&bref->users);
Willy Tarreaufd3828e2009-02-22 15:17:24 +0100555 LIST_INIT(&bref->users);
556 if (s->list.n != &sessions)
557 LIST_ADDQ(&LIST_ELEM(s->list.n, struct session *, list)->back_refs, &bref->users);
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100558 bref->ref = s->list.n;
559 }
Willy Tarreauf54f8bd2008-11-23 19:53:55 +0100560 LIST_DEL(&s->list);
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200561 pool_free2(pool2_session, s);
Willy Tarreau632f5a72007-07-11 10:42:35 +0200562
563 /* We may want to free the maximum amount of pools if the proxy is stopping */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200564 if (fe && unlikely(fe->state == PR_STSTOPPED)) {
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200565 pool_flush2(pool2_channel);
Willy Tarreau34eb6712011-10-24 18:15:04 +0200566 pool_flush2(pool2_hdr_idx);
Willy Tarreau48d63db2008-08-03 17:41:33 +0200567 pool_flush2(pool2_requri);
568 pool_flush2(pool2_capture);
569 pool_flush2(pool2_session);
570 pool_flush2(fe->req_cap_pool);
571 pool_flush2(fe->rsp_cap_pool);
Willy Tarreau632f5a72007-07-11 10:42:35 +0200572 }
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200573}
574
575
576/* perform minimal intializations, report 0 in case of error, 1 if OK. */
577int init_session()
578{
Willy Tarreauf54f8bd2008-11-23 19:53:55 +0100579 LIST_INIT(&sessions);
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200580 pool2_session = create_pool("session", sizeof(struct session), MEM_F_SHARED);
581 return pool2_session != NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200582}
583
Willy Tarreau30e71012007-11-26 20:15:35 +0100584void session_process_counters(struct session *s)
585{
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100586 unsigned long long bytes;
587
Willy Tarreau30e71012007-11-26 20:15:35 +0100588 if (s->req) {
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100589 bytes = s->req->total - s->logs.bytes_in;
Willy Tarreau30e71012007-11-26 20:15:35 +0100590 s->logs.bytes_in = s->req->total;
591 if (bytes) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100592 s->fe->fe_counters.bytes_in += bytes;
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100593
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100594 s->be->be_counters.bytes_in += bytes;
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100595
Willy Tarreau827aee92011-03-10 16:55:02 +0100596 if (target_srv(&s->target))
597 target_srv(&s->target)->counters.bytes_in += bytes;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200598
599 if (s->listener->counters)
600 s->listener->counters->bytes_in += bytes;
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200601
Willy Tarreau56123282010-08-06 19:06:56 +0200602 if (s->stkctr2_entry) {
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200603 void *ptr;
604
Willy Tarreau56123282010-08-06 19:06:56 +0200605 ptr = stktable_data_ptr(s->stkctr2_table,
606 s->stkctr2_entry,
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200607 STKTABLE_DT_BYTES_IN_CNT);
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200608 if (ptr)
609 stktable_data_cast(ptr, bytes_in_cnt) += bytes;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200610
Willy Tarreau56123282010-08-06 19:06:56 +0200611 ptr = stktable_data_ptr(s->stkctr2_table,
612 s->stkctr2_entry,
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200613 STKTABLE_DT_BYTES_IN_RATE);
614 if (ptr)
615 update_freq_ctr_period(&stktable_data_cast(ptr, bytes_in_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200616 s->stkctr2_table->data_arg[STKTABLE_DT_BYTES_IN_RATE].u, bytes);
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200617 }
618
Willy Tarreau56123282010-08-06 19:06:56 +0200619 if (s->stkctr1_entry) {
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200620 void *ptr;
621
Willy Tarreau56123282010-08-06 19:06:56 +0200622 ptr = stktable_data_ptr(s->stkctr1_table,
623 s->stkctr1_entry,
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200624 STKTABLE_DT_BYTES_IN_CNT);
625 if (ptr)
626 stktable_data_cast(ptr, bytes_in_cnt) += bytes;
627
Willy Tarreau56123282010-08-06 19:06:56 +0200628 ptr = stktable_data_ptr(s->stkctr1_table,
629 s->stkctr1_entry,
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200630 STKTABLE_DT_BYTES_IN_RATE);
631 if (ptr)
632 update_freq_ctr_period(&stktable_data_cast(ptr, bytes_in_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200633 s->stkctr1_table->data_arg[STKTABLE_DT_BYTES_IN_RATE].u, bytes);
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200634 }
Willy Tarreau30e71012007-11-26 20:15:35 +0100635 }
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100636 }
637
Willy Tarreau30e71012007-11-26 20:15:35 +0100638 if (s->rep) {
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100639 bytes = s->rep->total - s->logs.bytes_out;
Willy Tarreau30e71012007-11-26 20:15:35 +0100640 s->logs.bytes_out = s->rep->total;
641 if (bytes) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100642 s->fe->fe_counters.bytes_out += bytes;
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100643
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100644 s->be->be_counters.bytes_out += bytes;
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100645
Willy Tarreau827aee92011-03-10 16:55:02 +0100646 if (target_srv(&s->target))
647 target_srv(&s->target)->counters.bytes_out += bytes;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200648
649 if (s->listener->counters)
650 s->listener->counters->bytes_out += bytes;
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200651
Willy Tarreau56123282010-08-06 19:06:56 +0200652 if (s->stkctr2_entry) {
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200653 void *ptr;
654
Willy Tarreau56123282010-08-06 19:06:56 +0200655 ptr = stktable_data_ptr(s->stkctr2_table,
656 s->stkctr2_entry,
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200657 STKTABLE_DT_BYTES_OUT_CNT);
658 if (ptr)
659 stktable_data_cast(ptr, bytes_out_cnt) += bytes;
660
Willy Tarreau56123282010-08-06 19:06:56 +0200661 ptr = stktable_data_ptr(s->stkctr2_table,
662 s->stkctr2_entry,
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200663 STKTABLE_DT_BYTES_OUT_RATE);
664 if (ptr)
665 update_freq_ctr_period(&stktable_data_cast(ptr, bytes_out_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200666 s->stkctr2_table->data_arg[STKTABLE_DT_BYTES_OUT_RATE].u, bytes);
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200667 }
668
Willy Tarreau56123282010-08-06 19:06:56 +0200669 if (s->stkctr1_entry) {
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200670 void *ptr;
671
Willy Tarreau56123282010-08-06 19:06:56 +0200672 ptr = stktable_data_ptr(s->stkctr1_table,
673 s->stkctr1_entry,
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200674 STKTABLE_DT_BYTES_OUT_CNT);
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200675 if (ptr)
676 stktable_data_cast(ptr, bytes_out_cnt) += bytes;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200677
Willy Tarreau56123282010-08-06 19:06:56 +0200678 ptr = stktable_data_ptr(s->stkctr1_table,
679 s->stkctr1_entry,
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200680 STKTABLE_DT_BYTES_OUT_RATE);
681 if (ptr)
682 update_freq_ctr_period(&stktable_data_cast(ptr, bytes_out_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200683 s->stkctr1_table->data_arg[STKTABLE_DT_BYTES_OUT_RATE].u, bytes);
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200684 }
Willy Tarreau30e71012007-11-26 20:15:35 +0100685 }
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100686 }
687}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200688
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100689/* This function is called with (si->state == SI_ST_CON) meaning that a
690 * connection was attempted and that the file descriptor is already allocated.
691 * We must check for establishment, error and abort. Possible output states
692 * are SI_ST_EST (established), SI_ST_CER (error), SI_ST_DIS (abort), and
693 * SI_ST_CON (no change). The function returns 0 if it switches to SI_ST_CER,
694 * otherwise 1.
695 */
Simon Hormandec5be42011-06-08 09:19:07 +0900696static int sess_update_st_con_tcp(struct session *s, struct stream_interface *si)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100697{
Willy Tarreau7421efb2012-07-02 15:11:27 +0200698 struct channel *req = si->ob;
699 struct channel *rep = si->ib;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100700
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100701 /* If we got an error, or if nothing happened and the connection timed
702 * out, we must give up. The CER state handler will take care of retry
703 * attempts and error reports.
704 */
705 if (unlikely(si->flags & (SI_FL_EXP|SI_FL_ERR))) {
Willy Tarreau127334e2009-03-28 10:47:26 +0100706 si->exp = TICK_ETERNITY;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100707 si->state = SI_ST_CER;
Willy Tarreaufb7508a2012-05-21 16:47:54 +0200708 fd_delete(si_fd(si));
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100709
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200710 conn_xprt_close(&si->conn);
Willy Tarreau0bd05ea2010-07-02 11:18:03 +0200711 if (si->release)
712 si->release(si);
713
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100714 if (si->err_type)
715 return 0;
716
Willy Tarreau827aee92011-03-10 16:55:02 +0100717 si->err_loc = target_srv(&s->target);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100718 if (si->flags & SI_FL_ERR)
719 si->err_type = SI_ET_CONN_ERR;
720 else
721 si->err_type = SI_ET_CONN_TO;
722 return 0;
723 }
724
725 /* OK, maybe we want to abort */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200726 if (unlikely((rep->flags & CF_SHUTW) ||
727 ((req->flags & CF_SHUTW_NOW) && /* FIXME: this should not prevent a connection from establishing */
728 ((!(req->flags & CF_WRITE_ACTIVITY) && channel_is_empty(req)) ||
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100729 s->be->options & PR_O_ABRT_CLOSE)))) {
730 /* give up */
Willy Tarreau73b013b2012-05-21 16:31:45 +0200731 si_shutw(si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100732 si->err_type |= SI_ET_CONN_ABRT;
Willy Tarreau827aee92011-03-10 16:55:02 +0100733 si->err_loc = target_srv(&s->target);
Willy Tarreau84455332009-03-15 22:34:05 +0100734 if (s->srv_error)
735 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100736 return 1;
737 }
738
739 /* we need to wait a bit more if there was no activity either */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200740 if (!(req->flags & CF_WRITE_ACTIVITY))
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100741 return 1;
742
743 /* OK, this means that a connection succeeded. The caller will be
744 * responsible for handling the transition from CON to EST.
745 */
746 s->logs.t_connect = tv_ms_elapsed(&s->logs.tv_accept, &now);
Willy Tarreau127334e2009-03-28 10:47:26 +0100747 si->exp = TICK_ETERNITY;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100748 si->state = SI_ST_EST;
749 si->err_type = SI_ET_NONE;
750 si->err_loc = NULL;
751 return 1;
752}
753
754/* This function is called with (si->state == SI_ST_CER) meaning that a
755 * previous connection attempt has failed and that the file descriptor
756 * has already been released. Possible causes include asynchronous error
757 * notification and time out. Possible output states are SI_ST_CLO when
758 * retries are exhausted, SI_ST_TAR when a delay is wanted before a new
759 * connection attempt, SI_ST_ASS when it's wise to retry on the same server,
760 * and SI_ST_REQ when an immediate redispatch is wanted. The buffers are
761 * marked as in error state. It returns 0.
762 */
Simon Hormandec5be42011-06-08 09:19:07 +0900763static int sess_update_st_cer(struct session *s, struct stream_interface *si)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100764{
765 /* we probably have to release last session from the server */
Willy Tarreau827aee92011-03-10 16:55:02 +0100766 if (target_srv(&s->target)) {
767 health_adjust(target_srv(&s->target), HANA_STATUS_L4_ERR);
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +0100768
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100769 if (s->flags & SN_CURR_SESS) {
770 s->flags &= ~SN_CURR_SESS;
Willy Tarreau827aee92011-03-10 16:55:02 +0100771 target_srv(&s->target)->cur_sess--;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100772 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100773 }
774
775 /* ensure that we have enough retries left */
Willy Tarreauee28de02010-06-01 09:51:00 +0200776 si->conn_retries--;
777 if (si->conn_retries < 0) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100778 if (!si->err_type) {
779 si->err_type = SI_ET_CONN_ERR;
Willy Tarreau827aee92011-03-10 16:55:02 +0100780 si->err_loc = target_srv(&s->target);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100781 }
782
Willy Tarreau827aee92011-03-10 16:55:02 +0100783 if (target_srv(&s->target))
784 target_srv(&s->target)->counters.failed_conns++;
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100785 s->be->be_counters.failed_conns++;
Willy Tarreaub89cfca2010-12-29 14:32:28 +0100786 sess_change_server(s, NULL);
Willy Tarreau827aee92011-03-10 16:55:02 +0100787 if (may_dequeue_tasks(target_srv(&s->target), s->be))
788 process_srv_queue(target_srv(&s->target));
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100789
790 /* shutw is enough so stop a connecting socket */
Willy Tarreau73b013b2012-05-21 16:31:45 +0200791 si_shutw(si);
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200792 si->ob->flags |= CF_WRITE_ERROR;
793 si->ib->flags |= CF_READ_ERROR;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100794
795 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +0100796 if (s->srv_error)
797 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100798 return 0;
799 }
800
801 /* If the "redispatch" option is set on the backend, we are allowed to
802 * retry on another server for the last retry. In order to achieve this,
803 * we must mark the session unassigned, and eventually clear the DIRECT
804 * bit to ignore any persistence cookie. We won't count a retry nor a
805 * redispatch yet, because this will depend on what server is selected.
806 */
Willy Tarreau827aee92011-03-10 16:55:02 +0100807 if (target_srv(&s->target) && si->conn_retries == 0 &&
Willy Tarreau4de91492010-01-22 19:10:05 +0100808 s->be->options & PR_O_REDISP && !(s->flags & SN_FORCE_PRST)) {
Willy Tarreaub89cfca2010-12-29 14:32:28 +0100809 sess_change_server(s, NULL);
Willy Tarreau827aee92011-03-10 16:55:02 +0100810 if (may_dequeue_tasks(target_srv(&s->target), s->be))
811 process_srv_queue(target_srv(&s->target));
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100812
813 s->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100814 si->state = SI_ST_REQ;
815 } else {
Willy Tarreau827aee92011-03-10 16:55:02 +0100816 if (target_srv(&s->target))
817 target_srv(&s->target)->counters.retries++;
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100818 s->be->be_counters.retries++;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100819 si->state = SI_ST_ASS;
820 }
821
822 if (si->flags & SI_FL_ERR) {
823 /* The error was an asynchronous connection error, and we will
824 * likely have to retry connecting to the same server, most
825 * likely leading to the same result. To avoid this, we wait
826 * one second before retrying.
827 */
828
829 if (!si->err_type)
830 si->err_type = SI_ET_CONN_ERR;
831
832 si->state = SI_ST_TAR;
833 si->exp = tick_add(now_ms, MS_TO_TICKS(1000));
834 return 0;
835 }
836 return 0;
837}
838
839/*
840 * This function handles the transition between the SI_ST_CON state and the
Willy Tarreau85e7d002010-05-31 11:57:51 +0200841 * SI_ST_EST state. It must only be called after switching from SI_ST_CON (or
Willy Tarreau26d8c592012-05-07 18:12:14 +0200842 * SI_ST_INI) to SI_ST_EST, but only when a ->proto is defined.
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100843 */
Simon Hormandec5be42011-06-08 09:19:07 +0900844static void sess_establish(struct session *s, struct stream_interface *si)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100845{
Willy Tarreau7421efb2012-07-02 15:11:27 +0200846 struct channel *req = si->ob;
847 struct channel *rep = si->ib;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100848
Willy Tarreau827aee92011-03-10 16:55:02 +0100849 if (target_srv(&s->target))
850 health_adjust(target_srv(&s->target), HANA_STATUS_L4_OK);
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +0100851
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100852 if (s->be->mode == PR_MODE_TCP) { /* let's allow immediate data connection in this case */
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100853 /* if the user wants to log as soon as possible, without counting
854 * bytes from the server, then this is the right moment. */
855 if (s->fe->to_log && !(s->logs.logwait & LW_BYTES)) {
856 s->logs.t_close = s->logs.t_connect; /* to get a valid end date */
Willy Tarreaua5555ec2008-11-30 19:02:32 +0100857 s->do_log(s);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100858 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100859 }
860 else {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100861 s->txn.rsp.msg_state = HTTP_MSG_RPBEFORE;
862 /* reset hdr_idx which was already initialized by the request.
863 * right now, the http parser does it.
864 * hdr_idx_init(&s->txn.hdr_idx);
865 */
866 }
867
Willy Tarreau4e5b8282009-08-16 22:57:50 +0200868 rep->analysers |= s->fe->fe_rsp_ana | s->be->be_rsp_ana;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200869 rep->flags |= CF_READ_ATTACHED; /* producer is now attached */
Willy Tarreau73b013b2012-05-21 16:31:45 +0200870 if (si_ctrl(si)) {
Willy Tarreaud04e8582010-05-31 12:31:35 +0200871 /* real connections have timeouts */
872 req->wto = s->be->timeout.server;
873 rep->rto = s->be->timeout.server;
874 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100875 req->wex = TICK_ETERNITY;
876}
877
878/* Update stream interface status for input states SI_ST_ASS, SI_ST_QUE, SI_ST_TAR.
879 * Other input states are simply ignored.
880 * Possible output states are SI_ST_CLO, SI_ST_TAR, SI_ST_ASS, SI_ST_REQ, SI_ST_CON.
881 * Flags must have previously been updated for timeouts and other conditions.
882 */
Simon Hormandec5be42011-06-08 09:19:07 +0900883static void sess_update_stream_int(struct session *s, struct stream_interface *si)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100884{
Willy Tarreau827aee92011-03-10 16:55:02 +0100885 struct server *srv = target_srv(&s->target);
886
Willy Tarreau02d6cfc2012-03-01 18:19:58 +0100887 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 +0100888 now_ms, __FUNCTION__,
889 s,
890 s->req, s->rep,
891 s->req->rex, s->rep->wex,
892 s->req->flags, s->rep->flags,
Cyril Bonté3aaba442012-09-23 14:19:12 +0200893 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 +0100894
895 if (si->state == SI_ST_ASS) {
896 /* Server assigned to connection request, we have to try to connect now */
897 int conn_err;
898
899 conn_err = connect_server(s);
Willy Tarreau827aee92011-03-10 16:55:02 +0100900 srv = target_srv(&s->target);
901
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100902 if (conn_err == SN_ERR_NONE) {
903 /* state = SI_ST_CON now */
Willy Tarreau827aee92011-03-10 16:55:02 +0100904 if (srv)
905 srv_inc_sess_ctr(srv);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100906 return;
907 }
908
909 /* We have received a synchronous error. We might have to
910 * abort, retry immediately or redispatch.
911 */
912 if (conn_err == SN_ERR_INTERNAL) {
913 if (!si->err_type) {
914 si->err_type = SI_ET_CONN_OTHER;
Willy Tarreau827aee92011-03-10 16:55:02 +0100915 si->err_loc = srv;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100916 }
917
Willy Tarreau827aee92011-03-10 16:55:02 +0100918 if (srv)
919 srv_inc_sess_ctr(srv);
920 if (srv)
921 srv->counters.failed_conns++;
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100922 s->be->be_counters.failed_conns++;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100923
924 /* release other sessions waiting for this server */
Willy Tarreaub89cfca2010-12-29 14:32:28 +0100925 sess_change_server(s, NULL);
Willy Tarreau827aee92011-03-10 16:55:02 +0100926 if (may_dequeue_tasks(srv, s->be))
927 process_srv_queue(srv);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100928
929 /* Failed and not retryable. */
Willy Tarreau73b013b2012-05-21 16:31:45 +0200930 si_shutr(si);
931 si_shutw(si);
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200932 si->ob->flags |= CF_WRITE_ERROR;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100933
934 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
935
936 /* no session was ever accounted for this server */
937 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +0100938 if (s->srv_error)
939 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100940 return;
941 }
942
943 /* We are facing a retryable error, but we don't want to run a
944 * turn-around now, as the problem is likely a source port
945 * allocation problem, so we want to retry now.
946 */
947 si->state = SI_ST_CER;
948 si->flags &= ~SI_FL_ERR;
949 sess_update_st_cer(s, si);
950 /* now si->state is one of SI_ST_CLO, SI_ST_TAR, SI_ST_ASS, SI_ST_REQ */
951 return;
952 }
953 else if (si->state == SI_ST_QUE) {
954 /* connection request was queued, check for any update */
955 if (!s->pend_pos) {
956 /* The connection is not in the queue anymore. Either
957 * we have a server connection slot available and we
958 * go directly to the assigned state, or we need to
959 * load-balance first and go to the INI state.
960 */
961 si->exp = TICK_ETERNITY;
962 if (unlikely(!(s->flags & SN_ASSIGNED)))
963 si->state = SI_ST_REQ;
964 else {
965 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
966 si->state = SI_ST_ASS;
967 }
968 return;
969 }
970
971 /* Connection request still in queue... */
972 if (si->flags & SI_FL_EXP) {
973 /* ... and timeout expired */
974 si->exp = TICK_ETERNITY;
975 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
Willy Tarreau827aee92011-03-10 16:55:02 +0100976 if (srv)
977 srv->counters.failed_conns++;
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100978 s->be->be_counters.failed_conns++;
Willy Tarreau73b013b2012-05-21 16:31:45 +0200979 si_shutr(si);
980 si_shutw(si);
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200981 si->ob->flags |= CF_WRITE_TIMEOUT;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100982 if (!si->err_type)
983 si->err_type = SI_ET_QUEUE_TO;
984 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +0100985 if (s->srv_error)
986 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100987 return;
988 }
989
990 /* Connection remains in queue, check if we have to abort it */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200991 if ((si->ob->flags & (CF_READ_ERROR)) ||
992 ((si->ob->flags & CF_SHUTW_NOW) && /* empty and client aborted */
Willy Tarreau8e21bb92012-08-24 22:40:29 +0200993 (channel_is_empty(si->ob) || s->be->options & PR_O_ABRT_CLOSE))) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100994 /* give up */
995 si->exp = TICK_ETERNITY;
996 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
Willy Tarreau73b013b2012-05-21 16:31:45 +0200997 si_shutr(si);
998 si_shutw(si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100999 si->err_type |= SI_ET_QUEUE_ABRT;
1000 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +01001001 if (s->srv_error)
1002 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001003 return;
1004 }
1005
1006 /* Nothing changed */
1007 return;
1008 }
1009 else if (si->state == SI_ST_TAR) {
1010 /* Connection request might be aborted */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001011 if ((si->ob->flags & (CF_READ_ERROR)) ||
1012 ((si->ob->flags & CF_SHUTW_NOW) && /* empty and client aborted */
Willy Tarreau8e21bb92012-08-24 22:40:29 +02001013 (channel_is_empty(si->ob) || s->be->options & PR_O_ABRT_CLOSE))) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001014 /* give up */
1015 si->exp = TICK_ETERNITY;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001016 si_shutr(si);
1017 si_shutw(si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001018 si->err_type |= SI_ET_CONN_ABRT;
1019 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +01001020 if (s->srv_error)
1021 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001022 return;
1023 }
1024
1025 if (!(si->flags & SI_FL_EXP))
1026 return; /* still in turn-around */
1027
1028 si->exp = TICK_ETERNITY;
1029
1030 /* we keep trying on the same server as long as the session is
1031 * marked "assigned".
1032 * FIXME: Should we force a redispatch attempt when the server is down ?
1033 */
1034 if (s->flags & SN_ASSIGNED)
1035 si->state = SI_ST_ASS;
1036 else
1037 si->state = SI_ST_REQ;
1038 return;
1039 }
1040}
1041
Simon Hormandec5be42011-06-08 09:19:07 +09001042/* Set correct session termination flags in case no analyser has done it. It
1043 * also counts a failed request if the server state has not reached the request
1044 * stage.
1045 */
1046static void sess_set_term_flags(struct session *s)
1047{
1048 if (!(s->flags & SN_FINST_MASK)) {
1049 if (s->si[1].state < SI_ST_REQ) {
1050
1051 s->fe->fe_counters.failed_req++;
1052 if (s->listener->counters)
1053 s->listener->counters->failed_req++;
1054
1055 s->flags |= SN_FINST_R;
1056 }
1057 else if (s->si[1].state == SI_ST_QUE)
1058 s->flags |= SN_FINST_Q;
1059 else if (s->si[1].state < SI_ST_EST)
1060 s->flags |= SN_FINST_C;
1061 else if (s->si[1].state == SI_ST_EST || s->si[1].prev_state == SI_ST_EST)
1062 s->flags |= SN_FINST_D;
1063 else
1064 s->flags |= SN_FINST_L;
1065 }
1066}
1067
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001068/* This function initiates a server connection request on a stream interface
1069 * already in SI_ST_REQ state. Upon success, the state goes to SI_ST_ASS,
1070 * indicating that a server has been assigned. It may also return SI_ST_QUE,
1071 * or SI_ST_CLO upon error.
1072 */
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001073static void sess_prepare_conn_req(struct session *s, struct stream_interface *si)
1074{
1075 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 +01001076 now_ms, __FUNCTION__,
1077 s,
1078 s->req, s->rep,
1079 s->req->rex, s->rep->wex,
1080 s->req->flags, s->rep->flags,
Cyril Bonté3aaba442012-09-23 14:19:12 +02001081 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 +01001082
1083 if (si->state != SI_ST_REQ)
1084 return;
1085
1086 /* Try to assign a server */
1087 if (srv_redispatch_connect(s) != 0) {
1088 /* We did not get a server. Either we queued the
1089 * connection request, or we encountered an error.
1090 */
1091 if (si->state == SI_ST_QUE)
1092 return;
1093
1094 /* we did not get any server, let's check the cause */
Willy Tarreau73b013b2012-05-21 16:31:45 +02001095 si_shutr(si);
1096 si_shutw(si);
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001097 si->ob->flags |= CF_WRITE_ERROR;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001098 if (!si->err_type)
1099 si->err_type = SI_ET_CONN_OTHER;
1100 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +01001101 if (s->srv_error)
1102 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001103 return;
1104 }
1105
1106 /* The server is assigned */
1107 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
1108 si->state = SI_ST_ASS;
1109}
1110
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001111/* This stream analyser checks the switching rules and changes the backend
Willy Tarreau4de91492010-01-22 19:10:05 +01001112 * if appropriate. The default_backend rule is also considered, then the
1113 * target backend's forced persistence rules are also evaluated last if any.
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001114 * It returns 1 if the processing can continue on next analysers, or zero if it
1115 * either needs more data or wants to immediately abort the request.
1116 */
Willy Tarreau7421efb2012-07-02 15:11:27 +02001117static int process_switching_rules(struct session *s, struct channel *req, int an_bit)
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001118{
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001119 struct persist_rule *prst_rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01001120
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001121 req->analysers &= ~an_bit;
1122 req->analyse_exp = TICK_ETERNITY;
1123
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001124 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 +02001125 now_ms, __FUNCTION__,
1126 s,
1127 req,
1128 req->rex, req->wex,
1129 req->flags,
Cyril Bonté3aaba442012-09-23 14:19:12 +02001130 req->buf.i,
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001131 req->analysers);
1132
1133 /* now check whether we have some switching rules for this request */
1134 if (!(s->flags & SN_BE_ASSIGNED)) {
1135 struct switching_rule *rule;
1136
1137 list_for_each_entry(rule, &s->fe->switching_rules, list) {
1138 int ret;
1139
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001140 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 +02001141 ret = acl_pass(ret);
1142 if (rule->cond->pol == ACL_COND_UNLESS)
1143 ret = !ret;
1144
1145 if (ret) {
Willy Tarreaubedb9ba2009-07-12 08:27:39 +02001146 if (!session_set_backend(s, rule->be.backend))
1147 goto sw_failed;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001148 break;
1149 }
1150 }
1151
1152 /* To ensure correct connection accounting on the backend, we
1153 * have to assign one if it was not set (eg: a listen). This
1154 * measure also takes care of correctly setting the default
1155 * backend if any.
1156 */
1157 if (!(s->flags & SN_BE_ASSIGNED))
Willy Tarreaubedb9ba2009-07-12 08:27:39 +02001158 if (!session_set_backend(s, s->fe->defbe.be ? s->fe->defbe.be : s->be))
1159 goto sw_failed;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001160 }
1161
Willy Tarreaufb356202010-08-03 14:02:05 +02001162 /* we don't want to run the TCP or HTTP filters again if the backend has not changed */
1163 if (s->fe == s->be) {
1164 s->req->analysers &= ~AN_REQ_INSPECT_BE;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001165 s->req->analysers &= ~AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaufb356202010-08-03 14:02:05 +02001166 }
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001167
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001168 /* 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 +01001169 * persistence rule, and report that in the session.
1170 */
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001171 list_for_each_entry(prst_rule, &s->be->persist_rules, list) {
Willy Tarreau4de91492010-01-22 19:10:05 +01001172 int ret = 1;
1173
1174 if (prst_rule->cond) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001175 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 +01001176 ret = acl_pass(ret);
1177 if (prst_rule->cond->pol == ACL_COND_UNLESS)
1178 ret = !ret;
1179 }
1180
1181 if (ret) {
1182 /* no rule, or the rule matches */
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001183 if (prst_rule->type == PERSIST_TYPE_FORCE) {
1184 s->flags |= SN_FORCE_PRST;
1185 } else {
1186 s->flags |= SN_IGNORE_PRST;
1187 }
Willy Tarreau4de91492010-01-22 19:10:05 +01001188 break;
1189 }
1190 }
1191
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001192 return 1;
Willy Tarreaubedb9ba2009-07-12 08:27:39 +02001193
1194 sw_failed:
1195 /* immediately abort this request in case of allocation failure */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001196 channel_abort(s->req);
1197 channel_abort(s->rep);
Willy Tarreaubedb9ba2009-07-12 08:27:39 +02001198
1199 if (!(s->flags & SN_ERR_MASK))
1200 s->flags |= SN_ERR_RESOURCE;
1201 if (!(s->flags & SN_FINST_MASK))
1202 s->flags |= SN_FINST_R;
1203
1204 s->txn.status = 500;
1205 s->req->analysers = 0;
1206 s->req->analyse_exp = TICK_ETERNITY;
1207 return 0;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001208}
1209
Willy Tarreau4a5cade2012-04-05 21:09:48 +02001210/* This stream analyser works on a request. It applies all use-server rules on
1211 * it then returns 1. The data must already be present in the buffer otherwise
1212 * they won't match. It always returns 1.
1213 */
Willy Tarreau7421efb2012-07-02 15:11:27 +02001214static int process_server_rules(struct session *s, struct channel *req, int an_bit)
Willy Tarreau4a5cade2012-04-05 21:09:48 +02001215{
1216 struct proxy *px = s->be;
1217 struct server_rule *rule;
1218
1219 DPRINTF(stderr,"[%u] %s: session=%p b=%p, exp(r,w)=%u,%u bf=%08x bl=%d analysers=%02x\n",
1220 now_ms, __FUNCTION__,
1221 s,
1222 req,
1223 req->rex, req->wex,
1224 req->flags,
Cyril Bonté3aaba442012-09-23 14:19:12 +02001225 req->buf.i + req->buf.o,
Willy Tarreau4a5cade2012-04-05 21:09:48 +02001226 req->analysers);
1227
1228 if (!(s->flags & SN_ASSIGNED)) {
1229 list_for_each_entry(rule, &px->server_rules, list) {
1230 int ret;
1231
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001232 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 +02001233 ret = acl_pass(ret);
1234 if (rule->cond->pol == ACL_COND_UNLESS)
1235 ret = !ret;
1236
1237 if (ret) {
1238 struct server *srv = rule->srv.ptr;
1239
1240 if ((srv->state & SRV_RUNNING) ||
1241 (px->options & PR_O_PERSIST) ||
1242 (s->flags & SN_FORCE_PRST)) {
1243 s->flags |= SN_DIRECT | SN_ASSIGNED;
1244 set_target_server(&s->target, srv);
1245 break;
1246 }
1247 /* if the server is not UP, let's go on with next rules
1248 * just in case another one is suited.
1249 */
1250 }
1251 }
1252 }
1253
1254 req->analysers &= ~an_bit;
1255 req->analyse_exp = TICK_ETERNITY;
1256 return 1;
1257}
1258
Emeric Brun1d33b292010-01-04 15:47:17 +01001259/* This stream analyser works on a request. It applies all sticking rules on
1260 * it then returns 1. The data must already be present in the buffer otherwise
1261 * they won't match. It always returns 1.
1262 */
Willy Tarreau7421efb2012-07-02 15:11:27 +02001263static int process_sticking_rules(struct session *s, struct channel *req, int an_bit)
Emeric Brun1d33b292010-01-04 15:47:17 +01001264{
1265 struct proxy *px = s->be;
1266 struct sticking_rule *rule;
1267
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001268 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 +01001269 now_ms, __FUNCTION__,
1270 s,
1271 req,
1272 req->rex, req->wex,
1273 req->flags,
Cyril Bonté3aaba442012-09-23 14:19:12 +02001274 req->buf.i,
Emeric Brun1d33b292010-01-04 15:47:17 +01001275 req->analysers);
1276
1277 list_for_each_entry(rule, &px->sticking_rules, list) {
1278 int ret = 1 ;
1279 int i;
1280
1281 for (i = 0; i < s->store_count; i++) {
1282 if (rule->table.t == s->store[i].table)
1283 break;
1284 }
1285
1286 if (i != s->store_count)
1287 continue;
1288
1289 if (rule->cond) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001290 ret = acl_exec_cond(rule->cond, px, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
Emeric Brun1d33b292010-01-04 15:47:17 +01001291 ret = acl_pass(ret);
1292 if (rule->cond->pol == ACL_COND_UNLESS)
1293 ret = !ret;
1294 }
1295
1296 if (ret) {
1297 struct stktable_key *key;
1298
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001299 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 +01001300 if (!key)
1301 continue;
1302
1303 if (rule->flags & STK_IS_MATCH) {
1304 struct stksess *ts;
1305
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001306 if ((ts = stktable_lookup_key(rule->table.t, key)) != NULL) {
Emeric Brun1d33b292010-01-04 15:47:17 +01001307 if (!(s->flags & SN_ASSIGNED)) {
1308 struct eb32_node *node;
Willy Tarreau13c29de2010-06-06 16:40:39 +02001309 void *ptr;
Emeric Brun1d33b292010-01-04 15:47:17 +01001310
1311 /* srv found in table */
Willy Tarreau13c29de2010-06-06 16:40:39 +02001312 ptr = stktable_data_ptr(rule->table.t, ts, STKTABLE_DT_SERVER_ID);
1313 node = eb32_lookup(&px->conf.used_server_id, stktable_data_cast(ptr, server_id));
Emeric Brun1d33b292010-01-04 15:47:17 +01001314 if (node) {
1315 struct server *srv;
1316
1317 srv = container_of(node, struct server, conf.id);
Willy Tarreau4de91492010-01-22 19:10:05 +01001318 if ((srv->state & SRV_RUNNING) ||
1319 (px->options & PR_O_PERSIST) ||
1320 (s->flags & SN_FORCE_PRST)) {
Emeric Brun1d33b292010-01-04 15:47:17 +01001321 s->flags |= SN_DIRECT | SN_ASSIGNED;
Willy Tarreau9e000c62011-03-10 14:03:36 +01001322 set_target_server(&s->target, srv);
Emeric Brun1d33b292010-01-04 15:47:17 +01001323 }
1324 }
1325 }
Emeric Brun85e77c72010-09-23 18:16:52 +02001326 stktable_touch(rule->table.t, ts, 1);
Emeric Brun1d33b292010-01-04 15:47:17 +01001327 }
1328 }
1329 if (rule->flags & STK_IS_STORE) {
1330 if (s->store_count < (sizeof(s->store) / sizeof(s->store[0]))) {
1331 struct stksess *ts;
1332
1333 ts = stksess_new(rule->table.t, key);
1334 if (ts) {
1335 s->store[s->store_count].table = rule->table.t;
1336 s->store[s->store_count++].ts = ts;
1337 }
1338 }
1339 }
1340 }
1341 }
1342
1343 req->analysers &= ~an_bit;
1344 req->analyse_exp = TICK_ETERNITY;
1345 return 1;
1346}
1347
1348/* This stream analyser works on a response. It applies all store rules on it
1349 * then returns 1. The data must already be present in the buffer otherwise
1350 * they won't match. It always returns 1.
1351 */
Willy Tarreau7421efb2012-07-02 15:11:27 +02001352static int process_store_rules(struct session *s, struct channel *rep, int an_bit)
Emeric Brun1d33b292010-01-04 15:47:17 +01001353{
1354 struct proxy *px = s->be;
1355 struct sticking_rule *rule;
1356 int i;
1357
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001358 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 +01001359 now_ms, __FUNCTION__,
1360 s,
Willy Tarreau2e2b3eb2010-02-09 20:55:44 +01001361 rep,
1362 rep->rex, rep->wex,
1363 rep->flags,
Cyril Bonté3aaba442012-09-23 14:19:12 +02001364 rep->buf.i,
Willy Tarreau2e2b3eb2010-02-09 20:55:44 +01001365 rep->analysers);
Emeric Brun1d33b292010-01-04 15:47:17 +01001366
1367 list_for_each_entry(rule, &px->storersp_rules, list) {
1368 int ret = 1 ;
1369 int storereqidx = -1;
1370
1371 for (i = 0; i < s->store_count; i++) {
1372 if (rule->table.t == s->store[i].table) {
1373 if (!(s->store[i].flags))
1374 storereqidx = i;
1375 break;
1376 }
1377 }
1378
1379 if ((i != s->store_count) && (storereqidx == -1))
1380 continue;
1381
1382 if (rule->cond) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001383 ret = acl_exec_cond(rule->cond, px, s, &s->txn, SMP_OPT_DIR_RES|SMP_OPT_FINAL);
Emeric Brun1d33b292010-01-04 15:47:17 +01001384 ret = acl_pass(ret);
1385 if (rule->cond->pol == ACL_COND_UNLESS)
1386 ret = !ret;
1387 }
1388
1389 if (ret) {
1390 struct stktable_key *key;
1391
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001392 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 +01001393 if (!key)
1394 continue;
1395
1396 if (storereqidx != -1) {
Willy Tarreau393379c2010-06-06 12:11:37 +02001397 stksess_setkey(s->store[storereqidx].table, s->store[storereqidx].ts, key);
Emeric Brun1d33b292010-01-04 15:47:17 +01001398 s->store[storereqidx].flags = 1;
1399 }
1400 else if (s->store_count < (sizeof(s->store) / sizeof(s->store[0]))) {
1401 struct stksess *ts;
1402
1403 ts = stksess_new(rule->table.t, key);
1404 if (ts) {
1405 s->store[s->store_count].table = rule->table.t;
1406 s->store[s->store_count].flags = 1;
1407 s->store[s->store_count++].ts = ts;
1408 }
1409 }
1410 }
1411 }
1412
1413 /* process store request and store response */
1414 for (i = 0; i < s->store_count; i++) {
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001415 struct stksess *ts;
Willy Tarreau13c29de2010-06-06 16:40:39 +02001416 void *ptr;
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001417
Simon Hormanfa461682011-06-25 09:39:49 +09001418 if (target_srv(&s->target) && target_srv(&s->target)->state & SRV_NON_STICK) {
1419 stksess_free(s->store[i].table, s->store[i].ts);
1420 s->store[i].ts = NULL;
1421 continue;
1422 }
1423
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001424 ts = stktable_lookup(s->store[i].table, s->store[i].ts);
1425 if (ts) {
1426 /* the entry already existed, we can free ours */
Emeric Brun85e77c72010-09-23 18:16:52 +02001427 stktable_touch(s->store[i].table, ts, 1);
Emeric Brun1d33b292010-01-04 15:47:17 +01001428 stksess_free(s->store[i].table, s->store[i].ts);
Emeric Brun1d33b292010-01-04 15:47:17 +01001429 }
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001430 else
Emeric Brun85e77c72010-09-23 18:16:52 +02001431 ts = stktable_store(s->store[i].table, s->store[i].ts, 1);
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001432
1433 s->store[i].ts = NULL;
Willy Tarreau13c29de2010-06-06 16:40:39 +02001434 ptr = stktable_data_ptr(s->store[i].table, ts, STKTABLE_DT_SERVER_ID);
Willy Tarreau827aee92011-03-10 16:55:02 +01001435 stktable_data_cast(ptr, server_id) = target_srv(&s->target)->puid;
Emeric Brun1d33b292010-01-04 15:47:17 +01001436 }
Willy Tarreau2a164ee2010-06-18 09:57:45 +02001437 s->store_count = 0; /* everything is stored */
Emeric Brun1d33b292010-01-04 15:47:17 +01001438
1439 rep->analysers &= ~an_bit;
1440 rep->analyse_exp = TICK_ETERNITY;
1441 return 1;
1442}
1443
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001444/* This macro is very specific to the function below. See the comments in
1445 * process_session() below to understand the logic and the tests.
1446 */
1447#define UPDATE_ANALYSERS(real, list, back, flag) { \
1448 list = (((list) & ~(flag)) | ~(back)) & (real); \
1449 back = real; \
1450 if (!(list)) \
1451 break; \
1452 if (((list) ^ ((list) & ((list) - 1))) < (flag)) \
1453 continue; \
1454}
1455
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001456/* Processes the client, server, request and response jobs of a session task,
1457 * then puts it back to the wait queue in a clean state, or cleans up its
1458 * resources if it must be deleted. Returns in <next> the date the task wants
1459 * to be woken up, or TICK_ETERNITY. In order not to call all functions for
1460 * nothing too many times, the request and response buffers flags are monitored
1461 * and each function is called only if at least another function has changed at
1462 * least one flag it is interested in.
1463 */
Willy Tarreau26c25062009-03-08 09:38:41 +01001464struct task *process_session(struct task *t)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001465{
Willy Tarreau827aee92011-03-10 16:55:02 +01001466 struct server *srv;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001467 struct session *s = t->context;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001468 unsigned int rqf_last, rpf_last;
Willy Tarreau815a9b22010-07-27 17:15:12 +02001469 unsigned int rq_prod_last, rq_cons_last;
1470 unsigned int rp_cons_last, rp_prod_last;
Willy Tarreau576507f2010-01-07 00:09:04 +01001471 unsigned int req_ana_back;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001472
1473 //DPRINTF(stderr, "%s:%d: cs=%d ss=%d(%d) rqf=0x%08x rpf=0x%08x\n", __FUNCTION__, __LINE__,
1474 // s->si[0].state, s->si[1].state, s->si[1].err_type, s->req->flags, s->rep->flags);
1475
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001476 /* this data may be no longer valid, clear it */
1477 memset(&s->txn.auth, 0, sizeof(s->txn.auth));
1478
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001479 /* This flag must explicitly be set every time */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001480 s->req->flags &= ~CF_READ_NOEXP;
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001481
1482 /* Keep a copy of req/rep flags so that we can detect shutdowns */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001483 rqf_last = s->req->flags & ~CF_MASK_ANALYSER;
1484 rpf_last = s->rep->flags & ~CF_MASK_ANALYSER;
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001485
Willy Tarreau89f7ef22009-09-05 20:57:35 +02001486 /* we don't want the stream interface functions to recursively wake us up */
1487 if (s->req->prod->owner == t)
1488 s->req->prod->flags |= SI_FL_DONT_WAKE;
1489 if (s->req->cons->owner == t)
1490 s->req->cons->flags |= SI_FL_DONT_WAKE;
1491
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001492 /* 1a: Check for low level timeouts if needed. We just set a flag on
1493 * stream interfaces when their timeouts have expired.
1494 */
1495 if (unlikely(t->state & TASK_WOKEN_TIMER)) {
1496 stream_int_check_timeouts(&s->si[0]);
1497 stream_int_check_timeouts(&s->si[1]);
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001498
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001499 /* check channel timeouts, and close the corresponding stream interfaces
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001500 * for future reads or writes. Note: this will also concern upper layers
1501 * but we do not touch any other flag. We must be careful and correctly
1502 * detect state changes when calling them.
1503 */
1504
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001505 channel_check_timeouts(s->req);
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001506
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001507 if (unlikely((s->req->flags & (CF_SHUTW|CF_WRITE_TIMEOUT)) == CF_WRITE_TIMEOUT)) {
Willy Tarreau14641402009-12-29 14:49:56 +01001508 s->req->cons->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001509 si_shutw(s->req->cons);
Willy Tarreau14641402009-12-29 14:49:56 +01001510 }
1511
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001512 if (unlikely((s->req->flags & (CF_SHUTR|CF_READ_TIMEOUT)) == CF_READ_TIMEOUT)) {
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02001513 if (s->req->prod->flags & SI_FL_NOHALF)
1514 s->req->prod->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001515 si_shutr(s->req->prod);
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02001516 }
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001517
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001518 channel_check_timeouts(s->rep);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001519
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001520 if (unlikely((s->rep->flags & (CF_SHUTW|CF_WRITE_TIMEOUT)) == CF_WRITE_TIMEOUT)) {
Willy Tarreau14641402009-12-29 14:49:56 +01001521 s->rep->cons->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001522 si_shutw(s->rep->cons);
Willy Tarreau14641402009-12-29 14:49:56 +01001523 }
1524
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001525 if (unlikely((s->rep->flags & (CF_SHUTR|CF_READ_TIMEOUT)) == CF_READ_TIMEOUT)) {
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02001526 if (s->rep->prod->flags & SI_FL_NOHALF)
1527 s->rep->prod->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001528 si_shutr(s->rep->prod);
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02001529 }
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001530 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001531
1532 /* 1b: check for low-level errors reported at the stream interface.
1533 * First we check if it's a retryable error (in which case we don't
1534 * want to tell the buffer). Otherwise we report the error one level
1535 * upper by setting flags into the buffers. Note that the side towards
1536 * the client cannot have connect (hence retryable) errors. Also, the
1537 * connection setup code must be able to deal with any type of abort.
1538 */
Willy Tarreau827aee92011-03-10 16:55:02 +01001539 srv = target_srv(&s->target);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001540 if (unlikely(s->si[0].flags & SI_FL_ERR)) {
1541 if (s->si[0].state == SI_ST_EST || s->si[0].state == SI_ST_DIS) {
Willy Tarreau73b013b2012-05-21 16:31:45 +02001542 si_shutr(&s->si[0]);
1543 si_shutw(&s->si[0]);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001544 stream_int_report_error(&s->si[0]);
Willy Tarreau05cb29b2008-12-14 11:44:04 +01001545 if (!(s->req->analysers) && !(s->rep->analysers)) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001546 s->be->be_counters.cli_aborts++;
1547 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001548 if (srv)
1549 srv->counters.cli_aborts++;
Willy Tarreau05cb29b2008-12-14 11:44:04 +01001550 if (!(s->flags & SN_ERR_MASK))
1551 s->flags |= SN_ERR_CLICL;
1552 if (!(s->flags & SN_FINST_MASK))
1553 s->flags |= SN_FINST_D;
1554 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001555 }
1556 }
1557
1558 if (unlikely(s->si[1].flags & SI_FL_ERR)) {
1559 if (s->si[1].state == SI_ST_EST || s->si[1].state == SI_ST_DIS) {
Willy Tarreau73b013b2012-05-21 16:31:45 +02001560 si_shutr(&s->si[1]);
1561 si_shutw(&s->si[1]);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001562 stream_int_report_error(&s->si[1]);
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001563 s->be->be_counters.failed_resp++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001564 if (srv)
1565 srv->counters.failed_resp++;
Willy Tarreau05cb29b2008-12-14 11:44:04 +01001566 if (!(s->req->analysers) && !(s->rep->analysers)) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001567 s->be->be_counters.srv_aborts++;
1568 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001569 if (srv)
1570 srv->counters.srv_aborts++;
Willy Tarreau05cb29b2008-12-14 11:44:04 +01001571 if (!(s->flags & SN_ERR_MASK))
1572 s->flags |= SN_ERR_SRVCL;
1573 if (!(s->flags & SN_FINST_MASK))
1574 s->flags |= SN_FINST_D;
1575 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001576 }
1577 /* note: maybe we should process connection errors here ? */
1578 }
1579
1580 if (s->si[1].state == SI_ST_CON) {
1581 /* we were trying to establish a connection on the server side,
1582 * maybe it succeeded, maybe it failed, maybe we timed out, ...
1583 */
1584 if (unlikely(!sess_update_st_con_tcp(s, &s->si[1])))
1585 sess_update_st_cer(s, &s->si[1]);
1586 else if (s->si[1].state == SI_ST_EST)
1587 sess_establish(s, &s->si[1]);
1588
1589 /* state is now one of SI_ST_CON (still in progress), SI_ST_EST
1590 * (established), SI_ST_DIS (abort), SI_ST_CLO (last error),
1591 * SI_ST_ASS/SI_ST_TAR/SI_ST_REQ for retryable errors.
1592 */
1593 }
1594
Willy Tarreau815a9b22010-07-27 17:15:12 +02001595 rq_prod_last = s->si[0].state;
1596 rq_cons_last = s->si[1].state;
1597 rp_cons_last = s->si[0].state;
1598 rp_prod_last = s->si[1].state;
1599
1600 resync_stream_interface:
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001601 /* Check for connection closure */
1602
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001603 DPRINTF(stderr,
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001604 "[%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 +01001605 now_ms, __FUNCTION__, __LINE__,
1606 t,
1607 s, s->flags,
1608 s->req, s->rep,
1609 s->req->rex, s->rep->wex,
1610 s->req->flags, s->rep->flags,
Cyril Bonté3aaba442012-09-23 14:19:12 +02001611 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 +01001612 s->rep->cons->err_type, s->req->cons->err_type,
Willy Tarreauee28de02010-06-01 09:51:00 +02001613 s->req->cons->conn_retries);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001614
1615 /* nothing special to be done on client side */
1616 if (unlikely(s->req->prod->state == SI_ST_DIS))
1617 s->req->prod->state = SI_ST_CLO;
1618
1619 /* When a server-side connection is released, we have to count it and
1620 * check for pending connections on this server.
1621 */
1622 if (unlikely(s->req->cons->state == SI_ST_DIS)) {
1623 s->req->cons->state = SI_ST_CLO;
Willy Tarreau827aee92011-03-10 16:55:02 +01001624 srv = target_srv(&s->target);
1625 if (srv) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001626 if (s->flags & SN_CURR_SESS) {
1627 s->flags &= ~SN_CURR_SESS;
Willy Tarreau827aee92011-03-10 16:55:02 +01001628 srv->cur_sess--;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001629 }
1630 sess_change_server(s, NULL);
Willy Tarreau827aee92011-03-10 16:55:02 +01001631 if (may_dequeue_tasks(srv, s->be))
1632 process_srv_queue(srv);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001633 }
1634 }
1635
1636 /*
1637 * Note: of the transient states (REQ, CER, DIS), only REQ may remain
1638 * at this point.
1639 */
1640
Willy Tarreau0be0ef92009-03-08 19:20:25 +01001641 resync_request:
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001642 /* Analyse request */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001643 if (((s->req->flags & ~rqf_last) & CF_MASK_ANALYSER) ||
1644 ((s->req->flags ^ rqf_last) & CF_MASK_STATIC) ||
Willy Tarreau815a9b22010-07-27 17:15:12 +02001645 s->si[0].state != rq_prod_last ||
1646 s->si[1].state != rq_cons_last) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001647 unsigned int flags = s->req->flags;
1648
1649 if (s->req->prod->state >= SI_ST_EST) {
Willy Tarreaue34070e2010-01-08 00:32:27 +01001650 int max_loops = global.tune.maxpollevents;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001651 unsigned int ana_list;
1652 unsigned int ana_back;
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001653
Willy Tarreau90deb182010-01-07 00:20:41 +01001654 /* it's up to the analysers to stop new connections,
1655 * disable reading or closing. Note: if an analyser
1656 * disables any of these bits, it is responsible for
1657 * enabling them again when it disables itself, so
1658 * that other analysers are called in similar conditions.
1659 */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001660 channel_auto_read(s->req);
1661 channel_auto_connect(s->req);
1662 channel_auto_close(s->req);
Willy Tarreauedcf6682008-11-30 23:15:34 +01001663
1664 /* We will call all analysers for which a bit is set in
1665 * s->req->analysers, following the bit order from LSB
1666 * to MSB. The analysers must remove themselves from
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001667 * the list when not needed. Any analyser may return 0
1668 * to break out of the loop, either because of missing
1669 * data to take a decision, or because it decides to
1670 * kill the session. We loop at least once through each
1671 * analyser, and we may loop again if other analysers
1672 * are added in the middle.
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001673 *
1674 * We build a list of analysers to run. We evaluate all
1675 * of these analysers in the order of the lower bit to
1676 * the higher bit. This ordering is very important.
1677 * An analyser will often add/remove other analysers,
1678 * including itself. Any changes to itself have no effect
1679 * on the loop. If it removes any other analysers, we
1680 * want those analysers not to be called anymore during
1681 * this loop. If it adds an analyser that is located
1682 * after itself, we want it to be scheduled for being
1683 * processed during the loop. If it adds an analyser
1684 * which is located before it, we want it to switch to
1685 * it immediately, even if it has already been called
1686 * once but removed since.
1687 *
1688 * In order to achieve this, we compare the analyser
1689 * list after the call with a copy of it before the
1690 * call. The work list is fed with analyser bits that
1691 * appeared during the call. Then we compare previous
1692 * work list with the new one, and check the bits that
1693 * appeared. If the lowest of these bits is lower than
1694 * the current bit, it means we have enabled a previous
1695 * analyser and must immediately loop again.
Willy Tarreauedcf6682008-11-30 23:15:34 +01001696 */
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001697
1698 ana_list = ana_back = s->req->analysers;
Willy Tarreaue34070e2010-01-08 00:32:27 +01001699 while (ana_list && max_loops--) {
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001700 /* Warning! ensure that analysers are always placed in ascending order! */
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001701
Willy Tarreaufb356202010-08-03 14:02:05 +02001702 if (ana_list & AN_REQ_INSPECT_FE) {
1703 if (!tcp_inspect_request(s, s->req, AN_REQ_INSPECT_FE))
Willy Tarreauedcf6682008-11-30 23:15:34 +01001704 break;
Willy Tarreaufb356202010-08-03 14:02:05 +02001705 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_INSPECT_FE);
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001706 }
Willy Tarreauedcf6682008-11-30 23:15:34 +01001707
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001708 if (ana_list & AN_REQ_WAIT_HTTP) {
Willy Tarreau3a816292009-07-07 10:55:49 +02001709 if (!http_wait_for_request(s, s->req, AN_REQ_WAIT_HTTP))
Willy Tarreaud787e662009-07-07 10:14:51 +02001710 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001711 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_WAIT_HTTP);
Willy Tarreaud787e662009-07-07 10:14:51 +02001712 }
1713
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001714 if (ana_list & AN_REQ_HTTP_PROCESS_FE) {
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001715 if (!http_process_req_common(s, s->req, AN_REQ_HTTP_PROCESS_FE, s->fe))
1716 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001717 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_PROCESS_FE);
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001718 }
1719
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001720 if (ana_list & AN_REQ_SWITCHING_RULES) {
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001721 if (!process_switching_rules(s, s->req, AN_REQ_SWITCHING_RULES))
1722 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001723 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_SWITCHING_RULES);
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001724 }
1725
Willy Tarreaufb356202010-08-03 14:02:05 +02001726 if (ana_list & AN_REQ_INSPECT_BE) {
1727 if (!tcp_inspect_request(s, s->req, AN_REQ_INSPECT_BE))
1728 break;
1729 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_INSPECT_BE);
1730 }
1731
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001732 if (ana_list & AN_REQ_HTTP_PROCESS_BE) {
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001733 if (!http_process_req_common(s, s->req, AN_REQ_HTTP_PROCESS_BE, s->be))
1734 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001735 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_PROCESS_BE);
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001736 }
1737
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001738 if (ana_list & AN_REQ_HTTP_TARPIT) {
Willy Tarreau3a816292009-07-07 10:55:49 +02001739 if (!http_process_tarpit(s, s->req, AN_REQ_HTTP_TARPIT))
Willy Tarreau60b85b02008-11-30 23:28:40 +01001740 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001741 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_TARPIT);
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001742 }
Willy Tarreau60b85b02008-11-30 23:28:40 +01001743
Willy Tarreau4a5cade2012-04-05 21:09:48 +02001744 if (ana_list & AN_REQ_SRV_RULES) {
1745 if (!process_server_rules(s, s->req, AN_REQ_SRV_RULES))
1746 break;
1747 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_SRV_RULES);
1748 }
1749
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001750 if (ana_list & AN_REQ_HTTP_INNER) {
Willy Tarreauc465fd72009-08-31 00:17:18 +02001751 if (!http_process_request(s, s->req, AN_REQ_HTTP_INNER))
1752 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001753 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_INNER);
Willy Tarreauc465fd72009-08-31 00:17:18 +02001754 }
1755
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001756 if (ana_list & AN_REQ_HTTP_BODY) {
Willy Tarreau3a816292009-07-07 10:55:49 +02001757 if (!http_process_request_body(s, s->req, AN_REQ_HTTP_BODY))
Willy Tarreaud34af782008-11-30 23:36:37 +01001758 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001759 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_BODY);
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001760 }
Emeric Brun647caf12009-06-30 17:57:00 +02001761
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001762 if (ana_list & AN_REQ_PRST_RDP_COOKIE) {
Emeric Brun647caf12009-06-30 17:57:00 +02001763 if (!tcp_persist_rdp_cookie(s, s->req, AN_REQ_PRST_RDP_COOKIE))
1764 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001765 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_PRST_RDP_COOKIE);
Emeric Brun647caf12009-06-30 17:57:00 +02001766 }
Willy Tarreaud98cf932009-12-27 22:54:55 +01001767
Emeric Brun1d33b292010-01-04 15:47:17 +01001768 if (ana_list & AN_REQ_STICKING_RULES) {
1769 if (!process_sticking_rules(s, s->req, AN_REQ_STICKING_RULES))
1770 break;
1771 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_STICKING_RULES);
1772 }
1773
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001774 if (ana_list & AN_REQ_HTTP_XFER_BODY) {
Willy Tarreaud98cf932009-12-27 22:54:55 +01001775 if (!http_request_forward_body(s, s->req, AN_REQ_HTTP_XFER_BODY))
1776 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001777 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_XFER_BODY);
Willy Tarreaud98cf932009-12-27 22:54:55 +01001778 }
Willy Tarreaue34070e2010-01-08 00:32:27 +01001779 break;
1780 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001781 }
Willy Tarreau84455332009-03-15 22:34:05 +01001782
Willy Tarreau815a9b22010-07-27 17:15:12 +02001783 rq_prod_last = s->si[0].state;
1784 rq_cons_last = s->si[1].state;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001785 s->req->flags &= ~CF_WAKE_ONCE;
Willy Tarreau815a9b22010-07-27 17:15:12 +02001786 rqf_last = s->req->flags;
1787
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001788 if ((s->req->flags ^ flags) & CF_MASK_STATIC)
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001789 goto resync_request;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001790 }
1791
Willy Tarreau576507f2010-01-07 00:09:04 +01001792 /* we'll monitor the request analysers while parsing the response,
1793 * because some response analysers may indirectly enable new request
1794 * analysers (eg: HTTP keep-alive).
1795 */
1796 req_ana_back = s->req->analysers;
1797
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001798 resync_response:
1799 /* Analyse response */
1800
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001801 if (unlikely(s->rep->flags & CF_HIJACK)) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001802 /* In inject mode, we wake up everytime something has
1803 * happened on the write side of the buffer.
1804 */
1805 unsigned int flags = s->rep->flags;
1806
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001807 if ((s->rep->flags & (CF_WRITE_PARTIAL|CF_WRITE_ERROR|CF_SHUTW)) &&
Willy Tarreau3bf1b2b2012-08-27 20:46:07 +02001808 !channel_full(s->rep)) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001809 s->rep->hijacker(s, s->rep);
1810 }
1811
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001812 if ((s->rep->flags ^ flags) & CF_MASK_STATIC) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001813 rpf_last = s->rep->flags;
1814 goto resync_response;
1815 }
1816 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001817 else if (((s->rep->flags & ~rpf_last) & CF_MASK_ANALYSER) ||
1818 (s->rep->flags ^ rpf_last) & CF_MASK_STATIC ||
Willy Tarreau815a9b22010-07-27 17:15:12 +02001819 s->si[0].state != rp_cons_last ||
1820 s->si[1].state != rp_prod_last) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001821 unsigned int flags = s->rep->flags;
1822
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001823 if ((s->rep->flags & CF_MASK_ANALYSER) &&
Willy Tarreau0499e352010-12-17 07:13:42 +01001824 (s->rep->analysers & AN_REQ_WAIT_HTTP)) {
1825 /* Due to HTTP pipelining, the HTTP request analyser might be waiting
1826 * for some free space in the response buffer, so we might need to call
1827 * it when something changes in the response buffer, but still we pass
1828 * it the request buffer. Note that the SI state might very well still
1829 * be zero due to us returning a flow of redirects!
1830 */
1831 s->rep->analysers &= ~AN_REQ_WAIT_HTTP;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001832 s->req->flags |= CF_WAKE_ONCE;
Willy Tarreau0499e352010-12-17 07:13:42 +01001833 }
1834
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001835 if (s->rep->prod->state >= SI_ST_EST) {
Willy Tarreaue34070e2010-01-08 00:32:27 +01001836 int max_loops = global.tune.maxpollevents;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001837 unsigned int ana_list;
1838 unsigned int ana_back;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001839
Willy Tarreau90deb182010-01-07 00:20:41 +01001840 /* it's up to the analysers to stop disable reading or
1841 * closing. Note: if an analyser disables any of these
1842 * bits, it is responsible for enabling them again when
1843 * it disables itself, so that other analysers are called
1844 * in similar conditions.
1845 */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001846 channel_auto_read(s->rep);
1847 channel_auto_close(s->rep);
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001848
1849 /* We will call all analysers for which a bit is set in
1850 * s->rep->analysers, following the bit order from LSB
1851 * to MSB. The analysers must remove themselves from
1852 * the list when not needed. Any analyser may return 0
1853 * to break out of the loop, either because of missing
1854 * data to take a decision, or because it decides to
1855 * kill the session. We loop at least once through each
1856 * analyser, and we may loop again if other analysers
1857 * are added in the middle.
1858 */
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001859
1860 ana_list = ana_back = s->rep->analysers;
Willy Tarreaue34070e2010-01-08 00:32:27 +01001861 while (ana_list && max_loops--) {
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001862 /* Warning! ensure that analysers are always placed in ascending order! */
1863
Emeric Brun97679e72010-09-23 17:56:44 +02001864 if (ana_list & AN_RES_INSPECT) {
1865 if (!tcp_inspect_response(s, s->rep, AN_RES_INSPECT))
1866 break;
1867 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_INSPECT);
1868 }
1869
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001870 if (ana_list & AN_RES_WAIT_HTTP) {
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001871 if (!http_wait_for_response(s, s->rep, AN_RES_WAIT_HTTP))
1872 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001873 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_WAIT_HTTP);
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001874 }
1875
Emeric Brun1d33b292010-01-04 15:47:17 +01001876 if (ana_list & AN_RES_STORE_RULES) {
1877 if (!process_store_rules(s, s->rep, AN_RES_STORE_RULES))
1878 break;
1879 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_STORE_RULES);
1880 }
1881
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001882 if (ana_list & AN_RES_HTTP_PROCESS_BE) {
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001883 if (!http_process_res_common(s, s->rep, AN_RES_HTTP_PROCESS_BE, s->be))
1884 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001885 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_HTTP_PROCESS_BE);
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001886 }
Willy Tarreaud98cf932009-12-27 22:54:55 +01001887
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001888 if (ana_list & AN_RES_HTTP_XFER_BODY) {
Willy Tarreaud98cf932009-12-27 22:54:55 +01001889 if (!http_response_forward_body(s, s->rep, AN_RES_HTTP_XFER_BODY))
1890 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001891 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_HTTP_XFER_BODY);
Willy Tarreaud98cf932009-12-27 22:54:55 +01001892 }
Willy Tarreaue34070e2010-01-08 00:32:27 +01001893 break;
1894 }
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001895 }
1896
Willy Tarreau815a9b22010-07-27 17:15:12 +02001897 rp_cons_last = s->si[0].state;
1898 rp_prod_last = s->si[1].state;
1899 rpf_last = s->rep->flags;
1900
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001901 if ((s->rep->flags ^ flags) & CF_MASK_STATIC)
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001902 goto resync_response;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001903 }
1904
Willy Tarreau576507f2010-01-07 00:09:04 +01001905 /* maybe someone has added some request analysers, so we must check and loop */
1906 if (s->req->analysers & ~req_ana_back)
1907 goto resync_request;
1908
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001909 if ((s->req->flags & ~rqf_last) & CF_MASK_ANALYSER)
Willy Tarreau0499e352010-12-17 07:13:42 +01001910 goto resync_request;
1911
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001912 /* FIXME: here we should call protocol handlers which rely on
1913 * both buffers.
1914 */
1915
1916
1917 /*
Willy Tarreauae526782010-03-04 20:34:23 +01001918 * Now we propagate unhandled errors to the session. Normally
1919 * we're just in a data phase here since it means we have not
1920 * seen any analyser who could set an error status.
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001921 */
Willy Tarreau827aee92011-03-10 16:55:02 +01001922 srv = target_srv(&s->target);
Willy Tarreau2f976e12010-11-11 14:28:47 +01001923 if (unlikely(!(s->flags & SN_ERR_MASK))) {
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001924 if (s->req->flags & (CF_READ_ERROR|CF_READ_TIMEOUT|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001925 /* Report it if the client got an error or a read timeout expired */
Willy Tarreau84455332009-03-15 22:34:05 +01001926 s->req->analysers = 0;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001927 if (s->req->flags & CF_READ_ERROR) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001928 s->be->be_counters.cli_aborts++;
1929 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001930 if (srv)
1931 srv->counters.cli_aborts++;
Willy Tarreau84455332009-03-15 22:34:05 +01001932 s->flags |= SN_ERR_CLICL;
Willy Tarreauae526782010-03-04 20:34:23 +01001933 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001934 else if (s->req->flags & CF_READ_TIMEOUT) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001935 s->be->be_counters.cli_aborts++;
1936 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001937 if (srv)
1938 srv->counters.cli_aborts++;
Willy Tarreau84455332009-03-15 22:34:05 +01001939 s->flags |= SN_ERR_CLITO;
Willy Tarreauae526782010-03-04 20:34:23 +01001940 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001941 else if (s->req->flags & CF_WRITE_ERROR) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001942 s->be->be_counters.srv_aborts++;
1943 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001944 if (srv)
1945 srv->counters.srv_aborts++;
Willy Tarreau84455332009-03-15 22:34:05 +01001946 s->flags |= SN_ERR_SRVCL;
Willy Tarreauae526782010-03-04 20:34:23 +01001947 }
1948 else {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001949 s->be->be_counters.srv_aborts++;
1950 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001951 if (srv)
1952 srv->counters.srv_aborts++;
Willy Tarreau84455332009-03-15 22:34:05 +01001953 s->flags |= SN_ERR_SRVTO;
Willy Tarreauae526782010-03-04 20:34:23 +01001954 }
Willy Tarreau84455332009-03-15 22:34:05 +01001955 sess_set_term_flags(s);
1956 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001957 else if (s->rep->flags & (CF_READ_ERROR|CF_READ_TIMEOUT|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001958 /* Report it if the server got an error or a read timeout expired */
1959 s->rep->analysers = 0;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001960 if (s->rep->flags & CF_READ_ERROR) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001961 s->be->be_counters.srv_aborts++;
1962 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001963 if (srv)
1964 srv->counters.srv_aborts++;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001965 s->flags |= SN_ERR_SRVCL;
Willy Tarreauae526782010-03-04 20:34:23 +01001966 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001967 else if (s->rep->flags & CF_READ_TIMEOUT) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001968 s->be->be_counters.srv_aborts++;
1969 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001970 if (srv)
1971 srv->counters.srv_aborts++;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001972 s->flags |= SN_ERR_SRVTO;
Willy Tarreauae526782010-03-04 20:34:23 +01001973 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001974 else if (s->rep->flags & CF_WRITE_ERROR) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001975 s->be->be_counters.cli_aborts++;
1976 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001977 if (srv)
1978 srv->counters.cli_aborts++;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001979 s->flags |= SN_ERR_CLICL;
Willy Tarreauae526782010-03-04 20:34:23 +01001980 }
1981 else {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001982 s->be->be_counters.cli_aborts++;
1983 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001984 if (srv)
1985 srv->counters.cli_aborts++;
Willy Tarreauae526782010-03-04 20:34:23 +01001986 s->flags |= SN_ERR_CLITO;
1987 }
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001988 sess_set_term_flags(s);
1989 }
Willy Tarreau84455332009-03-15 22:34:05 +01001990 }
1991
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001992 /*
1993 * Here we take care of forwarding unhandled data. This also includes
1994 * connection establishments and shutdown requests.
1995 */
1996
1997
Willy Tarreau7c84bab2009-03-08 21:38:23 +01001998 /* If noone is interested in analysing data, it's time to forward
Willy Tarreau31971e52009-09-20 12:07:52 +02001999 * everything. We configure the buffer to forward indefinitely.
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002000 * Note that we're checking CF_SHUTR_NOW as an indication of a possible
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002001 * recent call to channel_abort().
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01002002 */
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002003 if (!s->req->analysers &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002004 !(s->req->flags & (CF_HIJACK|CF_SHUTW|CF_SHUTR_NOW)) &&
Willy Tarreau31971e52009-09-20 12:07:52 +02002005 (s->req->prod->state >= SI_ST_EST) &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002006 (s->req->to_forward != CHN_INFINITE_FORWARD)) {
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002007 /* This buffer is freewheeling, there's no analyser nor hijacker
2008 * attached to it. If any data are left in, we'll permit them to
2009 * move.
2010 */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002011 channel_auto_read(s->req);
2012 channel_auto_connect(s->req);
2013 channel_auto_close(s->req);
Willy Tarreaua75bcef2012-08-24 22:56:11 +02002014 buffer_flush(&s->req->buf);
Willy Tarreau5bd8c372009-01-19 00:32:22 +01002015
Willy Tarreauda4d9fe2010-11-07 20:26:56 +01002016 /* We'll let data flow between the producer (if still connected)
2017 * to the consumer (which might possibly not be connected yet).
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002018 */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002019 if (!(s->req->flags & (CF_SHUTR|CF_SHUTW_NOW)))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002020 channel_forward(s->req, CHN_INFINITE_FORWARD);
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01002021 }
Willy Tarreauf890dc92008-12-13 21:12:26 +01002022
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002023 /* check if it is wise to enable kernel splicing to forward request data */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002024 if (!(s->req->flags & (CF_KERN_SPLICING|CF_SHUTR)) &&
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002025 s->req->to_forward &&
2026 (global.tune.options & GTUNE_USE_SPLICE) &&
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002027 (s->si[0].conn.xprt && s->si[0].conn.xprt->rcv_pipe && s->si[0].conn.xprt->snd_pipe) &&
2028 (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 +01002029 (pipes_used < global.maxpipes) &&
2030 (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_REQ) ||
2031 (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_AUT) &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002032 (s->req->flags & CF_STREAMER_FAST)))) {
2033 s->req->flags |= CF_KERN_SPLICING;
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002034 }
2035
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002036 /* reflect what the L7 analysers have seen last */
2037 rqf_last = s->req->flags;
2038
2039 /*
2040 * Now forward all shutdown requests between both sides of the buffer
2041 */
2042
Willy Tarreau520d95e2009-09-19 21:04:57 +02002043 /* first, let's check if the request buffer needs to shutdown(write), which may
2044 * happen either because the input is closed or because we want to force a close
Willy Tarreaue4599762010-03-21 23:25:09 +01002045 * once the server has begun to respond.
Willy Tarreau520d95e2009-09-19 21:04:57 +02002046 */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002047 if (unlikely((s->req->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_HIJACK|CF_AUTO_CLOSE|CF_SHUTR)) ==
2048 (CF_AUTO_CLOSE|CF_SHUTR)))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002049 channel_shutw_now(s->req);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002050
2051 /* shutdown(write) pending */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002052 if (unlikely((s->req->flags & (CF_SHUTW|CF_SHUTW_NOW)) == CF_SHUTW_NOW &&
Willy Tarreau8e21bb92012-08-24 22:40:29 +02002053 channel_is_empty(s->req)))
Willy Tarreau73b013b2012-05-21 16:31:45 +02002054 si_shutw(s->req->cons);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002055
2056 /* shutdown(write) done on server side, we must stop the client too */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002057 if (unlikely((s->req->flags & (CF_SHUTW|CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTW &&
Willy Tarreau3dbc6942008-12-07 13:05:04 +01002058 !s->req->analysers))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002059 channel_shutr_now(s->req);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002060
2061 /* shutdown(read) pending */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002062 if (unlikely((s->req->flags & (CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTR_NOW)) {
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02002063 if (s->req->prod->flags & SI_FL_NOHALF)
2064 s->req->prod->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02002065 si_shutr(s->req->prod);
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02002066 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002067
Willy Tarreau520d95e2009-09-19 21:04:57 +02002068 /* it's possible that an upper layer has requested a connection setup or abort.
2069 * There are 2 situations where we decide to establish a new connection :
2070 * - there are data scheduled for emission in the buffer
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002071 * - the CF_AUTO_CONNECT flag is set (active connection)
Willy Tarreau520d95e2009-09-19 21:04:57 +02002072 */
2073 if (s->req->cons->state == SI_ST_INI) {
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002074 if (!(s->req->flags & CF_SHUTW)) {
2075 if ((s->req->flags & CF_AUTO_CONNECT) || !channel_is_empty(s->req)) {
Willy Tarreaub24281b2011-02-13 13:16:36 +01002076 /* If we have an applet without a connect method, we immediately
Willy Tarreau85e7d002010-05-31 11:57:51 +02002077 * switch to the connected state, otherwise we perform a connection
2078 * request.
Willy Tarreau520d95e2009-09-19 21:04:57 +02002079 */
Willy Tarreau85e7d002010-05-31 11:57:51 +02002080 s->req->cons->state = SI_ST_REQ; /* new connection requested */
Willy Tarreau070ceb62010-06-01 10:36:43 +02002081 s->req->cons->conn_retries = s->be->conn_retries;
Willy Tarreau3cefd522012-08-30 15:49:18 +02002082 if (unlikely(s->req->cons->conn.target.type == TARG_TYPE_APPLET &&
Willy Tarreau73b013b2012-05-21 16:31:45 +02002083 !(si_ctrl(s->req->cons) && si_ctrl(s->req->cons)->connect))) {
Willy Tarreau520d95e2009-09-19 21:04:57 +02002084 s->req->cons->state = SI_ST_EST; /* connection established */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002085 s->rep->flags |= CF_READ_ATTACHED; /* producer is now attached */
Willy Tarreau85e7d002010-05-31 11:57:51 +02002086 s->req->wex = TICK_ETERNITY;
2087 }
Willy Tarreau520d95e2009-09-19 21:04:57 +02002088 }
Willy Tarreau73201222009-08-16 18:27:24 +02002089 }
Willy Tarreauf41ffdc2009-09-20 08:19:25 +02002090 else {
Willy Tarreau92795622009-03-06 12:51:23 +01002091 s->req->cons->state = SI_ST_CLO; /* shutw+ini = abort */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002092 channel_shutw_now(s->req); /* fix buffer flags upon abort */
2093 channel_shutr_now(s->rep);
Willy Tarreauf41ffdc2009-09-20 08:19:25 +02002094 }
Willy Tarreau92795622009-03-06 12:51:23 +01002095 }
2096
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002097
2098 /* we may have a pending connection request, or a connection waiting
2099 * for completion.
2100 */
2101 if (s->si[1].state >= SI_ST_REQ && s->si[1].state < SI_ST_CON) {
2102 do {
2103 /* nb: step 1 might switch from QUE to ASS, but we first want
2104 * to give a chance to step 2 to perform a redirect if needed.
2105 */
2106 if (s->si[1].state != SI_ST_REQ)
2107 sess_update_stream_int(s, &s->si[1]);
2108 if (s->si[1].state == SI_ST_REQ)
2109 sess_prepare_conn_req(s, &s->si[1]);
2110
Willy Tarreau827aee92011-03-10 16:55:02 +01002111 srv = target_srv(&s->target);
2112 if (s->si[1].state == SI_ST_ASS && srv && srv->rdr_len && (s->flags & SN_REDIRECTABLE))
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002113 perform_http_redirect(s, &s->si[1]);
2114 } while (s->si[1].state == SI_ST_ASS);
Mark Lamourinec2247f02012-01-04 13:02:01 -05002115
2116 /* Now we can add the server name to a header (if requested) */
2117 /* check for HTTP mode and proxy server_name_hdr_name != NULL */
Stathis Voukelatos09a030a2012-01-09 14:27:13 +01002118 if ((s->flags & SN_BE_ASSIGNED) &&
Willy Tarreau45c0d982012-03-09 12:11:57 +01002119 (s->be->mode == PR_MODE_HTTP) &&
2120 (s->be->server_id_hdr_name != NULL)) {
2121 http_send_name_header(&s->txn, s->be, target_srv(&s->target)->id);
Mark Lamourinec2247f02012-01-04 13:02:01 -05002122 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002123 }
2124
Willy Tarreau3deb3d02009-06-21 22:43:05 +02002125 /* Benchmarks have shown that it's optimal to do a full resync now */
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002126 if (s->req->prod->state == SI_ST_DIS || s->req->cons->state == SI_ST_DIS)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002127 goto resync_stream_interface;
2128
Willy Tarreau815a9b22010-07-27 17:15:12 +02002129 /* otherwise we want to check if we need to resync the req buffer or not */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002130 if ((s->req->flags ^ rqf_last) & CF_MASK_STATIC)
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002131 goto resync_request;
2132
Willy Tarreau3deb3d02009-06-21 22:43:05 +02002133 /* perform output updates to the response buffer */
Willy Tarreau84455332009-03-15 22:34:05 +01002134
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002135 /* If noone is interested in analysing data, it's time to forward
Willy Tarreau31971e52009-09-20 12:07:52 +02002136 * everything. We configure the buffer to forward indefinitely.
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002137 * Note that we're checking CF_SHUTR_NOW as an indication of a possible
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002138 * recent call to channel_abort().
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01002139 */
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002140 if (!s->rep->analysers &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002141 !(s->rep->flags & (CF_HIJACK|CF_SHUTW|CF_SHUTR_NOW)) &&
Willy Tarreau31971e52009-09-20 12:07:52 +02002142 (s->rep->prod->state >= SI_ST_EST) &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002143 (s->rep->to_forward != CHN_INFINITE_FORWARD)) {
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002144 /* This buffer is freewheeling, there's no analyser nor hijacker
2145 * attached to it. If any data are left in, we'll permit them to
2146 * move.
2147 */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002148 channel_auto_read(s->rep);
2149 channel_auto_close(s->rep);
Willy Tarreaua75bcef2012-08-24 22:56:11 +02002150 buffer_flush(&s->rep->buf);
Willy Tarreauda4d9fe2010-11-07 20:26:56 +01002151
2152 /* We'll let data flow between the producer (if still connected)
2153 * to the consumer.
2154 */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002155 if (!(s->rep->flags & (CF_SHUTR|CF_SHUTW_NOW)))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002156 channel_forward(s->rep, CHN_INFINITE_FORWARD);
Willy Tarreauce887fd2012-05-12 12:50:00 +02002157
2158 /* if we have no analyser anymore in any direction and have a
2159 * tunnel timeout set, use it now.
2160 */
2161 if (!s->req->analysers && s->be->timeout.tunnel) {
2162 s->req->rto = s->req->wto = s->rep->rto = s->rep->wto =
2163 s->be->timeout.tunnel;
2164 s->req->rex = s->req->wex = s->rep->rex = s->rep->wex =
2165 tick_add(now_ms, s->be->timeout.tunnel);
2166 }
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01002167 }
Willy Tarreauf890dc92008-12-13 21:12:26 +01002168
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002169 /* check if it is wise to enable kernel splicing to forward response data */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002170 if (!(s->rep->flags & (CF_KERN_SPLICING|CF_SHUTR)) &&
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002171 s->rep->to_forward &&
2172 (global.tune.options & GTUNE_USE_SPLICE) &&
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002173 (s->si[0].conn.xprt && s->si[0].conn.xprt->rcv_pipe && s->si[0].conn.xprt->snd_pipe) &&
2174 (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 +01002175 (pipes_used < global.maxpipes) &&
2176 (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_RTR) ||
2177 (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_AUT) &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002178 (s->rep->flags & CF_STREAMER_FAST)))) {
2179 s->rep->flags |= CF_KERN_SPLICING;
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002180 }
2181
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002182 /* reflect what the L7 analysers have seen last */
2183 rpf_last = s->rep->flags;
2184
2185 /*
2186 * Now forward all shutdown requests between both sides of the buffer
2187 */
2188
2189 /*
2190 * FIXME: this is probably where we should produce error responses.
2191 */
2192
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01002193 /* first, let's check if the response buffer needs to shutdown(write) */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002194 if (unlikely((s->rep->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_HIJACK|CF_AUTO_CLOSE|CF_SHUTR)) ==
2195 (CF_AUTO_CLOSE|CF_SHUTR)))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002196 channel_shutw_now(s->rep);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002197
2198 /* shutdown(write) pending */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002199 if (unlikely((s->rep->flags & (CF_SHUTW|CF_SHUTW_NOW)) == CF_SHUTW_NOW &&
Willy Tarreau8e21bb92012-08-24 22:40:29 +02002200 channel_is_empty(s->rep)))
Willy Tarreau73b013b2012-05-21 16:31:45 +02002201 si_shutw(s->rep->cons);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002202
2203 /* shutdown(write) done on the client side, we must stop the server too */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002204 if (unlikely((s->rep->flags & (CF_SHUTW|CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTW) &&
Willy Tarreau3dbc6942008-12-07 13:05:04 +01002205 !s->rep->analysers)
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002206 channel_shutr_now(s->rep);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002207
2208 /* shutdown(read) pending */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002209 if (unlikely((s->rep->flags & (CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTR_NOW)) {
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02002210 if (s->rep->prod->flags & SI_FL_NOHALF)
2211 s->rep->prod->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02002212 si_shutr(s->rep->prod);
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02002213 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002214
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002215 if (s->req->prod->state == SI_ST_DIS || s->req->cons->state == SI_ST_DIS)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002216 goto resync_stream_interface;
2217
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002218 if (s->req->flags != rqf_last)
2219 goto resync_request;
2220
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002221 if ((s->rep->flags ^ rpf_last) & CF_MASK_STATIC)
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002222 goto resync_response;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002223
Willy Tarreau89f7ef22009-09-05 20:57:35 +02002224 /* we're interested in getting wakeups again */
2225 s->req->prod->flags &= ~SI_FL_DONT_WAKE;
2226 s->req->cons->flags &= ~SI_FL_DONT_WAKE;
2227
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002228 /* This is needed only when debugging is enabled, to indicate
2229 * client-side or server-side close. Please note that in the unlikely
2230 * event where both sides would close at once, the sequence is reported
2231 * on the server side first.
2232 */
2233 if (unlikely((global.mode & MODE_DEBUG) &&
2234 (!(global.mode & MODE_QUIET) ||
2235 (global.mode & MODE_VERBOSE)))) {
2236 int len;
2237
2238 if (s->si[1].state == SI_ST_CLO &&
2239 s->si[1].prev_state == SI_ST_EST) {
2240 len = sprintf(trash, "%08x:%s.srvcls[%04x:%04x]\n",
2241 s->uniq_id, s->be->id,
Willy Tarreaufb7508a2012-05-21 16:47:54 +02002242 (unsigned short)si_fd(&s->si[0]),
2243 (unsigned short)si_fd(&s->si[1]));
Willy Tarreau21337822012-04-29 14:11:38 +02002244 if (write(1, trash, len) < 0) /* shut gcc warning */;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002245 }
2246
2247 if (s->si[0].state == SI_ST_CLO &&
2248 s->si[0].prev_state == SI_ST_EST) {
2249 len = sprintf(trash, "%08x:%s.clicls[%04x:%04x]\n",
2250 s->uniq_id, s->be->id,
Willy Tarreaufb7508a2012-05-21 16:47:54 +02002251 (unsigned short)si_fd(&s->si[0]),
2252 (unsigned short)si_fd(&s->si[1]));
Willy Tarreau21337822012-04-29 14:11:38 +02002253 if (write(1, trash, len) < 0) /* shut gcc warning */;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002254 }
2255 }
2256
2257 if (likely((s->rep->cons->state != SI_ST_CLO) ||
2258 (s->req->cons->state > SI_ST_INI && s->req->cons->state < SI_ST_CLO))) {
2259
2260 if ((s->fe->options & PR_O_CONTSTATS) && (s->flags & SN_BE_ASSIGNED))
2261 session_process_counters(s);
2262
Willy Tarreau3cefd522012-08-30 15:49:18 +02002263 if (s->rep->cons->state == SI_ST_EST && s->rep->cons->conn.target.type != TARG_TYPE_APPLET)
Willy Tarreau73b013b2012-05-21 16:31:45 +02002264 si_update(s->rep->cons);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002265
Willy Tarreau3cefd522012-08-30 15:49:18 +02002266 if (s->req->cons->state == SI_ST_EST && s->req->cons->conn.target.type != TARG_TYPE_APPLET)
Willy Tarreau73b013b2012-05-21 16:31:45 +02002267 si_update(s->req->cons);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002268
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002269 s->req->flags &= ~(CF_READ_NULL|CF_READ_PARTIAL|CF_WRITE_NULL|CF_WRITE_PARTIAL|CF_READ_ATTACHED);
2270 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 +01002271 s->si[0].prev_state = s->si[0].state;
2272 s->si[1].prev_state = s->si[1].state;
Willy Tarreaub0ef7352008-12-14 13:26:20 +01002273 s->si[0].flags &= ~(SI_FL_ERR|SI_FL_EXP);
2274 s->si[1].flags &= ~(SI_FL_ERR|SI_FL_EXP);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002275
2276 /* Trick: if a request is being waiting for the server to respond,
2277 * and if we know the server can timeout, we don't want the timeout
2278 * to expire on the client side first, but we're still interested
2279 * in passing data from the client to the server (eg: POST). Thus,
2280 * we can cancel the client's request timeout if the server's
2281 * request timeout is set and the server has not yet sent a response.
2282 */
2283
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002284 if ((s->rep->flags & (CF_AUTO_CLOSE|CF_SHUTR)) == 0 &&
Willy Tarreau86491c32008-12-14 09:04:47 +01002285 (tick_isset(s->req->wex) || tick_isset(s->rep->rex))) {
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002286 s->req->flags |= CF_READ_NOEXP;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002287 s->req->rex = TICK_ETERNITY;
Willy Tarreau86491c32008-12-14 09:04:47 +01002288 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002289
Willy Tarreau7a20aa62010-07-13 16:30:45 +02002290 /* Call the stream interfaces' I/O handlers when embedded.
Willy Tarreau1accfc02009-09-05 20:57:35 +02002291 * Note that this one may wake the task up again.
2292 */
Willy Tarreau3cefd522012-08-30 15:49:18 +02002293 if (s->req->cons->conn.target.type == TARG_TYPE_APPLET ||
2294 s->rep->cons->conn.target.type == TARG_TYPE_APPLET) {
2295 if (s->req->cons->conn.target.type == TARG_TYPE_APPLET)
2296 s->req->cons->conn.target.ptr.a->fct(s->req->cons);
2297 if (s->rep->cons->conn.target.type == TARG_TYPE_APPLET)
2298 s->rep->cons->conn.target.ptr.a->fct(s->rep->cons);
Willy Tarreau1accfc02009-09-05 20:57:35 +02002299 if (task_in_rq(t)) {
2300 /* If we woke up, we don't want to requeue the
2301 * task to the wait queue, but rather requeue
2302 * it into the runqueue ASAP.
2303 */
2304 t->expire = TICK_ETERNITY;
2305 return t;
2306 }
2307 }
2308
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002309 t->expire = tick_first(tick_first(s->req->rex, s->req->wex),
2310 tick_first(s->rep->rex, s->rep->wex));
2311 if (s->req->analysers)
2312 t->expire = tick_first(t->expire, s->req->analyse_exp);
2313
2314 if (s->si[0].exp)
2315 t->expire = tick_first(t->expire, s->si[0].exp);
2316
2317 if (s->si[1].exp)
2318 t->expire = tick_first(t->expire, s->si[1].exp);
2319
2320#ifdef DEBUG_FULL
Willy Tarreau127334e2009-03-28 10:47:26 +01002321 fprintf(stderr,
2322 "[%u] queuing with exp=%u req->rex=%u req->wex=%u req->ana_exp=%u"
2323 " rep->rex=%u rep->wex=%u, si[0].exp=%u, si[1].exp=%u, cs=%d, ss=%d\n",
2324 now_ms, t->expire, s->req->rex, s->req->wex, s->req->analyse_exp,
2325 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 +01002326#endif
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002327
2328#ifdef DEBUG_DEV
2329 /* this may only happen when no timeout is set or in case of an FSM bug */
Willy Tarreaud0a201b2009-03-08 15:53:06 +01002330 if (!tick_isset(t->expire))
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002331 ABORT_NOW();
2332#endif
Willy Tarreau26c25062009-03-08 09:38:41 +01002333 return t; /* nothing more to do */
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002334 }
2335
2336 s->fe->feconn--;
2337 if (s->flags & SN_BE_ASSIGNED)
2338 s->be->beconn--;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02002339 if (!(s->listener->options & LI_O_UNLIMITED))
2340 actconn--;
Willy Tarreauaf7ad002010-08-31 15:39:26 +02002341 jobs--;
Willy Tarreau6e6fb2b2009-08-16 18:20:44 +02002342 s->listener->nbconn--;
Willy Tarreau62793712011-07-24 19:23:38 +02002343 if (s->listener->state == LI_FULL)
2344 resume_listener(s->listener);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002345
Willy Tarreau08ceb102011-07-24 22:58:00 +02002346 /* Dequeues all of the listeners waiting for a resource */
2347 if (!LIST_ISEMPTY(&global_listener_queue))
2348 dequeue_all_listeners(&global_listener_queue);
2349
Willy Tarreaub32907b2011-07-25 08:37:44 +02002350 if (!LIST_ISEMPTY(&s->fe->listener_queue) &&
2351 (!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 +02002352 dequeue_all_listeners(&s->fe->listener_queue);
2353
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002354 if (unlikely((global.mode & MODE_DEBUG) &&
2355 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)))) {
2356 int len;
Willy Tarreauec22b2c2009-03-06 13:07:40 +01002357 len = sprintf(trash, "%08x:%s.closed[%04x:%04x]\n",
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002358 s->uniq_id, s->be->id,
Willy Tarreaufb7508a2012-05-21 16:47:54 +02002359 (unsigned short)si_fd(s->req->prod), (unsigned short)si_fd(s->req->cons));
Willy Tarreau21337822012-04-29 14:11:38 +02002360 if (write(1, trash, len) < 0) /* shut gcc warning */;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002361 }
2362
2363 s->logs.t_close = tv_ms_elapsed(&s->logs.tv_accept, &now);
2364 session_process_counters(s);
2365
Krzysztof Piotr Oledzkide71d162009-10-24 15:36:15 +02002366 if (s->txn.status) {
2367 int n;
2368
2369 n = s->txn.status / 100;
2370 if (n < 1 || n > 5)
2371 n = 0;
2372
2373 if (s->fe->mode == PR_MODE_HTTP)
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01002374 s->fe->fe_counters.p.http.rsp[n]++;
Krzysztof Piotr Oledzkide71d162009-10-24 15:36:15 +02002375
Willy Tarreau24657792010-02-26 10:30:28 +01002376 if ((s->flags & SN_BE_ASSIGNED) &&
Krzysztof Piotr Oledzkide71d162009-10-24 15:36:15 +02002377 (s->be->mode == PR_MODE_HTTP))
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01002378 s->be->be_counters.p.http.rsp[n]++;
Krzysztof Piotr Oledzkide71d162009-10-24 15:36:15 +02002379 }
2380
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002381 /* let's do a final log if we need it */
2382 if (s->logs.logwait &&
2383 !(s->flags & SN_MONITOR) &&
2384 (!(s->fe->options & PR_O_NULLNOLOG) || s->req->total)) {
Willy Tarreaua5555ec2008-11-30 19:02:32 +01002385 s->do_log(s);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002386 }
2387
2388 /* the task MUST not be in the run queue anymore */
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002389 session_free(s);
Willy Tarreau26c25062009-03-08 09:38:41 +01002390 task_delete(t);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002391 task_free(t);
Willy Tarreau26c25062009-03-08 09:38:41 +01002392 return NULL;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002393}
2394
Willy Tarreau7c669d72008-06-20 15:04:11 +02002395/*
2396 * This function adjusts sess->srv_conn and maintains the previous and new
2397 * server's served session counts. Setting newsrv to NULL is enough to release
2398 * current connection slot. This function also notifies any LB algo which might
2399 * expect to be informed about any change in the number of active sessions on a
2400 * server.
2401 */
2402void sess_change_server(struct session *sess, struct server *newsrv)
2403{
2404 if (sess->srv_conn == newsrv)
2405 return;
2406
2407 if (sess->srv_conn) {
2408 sess->srv_conn->served--;
2409 if (sess->srv_conn->proxy->lbprm.server_drop_conn)
2410 sess->srv_conn->proxy->lbprm.server_drop_conn(sess->srv_conn);
Simon Hormanaf514952011-06-21 14:34:57 +09002411 session_del_srv_conn(sess);
Willy Tarreau7c669d72008-06-20 15:04:11 +02002412 }
2413
2414 if (newsrv) {
2415 newsrv->served++;
2416 if (newsrv->proxy->lbprm.server_take_conn)
2417 newsrv->proxy->lbprm.server_take_conn(newsrv);
Simon Hormanaf514952011-06-21 14:34:57 +09002418 session_add_srv_conn(sess, newsrv);
Willy Tarreau7c669d72008-06-20 15:04:11 +02002419 }
2420}
2421
Willy Tarreau84455332009-03-15 22:34:05 +01002422/* Handle server-side errors for default protocols. It is called whenever a a
2423 * connection setup is aborted or a request is aborted in queue. It sets the
2424 * session termination flags so that the caller does not have to worry about
2425 * them. It's installed as ->srv_error for the server-side stream_interface.
2426 */
2427void default_srv_error(struct session *s, struct stream_interface *si)
2428{
2429 int err_type = si->err_type;
2430 int err = 0, fin = 0;
2431
2432 if (err_type & SI_ET_QUEUE_ABRT) {
2433 err = SN_ERR_CLICL;
2434 fin = SN_FINST_Q;
2435 }
2436 else if (err_type & SI_ET_CONN_ABRT) {
2437 err = SN_ERR_CLICL;
2438 fin = SN_FINST_C;
2439 }
2440 else if (err_type & SI_ET_QUEUE_TO) {
2441 err = SN_ERR_SRVTO;
2442 fin = SN_FINST_Q;
2443 }
2444 else if (err_type & SI_ET_QUEUE_ERR) {
2445 err = SN_ERR_SRVCL;
2446 fin = SN_FINST_Q;
2447 }
2448 else if (err_type & SI_ET_CONN_TO) {
2449 err = SN_ERR_SRVTO;
2450 fin = SN_FINST_C;
2451 }
2452 else if (err_type & SI_ET_CONN_ERR) {
2453 err = SN_ERR_SRVCL;
2454 fin = SN_FINST_C;
2455 }
2456 else /* SI_ET_CONN_OTHER and others */ {
2457 err = SN_ERR_INTERNAL;
2458 fin = SN_FINST_C;
2459 }
2460
2461 if (!(s->flags & SN_ERR_MASK))
2462 s->flags |= err;
2463 if (!(s->flags & SN_FINST_MASK))
2464 s->flags |= fin;
2465}
Willy Tarreau7c669d72008-06-20 15:04:11 +02002466
Willy Tarreaua2a64e92011-09-07 23:01:56 +02002467/* kill a session and set the termination flags to <why> (one of SN_ERR_*) */
2468void session_shutdown(struct session *session, int why)
2469{
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002470 if (session->req->flags & (CF_SHUTW|CF_SHUTW_NOW))
Willy Tarreaua2a64e92011-09-07 23:01:56 +02002471 return;
2472
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002473 channel_shutw_now(session->req);
2474 channel_shutr_now(session->rep);
Willy Tarreaua2a64e92011-09-07 23:01:56 +02002475 session->task->nice = 1024;
2476 if (!(session->flags & SN_ERR_MASK))
2477 session->flags |= why;
2478 task_wakeup(session->task, TASK_WOKEN_OTHER);
2479}
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02002480
Willy Tarreau8b22a712010-06-18 17:46:06 +02002481/************************************************************************/
2482/* All supported ACL keywords must be declared here. */
2483/************************************************************************/
2484
Willy Tarreaua5e37562011-12-16 17:06:15 +01002485/* set temp integer to the General Purpose Counter 0 value in the stksess entry <ts> */
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002486static int
Willy Tarreau37406352012-04-23 16:16:37 +02002487acl_fetch_get_gpc0(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002488{
Willy Tarreau37406352012-04-23 16:16:37 +02002489 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002490 smp->type = SMP_T_UINT;
2491 smp->data.uint = 0;
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002492 if (ts != NULL) {
2493 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_GPC0);
2494 if (!ptr)
2495 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002496 smp->data.uint = stktable_data_cast(ptr, gpc0);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002497 }
2498 return 1;
2499}
2500
Willy Tarreaua5e37562011-12-16 17:06:15 +01002501/* set temp integer to the General Purpose Counter 0 value from the session's tracked
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002502 * frontend counters.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002503 */
2504static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002505acl_fetch_sc1_get_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002506 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002507{
Willy Tarreau56123282010-08-06 19:06:56 +02002508 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002509 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002510 return acl_fetch_get_gpc0(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002511}
2512
Willy Tarreaua5e37562011-12-16 17:06:15 +01002513/* set temp integer to the General Purpose Counter 0 value from the session's tracked
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002514 * backend counters.
2515 */
2516static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002517acl_fetch_sc2_get_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002518 const struct arg *args, struct sample *smp)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002519{
Willy Tarreau56123282010-08-06 19:06:56 +02002520 if (!l4->stkctr2_entry)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002521 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002522 return acl_fetch_get_gpc0(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002523}
2524
Willy Tarreaua5e37562011-12-16 17:06:15 +01002525/* set temp integer to the General Purpose Counter 0 value from the session's source
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002526 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002527 * Accepts exactly 1 argument of type table.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002528 */
2529static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002530acl_fetch_src_get_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002531 const struct arg *args, struct sample *smp)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002532{
2533 struct stktable_key *key;
2534
Willy Tarreau64ee4912012-08-30 22:59:48 +02002535 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002536 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002537 return 0;
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002538
Willy Tarreau24e32d82012-04-23 23:55:44 +02002539 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002540 return acl_fetch_get_gpc0(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002541}
2542
2543/* Increment the General Purpose Counter 0 value in the stksess entry <ts> and
Willy Tarreaua5e37562011-12-16 17:06:15 +01002544 * return it into temp integer.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002545 */
2546static int
Willy Tarreau37406352012-04-23 16:16:37 +02002547acl_fetch_inc_gpc0(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002548{
Willy Tarreau37406352012-04-23 16:16:37 +02002549 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002550 smp->type = SMP_T_UINT;
2551 smp->data.uint = 0;
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002552 if (ts != NULL) {
2553 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_GPC0);
2554 if (!ptr)
2555 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002556 smp->data.uint = ++stktable_data_cast(ptr, gpc0);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002557 }
2558 return 1;
2559}
2560
2561/* Increment the General Purpose Counter 0 value from the session's tracked
Willy Tarreaua5e37562011-12-16 17:06:15 +01002562 * frontend counters and return it into temp integer.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002563 */
2564static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002565acl_fetch_sc1_inc_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002566 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002567{
Willy Tarreau56123282010-08-06 19:06:56 +02002568 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002569 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002570 return acl_fetch_inc_gpc0(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002571}
2572
2573/* Increment the General Purpose Counter 0 value from the session's tracked
Willy Tarreaua5e37562011-12-16 17:06:15 +01002574 * backend counters and return it into temp integer.
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002575 */
2576static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002577acl_fetch_sc2_inc_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002578 const struct arg *args, struct sample *smp)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002579{
Willy Tarreau56123282010-08-06 19:06:56 +02002580 if (!l4->stkctr2_entry)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002581 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002582 return acl_fetch_inc_gpc0(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002583}
2584
2585/* Increment the General Purpose Counter 0 value from the session's source
Willy Tarreaua5e37562011-12-16 17:06:15 +01002586 * address in the table pointed to by expr, and return it into temp integer.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002587 * Accepts exactly 1 argument of type table.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002588 */
2589static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002590acl_fetch_src_inc_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002591 const struct arg *args, struct sample *smp)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002592{
2593 struct stktable_key *key;
2594
Willy Tarreau64ee4912012-08-30 22:59:48 +02002595 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002596 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002597 return 0;
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002598
Willy Tarreau24e32d82012-04-23 23:55:44 +02002599 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002600 return acl_fetch_inc_gpc0(&px->table, smp, stktable_update_key(&px->table, key));
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002601}
2602
Willy Tarreauf73cd112011-08-13 01:45:16 +02002603/* Clear the General Purpose Counter 0 value in the stksess entry <ts> and
Willy Tarreaua5e37562011-12-16 17:06:15 +01002604 * return its previous value into temp integer.
Willy Tarreauf73cd112011-08-13 01:45:16 +02002605 */
2606static int
Willy Tarreau37406352012-04-23 16:16:37 +02002607acl_fetch_clr_gpc0(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauf73cd112011-08-13 01:45:16 +02002608{
Willy Tarreau37406352012-04-23 16:16:37 +02002609 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002610 smp->type = SMP_T_UINT;
2611 smp->data.uint = 0;
Willy Tarreauf73cd112011-08-13 01:45:16 +02002612 if (ts != NULL) {
2613 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_GPC0);
2614 if (!ptr)
2615 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002616 smp->data.uint = stktable_data_cast(ptr, gpc0);
Willy Tarreauf73cd112011-08-13 01:45:16 +02002617 stktable_data_cast(ptr, gpc0) = 0;
2618 }
2619 return 1;
2620}
2621
2622/* Clear the General Purpose Counter 0 value from the session's tracked
Willy Tarreaua5e37562011-12-16 17:06:15 +01002623 * frontend counters and return its previous value into temp integer.
Willy Tarreauf73cd112011-08-13 01:45:16 +02002624 */
2625static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002626acl_fetch_sc1_clr_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002627 const struct arg *args, struct sample *smp)
Willy Tarreauf73cd112011-08-13 01:45:16 +02002628{
2629 if (!l4->stkctr1_entry)
2630 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002631 return acl_fetch_clr_gpc0(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf73cd112011-08-13 01:45:16 +02002632}
2633
2634/* Clear the General Purpose Counter 0 value from the session's tracked
Willy Tarreaua5e37562011-12-16 17:06:15 +01002635 * backend counters and return its previous value into temp integer.
Willy Tarreauf73cd112011-08-13 01:45:16 +02002636 */
2637static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002638acl_fetch_sc2_clr_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002639 const struct arg *args, struct sample *smp)
Willy Tarreauf73cd112011-08-13 01:45:16 +02002640{
2641 if (!l4->stkctr2_entry)
2642 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002643 return acl_fetch_clr_gpc0(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauf73cd112011-08-13 01:45:16 +02002644}
2645
2646/* Clear the General Purpose Counter 0 value from the session's source address
Willy Tarreaua5e37562011-12-16 17:06:15 +01002647 * in the table pointed to by expr, and return its previous value into temp integer.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002648 * Accepts exactly 1 argument of type table.
Willy Tarreauf73cd112011-08-13 01:45:16 +02002649 */
2650static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002651acl_fetch_src_clr_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002652 const struct arg *args, struct sample *smp)
Willy Tarreauf73cd112011-08-13 01:45:16 +02002653{
2654 struct stktable_key *key;
2655
Willy Tarreau64ee4912012-08-30 22:59:48 +02002656 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauf73cd112011-08-13 01:45:16 +02002657 if (!key)
2658 return 0;
2659
Willy Tarreau24e32d82012-04-23 23:55:44 +02002660 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002661 return acl_fetch_clr_gpc0(&px->table, smp, stktable_update_key(&px->table, key));
Willy Tarreauf73cd112011-08-13 01:45:16 +02002662}
2663
Willy Tarreaua5e37562011-12-16 17:06:15 +01002664/* set temp integer to the cumulated number of connections in the stksess entry <ts> */
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002665static int
Willy Tarreau37406352012-04-23 16:16:37 +02002666acl_fetch_conn_cnt(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002667{
Willy Tarreau37406352012-04-23 16:16:37 +02002668 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002669 smp->type = SMP_T_UINT;
2670 smp->data.uint = 0;
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002671 if (ts != NULL) {
2672 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_CONN_CNT);
2673 if (!ptr)
2674 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002675 smp->data.uint = stktable_data_cast(ptr, conn_cnt);
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002676 }
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002677 return 1;
2678}
2679
Willy Tarreaua5e37562011-12-16 17:06:15 +01002680/* set temp integer to the cumulated number of connections from the session's tracked FE counters */
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002681static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002682acl_fetch_sc1_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002683 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002684{
Willy Tarreau56123282010-08-06 19:06:56 +02002685 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002686 return 0;
2687
Willy Tarreau37406352012-04-23 16:16:37 +02002688 return acl_fetch_conn_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002689}
2690
Willy Tarreaua5e37562011-12-16 17:06:15 +01002691/* set temp integer to the cumulated number of connections from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002692static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002693acl_fetch_sc2_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002694 const struct arg *args, struct sample *smp)
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002695{
Willy Tarreau56123282010-08-06 19:06:56 +02002696 if (!l4->stkctr2_entry)
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002697 return 0;
2698
Willy Tarreau37406352012-04-23 16:16:37 +02002699 return acl_fetch_conn_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002700}
2701
Willy Tarreaua5e37562011-12-16 17:06:15 +01002702/* set temp integer to the cumulated number of connections from the session's source
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002703 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002704 * Accepts exactly 1 argument of type table.
Willy Tarreau8b22a712010-06-18 17:46:06 +02002705 */
2706static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002707acl_fetch_src_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002708 const struct arg *args, struct sample *smp)
Willy Tarreau8b22a712010-06-18 17:46:06 +02002709{
Willy Tarreau8b22a712010-06-18 17:46:06 +02002710 struct stktable_key *key;
2711
Willy Tarreau64ee4912012-08-30 22:59:48 +02002712 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau8b22a712010-06-18 17:46:06 +02002713 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002714 return 0;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002715
Willy Tarreau24e32d82012-04-23 23:55:44 +02002716 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002717 return acl_fetch_conn_cnt(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau8b22a712010-06-18 17:46:06 +02002718}
2719
Willy Tarreaua5e37562011-12-16 17:06:15 +01002720/* set temp integer to the connection rate in the stksess entry <ts> over the configured period */
Willy Tarreau91c43d72010-06-20 11:19:22 +02002721static int
Willy Tarreau37406352012-04-23 16:16:37 +02002722acl_fetch_conn_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002723{
Willy Tarreau37406352012-04-23 16:16:37 +02002724 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002725 smp->type = SMP_T_UINT;
2726 smp->data.uint = 0;
Willy Tarreau91c43d72010-06-20 11:19:22 +02002727 if (ts != NULL) {
2728 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_CONN_RATE);
2729 if (!ptr)
2730 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002731 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, conn_rate),
Willy Tarreau91c43d72010-06-20 11:19:22 +02002732 table->data_arg[STKTABLE_DT_CONN_RATE].u);
2733 }
2734 return 1;
2735}
2736
Willy Tarreaua5e37562011-12-16 17:06:15 +01002737/* set temp integer to the connection rate from the session's tracked FE counters over
Willy Tarreau91c43d72010-06-20 11:19:22 +02002738 * the configured period.
2739 */
2740static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002741acl_fetch_sc1_conn_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002742 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002743{
Willy Tarreau56123282010-08-06 19:06:56 +02002744 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002745 return 0;
2746
Willy Tarreau37406352012-04-23 16:16:37 +02002747 return acl_fetch_conn_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002748}
2749
Willy Tarreaua5e37562011-12-16 17:06:15 +01002750/* set temp integer to the connection rate from the session's tracked BE counters over
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002751 * the configured period.
2752 */
2753static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002754acl_fetch_sc2_conn_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002755 const struct arg *args, struct sample *smp)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002756{
Willy Tarreau56123282010-08-06 19:06:56 +02002757 if (!l4->stkctr2_entry)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002758 return 0;
2759
Willy Tarreau37406352012-04-23 16:16:37 +02002760 return acl_fetch_conn_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau91c43d72010-06-20 11:19:22 +02002761}
2762
Willy Tarreaua5e37562011-12-16 17:06:15 +01002763/* set temp integer to the connection rate from the session's source address in the
Willy Tarreau91c43d72010-06-20 11:19:22 +02002764 * table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002765 * Accepts exactly 1 argument of type table.
Willy Tarreau91c43d72010-06-20 11:19:22 +02002766 */
2767static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002768acl_fetch_src_conn_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002769 const struct arg *args, struct sample *smp)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002770{
2771 struct stktable_key *key;
2772
Willy Tarreau64ee4912012-08-30 22:59:48 +02002773 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau91c43d72010-06-20 11:19:22 +02002774 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002775 return 0;
Willy Tarreau91c43d72010-06-20 11:19:22 +02002776
Willy Tarreau24e32d82012-04-23 23:55:44 +02002777 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002778 return acl_fetch_conn_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau91c43d72010-06-20 11:19:22 +02002779}
2780
Willy Tarreaua5e37562011-12-16 17:06:15 +01002781/* set temp integer to the number of connections from the session's source address
Willy Tarreau8b22a712010-06-18 17:46:06 +02002782 * in the table pointed to by expr, after updating it.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002783 * Accepts exactly 1 argument of type table.
Willy Tarreau8b22a712010-06-18 17:46:06 +02002784 */
2785static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002786acl_fetch_src_updt_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002787 const struct arg *args, struct sample *smp)
Willy Tarreau8b22a712010-06-18 17:46:06 +02002788{
2789 struct stksess *ts;
2790 struct stktable_key *key;
2791 void *ptr;
2792
Willy Tarreau64ee4912012-08-30 22:59:48 +02002793 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau8b22a712010-06-18 17:46:06 +02002794 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002795 return 0;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002796
Willy Tarreau24e32d82012-04-23 23:55:44 +02002797 px = args->data.prx;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002798
Willy Tarreau1f7e9252010-06-20 12:27:21 +02002799 if ((ts = stktable_update_key(&px->table, key)) == NULL)
2800 /* entry does not exist and could not be created */
2801 return 0;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002802
2803 ptr = stktable_data_ptr(&px->table, ts, STKTABLE_DT_CONN_CNT);
2804 if (!ptr)
2805 return 0; /* parameter not stored in this table */
2806
Willy Tarreauf853c462012-04-23 18:53:56 +02002807 smp->type = SMP_T_UINT;
2808 smp->data.uint = ++stktable_data_cast(ptr, conn_cnt);
Willy Tarreau37406352012-04-23 16:16:37 +02002809 smp->flags = SMP_F_VOL_TEST;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002810 return 1;
2811}
2812
Willy Tarreaua5e37562011-12-16 17:06:15 +01002813/* set temp integer to the number of concurrent connections in the stksess entry <ts> */
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002814static int
Willy Tarreau37406352012-04-23 16:16:37 +02002815acl_fetch_conn_cur(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002816{
Willy Tarreau37406352012-04-23 16:16:37 +02002817 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002818 smp->type = SMP_T_UINT;
2819 smp->data.uint = 0;
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002820
2821 if (ts != NULL) {
2822 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_CONN_CUR);
2823 if (!ptr)
2824 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002825 smp->data.uint = stktable_data_cast(ptr, conn_cur);
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002826 }
2827 return 1;
2828}
2829
Willy Tarreaua5e37562011-12-16 17:06:15 +01002830/* set temp integer to the number of concurrent connections from the session's tracked FE counters */
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002831static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002832acl_fetch_sc1_conn_cur(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002833 const struct arg *args, struct sample *smp)
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002834{
Willy Tarreau56123282010-08-06 19:06:56 +02002835 if (!l4->stkctr1_entry)
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002836 return 0;
2837
Willy Tarreau37406352012-04-23 16:16:37 +02002838 return acl_fetch_conn_cur(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002839}
2840
Willy Tarreaua5e37562011-12-16 17:06:15 +01002841/* set temp integer to the number of concurrent connections from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002842static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002843acl_fetch_sc2_conn_cur(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002844 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002845{
Willy Tarreau56123282010-08-06 19:06:56 +02002846 if (!l4->stkctr2_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002847 return 0;
2848
Willy Tarreau37406352012-04-23 16:16:37 +02002849 return acl_fetch_conn_cur(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002850}
2851
Willy Tarreaua5e37562011-12-16 17:06:15 +01002852/* set temp integer to the number of concurrent connections from the session's source
Willy Tarreau38285c12010-06-18 16:35:43 +02002853 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002854 * Accepts exactly 1 argument of type table.
Willy Tarreau38285c12010-06-18 16:35:43 +02002855 */
2856static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002857acl_fetch_src_conn_cur(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002858 const struct arg *args, struct sample *smp)
Willy Tarreau38285c12010-06-18 16:35:43 +02002859{
Willy Tarreau38285c12010-06-18 16:35:43 +02002860 struct stktable_key *key;
2861
Willy Tarreau64ee4912012-08-30 22:59:48 +02002862 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau38285c12010-06-18 16:35:43 +02002863 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002864 return 0;
Willy Tarreau38285c12010-06-18 16:35:43 +02002865
Willy Tarreau24e32d82012-04-23 23:55:44 +02002866 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002867 return acl_fetch_conn_cur(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau38285c12010-06-18 16:35:43 +02002868}
2869
Willy Tarreaua5e37562011-12-16 17:06:15 +01002870/* set temp integer to the cumulated number of sessions in the stksess entry <ts> */
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002871static int
Willy Tarreau37406352012-04-23 16:16:37 +02002872acl_fetch_sess_cnt(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002873{
Willy Tarreau37406352012-04-23 16:16:37 +02002874 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002875 smp->type = SMP_T_UINT;
2876 smp->data.uint = 0;
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002877 if (ts != NULL) {
2878 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_SESS_CNT);
2879 if (!ptr)
2880 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002881 smp->data.uint = stktable_data_cast(ptr, sess_cnt);
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002882 }
2883 return 1;
2884}
2885
Willy Tarreaua5e37562011-12-16 17:06:15 +01002886/* set temp integer to the cumulated number of sessions from the session's tracked FE counters */
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002887static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002888acl_fetch_sc1_sess_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002889 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002890{
Willy Tarreau56123282010-08-06 19:06:56 +02002891 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002892 return 0;
2893
Willy Tarreau37406352012-04-23 16:16:37 +02002894 return acl_fetch_sess_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002895}
2896
Willy Tarreaua5e37562011-12-16 17:06:15 +01002897/* set temp integer to the cumulated number of sessions from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002898static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002899acl_fetch_sc2_sess_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002900 const struct arg *args, struct sample *smp)
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002901{
Willy Tarreau56123282010-08-06 19:06:56 +02002902 if (!l4->stkctr2_entry)
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002903 return 0;
2904
Willy Tarreau37406352012-04-23 16:16:37 +02002905 return acl_fetch_sess_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002906}
2907
Willy Tarreaua5e37562011-12-16 17:06:15 +01002908/* set temp integer to the cumulated number of session from the session's source
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002909 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002910 * Accepts exactly 1 argument of type table.
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002911 */
2912static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002913acl_fetch_src_sess_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002914 const struct arg *args, struct sample *smp)
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002915{
2916 struct stktable_key *key;
2917
Willy Tarreau64ee4912012-08-30 22:59:48 +02002918 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002919 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002920 return 0;
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002921
Willy Tarreau24e32d82012-04-23 23:55:44 +02002922 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002923 return acl_fetch_sess_cnt(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002924}
2925
Willy Tarreaua5e37562011-12-16 17:06:15 +01002926/* set temp integer to the session rate in the stksess entry <ts> over the configured period */
Willy Tarreau91c43d72010-06-20 11:19:22 +02002927static int
Willy Tarreau37406352012-04-23 16:16:37 +02002928acl_fetch_sess_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002929{
Willy Tarreau37406352012-04-23 16:16:37 +02002930 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002931 smp->type = SMP_T_UINT;
2932 smp->data.uint = 0;
Willy Tarreau91c43d72010-06-20 11:19:22 +02002933 if (ts != NULL) {
2934 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_SESS_RATE);
2935 if (!ptr)
2936 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002937 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, sess_rate),
Willy Tarreau91c43d72010-06-20 11:19:22 +02002938 table->data_arg[STKTABLE_DT_SESS_RATE].u);
2939 }
2940 return 1;
2941}
2942
Willy Tarreaua5e37562011-12-16 17:06:15 +01002943/* set temp integer to the session rate from the session's tracked FE counters over
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002944 * the configured period.
2945 */
2946static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002947acl_fetch_sc1_sess_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002948 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002949{
Willy Tarreau56123282010-08-06 19:06:56 +02002950 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002951 return 0;
2952
Willy Tarreau37406352012-04-23 16:16:37 +02002953 return acl_fetch_sess_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002954}
2955
Willy Tarreaua5e37562011-12-16 17:06:15 +01002956/* set temp integer to the session rate from the session's tracked BE counters over
Willy Tarreau91c43d72010-06-20 11:19:22 +02002957 * the configured period.
2958 */
2959static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002960acl_fetch_sc2_sess_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002961 const struct arg *args, struct sample *smp)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002962{
Willy Tarreau56123282010-08-06 19:06:56 +02002963 if (!l4->stkctr2_entry)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002964 return 0;
2965
Willy Tarreau37406352012-04-23 16:16:37 +02002966 return acl_fetch_sess_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau91c43d72010-06-20 11:19:22 +02002967}
2968
Willy Tarreaua5e37562011-12-16 17:06:15 +01002969/* set temp integer to the session rate from the session's source address in the
Willy Tarreau91c43d72010-06-20 11:19:22 +02002970 * table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002971 * Accepts exactly 1 argument of type table.
Willy Tarreau91c43d72010-06-20 11:19:22 +02002972 */
2973static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002974acl_fetch_src_sess_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002975 const struct arg *args, struct sample *smp)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002976{
2977 struct stktable_key *key;
2978
Willy Tarreau64ee4912012-08-30 22:59:48 +02002979 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau91c43d72010-06-20 11:19:22 +02002980 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002981 return 0;
Willy Tarreau91c43d72010-06-20 11:19:22 +02002982
Willy Tarreau24e32d82012-04-23 23:55:44 +02002983 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002984 return acl_fetch_sess_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau91c43d72010-06-20 11:19:22 +02002985}
2986
Willy Tarreaua5e37562011-12-16 17:06:15 +01002987/* set temp integer to the cumulated number of sessions in the stksess entry <ts> */
Willy Tarreauda7ff642010-06-23 11:44:09 +02002988static int
Willy Tarreau37406352012-04-23 16:16:37 +02002989acl_fetch_http_req_cnt(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauda7ff642010-06-23 11:44:09 +02002990{
Willy Tarreau37406352012-04-23 16:16:37 +02002991 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002992 smp->type = SMP_T_UINT;
2993 smp->data.uint = 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02002994 if (ts != NULL) {
2995 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_HTTP_REQ_CNT);
2996 if (!ptr)
2997 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002998 smp->data.uint = stktable_data_cast(ptr, http_req_cnt);
Willy Tarreauda7ff642010-06-23 11:44:09 +02002999 }
3000 return 1;
3001}
3002
Willy Tarreaua5e37562011-12-16 17:06:15 +01003003/* set temp integer to the cumulated number of sessions from the session's tracked FE counters */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003004static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003005acl_fetch_sc1_http_req_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003006 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003007{
Willy Tarreau56123282010-08-06 19:06:56 +02003008 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003009 return 0;
3010
Willy Tarreau37406352012-04-23 16:16:37 +02003011 return acl_fetch_http_req_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003012}
3013
Willy Tarreaua5e37562011-12-16 17:06:15 +01003014/* set temp integer to the cumulated number of sessions from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003015static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003016acl_fetch_sc2_http_req_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003017 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003018{
Willy Tarreau56123282010-08-06 19:06:56 +02003019 if (!l4->stkctr2_entry)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003020 return 0;
3021
Willy Tarreau37406352012-04-23 16:16:37 +02003022 return acl_fetch_http_req_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003023}
3024
Willy Tarreaua5e37562011-12-16 17:06:15 +01003025/* set temp integer to the cumulated number of session from the session's source
Willy Tarreauda7ff642010-06-23 11:44:09 +02003026 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003027 * Accepts exactly 1 argument of type table.
Willy Tarreauda7ff642010-06-23 11:44:09 +02003028 */
3029static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003030acl_fetch_src_http_req_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003031 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003032{
3033 struct stktable_key *key;
3034
Willy Tarreau64ee4912012-08-30 22:59:48 +02003035 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003036 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003037 return 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003038
Willy Tarreau24e32d82012-04-23 23:55:44 +02003039 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003040 return acl_fetch_http_req_cnt(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauda7ff642010-06-23 11:44:09 +02003041}
3042
Willy Tarreaua5e37562011-12-16 17:06:15 +01003043/* set temp integer to the session rate in the stksess entry <ts> over the configured period */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003044static int
Willy Tarreau37406352012-04-23 16:16:37 +02003045acl_fetch_http_req_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003046{
Willy Tarreau37406352012-04-23 16:16:37 +02003047 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003048 smp->type = SMP_T_UINT;
3049 smp->data.uint = 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003050 if (ts != NULL) {
3051 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_HTTP_REQ_RATE);
3052 if (!ptr)
3053 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003054 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, http_req_rate),
Willy Tarreauda7ff642010-06-23 11:44:09 +02003055 table->data_arg[STKTABLE_DT_HTTP_REQ_RATE].u);
3056 }
3057 return 1;
3058}
3059
Willy Tarreaua5e37562011-12-16 17:06:15 +01003060/* set temp integer to the session rate from the session's tracked FE counters over
Willy Tarreauda7ff642010-06-23 11:44:09 +02003061 * the configured period.
3062 */
3063static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003064acl_fetch_sc1_http_req_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003065 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003066{
Willy Tarreau56123282010-08-06 19:06:56 +02003067 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003068 return 0;
3069
Willy Tarreau37406352012-04-23 16:16:37 +02003070 return acl_fetch_http_req_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003071}
3072
Willy Tarreaua5e37562011-12-16 17:06:15 +01003073/* set temp integer to the session rate from the session's tracked BE counters over
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003074 * the configured period.
3075 */
3076static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003077acl_fetch_sc2_http_req_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003078 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003079{
Willy Tarreau56123282010-08-06 19:06:56 +02003080 if (!l4->stkctr2_entry)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003081 return 0;
3082
Willy Tarreau37406352012-04-23 16:16:37 +02003083 return acl_fetch_http_req_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003084}
3085
Willy Tarreaua5e37562011-12-16 17:06:15 +01003086/* set temp integer to the session rate from the session's source address in the
Willy Tarreauda7ff642010-06-23 11:44:09 +02003087 * table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003088 * Accepts exactly 1 argument of type table.
Willy Tarreauda7ff642010-06-23 11:44:09 +02003089 */
3090static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003091acl_fetch_src_http_req_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003092 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003093{
3094 struct stktable_key *key;
3095
Willy Tarreau64ee4912012-08-30 22:59:48 +02003096 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003097 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003098 return 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003099
Willy Tarreau24e32d82012-04-23 23:55:44 +02003100 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003101 return acl_fetch_http_req_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauda7ff642010-06-23 11:44:09 +02003102}
3103
Willy Tarreaua5e37562011-12-16 17:06:15 +01003104/* set temp integer to the cumulated number of sessions in the stksess entry <ts> */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003105static int
Willy Tarreau37406352012-04-23 16:16:37 +02003106acl_fetch_http_err_cnt(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003107{
Willy Tarreau37406352012-04-23 16:16:37 +02003108 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003109 smp->type = SMP_T_UINT;
3110 smp->data.uint = 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003111 if (ts != NULL) {
3112 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_HTTP_ERR_CNT);
3113 if (!ptr)
3114 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003115 smp->data.uint = stktable_data_cast(ptr, http_err_cnt);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003116 }
3117 return 1;
3118}
3119
Willy Tarreaua5e37562011-12-16 17:06:15 +01003120/* set temp integer to the cumulated number of sessions from the session's tracked FE counters */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003121static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003122acl_fetch_sc1_http_err_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003123 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003124{
Willy Tarreau56123282010-08-06 19:06:56 +02003125 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003126 return 0;
3127
Willy Tarreau37406352012-04-23 16:16:37 +02003128 return acl_fetch_http_err_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003129}
3130
Willy Tarreaua5e37562011-12-16 17:06:15 +01003131/* set temp integer to the cumulated number of sessions from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003132static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003133acl_fetch_sc2_http_err_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003134 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003135{
Willy Tarreau56123282010-08-06 19:06:56 +02003136 if (!l4->stkctr2_entry)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003137 return 0;
3138
Willy Tarreau37406352012-04-23 16:16:37 +02003139 return acl_fetch_http_err_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003140}
3141
Willy Tarreaua5e37562011-12-16 17:06:15 +01003142/* set temp integer to the cumulated number of session from the session's source
Willy Tarreauda7ff642010-06-23 11:44:09 +02003143 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003144 * Accepts exactly 1 argument of type table.
Willy Tarreauda7ff642010-06-23 11:44:09 +02003145 */
3146static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003147acl_fetch_src_http_err_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003148 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003149{
3150 struct stktable_key *key;
3151
Willy Tarreau64ee4912012-08-30 22:59:48 +02003152 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003153 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003154 return 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003155
Willy Tarreau24e32d82012-04-23 23:55:44 +02003156 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003157 return acl_fetch_http_err_cnt(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauda7ff642010-06-23 11:44:09 +02003158}
3159
Willy Tarreaua5e37562011-12-16 17:06:15 +01003160/* set temp integer to the session rate in the stksess entry <ts> over the configured period */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003161static int
Willy Tarreau37406352012-04-23 16:16:37 +02003162acl_fetch_http_err_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003163{
Willy Tarreau37406352012-04-23 16:16:37 +02003164 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003165 smp->type = SMP_T_UINT;
3166 smp->data.uint = 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003167 if (ts != NULL) {
3168 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_HTTP_ERR_RATE);
3169 if (!ptr)
3170 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003171 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, http_err_rate),
Willy Tarreauda7ff642010-06-23 11:44:09 +02003172 table->data_arg[STKTABLE_DT_HTTP_ERR_RATE].u);
3173 }
3174 return 1;
3175}
3176
Willy Tarreaua5e37562011-12-16 17:06:15 +01003177/* set temp integer to the session rate from the session's tracked FE counters over
Willy Tarreauda7ff642010-06-23 11:44:09 +02003178 * the configured period.
3179 */
3180static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003181acl_fetch_sc1_http_err_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003182 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003183{
Willy Tarreau56123282010-08-06 19:06:56 +02003184 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003185 return 0;
3186
Willy Tarreau37406352012-04-23 16:16:37 +02003187 return acl_fetch_http_err_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003188}
3189
Willy Tarreaua5e37562011-12-16 17:06:15 +01003190/* set temp integer to the session rate from the session's tracked BE counters over
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003191 * the configured period.
3192 */
3193static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003194acl_fetch_sc2_http_err_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003195 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003196{
Willy Tarreau56123282010-08-06 19:06:56 +02003197 if (!l4->stkctr2_entry)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003198 return 0;
3199
Willy Tarreau37406352012-04-23 16:16:37 +02003200 return acl_fetch_http_err_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003201}
3202
Willy Tarreaua5e37562011-12-16 17:06:15 +01003203/* set temp integer to the session rate from the session's source address in the
Willy Tarreauda7ff642010-06-23 11:44:09 +02003204 * table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003205 * Accepts exactly 1 argument of type table.
Willy Tarreauda7ff642010-06-23 11:44:09 +02003206 */
3207static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003208acl_fetch_src_http_err_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003209 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003210{
3211 struct stktable_key *key;
3212
Willy Tarreau64ee4912012-08-30 22:59:48 +02003213 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003214 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003215 return 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003216
Willy Tarreau24e32d82012-04-23 23:55:44 +02003217 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003218 return acl_fetch_http_err_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauda7ff642010-06-23 11:44:09 +02003219}
3220
Willy Tarreaua5e37562011-12-16 17:06:15 +01003221/* set temp integer to the number of kbytes received from clients matching the stksess entry <ts> */
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003222static int
Willy Tarreau37406352012-04-23 16:16:37 +02003223acl_fetch_kbytes_in(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003224{
Willy Tarreau37406352012-04-23 16:16:37 +02003225 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003226 smp->type = SMP_T_UINT;
3227 smp->data.uint = 0;
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003228
3229 if (ts != NULL) {
3230 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_BYTES_IN_CNT);
3231 if (!ptr)
3232 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003233 smp->data.uint = stktable_data_cast(ptr, bytes_in_cnt) >> 10;
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003234 }
3235 return 1;
3236}
3237
Willy Tarreaua5e37562011-12-16 17:06:15 +01003238/* set temp integer to the number of kbytes received from clients according to the
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003239 * session's tracked FE counters.
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003240 */
3241static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003242acl_fetch_sc1_kbytes_in(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003243 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003244{
Willy Tarreau56123282010-08-06 19:06:56 +02003245 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003246 return 0;
3247
Willy Tarreau37406352012-04-23 16:16:37 +02003248 return acl_fetch_kbytes_in(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003249}
3250
Willy Tarreaua5e37562011-12-16 17:06:15 +01003251/* set temp integer to the number of kbytes received from clients according to the
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003252 * session's tracked BE counters.
3253 */
3254static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003255acl_fetch_sc2_kbytes_in(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003256 const struct arg *args, struct sample *smp)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003257{
Willy Tarreau56123282010-08-06 19:06:56 +02003258 if (!l4->stkctr2_entry)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003259 return 0;
3260
Willy Tarreau37406352012-04-23 16:16:37 +02003261 return acl_fetch_kbytes_in(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003262}
3263
Willy Tarreaua5e37562011-12-16 17:06:15 +01003264/* set temp integer to the number of kbytes received from the session's source
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003265 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003266 * Accepts exactly 1 argument of type table.
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003267 */
3268static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003269acl_fetch_src_kbytes_in(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003270 const struct arg *args, struct sample *smp)
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003271{
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003272 struct stktable_key *key;
3273
Willy Tarreau64ee4912012-08-30 22:59:48 +02003274 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003275 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003276 return 0;
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003277
Willy Tarreau24e32d82012-04-23 23:55:44 +02003278 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003279 return acl_fetch_kbytes_in(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003280}
3281
Willy Tarreaua5e37562011-12-16 17:06:15 +01003282/* set temp integer to the bytes rate from clients in the stksess entry <ts> over the
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003283 * configured period.
3284 */
3285static int
Willy Tarreau37406352012-04-23 16:16:37 +02003286acl_fetch_bytes_in_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003287{
Willy Tarreau37406352012-04-23 16:16:37 +02003288 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003289 smp->type = SMP_T_UINT;
3290 smp->data.uint = 0;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003291 if (ts != NULL) {
3292 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_BYTES_IN_RATE);
3293 if (!ptr)
3294 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003295 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, bytes_in_rate),
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003296 table->data_arg[STKTABLE_DT_BYTES_IN_RATE].u);
3297 }
3298 return 1;
3299}
3300
Willy Tarreaua5e37562011-12-16 17:06:15 +01003301/* set temp integer to the bytes rate from clients from the session's tracked FE
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003302 * counters over the configured period.
3303 */
3304static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003305acl_fetch_sc1_bytes_in_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003306 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003307{
Willy Tarreau56123282010-08-06 19:06:56 +02003308 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003309 return 0;
3310
Willy Tarreau37406352012-04-23 16:16:37 +02003311 return acl_fetch_bytes_in_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003312}
3313
Willy Tarreaua5e37562011-12-16 17:06:15 +01003314/* set temp integer to the bytes rate from clients from the session's tracked BE
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003315 * counters over the configured period.
3316 */
3317static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003318acl_fetch_sc2_bytes_in_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003319 const struct arg *args, struct sample *smp)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003320{
Willy Tarreau56123282010-08-06 19:06:56 +02003321 if (!l4->stkctr2_entry)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003322 return 0;
3323
Willy Tarreau37406352012-04-23 16:16:37 +02003324 return acl_fetch_bytes_in_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003325}
3326
Willy Tarreaua5e37562011-12-16 17:06:15 +01003327/* set temp integer to the bytes rate from clients from the session's source address
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003328 * in the table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003329 * Accepts exactly 1 argument of type table.
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003330 */
3331static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003332acl_fetch_src_bytes_in_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003333 const struct arg *args, struct sample *smp)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003334{
3335 struct stktable_key *key;
3336
Willy Tarreau64ee4912012-08-30 22:59:48 +02003337 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003338 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003339 return 0;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003340
Willy Tarreau24e32d82012-04-23 23:55:44 +02003341 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003342 return acl_fetch_bytes_in_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003343}
3344
Willy Tarreaua5e37562011-12-16 17:06:15 +01003345/* set temp integer to the number of kbytes sent to clients matching the stksess entry <ts> */
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003346static int
Willy Tarreau37406352012-04-23 16:16:37 +02003347acl_fetch_kbytes_out(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003348{
Willy Tarreau37406352012-04-23 16:16:37 +02003349 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003350 smp->type = SMP_T_UINT;
3351 smp->data.uint = 0;
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003352
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003353 if (ts != NULL) {
3354 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_BYTES_OUT_CNT);
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003355 if (!ptr)
3356 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003357 smp->data.uint = stktable_data_cast(ptr, bytes_out_cnt) >> 10;
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003358 }
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003359 return 1;
3360}
3361
Willy Tarreaua5e37562011-12-16 17:06:15 +01003362/* set temp integer to the number of kbytes sent to clients according to the session's
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003363 * tracked FE counters.
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003364 */
3365static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003366acl_fetch_sc1_kbytes_out(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003367 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003368{
Willy Tarreau56123282010-08-06 19:06:56 +02003369 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003370 return 0;
3371
Willy Tarreau37406352012-04-23 16:16:37 +02003372 return acl_fetch_kbytes_out(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003373}
3374
Willy Tarreaua5e37562011-12-16 17:06:15 +01003375/* set temp integer to the number of kbytes sent to clients according to the session's
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003376 * tracked BE counters.
3377 */
3378static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003379acl_fetch_sc2_kbytes_out(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003380 const struct arg *args, struct sample *smp)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003381{
Willy Tarreau56123282010-08-06 19:06:56 +02003382 if (!l4->stkctr2_entry)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003383 return 0;
3384
Willy Tarreau37406352012-04-23 16:16:37 +02003385 return acl_fetch_kbytes_out(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003386}
3387
Willy Tarreaua5e37562011-12-16 17:06:15 +01003388/* set temp integer to the number of kbytes sent to the session's source address in
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003389 * the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003390 * Accepts exactly 1 argument of type table.
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003391 */
3392static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003393acl_fetch_src_kbytes_out(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003394 const struct arg *args, struct sample *smp)
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003395{
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003396 struct stktable_key *key;
3397
Willy Tarreau64ee4912012-08-30 22:59:48 +02003398 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003399 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003400 return 0;
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003401
Willy Tarreau24e32d82012-04-23 23:55:44 +02003402 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003403 return acl_fetch_kbytes_out(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003404}
3405
Willy Tarreaua5e37562011-12-16 17:06:15 +01003406/* set temp integer to the bytes rate to clients in the stksess entry <ts> over the
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003407 * configured period.
3408 */
3409static int
Willy Tarreau37406352012-04-23 16:16:37 +02003410acl_fetch_bytes_out_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003411{
Willy Tarreau37406352012-04-23 16:16:37 +02003412 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003413 smp->type = SMP_T_UINT;
3414 smp->data.uint = 0;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003415 if (ts != NULL) {
3416 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_BYTES_OUT_RATE);
3417 if (!ptr)
3418 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003419 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, bytes_out_rate),
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003420 table->data_arg[STKTABLE_DT_BYTES_OUT_RATE].u);
3421 }
3422 return 1;
3423}
3424
Willy Tarreaua5e37562011-12-16 17:06:15 +01003425/* set temp integer to the bytes rate to clients from the session's tracked FE counters
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003426 * over the configured period.
3427 */
3428static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003429acl_fetch_sc1_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003430 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003431{
Willy Tarreau56123282010-08-06 19:06:56 +02003432 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003433 return 0;
3434
Willy Tarreau37406352012-04-23 16:16:37 +02003435 return acl_fetch_bytes_out_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003436}
3437
Willy Tarreaua5e37562011-12-16 17:06:15 +01003438/* set temp integer to the bytes rate to clients from the session's tracked BE counters
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003439 * over the configured period.
3440 */
3441static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003442acl_fetch_sc2_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003443 const struct arg *args, struct sample *smp)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003444{
Willy Tarreau56123282010-08-06 19:06:56 +02003445 if (!l4->stkctr2_entry)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003446 return 0;
3447
Willy Tarreau37406352012-04-23 16:16:37 +02003448 return acl_fetch_bytes_out_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003449}
3450
Willy Tarreaua5e37562011-12-16 17:06:15 +01003451/* set temp integer to the bytes rate to client from the session's source address in
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003452 * the table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003453 * Accepts exactly 1 argument of type table.
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003454 */
3455static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003456acl_fetch_src_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003457 const struct arg *args, struct sample *smp)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003458{
3459 struct stktable_key *key;
3460
Willy Tarreau64ee4912012-08-30 22:59:48 +02003461 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003462 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003463 return 0;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003464
Willy Tarreau24e32d82012-04-23 23:55:44 +02003465 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003466 return acl_fetch_bytes_out_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003467}
3468
Willy Tarreau34db1082012-04-19 17:16:54 +02003469/* set temp integer to the number of used entries in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003470 * Accepts exactly 1 argument of type table.
Willy Tarreau34db1082012-04-19 17:16:54 +02003471 */
Willy Tarreauc735a072011-03-29 00:57:02 +02003472static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003473acl_fetch_table_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003474 const struct arg *args, struct sample *smp)
Willy Tarreauc735a072011-03-29 00:57:02 +02003475{
Willy Tarreau37406352012-04-23 16:16:37 +02003476 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003477 smp->type = SMP_T_UINT;
Willy Tarreau24e32d82012-04-23 23:55:44 +02003478 smp->data.uint = args->data.prx->table.current;
Willy Tarreauc735a072011-03-29 00:57:02 +02003479 return 1;
3480}
3481
Willy Tarreau34db1082012-04-19 17:16:54 +02003482/* set temp integer to the number of free entries in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003483 * Accepts exactly 1 argument of type table.
Willy Tarreau34db1082012-04-19 17:16:54 +02003484 */
Willy Tarreauc735a072011-03-29 00:57:02 +02003485static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003486acl_fetch_table_avl(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003487 const struct arg *args, struct sample *smp)
Willy Tarreauc735a072011-03-29 00:57:02 +02003488{
Willy Tarreau24e32d82012-04-23 23:55:44 +02003489 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003490 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003491 smp->type = SMP_T_UINT;
3492 smp->data.uint = px->table.size - px->table.current;
Willy Tarreauc735a072011-03-29 00:57:02 +02003493 return 1;
3494}
Willy Tarreau8b22a712010-06-18 17:46:06 +02003495
Willy Tarreau61612d42012-04-19 18:42:05 +02003496/* Note: must not be declared <const> as its list will be overwritten.
3497 * Please take care of keeping this list alphabetically sorted.
3498 */
Willy Tarreau8b22a712010-06-18 17:46:06 +02003499static struct acl_kw_list acl_kws = {{ },{
Willy Tarreau61612d42012-04-19 18:42:05 +02003500 { "sc1_bytes_in_rate", acl_parse_int, acl_fetch_sc1_bytes_in_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3501 { "sc1_bytes_out_rate", acl_parse_int, acl_fetch_sc1_bytes_out_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3502 { "sc1_clr_gpc0", acl_parse_int, acl_fetch_sc1_clr_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3503 { "sc1_conn_cnt", acl_parse_int, acl_fetch_sc1_conn_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3504 { "sc1_conn_cur", acl_parse_int, acl_fetch_sc1_conn_cur, acl_match_int, ACL_USE_NOTHING, 0 },
3505 { "sc1_conn_rate", acl_parse_int, acl_fetch_sc1_conn_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3506 { "sc1_get_gpc0", acl_parse_int, acl_fetch_sc1_get_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3507 { "sc1_http_err_cnt", acl_parse_int, acl_fetch_sc1_http_err_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3508 { "sc1_http_err_rate", acl_parse_int, acl_fetch_sc1_http_err_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3509 { "sc1_http_req_cnt", acl_parse_int, acl_fetch_sc1_http_req_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3510 { "sc1_http_req_rate", acl_parse_int, acl_fetch_sc1_http_req_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3511 { "sc1_inc_gpc0", acl_parse_int, acl_fetch_sc1_inc_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3512 { "sc1_kbytes_in", acl_parse_int, acl_fetch_sc1_kbytes_in, acl_match_int, ACL_USE_TCP4_VOLATILE, 0 },
3513 { "sc1_kbytes_out", acl_parse_int, acl_fetch_sc1_kbytes_out, acl_match_int, ACL_USE_TCP4_VOLATILE, 0 },
3514 { "sc1_sess_cnt", acl_parse_int, acl_fetch_sc1_sess_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3515 { "sc1_sess_rate", acl_parse_int, acl_fetch_sc1_sess_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3516 { "sc2_bytes_in_rate", acl_parse_int, acl_fetch_sc2_bytes_in_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3517 { "sc2_bytes_out_rate", acl_parse_int, acl_fetch_sc2_bytes_out_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3518 { "sc2_clr_gpc0", acl_parse_int, acl_fetch_sc2_clr_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3519 { "sc2_conn_cnt", acl_parse_int, acl_fetch_sc2_conn_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3520 { "sc2_conn_cur", acl_parse_int, acl_fetch_sc2_conn_cur, acl_match_int, ACL_USE_NOTHING, 0 },
3521 { "sc2_conn_rate", acl_parse_int, acl_fetch_sc2_conn_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3522 { "sc2_get_gpc0", acl_parse_int, acl_fetch_sc2_get_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3523 { "sc2_http_err_cnt", acl_parse_int, acl_fetch_sc2_http_err_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3524 { "sc2_http_err_rate", acl_parse_int, acl_fetch_sc2_http_err_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3525 { "sc2_http_req_cnt", acl_parse_int, acl_fetch_sc2_http_req_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3526 { "sc2_http_req_rate", acl_parse_int, acl_fetch_sc2_http_req_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3527 { "sc2_inc_gpc0", acl_parse_int, acl_fetch_sc2_inc_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3528 { "sc2_kbytes_in", acl_parse_int, acl_fetch_sc2_kbytes_in, acl_match_int, ACL_USE_TCP4_VOLATILE, 0 },
3529 { "sc2_kbytes_out", acl_parse_int, acl_fetch_sc2_kbytes_out, acl_match_int, ACL_USE_TCP4_VOLATILE, 0 },
3530 { "sc2_sess_cnt", acl_parse_int, acl_fetch_sc2_sess_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3531 { "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 +02003532 { "src_bytes_in_rate", acl_parse_int, acl_fetch_src_bytes_in_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3533 { "src_bytes_out_rate", acl_parse_int, acl_fetch_src_bytes_out_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3534 { "src_clr_gpc0", acl_parse_int, acl_fetch_src_clr_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3535 { "src_conn_cnt", acl_parse_int, acl_fetch_src_conn_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3536 { "src_conn_cur", acl_parse_int, acl_fetch_src_conn_cur, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3537 { "src_conn_rate", acl_parse_int, acl_fetch_src_conn_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3538 { "src_get_gpc0", acl_parse_int, acl_fetch_src_get_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3539 { "src_http_err_cnt", acl_parse_int, acl_fetch_src_http_err_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3540 { "src_http_err_rate", acl_parse_int, acl_fetch_src_http_err_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3541 { "src_http_req_cnt", acl_parse_int, acl_fetch_src_http_req_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3542 { "src_http_req_rate", acl_parse_int, acl_fetch_src_http_req_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3543 { "src_inc_gpc0", acl_parse_int, acl_fetch_src_inc_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3544 { "src_kbytes_in", acl_parse_int, acl_fetch_src_kbytes_in, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3545 { "src_kbytes_out", acl_parse_int, acl_fetch_src_kbytes_out, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3546 { "src_sess_cnt", acl_parse_int, acl_fetch_src_sess_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3547 { "src_sess_rate", acl_parse_int, acl_fetch_src_sess_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3548 { "src_updt_conn_cnt", acl_parse_int, acl_fetch_src_updt_conn_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3549 { "table_avl", acl_parse_int, acl_fetch_table_avl, acl_match_int, ACL_USE_NOTHING, ARG1(1,TAB) },
3550 { "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 +02003551 { NULL, NULL, NULL, NULL },
3552}};
3553
3554
Willy Tarreau56123282010-08-06 19:06:56 +02003555/* Parse a "track-sc[12]" line starting with "track-sc[12]" in args[arg-1].
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003556 * Returns the number of warnings emitted, or -1 in case of fatal errors. The
3557 * <prm> struct is fed with the table name if any. If unspecified, the caller
3558 * will assume that the current proxy's table is used.
3559 */
3560int parse_track_counters(char **args, int *arg,
3561 int section_type, struct proxy *curpx,
3562 struct track_ctr_prm *prm,
Willy Tarreau0a3dd742012-05-08 19:47:01 +02003563 struct proxy *defpx, char **err)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003564{
Willy Tarreau12785782012-04-27 21:37:17 +02003565 int sample_type = 0;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003566
Willy Tarreau56123282010-08-06 19:06:56 +02003567 /* parse the arguments of "track-sc[12]" before the condition in the
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003568 * following form :
Willy Tarreau56123282010-08-06 19:06:56 +02003569 * track-sc[12] src [ table xxx ] [ if|unless ... ]
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003570 */
3571 while (args[*arg]) {
3572 if (strcmp(args[*arg], "src") == 0) {
3573 prm->type = STKTABLE_TYPE_IP;
Willy Tarreau12785782012-04-27 21:37:17 +02003574 sample_type = 1;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003575 }
3576 else if (strcmp(args[*arg], "table") == 0) {
3577 if (!args[*arg + 1]) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02003578 memprintf(err, "missing table name");
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003579 return -1;
3580 }
3581 /* we copy the table name for now, it will be resolved later */
3582 prm->table.n = strdup(args[*arg + 1]);
3583 (*arg)++;
3584 }
3585 else {
3586 /* unhandled keywords are handled by the caller */
3587 break;
3588 }
3589 (*arg)++;
3590 }
3591
Willy Tarreau12785782012-04-27 21:37:17 +02003592 if (!sample_type) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02003593 memprintf(err,
3594 "tracking key not specified (found %s, only 'src' is supported)",
3595 quote_arg(args[*arg]));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003596 return -1;
3597 }
3598
3599 return 0;
3600}
3601
Willy Tarreau8b22a712010-06-18 17:46:06 +02003602__attribute__((constructor))
3603static void __session_init(void)
3604{
3605 acl_register_keywords(&acl_kws);
3606}
3607
Willy Tarreaubaaee002006-06-26 02:48:02 +02003608/*
3609 * Local variables:
3610 * c-indent-level: 8
3611 * c-basic-offset: 8
3612 * End:
3613 */