blob: 6fb79e3f254714d60586a2e6bbcd1057f96b6107 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
Willy Tarreau81f9aa32010-06-01 17:45:26 +02002 * Session management functions.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003 *
Willy Tarreaud28c3532012-04-19 19:28:33 +02004 * Copyright 2000-2012 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdlib.h>
Willy Tarreau81f9aa32010-06-01 17:45:26 +020014#include <unistd.h>
15#include <fcntl.h>
Willy Tarreaue3ba5f02006-06-29 18:54:54 +020016
17#include <common/config.h>
Willy Tarreau7c669d72008-06-20 15:04:11 +020018#include <common/debug.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020019#include <common/memory.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020020
Willy Tarreaubaaee002006-06-26 02:48:02 +020021#include <types/capture.h>
Willy Tarreau55a8d0e2008-11-30 18:47:21 +010022#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020023
Willy Tarreau1d0dfb12009-07-07 15:10:31 +020024#include <proto/acl.h>
Willy Tarreau61612d42012-04-19 18:42:05 +020025#include <proto/arg.h>
Willy Tarreau55a8d0e2008-11-30 18:47:21 +010026#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <proto/channel.h>
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +010028#include <proto/checks.h>
Willy Tarreaud2274c62012-07-06 14:29:45 +020029#include <proto/connection.h>
Willy Tarreau5ca791d2009-08-16 19:06:42 +020030#include <proto/dumpstats.h>
Willy Tarreaudd2f85e2012-09-02 22:34:23 +020031#include <proto/fd.h>
Willy Tarreau91c43d72010-06-20 11:19:22 +020032#include <proto/freq_ctr.h>
Willy Tarreau3041b9f2010-10-15 23:25:20 +020033#include <proto/frontend.h>
Willy Tarreau8d5d7f22007-01-21 19:16:41 +010034#include <proto/hdr_idx.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020035#include <proto/listener.h>
Willy Tarreau332f8bf2007-05-13 21:36:56 +020036#include <proto/log.h>
Willy Tarreaucbaaec42012-09-06 11:32:07 +020037#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038#include <proto/session.h>
Willy Tarreau3eba98a2009-01-25 13:56:13 +010039#include <proto/pipe.h>
Willy Tarreau55a8d0e2008-11-30 18:47:21 +010040#include <proto/proto_http.h>
41#include <proto/proto_tcp.h>
Willy Tarreau1d0dfb12009-07-07 15:10:31 +020042#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/queue.h>
Willy Tarreau7f062c42009-03-05 18:43:00 +010044#include <proto/server.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020045#include <proto/sample.h>
Emeric Brun1d33b292010-01-04 15:47:17 +010046#include <proto/stick_table.h>
Willy Tarreau55a8d0e2008-11-30 18:47:21 +010047#include <proto/stream_interface.h>
Willy Tarreau55a8d0e2008-11-30 18:47:21 +010048#include <proto/task.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049
Willy Tarreauc6ca1a02007-05-13 19:43:47 +020050struct pool_head *pool2_session;
Willy Tarreauf54f8bd2008-11-23 19:53:55 +010051struct list sessions;
Willy Tarreaubaaee002006-06-26 02:48:02 +020052
Willy Tarreau2542b532012-08-31 16:01:23 +020053static struct task *expire_mini_session(struct task *t);
54int session_complete(struct session *s);
55
56/* This function is called from the protocol layer accept() in order to
57 * instanciate a new embryonic session on behalf of a given listener and
58 * frontend. It returns a positive value upon success, 0 if the connection
59 * can be ignored, or a negative value upon critical failure. The accepted
60 * file descriptor is closed if we return <= 0.
Willy Tarreau81f9aa32010-06-01 17:45:26 +020061 */
62int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
63{
64 struct proxy *p = l->frontend;
65 struct session *s;
Willy Tarreau81f9aa32010-06-01 17:45:26 +020066 struct task *t;
Willy Tarreauabe8ea52010-11-11 10:56:04 +010067 int ret;
68
69
70 ret = -1; /* assume unrecoverable error by default */
Willy Tarreau81f9aa32010-06-01 17:45:26 +020071
Willy Tarreaufffe1322010-11-11 09:48:16 +010072 if (unlikely((s = pool_alloc2(pool2_session)) == NULL))
Willy Tarreau81f9aa32010-06-01 17:45:26 +020073 goto out_close;
Willy Tarreau81f9aa32010-06-01 17:45:26 +020074
Willy Tarreau2542b532012-08-31 16:01:23 +020075 /* minimum session initialization required for an embryonic session is
76 * fairly low. We need very little to execute L4 ACLs, then we need a
77 * task to make the client-side connection live on its own.
78 * - flags
79 * - stick-entry tracking
80 */
Willy Tarreau81f9aa32010-06-01 17:45:26 +020081 s->flags = 0;
82 s->logs.logwait = p->to_log;
Willy Tarreau56123282010-08-06 19:06:56 +020083 s->stkctr1_entry = NULL;
84 s->stkctr2_entry = NULL;
85 s->stkctr1_table = NULL;
86 s->stkctr2_table = NULL;
Willy Tarreau81f9aa32010-06-01 17:45:26 +020087
Willy Tarreau2542b532012-08-31 16:01:23 +020088 s->listener = l;
89 s->fe = p;
Willy Tarreauabe8ea52010-11-11 10:56:04 +010090
Willy Tarreau81f9aa32010-06-01 17:45:26 +020091 /* OK, we're keeping the session, so let's properly initialize the session */
Willy Tarreau96596ae2012-06-08 22:57:36 +020092 s->si[0].conn.t.sock.fd = cfd;
93 s->si[0].conn.ctrl = l->proto;
Willy Tarreau2542b532012-08-31 16:01:23 +020094 s->si[0].conn.flags = CO_FL_NONE;
Willy Tarreau986a9d22012-08-30 21:11:38 +020095 s->si[0].conn.addr.from = *addr;
Willy Tarreau2542b532012-08-31 16:01:23 +020096 set_target_client(&s->si[0].conn.target, l);
97
Willy Tarreau81f9aa32010-06-01 17:45:26 +020098 s->logs.accept_date = date; /* user-visible date for logging */
99 s->logs.tv_accept = now; /* corrected date for internal use */
100 s->uniq_id = totalconn;
Willy Tarreau2542b532012-08-31 16:01:23 +0200101 p->feconn++;
102 /* This session was accepted, count it now */
103 if (p->feconn > p->fe_counters.conn_max)
104 p->fe_counters.conn_max = p->feconn;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200105
Willy Tarreau2542b532012-08-31 16:01:23 +0200106 proxy_inc_fe_conn_ctr(l, p);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200107
Willy Tarreaufe7f1ea2012-05-20 19:22:25 +0200108 /* if this session comes from a known monitoring system, we want to ignore
109 * it as soon as possible, which means closing it immediately for TCP, but
110 * cleanly.
111 */
112 if (unlikely((l->options & LI_O_CHK_MONNET) &&
113 addr->ss_family == AF_INET &&
114 (((struct sockaddr_in *)addr)->sin_addr.s_addr & p->mon_mask.s_addr) == p->mon_net.s_addr)) {
115 s->flags |= SN_MONITOR;
116 s->logs.logwait = 0;
117 }
118
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200119 /* now evaluate the tcp-request layer4 rules. Since we expect to be able
120 * to abort right here as soon as possible, we check the rules before
121 * even initializing the stream interfaces.
122 */
123 if ((l->options & LI_O_TCP_RULES) && !tcp_exec_req_rules(s)) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200124 /* let's do a no-linger now to close with a single RST. */
125 setsockopt(cfd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100126 ret = 0; /* successful termination */
Willy Tarreau2542b532012-08-31 16:01:23 +0200127 goto out_free_session;
128 }
129
Willy Tarreau22cda212012-08-31 17:43:29 +0200130 /* wait for a PROXY protocol header */
131 if (l->options & LI_O_ACC_PROXY) {
132 s->si[0].conn.flags |= CO_FL_ACCEPT_PROXY;
133 conn_sock_want_recv(&s->si[0].conn);
134 }
135
Willy Tarreau2542b532012-08-31 16:01:23 +0200136 /* Adjust some socket options */
137 if (unlikely(fcntl(cfd, F_SETFL, O_NONBLOCK) == -1))
138 goto out_free_session;
139
140 if (unlikely((t = task_new()) == NULL))
141 goto out_free_session;
142
143 t->context = s;
144 t->nice = l->nice;
145 s->task = t;
146
147 /* add the various callbacks. Right now the data layer is present but
148 * not initialized. Also note we need to be careful as the stream int
149 * is not initialized yet.
150 */
151 si_prepare_conn(&s->si[0], l->proto, l->data);
152
153 /* finish initialization of the accepted file descriptor */
154 fd_insert(cfd);
155 fdtab[cfd].owner = &s->si[0].conn;
Willy Tarreau2542b532012-08-31 16:01:23 +0200156 fdtab[cfd].iocb = conn_fd_handler;
157 conn_data_want_recv(&s->si[0].conn);
158 if (conn_data_init(&s->si[0].conn) < 0)
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100159 goto out_free_task;
Willy Tarreau2542b532012-08-31 16:01:23 +0200160
161 /* OK, now either we have a pending handshake to execute with and
162 * then we must return to the I/O layer, or we can proceed with the
163 * end of the session initialization. In case of handshake, we also
164 * set the I/O timeout to the frontend's client timeout.
165 */
166
167 if (s->si[0].conn.flags & CO_FL_HANDSHAKE) {
168 t->process = expire_mini_session;
169 t->expire = tick_add_ifset(now_ms, p->timeout.client);
170 task_queue(t);
171 s->si[0].conn.flags |= CO_FL_INIT_SESS;
172 return 1;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200173 }
174
Willy Tarreau2542b532012-08-31 16:01:23 +0200175 /* OK let's complete session initialization */
176 ret = session_complete(s);
177 if (ret > 0)
178 return ret;
179
180 /* Error unrolling */
181 out_free_task:
182 task_free(t);
183 out_free_session:
184 p->feconn--;
185 if (s->stkctr1_entry || s->stkctr2_entry)
186 session_store_counters(s);
187 pool_free2(pool2_session, s);
188 out_close:
Willy Tarreaucbaaec42012-09-06 11:32:07 +0200189 if (ret < 0 && l->data == &raw_sock && p->mode == PR_MODE_HTTP) {
Willy Tarreau2542b532012-08-31 16:01:23 +0200190 /* critical error, no more memory, try to emit a 500 response */
Willy Tarreau783f2582012-09-04 12:19:04 +0200191 struct chunk *err_msg = http_error_message(s, HTTP_ERR_500);
Willy Tarreau2542b532012-08-31 16:01:23 +0200192 send(cfd, err_msg->str, err_msg->len, MSG_DONTWAIT|MSG_NOSIGNAL);
193 }
194
195 if (fdtab[cfd].owner)
196 fd_delete(cfd);
197 else
198 close(cfd);
199 return ret;
200}
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100201
Willy Tarreau2542b532012-08-31 16:01:23 +0200202/* This function kills an existing embryonic session. It stops the connection's
203 * data layer, releases assigned resources, resumes the listener if it was
204 * disabled and finally kills the file descriptor.
205 */
206static void kill_mini_session(struct session *s)
207{
208 /* kill the connection now */
209 conn_data_close(&s->si[0].conn);
210
211 s->fe->feconn--;
212 if (s->stkctr1_entry || s->stkctr2_entry)
213 session_store_counters(s);
214
215 if (!(s->listener->options & LI_O_UNLIMITED))
216 actconn--;
217 jobs--;
218 s->listener->nbconn--;
219 if (s->listener->state == LI_FULL)
220 resume_listener(s->listener);
221
222 /* Dequeues all of the listeners waiting for a resource */
223 if (!LIST_ISEMPTY(&global_listener_queue))
224 dequeue_all_listeners(&global_listener_queue);
225
226 if (!LIST_ISEMPTY(&s->fe->listener_queue) &&
227 (!s->fe->fe_sps_lim || freq_ctr_remain(&s->fe->fe_sess_per_sec, s->fe->fe_sps_lim, 0) > 0))
228 dequeue_all_listeners(&s->fe->listener_queue);
229
230 task_delete(s->task);
231 task_free(s->task);
232
233 if (fdtab[s->si[0].conn.t.sock.fd].owner)
234 fd_delete(s->si[0].conn.t.sock.fd);
235 else
236 close(s->si[0].conn.t.sock.fd);
237
238 pool_free2(pool2_session, s);
239}
240
Willy Tarreau22cda212012-08-31 17:43:29 +0200241/* Finish initializing a session from a connection, or kills it if the
242 * connection shows and error. Returns <0 if the connection was killed.
Willy Tarreau2542b532012-08-31 16:01:23 +0200243 */
Willy Tarreau22cda212012-08-31 17:43:29 +0200244int conn_session_complete(struct connection *conn, int flag)
Willy Tarreau2542b532012-08-31 16:01:23 +0200245{
246 struct session *s = container_of(conn, struct session, si[0].conn);
247
Willy Tarreau22cda212012-08-31 17:43:29 +0200248 if (!(conn->flags & CO_FL_ERROR) && (session_complete(s) > 0)) {
Willy Tarreau2542b532012-08-31 16:01:23 +0200249 conn->flags &= ~flag;
250 return 0;
251 }
252
253 /* kill the connection now */
254 kill_mini_session(s);
255 return -1;
256}
257
258/* Manages embryonic sessions timeout. It is only called when the timeout
259 * strikes and performs the required cleanup.
260 */
261static struct task *expire_mini_session(struct task *t)
262{
263 struct session *s = t->context;
264
265 if (!(t->state & TASK_WOKEN_TIMER))
266 return t;
267
268 kill_mini_session(s);
269 return NULL;
270}
271
272/* This function is called from the I/O handler which detects the end of
273 * handshake, in order to complete initialization of a valid session. It must
274 * be called with an embryonic session. It returns a positive value upon
275 * success, 0 if the connection can be ignored, or a negative value upon
276 * critical failure. The accepted file descriptor is closed if we return <= 0.
277 */
278int session_complete(struct session *s)
279{
280 struct listener *l = s->listener;
281 struct proxy *p = s->fe;
282 struct http_txn *txn;
283 struct task *t = s->task;
284 int ret;
285
286 ret = -1; /* assume unrecoverable error by default */
287
288 /* OK, we're keeping the session, so let's properly initialize the session */
289 LIST_ADDQ(&sessions, &s->list);
290 LIST_INIT(&s->back_refs);
291 s->flags |= SN_INITIALIZED;
292
293 s->unique_id = NULL;
294 s->term_trace = 0;
295
296 t->process = l->handler;
297 t->context = s;
298 t->expire = TICK_ETERNITY;
299
300 /* Note: initially, the session's backend points to the frontend.
301 * This changes later when switching rules are executed or
302 * when the default backend is assigned.
303 */
304 s->be = s->fe;
305 s->req = s->rep = NULL; /* will be allocated later */
306
307 /* Let's count a session now */
Willy Tarreaub36b4242010-06-04 20:59:39 +0200308 proxy_inc_fe_sess_ctr(l, p);
Willy Tarreau56123282010-08-06 19:06:56 +0200309 if (s->stkctr1_entry) {
Willy Tarreau91c43d72010-06-20 11:19:22 +0200310 void *ptr;
311
Willy Tarreau56123282010-08-06 19:06:56 +0200312 ptr = stktable_data_ptr(s->stkctr1_table, s->stkctr1_entry, STKTABLE_DT_SESS_CNT);
Willy Tarreauf4d17d92010-06-18 22:10:12 +0200313 if (ptr)
314 stktable_data_cast(ptr, sess_cnt)++;
Willy Tarreau91c43d72010-06-20 11:19:22 +0200315
Willy Tarreau56123282010-08-06 19:06:56 +0200316 ptr = stktable_data_ptr(s->stkctr1_table, s->stkctr1_entry, STKTABLE_DT_SESS_RATE);
Willy Tarreau91c43d72010-06-20 11:19:22 +0200317 if (ptr)
318 update_freq_ctr_period(&stktable_data_cast(ptr, sess_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200319 s->stkctr1_table->data_arg[STKTABLE_DT_SESS_RATE].u, 1);
Willy Tarreauf4d17d92010-06-18 22:10:12 +0200320 }
Willy Tarreaub36b4242010-06-04 20:59:39 +0200321
Willy Tarreau56123282010-08-06 19:06:56 +0200322 if (s->stkctr2_entry) {
Willy Tarreau9e9879a2010-08-06 15:25:22 +0200323 void *ptr;
324
Willy Tarreau56123282010-08-06 19:06:56 +0200325 ptr = stktable_data_ptr(s->stkctr2_table, s->stkctr2_entry, STKTABLE_DT_SESS_CNT);
Willy Tarreau9e9879a2010-08-06 15:25:22 +0200326 if (ptr)
327 stktable_data_cast(ptr, sess_cnt)++;
328
Willy Tarreau56123282010-08-06 19:06:56 +0200329 ptr = stktable_data_ptr(s->stkctr2_table, s->stkctr2_entry, STKTABLE_DT_SESS_RATE);
Willy Tarreau9e9879a2010-08-06 15:25:22 +0200330 if (ptr)
331 update_freq_ctr_period(&stktable_data_cast(ptr, sess_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200332 s->stkctr2_table->data_arg[STKTABLE_DT_SESS_RATE].u, 1);
Willy Tarreau9e9879a2010-08-06 15:25:22 +0200333 }
334
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200335 /* this part should be common with other protocols */
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200336 s->si[0].owner = t;
337 s->si[0].state = s->si[0].prev_state = SI_ST_EST;
338 s->si[0].err_type = SI_ET_NONE;
339 s->si[0].err_loc = NULL;
Willy Tarreau0bd05ea2010-07-02 11:18:03 +0200340 s->si[0].release = NULL;
Willy Tarreau63e7fe32012-05-08 15:20:43 +0200341 s->si[0].send_proxy_ofs = 0;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200342 s->si[0].exp = TICK_ETERNITY;
343 s->si[0].flags = SI_FL_NONE;
344
345 if (likely(s->fe->options2 & PR_O2_INDEPSTR))
346 s->si[0].flags |= SI_FL_INDEP_STR;
347
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200348 /* pre-initialize the other side's stream interface to an INIT state. The
349 * callbacks will be initialized before attempting to connect.
350 */
Willy Tarreaufb7508a2012-05-21 16:47:54 +0200351 s->si[1].conn.t.sock.fd = -1; /* just to help with debugging */
Willy Tarreau505e34a2012-07-06 10:17:53 +0200352 s->si[1].conn.flags = CO_FL_NONE;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200353 s->si[1].owner = t;
354 s->si[1].state = s->si[1].prev_state = SI_ST_INI;
355 s->si[1].err_type = SI_ET_NONE;
Willy Tarreau0b3a4112011-03-27 19:16:56 +0200356 s->si[1].conn_retries = 0; /* used for logging too */
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200357 s->si[1].err_loc = NULL;
Willy Tarreau0bd05ea2010-07-02 11:18:03 +0200358 s->si[1].release = NULL;
Willy Tarreau63e7fe32012-05-08 15:20:43 +0200359 s->si[1].send_proxy_ofs = 0;
Willy Tarreau3cefd522012-08-30 15:49:18 +0200360 clear_target(&s->si[1].conn.target);
Willy Tarreauc5788912012-08-24 18:12:41 +0200361 si_prepare_embedded(&s->si[1]);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200362 s->si[1].exp = TICK_ETERNITY;
363 s->si[1].flags = SI_FL_NONE;
364
365 if (likely(s->fe->options2 & PR_O2_INDEPSTR))
366 s->si[1].flags |= SI_FL_INDEP_STR;
367
Willy Tarreau9bd0d742011-07-20 00:17:39 +0200368 session_init_srv_conn(s);
Willy Tarreau9e000c62011-03-10 14:03:36 +0100369 clear_target(&s->target);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200370 s->pend_pos = NULL;
371
372 /* init store persistence */
373 s->store_count = 0;
374
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200375 if (unlikely((s->req = pool_alloc2(pool2_channel)) == NULL))
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200376 goto out_free_task; /* no memory */
377
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200378 if (unlikely((s->rep = pool_alloc2(pool2_channel)) == NULL))
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200379 goto out_free_req; /* no memory */
380
381 /* initialize the request buffer */
Willy Tarreau572bf902012-07-02 17:01:20 +0200382 s->req->buf.size = global.tune.bufsize;
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200383 channel_init(s->req);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200384 s->req->prod = &s->si[0];
385 s->req->cons = &s->si[1];
386 s->si[0].ib = s->si[1].ob = s->req;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200387 s->req->flags |= CF_READ_ATTACHED; /* the producer is already connected */
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200388
389 /* activate default analysers enabled for this listener */
390 s->req->analysers = l->analysers;
391
392 s->req->wto = TICK_ETERNITY;
393 s->req->rto = TICK_ETERNITY;
394 s->req->rex = TICK_ETERNITY;
395 s->req->wex = TICK_ETERNITY;
396 s->req->analyse_exp = TICK_ETERNITY;
397
398 /* initialize response buffer */
Willy Tarreau572bf902012-07-02 17:01:20 +0200399 s->rep->buf.size = global.tune.bufsize;
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200400 channel_init(s->rep);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200401 s->rep->prod = &s->si[1];
402 s->rep->cons = &s->si[0];
403 s->si[0].ob = s->si[1].ib = s->rep;
404 s->rep->analysers = 0;
405
Willy Tarreau96e31212011-05-30 18:10:30 +0200406 if (s->fe->options2 & PR_O2_NODELAY) {
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200407 s->req->flags |= CF_NEVER_WAIT;
408 s->rep->flags |= CF_NEVER_WAIT;
Willy Tarreau96e31212011-05-30 18:10:30 +0200409 }
410
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200411 s->rep->rto = TICK_ETERNITY;
412 s->rep->wto = TICK_ETERNITY;
413 s->rep->rex = TICK_ETERNITY;
414 s->rep->wex = TICK_ETERNITY;
415 s->rep->analyse_exp = TICK_ETERNITY;
416
Willy Tarreau62f791e2012-03-09 11:32:30 +0100417 txn = &s->txn;
418 /* Those variables will be checked and freed if non-NULL in
419 * session.c:session_free(). It is important that they are
420 * properly initialized.
421 */
422 txn->sessid = NULL;
423 txn->srv_cookie = NULL;
424 txn->cli_cookie = NULL;
425 txn->uri = NULL;
426 txn->req.cap = NULL;
427 txn->rsp.cap = NULL;
428 txn->hdr_idx.v = NULL;
429 txn->hdr_idx.size = txn->hdr_idx.used = 0;
430 txn->req.flags = 0;
431 txn->rsp.flags = 0;
432 /* the HTTP messages need to know what buffer they're associated with */
433 txn->req.buf = s->req;
434 txn->rsp.buf = s->rep;
435
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200436 /* finish initialization of the accepted file descriptor */
Willy Tarreauf9dabec2012-08-17 17:33:53 +0200437 conn_data_want_recv(&s->si[0].conn);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200438
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100439 if (p->accept && (ret = p->accept(s)) <= 0) {
440 /* Either we had an unrecoverable error (<0) or work is
441 * finished (=0, eg: monitoring), in both situations,
442 * we can release everything and close.
443 */
444 goto out_free_rep;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200445 }
446
Willy Tarreau2542b532012-08-31 16:01:23 +0200447 /* we want the connection handler to notify the stream interface about updates. */
448 s->si[0].conn.flags |= CO_FL_NOTIFY_SI;
449
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200450 /* it is important not to call the wakeup function directly but to
451 * pass through task_wakeup(), because this one knows how to apply
452 * priorities to tasks.
453 */
454 task_wakeup(t, TASK_WOKEN_INIT);
455 return 1;
456
457 /* Error unrolling */
458 out_free_rep:
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200459 pool_free2(pool2_channel, s->rep);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200460 out_free_req:
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200461 pool_free2(pool2_channel, s->req);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200462 out_free_task:
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100463 return ret;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200464}
465
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466/*
467 * frees the context associated to a session. It must have been removed first.
468 */
Simon Hormandec5be42011-06-08 09:19:07 +0900469static void session_free(struct session *s)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470{
Willy Tarreau4dbc4a22007-03-03 16:23:22 +0100471 struct http_txn *txn = &s->txn;
Willy Tarreau632f5a72007-07-11 10:42:35 +0200472 struct proxy *fe = s->fe;
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100473 struct bref *bref, *back;
Willy Tarreaua4cda672010-06-06 18:28:49 +0200474 int i;
Willy Tarreau0f7562b2007-01-07 15:46:13 +0100475
Willy Tarreaubaaee002006-06-26 02:48:02 +0200476 if (s->pend_pos)
477 pendconn_free(s->pend_pos);
Willy Tarreau922a8062008-12-04 09:33:58 +0100478
Willy Tarreau827aee92011-03-10 16:55:02 +0100479 if (target_srv(&s->target)) { /* there may be requests left pending in queue */
Willy Tarreau1e62de62008-11-11 20:20:02 +0100480 if (s->flags & SN_CURR_SESS) {
481 s->flags &= ~SN_CURR_SESS;
Willy Tarreau827aee92011-03-10 16:55:02 +0100482 target_srv(&s->target)->cur_sess--;
Willy Tarreau1e62de62008-11-11 20:20:02 +0100483 }
Willy Tarreau827aee92011-03-10 16:55:02 +0100484 if (may_dequeue_tasks(target_srv(&s->target), s->be))
485 process_srv_queue(target_srv(&s->target));
Willy Tarreau1e62de62008-11-11 20:20:02 +0100486 }
Willy Tarreau922a8062008-12-04 09:33:58 +0100487
Willy Tarreau7c669d72008-06-20 15:04:11 +0200488 if (unlikely(s->srv_conn)) {
489 /* the session still has a reserved slot on a server, but
490 * it should normally be only the same as the one above,
491 * so this should not happen in fact.
492 */
493 sess_change_server(s, NULL);
494 }
495
Willy Tarreau3eba98a2009-01-25 13:56:13 +0100496 if (s->req->pipe)
497 put_pipe(s->req->pipe);
Willy Tarreau259de1b2009-01-18 21:56:21 +0100498
Willy Tarreau3eba98a2009-01-25 13:56:13 +0100499 if (s->rep->pipe)
500 put_pipe(s->rep->pipe);
Willy Tarreau259de1b2009-01-18 21:56:21 +0100501
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200502 pool_free2(pool2_channel, s->req);
503 pool_free2(pool2_channel, s->rep);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200504
Willy Tarreau46023632010-01-07 22:51:47 +0100505 http_end_txn(s);
506
Willy Tarreaua4cda672010-06-06 18:28:49 +0200507 for (i = 0; i < s->store_count; i++) {
508 if (!s->store[i].ts)
509 continue;
510 stksess_free(s->store[i].table, s->store[i].ts);
511 s->store[i].ts = NULL;
512 }
513
Willy Tarreau34eb6712011-10-24 18:15:04 +0200514 pool_free2(pool2_hdr_idx, txn->hdr_idx.v);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200515 if (fe) {
Willy Tarreau46023632010-01-07 22:51:47 +0100516 pool_free2(fe->rsp_cap_pool, txn->rsp.cap);
517 pool_free2(fe->req_cap_pool, txn->req.cap);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200518 }
Willy Tarreau0937bc42009-12-22 15:03:09 +0100519
Willy Tarreau56123282010-08-06 19:06:56 +0200520 if (s->stkctr1_entry || s->stkctr2_entry)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +0200521 session_store_counters(s);
522
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100523 list_for_each_entry_safe(bref, back, &s->back_refs, users) {
Willy Tarreaufd3828e2009-02-22 15:17:24 +0100524 /* we have to unlink all watchers. We must not relink them if
525 * this session was the last one in the list.
526 */
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100527 LIST_DEL(&bref->users);
Willy Tarreaufd3828e2009-02-22 15:17:24 +0100528 LIST_INIT(&bref->users);
529 if (s->list.n != &sessions)
530 LIST_ADDQ(&LIST_ELEM(s->list.n, struct session *, list)->back_refs, &bref->users);
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100531 bref->ref = s->list.n;
532 }
Willy Tarreauf54f8bd2008-11-23 19:53:55 +0100533 LIST_DEL(&s->list);
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200534 pool_free2(pool2_session, s);
Willy Tarreau632f5a72007-07-11 10:42:35 +0200535
536 /* We may want to free the maximum amount of pools if the proxy is stopping */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200537 if (fe && unlikely(fe->state == PR_STSTOPPED)) {
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200538 pool_flush2(pool2_channel);
Willy Tarreau34eb6712011-10-24 18:15:04 +0200539 pool_flush2(pool2_hdr_idx);
Willy Tarreau48d63db2008-08-03 17:41:33 +0200540 pool_flush2(pool2_requri);
541 pool_flush2(pool2_capture);
542 pool_flush2(pool2_session);
543 pool_flush2(fe->req_cap_pool);
544 pool_flush2(fe->rsp_cap_pool);
Willy Tarreau632f5a72007-07-11 10:42:35 +0200545 }
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200546}
547
548
549/* perform minimal intializations, report 0 in case of error, 1 if OK. */
550int init_session()
551{
Willy Tarreauf54f8bd2008-11-23 19:53:55 +0100552 LIST_INIT(&sessions);
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200553 pool2_session = create_pool("session", sizeof(struct session), MEM_F_SHARED);
554 return pool2_session != NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200555}
556
Willy Tarreau30e71012007-11-26 20:15:35 +0100557void session_process_counters(struct session *s)
558{
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100559 unsigned long long bytes;
560
Willy Tarreau30e71012007-11-26 20:15:35 +0100561 if (s->req) {
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100562 bytes = s->req->total - s->logs.bytes_in;
Willy Tarreau30e71012007-11-26 20:15:35 +0100563 s->logs.bytes_in = s->req->total;
564 if (bytes) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100565 s->fe->fe_counters.bytes_in += bytes;
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100566
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100567 s->be->be_counters.bytes_in += bytes;
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100568
Willy Tarreau827aee92011-03-10 16:55:02 +0100569 if (target_srv(&s->target))
570 target_srv(&s->target)->counters.bytes_in += bytes;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200571
572 if (s->listener->counters)
573 s->listener->counters->bytes_in += bytes;
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200574
Willy Tarreau56123282010-08-06 19:06:56 +0200575 if (s->stkctr2_entry) {
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200576 void *ptr;
577
Willy Tarreau56123282010-08-06 19:06:56 +0200578 ptr = stktable_data_ptr(s->stkctr2_table,
579 s->stkctr2_entry,
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200580 STKTABLE_DT_BYTES_IN_CNT);
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200581 if (ptr)
582 stktable_data_cast(ptr, bytes_in_cnt) += bytes;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200583
Willy Tarreau56123282010-08-06 19:06:56 +0200584 ptr = stktable_data_ptr(s->stkctr2_table,
585 s->stkctr2_entry,
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200586 STKTABLE_DT_BYTES_IN_RATE);
587 if (ptr)
588 update_freq_ctr_period(&stktable_data_cast(ptr, bytes_in_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200589 s->stkctr2_table->data_arg[STKTABLE_DT_BYTES_IN_RATE].u, bytes);
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200590 }
591
Willy Tarreau56123282010-08-06 19:06:56 +0200592 if (s->stkctr1_entry) {
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200593 void *ptr;
594
Willy Tarreau56123282010-08-06 19:06:56 +0200595 ptr = stktable_data_ptr(s->stkctr1_table,
596 s->stkctr1_entry,
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200597 STKTABLE_DT_BYTES_IN_CNT);
598 if (ptr)
599 stktable_data_cast(ptr, bytes_in_cnt) += bytes;
600
Willy Tarreau56123282010-08-06 19:06:56 +0200601 ptr = stktable_data_ptr(s->stkctr1_table,
602 s->stkctr1_entry,
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200603 STKTABLE_DT_BYTES_IN_RATE);
604 if (ptr)
605 update_freq_ctr_period(&stktable_data_cast(ptr, bytes_in_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200606 s->stkctr1_table->data_arg[STKTABLE_DT_BYTES_IN_RATE].u, bytes);
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200607 }
Willy Tarreau30e71012007-11-26 20:15:35 +0100608 }
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100609 }
610
Willy Tarreau30e71012007-11-26 20:15:35 +0100611 if (s->rep) {
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100612 bytes = s->rep->total - s->logs.bytes_out;
Willy Tarreau30e71012007-11-26 20:15:35 +0100613 s->logs.bytes_out = s->rep->total;
614 if (bytes) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100615 s->fe->fe_counters.bytes_out += bytes;
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100616
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100617 s->be->be_counters.bytes_out += bytes;
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100618
Willy Tarreau827aee92011-03-10 16:55:02 +0100619 if (target_srv(&s->target))
620 target_srv(&s->target)->counters.bytes_out += bytes;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200621
622 if (s->listener->counters)
623 s->listener->counters->bytes_out += bytes;
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200624
Willy Tarreau56123282010-08-06 19:06:56 +0200625 if (s->stkctr2_entry) {
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200626 void *ptr;
627
Willy Tarreau56123282010-08-06 19:06:56 +0200628 ptr = stktable_data_ptr(s->stkctr2_table,
629 s->stkctr2_entry,
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200630 STKTABLE_DT_BYTES_OUT_CNT);
631 if (ptr)
632 stktable_data_cast(ptr, bytes_out_cnt) += bytes;
633
Willy Tarreau56123282010-08-06 19:06:56 +0200634 ptr = stktable_data_ptr(s->stkctr2_table,
635 s->stkctr2_entry,
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200636 STKTABLE_DT_BYTES_OUT_RATE);
637 if (ptr)
638 update_freq_ctr_period(&stktable_data_cast(ptr, bytes_out_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200639 s->stkctr2_table->data_arg[STKTABLE_DT_BYTES_OUT_RATE].u, bytes);
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200640 }
641
Willy Tarreau56123282010-08-06 19:06:56 +0200642 if (s->stkctr1_entry) {
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200643 void *ptr;
644
Willy Tarreau56123282010-08-06 19:06:56 +0200645 ptr = stktable_data_ptr(s->stkctr1_table,
646 s->stkctr1_entry,
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200647 STKTABLE_DT_BYTES_OUT_CNT);
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200648 if (ptr)
649 stktable_data_cast(ptr, bytes_out_cnt) += bytes;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200650
Willy Tarreau56123282010-08-06 19:06:56 +0200651 ptr = stktable_data_ptr(s->stkctr1_table,
652 s->stkctr1_entry,
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200653 STKTABLE_DT_BYTES_OUT_RATE);
654 if (ptr)
655 update_freq_ctr_period(&stktable_data_cast(ptr, bytes_out_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200656 s->stkctr1_table->data_arg[STKTABLE_DT_BYTES_OUT_RATE].u, bytes);
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200657 }
Willy Tarreau30e71012007-11-26 20:15:35 +0100658 }
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100659 }
660}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100662/* This function is called with (si->state == SI_ST_CON) meaning that a
663 * connection was attempted and that the file descriptor is already allocated.
664 * We must check for establishment, error and abort. Possible output states
665 * are SI_ST_EST (established), SI_ST_CER (error), SI_ST_DIS (abort), and
666 * SI_ST_CON (no change). The function returns 0 if it switches to SI_ST_CER,
667 * otherwise 1.
668 */
Simon Hormandec5be42011-06-08 09:19:07 +0900669static int sess_update_st_con_tcp(struct session *s, struct stream_interface *si)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100670{
Willy Tarreau7421efb2012-07-02 15:11:27 +0200671 struct channel *req = si->ob;
672 struct channel *rep = si->ib;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100673
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100674 /* If we got an error, or if nothing happened and the connection timed
675 * out, we must give up. The CER state handler will take care of retry
676 * attempts and error reports.
677 */
678 if (unlikely(si->flags & (SI_FL_EXP|SI_FL_ERR))) {
Willy Tarreau127334e2009-03-28 10:47:26 +0100679 si->exp = TICK_ETERNITY;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100680 si->state = SI_ST_CER;
Willy Tarreaufb7508a2012-05-21 16:47:54 +0200681 fd_delete(si_fd(si));
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100682
Willy Tarreau8b117082012-08-06 15:06:49 +0200683 conn_data_close(&si->conn);
Willy Tarreau0bd05ea2010-07-02 11:18:03 +0200684 if (si->release)
685 si->release(si);
686
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100687 if (si->err_type)
688 return 0;
689
Willy Tarreau827aee92011-03-10 16:55:02 +0100690 si->err_loc = target_srv(&s->target);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100691 if (si->flags & SI_FL_ERR)
692 si->err_type = SI_ET_CONN_ERR;
693 else
694 si->err_type = SI_ET_CONN_TO;
695 return 0;
696 }
697
698 /* OK, maybe we want to abort */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200699 if (unlikely((rep->flags & CF_SHUTW) ||
700 ((req->flags & CF_SHUTW_NOW) && /* FIXME: this should not prevent a connection from establishing */
701 ((!(req->flags & CF_WRITE_ACTIVITY) && channel_is_empty(req)) ||
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100702 s->be->options & PR_O_ABRT_CLOSE)))) {
703 /* give up */
Willy Tarreau73b013b2012-05-21 16:31:45 +0200704 si_shutw(si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100705 si->err_type |= SI_ET_CONN_ABRT;
Willy Tarreau827aee92011-03-10 16:55:02 +0100706 si->err_loc = target_srv(&s->target);
Willy Tarreau84455332009-03-15 22:34:05 +0100707 if (s->srv_error)
708 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100709 return 1;
710 }
711
712 /* we need to wait a bit more if there was no activity either */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200713 if (!(req->flags & CF_WRITE_ACTIVITY))
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100714 return 1;
715
716 /* OK, this means that a connection succeeded. The caller will be
717 * responsible for handling the transition from CON to EST.
718 */
719 s->logs.t_connect = tv_ms_elapsed(&s->logs.tv_accept, &now);
Willy Tarreau127334e2009-03-28 10:47:26 +0100720 si->exp = TICK_ETERNITY;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100721 si->state = SI_ST_EST;
722 si->err_type = SI_ET_NONE;
723 si->err_loc = NULL;
724 return 1;
725}
726
727/* This function is called with (si->state == SI_ST_CER) meaning that a
728 * previous connection attempt has failed and that the file descriptor
729 * has already been released. Possible causes include asynchronous error
730 * notification and time out. Possible output states are SI_ST_CLO when
731 * retries are exhausted, SI_ST_TAR when a delay is wanted before a new
732 * connection attempt, SI_ST_ASS when it's wise to retry on the same server,
733 * and SI_ST_REQ when an immediate redispatch is wanted. The buffers are
734 * marked as in error state. It returns 0.
735 */
Simon Hormandec5be42011-06-08 09:19:07 +0900736static int sess_update_st_cer(struct session *s, struct stream_interface *si)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100737{
738 /* we probably have to release last session from the server */
Willy Tarreau827aee92011-03-10 16:55:02 +0100739 if (target_srv(&s->target)) {
740 health_adjust(target_srv(&s->target), HANA_STATUS_L4_ERR);
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +0100741
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100742 if (s->flags & SN_CURR_SESS) {
743 s->flags &= ~SN_CURR_SESS;
Willy Tarreau827aee92011-03-10 16:55:02 +0100744 target_srv(&s->target)->cur_sess--;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100745 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100746 }
747
748 /* ensure that we have enough retries left */
Willy Tarreauee28de02010-06-01 09:51:00 +0200749 si->conn_retries--;
750 if (si->conn_retries < 0) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100751 if (!si->err_type) {
752 si->err_type = SI_ET_CONN_ERR;
Willy Tarreau827aee92011-03-10 16:55:02 +0100753 si->err_loc = target_srv(&s->target);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100754 }
755
Willy Tarreau827aee92011-03-10 16:55:02 +0100756 if (target_srv(&s->target))
757 target_srv(&s->target)->counters.failed_conns++;
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100758 s->be->be_counters.failed_conns++;
Willy Tarreaub89cfca2010-12-29 14:32:28 +0100759 sess_change_server(s, NULL);
Willy Tarreau827aee92011-03-10 16:55:02 +0100760 if (may_dequeue_tasks(target_srv(&s->target), s->be))
761 process_srv_queue(target_srv(&s->target));
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100762
763 /* shutw is enough so stop a connecting socket */
Willy Tarreau73b013b2012-05-21 16:31:45 +0200764 si_shutw(si);
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200765 si->ob->flags |= CF_WRITE_ERROR;
766 si->ib->flags |= CF_READ_ERROR;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100767
768 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +0100769 if (s->srv_error)
770 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100771 return 0;
772 }
773
774 /* If the "redispatch" option is set on the backend, we are allowed to
775 * retry on another server for the last retry. In order to achieve this,
776 * we must mark the session unassigned, and eventually clear the DIRECT
777 * bit to ignore any persistence cookie. We won't count a retry nor a
778 * redispatch yet, because this will depend on what server is selected.
779 */
Willy Tarreau827aee92011-03-10 16:55:02 +0100780 if (target_srv(&s->target) && si->conn_retries == 0 &&
Willy Tarreau4de91492010-01-22 19:10:05 +0100781 s->be->options & PR_O_REDISP && !(s->flags & SN_FORCE_PRST)) {
Willy Tarreaub89cfca2010-12-29 14:32:28 +0100782 sess_change_server(s, NULL);
Willy Tarreau827aee92011-03-10 16:55:02 +0100783 if (may_dequeue_tasks(target_srv(&s->target), s->be))
784 process_srv_queue(target_srv(&s->target));
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100785
786 s->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100787 si->state = SI_ST_REQ;
788 } else {
Willy Tarreau827aee92011-03-10 16:55:02 +0100789 if (target_srv(&s->target))
790 target_srv(&s->target)->counters.retries++;
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100791 s->be->be_counters.retries++;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100792 si->state = SI_ST_ASS;
793 }
794
795 if (si->flags & SI_FL_ERR) {
796 /* The error was an asynchronous connection error, and we will
797 * likely have to retry connecting to the same server, most
798 * likely leading to the same result. To avoid this, we wait
799 * one second before retrying.
800 */
801
802 if (!si->err_type)
803 si->err_type = SI_ET_CONN_ERR;
804
805 si->state = SI_ST_TAR;
806 si->exp = tick_add(now_ms, MS_TO_TICKS(1000));
807 return 0;
808 }
809 return 0;
810}
811
812/*
813 * This function handles the transition between the SI_ST_CON state and the
Willy Tarreau85e7d002010-05-31 11:57:51 +0200814 * SI_ST_EST state. It must only be called after switching from SI_ST_CON (or
Willy Tarreau26d8c592012-05-07 18:12:14 +0200815 * SI_ST_INI) to SI_ST_EST, but only when a ->proto is defined.
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100816 */
Simon Hormandec5be42011-06-08 09:19:07 +0900817static void sess_establish(struct session *s, struct stream_interface *si)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100818{
Willy Tarreau7421efb2012-07-02 15:11:27 +0200819 struct channel *req = si->ob;
820 struct channel *rep = si->ib;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100821
Willy Tarreau827aee92011-03-10 16:55:02 +0100822 if (target_srv(&s->target))
823 health_adjust(target_srv(&s->target), HANA_STATUS_L4_OK);
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +0100824
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100825 if (s->be->mode == PR_MODE_TCP) { /* let's allow immediate data connection in this case */
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100826 /* if the user wants to log as soon as possible, without counting
827 * bytes from the server, then this is the right moment. */
828 if (s->fe->to_log && !(s->logs.logwait & LW_BYTES)) {
829 s->logs.t_close = s->logs.t_connect; /* to get a valid end date */
Willy Tarreaua5555ec2008-11-30 19:02:32 +0100830 s->do_log(s);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100831 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100832 }
833 else {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100834 s->txn.rsp.msg_state = HTTP_MSG_RPBEFORE;
835 /* reset hdr_idx which was already initialized by the request.
836 * right now, the http parser does it.
837 * hdr_idx_init(&s->txn.hdr_idx);
838 */
839 }
840
Willy Tarreau4e5b8282009-08-16 22:57:50 +0200841 rep->analysers |= s->fe->fe_rsp_ana | s->be->be_rsp_ana;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200842 rep->flags |= CF_READ_ATTACHED; /* producer is now attached */
Willy Tarreau73b013b2012-05-21 16:31:45 +0200843 if (si_ctrl(si)) {
Willy Tarreaud04e8582010-05-31 12:31:35 +0200844 /* real connections have timeouts */
845 req->wto = s->be->timeout.server;
846 rep->rto = s->be->timeout.server;
847 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100848 req->wex = TICK_ETERNITY;
849}
850
851/* Update stream interface status for input states SI_ST_ASS, SI_ST_QUE, SI_ST_TAR.
852 * Other input states are simply ignored.
853 * Possible output states are SI_ST_CLO, SI_ST_TAR, SI_ST_ASS, SI_ST_REQ, SI_ST_CON.
854 * Flags must have previously been updated for timeouts and other conditions.
855 */
Simon Hormandec5be42011-06-08 09:19:07 +0900856static void sess_update_stream_int(struct session *s, struct stream_interface *si)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100857{
Willy Tarreau827aee92011-03-10 16:55:02 +0100858 struct server *srv = target_srv(&s->target);
859
Willy Tarreau02d6cfc2012-03-01 18:19:58 +0100860 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 +0100861 now_ms, __FUNCTION__,
862 s,
863 s->req, s->rep,
864 s->req->rex, s->rep->wex,
865 s->req->flags, s->rep->flags,
Willy Tarreau02d6cfc2012-03-01 18:19:58 +0100866 s->req->i, s->req->o, s->rep->i, s->rep->o, s->rep->cons->state, s->req->cons->state);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100867
868 if (si->state == SI_ST_ASS) {
869 /* Server assigned to connection request, we have to try to connect now */
870 int conn_err;
871
872 conn_err = connect_server(s);
Willy Tarreau827aee92011-03-10 16:55:02 +0100873 srv = target_srv(&s->target);
874
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100875 if (conn_err == SN_ERR_NONE) {
876 /* state = SI_ST_CON now */
Willy Tarreau827aee92011-03-10 16:55:02 +0100877 if (srv)
878 srv_inc_sess_ctr(srv);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100879 return;
880 }
881
882 /* We have received a synchronous error. We might have to
883 * abort, retry immediately or redispatch.
884 */
885 if (conn_err == SN_ERR_INTERNAL) {
886 if (!si->err_type) {
887 si->err_type = SI_ET_CONN_OTHER;
Willy Tarreau827aee92011-03-10 16:55:02 +0100888 si->err_loc = srv;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100889 }
890
Willy Tarreau827aee92011-03-10 16:55:02 +0100891 if (srv)
892 srv_inc_sess_ctr(srv);
893 if (srv)
894 srv->counters.failed_conns++;
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100895 s->be->be_counters.failed_conns++;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100896
897 /* release other sessions waiting for this server */
Willy Tarreaub89cfca2010-12-29 14:32:28 +0100898 sess_change_server(s, NULL);
Willy Tarreau827aee92011-03-10 16:55:02 +0100899 if (may_dequeue_tasks(srv, s->be))
900 process_srv_queue(srv);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100901
902 /* Failed and not retryable. */
Willy Tarreau73b013b2012-05-21 16:31:45 +0200903 si_shutr(si);
904 si_shutw(si);
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200905 si->ob->flags |= CF_WRITE_ERROR;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100906
907 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
908
909 /* no session was ever accounted for this server */
910 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +0100911 if (s->srv_error)
912 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100913 return;
914 }
915
916 /* We are facing a retryable error, but we don't want to run a
917 * turn-around now, as the problem is likely a source port
918 * allocation problem, so we want to retry now.
919 */
920 si->state = SI_ST_CER;
921 si->flags &= ~SI_FL_ERR;
922 sess_update_st_cer(s, si);
923 /* now si->state is one of SI_ST_CLO, SI_ST_TAR, SI_ST_ASS, SI_ST_REQ */
924 return;
925 }
926 else if (si->state == SI_ST_QUE) {
927 /* connection request was queued, check for any update */
928 if (!s->pend_pos) {
929 /* The connection is not in the queue anymore. Either
930 * we have a server connection slot available and we
931 * go directly to the assigned state, or we need to
932 * load-balance first and go to the INI state.
933 */
934 si->exp = TICK_ETERNITY;
935 if (unlikely(!(s->flags & SN_ASSIGNED)))
936 si->state = SI_ST_REQ;
937 else {
938 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
939 si->state = SI_ST_ASS;
940 }
941 return;
942 }
943
944 /* Connection request still in queue... */
945 if (si->flags & SI_FL_EXP) {
946 /* ... and timeout expired */
947 si->exp = TICK_ETERNITY;
948 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
Willy Tarreau827aee92011-03-10 16:55:02 +0100949 if (srv)
950 srv->counters.failed_conns++;
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100951 s->be->be_counters.failed_conns++;
Willy Tarreau73b013b2012-05-21 16:31:45 +0200952 si_shutr(si);
953 si_shutw(si);
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200954 si->ob->flags |= CF_WRITE_TIMEOUT;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100955 if (!si->err_type)
956 si->err_type = SI_ET_QUEUE_TO;
957 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +0100958 if (s->srv_error)
959 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100960 return;
961 }
962
963 /* Connection remains in queue, check if we have to abort it */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200964 if ((si->ob->flags & (CF_READ_ERROR)) ||
965 ((si->ob->flags & CF_SHUTW_NOW) && /* empty and client aborted */
Willy Tarreau8e21bb92012-08-24 22:40:29 +0200966 (channel_is_empty(si->ob) || s->be->options & PR_O_ABRT_CLOSE))) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100967 /* give up */
968 si->exp = TICK_ETERNITY;
969 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
Willy Tarreau73b013b2012-05-21 16:31:45 +0200970 si_shutr(si);
971 si_shutw(si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100972 si->err_type |= SI_ET_QUEUE_ABRT;
973 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +0100974 if (s->srv_error)
975 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100976 return;
977 }
978
979 /* Nothing changed */
980 return;
981 }
982 else if (si->state == SI_ST_TAR) {
983 /* Connection request might be aborted */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200984 if ((si->ob->flags & (CF_READ_ERROR)) ||
985 ((si->ob->flags & CF_SHUTW_NOW) && /* empty and client aborted */
Willy Tarreau8e21bb92012-08-24 22:40:29 +0200986 (channel_is_empty(si->ob) || s->be->options & PR_O_ABRT_CLOSE))) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100987 /* give up */
988 si->exp = TICK_ETERNITY;
Willy Tarreau73b013b2012-05-21 16:31:45 +0200989 si_shutr(si);
990 si_shutw(si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100991 si->err_type |= SI_ET_CONN_ABRT;
992 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +0100993 if (s->srv_error)
994 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100995 return;
996 }
997
998 if (!(si->flags & SI_FL_EXP))
999 return; /* still in turn-around */
1000
1001 si->exp = TICK_ETERNITY;
1002
1003 /* we keep trying on the same server as long as the session is
1004 * marked "assigned".
1005 * FIXME: Should we force a redispatch attempt when the server is down ?
1006 */
1007 if (s->flags & SN_ASSIGNED)
1008 si->state = SI_ST_ASS;
1009 else
1010 si->state = SI_ST_REQ;
1011 return;
1012 }
1013}
1014
Simon Hormandec5be42011-06-08 09:19:07 +09001015/* Set correct session termination flags in case no analyser has done it. It
1016 * also counts a failed request if the server state has not reached the request
1017 * stage.
1018 */
1019static void sess_set_term_flags(struct session *s)
1020{
1021 if (!(s->flags & SN_FINST_MASK)) {
1022 if (s->si[1].state < SI_ST_REQ) {
1023
1024 s->fe->fe_counters.failed_req++;
1025 if (s->listener->counters)
1026 s->listener->counters->failed_req++;
1027
1028 s->flags |= SN_FINST_R;
1029 }
1030 else if (s->si[1].state == SI_ST_QUE)
1031 s->flags |= SN_FINST_Q;
1032 else if (s->si[1].state < SI_ST_EST)
1033 s->flags |= SN_FINST_C;
1034 else if (s->si[1].state == SI_ST_EST || s->si[1].prev_state == SI_ST_EST)
1035 s->flags |= SN_FINST_D;
1036 else
1037 s->flags |= SN_FINST_L;
1038 }
1039}
1040
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001041/* This function initiates a server connection request on a stream interface
1042 * already in SI_ST_REQ state. Upon success, the state goes to SI_ST_ASS,
1043 * indicating that a server has been assigned. It may also return SI_ST_QUE,
1044 * or SI_ST_CLO upon error.
1045 */
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001046static void sess_prepare_conn_req(struct session *s, struct stream_interface *si)
1047{
1048 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 +01001049 now_ms, __FUNCTION__,
1050 s,
1051 s->req, s->rep,
1052 s->req->rex, s->rep->wex,
1053 s->req->flags, s->rep->flags,
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001054 s->req->i, s->req->o, s->rep->i, s->rep->o, s->rep->cons->state, s->req->cons->state);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001055
1056 if (si->state != SI_ST_REQ)
1057 return;
1058
1059 /* Try to assign a server */
1060 if (srv_redispatch_connect(s) != 0) {
1061 /* We did not get a server. Either we queued the
1062 * connection request, or we encountered an error.
1063 */
1064 if (si->state == SI_ST_QUE)
1065 return;
1066
1067 /* we did not get any server, let's check the cause */
Willy Tarreau73b013b2012-05-21 16:31:45 +02001068 si_shutr(si);
1069 si_shutw(si);
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001070 si->ob->flags |= CF_WRITE_ERROR;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001071 if (!si->err_type)
1072 si->err_type = SI_ET_CONN_OTHER;
1073 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +01001074 if (s->srv_error)
1075 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001076 return;
1077 }
1078
1079 /* The server is assigned */
1080 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
1081 si->state = SI_ST_ASS;
1082}
1083
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001084/* This stream analyser checks the switching rules and changes the backend
Willy Tarreau4de91492010-01-22 19:10:05 +01001085 * if appropriate. The default_backend rule is also considered, then the
1086 * target backend's forced persistence rules are also evaluated last if any.
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001087 * It returns 1 if the processing can continue on next analysers, or zero if it
1088 * either needs more data or wants to immediately abort the request.
1089 */
Willy Tarreau7421efb2012-07-02 15:11:27 +02001090static int process_switching_rules(struct session *s, struct channel *req, int an_bit)
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001091{
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001092 struct persist_rule *prst_rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01001093
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001094 req->analysers &= ~an_bit;
1095 req->analyse_exp = TICK_ETERNITY;
1096
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001097 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 +02001098 now_ms, __FUNCTION__,
1099 s,
1100 req,
1101 req->rex, req->wex,
1102 req->flags,
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001103 req->i,
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001104 req->analysers);
1105
1106 /* now check whether we have some switching rules for this request */
1107 if (!(s->flags & SN_BE_ASSIGNED)) {
1108 struct switching_rule *rule;
1109
1110 list_for_each_entry(rule, &s->fe->switching_rules, list) {
1111 int ret;
1112
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001113 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 +02001114 ret = acl_pass(ret);
1115 if (rule->cond->pol == ACL_COND_UNLESS)
1116 ret = !ret;
1117
1118 if (ret) {
Willy Tarreaubedb9ba2009-07-12 08:27:39 +02001119 if (!session_set_backend(s, rule->be.backend))
1120 goto sw_failed;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001121 break;
1122 }
1123 }
1124
1125 /* To ensure correct connection accounting on the backend, we
1126 * have to assign one if it was not set (eg: a listen). This
1127 * measure also takes care of correctly setting the default
1128 * backend if any.
1129 */
1130 if (!(s->flags & SN_BE_ASSIGNED))
Willy Tarreaubedb9ba2009-07-12 08:27:39 +02001131 if (!session_set_backend(s, s->fe->defbe.be ? s->fe->defbe.be : s->be))
1132 goto sw_failed;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001133 }
1134
Willy Tarreaufb356202010-08-03 14:02:05 +02001135 /* we don't want to run the TCP or HTTP filters again if the backend has not changed */
1136 if (s->fe == s->be) {
1137 s->req->analysers &= ~AN_REQ_INSPECT_BE;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001138 s->req->analysers &= ~AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaufb356202010-08-03 14:02:05 +02001139 }
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001140
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001141 /* 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 +01001142 * persistence rule, and report that in the session.
1143 */
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001144 list_for_each_entry(prst_rule, &s->be->persist_rules, list) {
Willy Tarreau4de91492010-01-22 19:10:05 +01001145 int ret = 1;
1146
1147 if (prst_rule->cond) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001148 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 +01001149 ret = acl_pass(ret);
1150 if (prst_rule->cond->pol == ACL_COND_UNLESS)
1151 ret = !ret;
1152 }
1153
1154 if (ret) {
1155 /* no rule, or the rule matches */
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001156 if (prst_rule->type == PERSIST_TYPE_FORCE) {
1157 s->flags |= SN_FORCE_PRST;
1158 } else {
1159 s->flags |= SN_IGNORE_PRST;
1160 }
Willy Tarreau4de91492010-01-22 19:10:05 +01001161 break;
1162 }
1163 }
1164
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001165 return 1;
Willy Tarreaubedb9ba2009-07-12 08:27:39 +02001166
1167 sw_failed:
1168 /* immediately abort this request in case of allocation failure */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001169 channel_abort(s->req);
1170 channel_abort(s->rep);
Willy Tarreaubedb9ba2009-07-12 08:27:39 +02001171
1172 if (!(s->flags & SN_ERR_MASK))
1173 s->flags |= SN_ERR_RESOURCE;
1174 if (!(s->flags & SN_FINST_MASK))
1175 s->flags |= SN_FINST_R;
1176
1177 s->txn.status = 500;
1178 s->req->analysers = 0;
1179 s->req->analyse_exp = TICK_ETERNITY;
1180 return 0;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001181}
1182
Willy Tarreau4a5cade2012-04-05 21:09:48 +02001183/* This stream analyser works on a request. It applies all use-server rules on
1184 * it then returns 1. The data must already be present in the buffer otherwise
1185 * they won't match. It always returns 1.
1186 */
Willy Tarreau7421efb2012-07-02 15:11:27 +02001187static int process_server_rules(struct session *s, struct channel *req, int an_bit)
Willy Tarreau4a5cade2012-04-05 21:09:48 +02001188{
1189 struct proxy *px = s->be;
1190 struct server_rule *rule;
1191
1192 DPRINTF(stderr,"[%u] %s: session=%p b=%p, exp(r,w)=%u,%u bf=%08x bl=%d analysers=%02x\n",
1193 now_ms, __FUNCTION__,
1194 s,
1195 req,
1196 req->rex, req->wex,
1197 req->flags,
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001198 req->i + req->o,
Willy Tarreau4a5cade2012-04-05 21:09:48 +02001199 req->analysers);
1200
1201 if (!(s->flags & SN_ASSIGNED)) {
1202 list_for_each_entry(rule, &px->server_rules, list) {
1203 int ret;
1204
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001205 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 +02001206 ret = acl_pass(ret);
1207 if (rule->cond->pol == ACL_COND_UNLESS)
1208 ret = !ret;
1209
1210 if (ret) {
1211 struct server *srv = rule->srv.ptr;
1212
1213 if ((srv->state & SRV_RUNNING) ||
1214 (px->options & PR_O_PERSIST) ||
1215 (s->flags & SN_FORCE_PRST)) {
1216 s->flags |= SN_DIRECT | SN_ASSIGNED;
1217 set_target_server(&s->target, srv);
1218 break;
1219 }
1220 /* if the server is not UP, let's go on with next rules
1221 * just in case another one is suited.
1222 */
1223 }
1224 }
1225 }
1226
1227 req->analysers &= ~an_bit;
1228 req->analyse_exp = TICK_ETERNITY;
1229 return 1;
1230}
1231
Emeric Brun1d33b292010-01-04 15:47:17 +01001232/* This stream analyser works on a request. It applies all sticking rules on
1233 * it then returns 1. The data must already be present in the buffer otherwise
1234 * they won't match. It always returns 1.
1235 */
Willy Tarreau7421efb2012-07-02 15:11:27 +02001236static int process_sticking_rules(struct session *s, struct channel *req, int an_bit)
Emeric Brun1d33b292010-01-04 15:47:17 +01001237{
1238 struct proxy *px = s->be;
1239 struct sticking_rule *rule;
1240
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001241 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 +01001242 now_ms, __FUNCTION__,
1243 s,
1244 req,
1245 req->rex, req->wex,
1246 req->flags,
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001247 req->i,
Emeric Brun1d33b292010-01-04 15:47:17 +01001248 req->analysers);
1249
1250 list_for_each_entry(rule, &px->sticking_rules, list) {
1251 int ret = 1 ;
1252 int i;
1253
1254 for (i = 0; i < s->store_count; i++) {
1255 if (rule->table.t == s->store[i].table)
1256 break;
1257 }
1258
1259 if (i != s->store_count)
1260 continue;
1261
1262 if (rule->cond) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001263 ret = acl_exec_cond(rule->cond, px, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
Emeric Brun1d33b292010-01-04 15:47:17 +01001264 ret = acl_pass(ret);
1265 if (rule->cond->pol == ACL_COND_UNLESS)
1266 ret = !ret;
1267 }
1268
1269 if (ret) {
1270 struct stktable_key *key;
1271
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001272 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 +01001273 if (!key)
1274 continue;
1275
1276 if (rule->flags & STK_IS_MATCH) {
1277 struct stksess *ts;
1278
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001279 if ((ts = stktable_lookup_key(rule->table.t, key)) != NULL) {
Emeric Brun1d33b292010-01-04 15:47:17 +01001280 if (!(s->flags & SN_ASSIGNED)) {
1281 struct eb32_node *node;
Willy Tarreau13c29de2010-06-06 16:40:39 +02001282 void *ptr;
Emeric Brun1d33b292010-01-04 15:47:17 +01001283
1284 /* srv found in table */
Willy Tarreau13c29de2010-06-06 16:40:39 +02001285 ptr = stktable_data_ptr(rule->table.t, ts, STKTABLE_DT_SERVER_ID);
1286 node = eb32_lookup(&px->conf.used_server_id, stktable_data_cast(ptr, server_id));
Emeric Brun1d33b292010-01-04 15:47:17 +01001287 if (node) {
1288 struct server *srv;
1289
1290 srv = container_of(node, struct server, conf.id);
Willy Tarreau4de91492010-01-22 19:10:05 +01001291 if ((srv->state & SRV_RUNNING) ||
1292 (px->options & PR_O_PERSIST) ||
1293 (s->flags & SN_FORCE_PRST)) {
Emeric Brun1d33b292010-01-04 15:47:17 +01001294 s->flags |= SN_DIRECT | SN_ASSIGNED;
Willy Tarreau9e000c62011-03-10 14:03:36 +01001295 set_target_server(&s->target, srv);
Emeric Brun1d33b292010-01-04 15:47:17 +01001296 }
1297 }
1298 }
Emeric Brun85e77c72010-09-23 18:16:52 +02001299 stktable_touch(rule->table.t, ts, 1);
Emeric Brun1d33b292010-01-04 15:47:17 +01001300 }
1301 }
1302 if (rule->flags & STK_IS_STORE) {
1303 if (s->store_count < (sizeof(s->store) / sizeof(s->store[0]))) {
1304 struct stksess *ts;
1305
1306 ts = stksess_new(rule->table.t, key);
1307 if (ts) {
1308 s->store[s->store_count].table = rule->table.t;
1309 s->store[s->store_count++].ts = ts;
1310 }
1311 }
1312 }
1313 }
1314 }
1315
1316 req->analysers &= ~an_bit;
1317 req->analyse_exp = TICK_ETERNITY;
1318 return 1;
1319}
1320
1321/* This stream analyser works on a response. It applies all store rules on it
1322 * then returns 1. The data must already be present in the buffer otherwise
1323 * they won't match. It always returns 1.
1324 */
Willy Tarreau7421efb2012-07-02 15:11:27 +02001325static int process_store_rules(struct session *s, struct channel *rep, int an_bit)
Emeric Brun1d33b292010-01-04 15:47:17 +01001326{
1327 struct proxy *px = s->be;
1328 struct sticking_rule *rule;
1329 int i;
1330
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001331 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 +01001332 now_ms, __FUNCTION__,
1333 s,
Willy Tarreau2e2b3eb2010-02-09 20:55:44 +01001334 rep,
1335 rep->rex, rep->wex,
1336 rep->flags,
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001337 rep->i,
Willy Tarreau2e2b3eb2010-02-09 20:55:44 +01001338 rep->analysers);
Emeric Brun1d33b292010-01-04 15:47:17 +01001339
1340 list_for_each_entry(rule, &px->storersp_rules, list) {
1341 int ret = 1 ;
1342 int storereqidx = -1;
1343
1344 for (i = 0; i < s->store_count; i++) {
1345 if (rule->table.t == s->store[i].table) {
1346 if (!(s->store[i].flags))
1347 storereqidx = i;
1348 break;
1349 }
1350 }
1351
1352 if ((i != s->store_count) && (storereqidx == -1))
1353 continue;
1354
1355 if (rule->cond) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001356 ret = acl_exec_cond(rule->cond, px, s, &s->txn, SMP_OPT_DIR_RES|SMP_OPT_FINAL);
Emeric Brun1d33b292010-01-04 15:47:17 +01001357 ret = acl_pass(ret);
1358 if (rule->cond->pol == ACL_COND_UNLESS)
1359 ret = !ret;
1360 }
1361
1362 if (ret) {
1363 struct stktable_key *key;
1364
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001365 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 +01001366 if (!key)
1367 continue;
1368
1369 if (storereqidx != -1) {
Willy Tarreau393379c2010-06-06 12:11:37 +02001370 stksess_setkey(s->store[storereqidx].table, s->store[storereqidx].ts, key);
Emeric Brun1d33b292010-01-04 15:47:17 +01001371 s->store[storereqidx].flags = 1;
1372 }
1373 else if (s->store_count < (sizeof(s->store) / sizeof(s->store[0]))) {
1374 struct stksess *ts;
1375
1376 ts = stksess_new(rule->table.t, key);
1377 if (ts) {
1378 s->store[s->store_count].table = rule->table.t;
1379 s->store[s->store_count].flags = 1;
1380 s->store[s->store_count++].ts = ts;
1381 }
1382 }
1383 }
1384 }
1385
1386 /* process store request and store response */
1387 for (i = 0; i < s->store_count; i++) {
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001388 struct stksess *ts;
Willy Tarreau13c29de2010-06-06 16:40:39 +02001389 void *ptr;
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001390
Simon Hormanfa461682011-06-25 09:39:49 +09001391 if (target_srv(&s->target) && target_srv(&s->target)->state & SRV_NON_STICK) {
1392 stksess_free(s->store[i].table, s->store[i].ts);
1393 s->store[i].ts = NULL;
1394 continue;
1395 }
1396
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001397 ts = stktable_lookup(s->store[i].table, s->store[i].ts);
1398 if (ts) {
1399 /* the entry already existed, we can free ours */
Emeric Brun85e77c72010-09-23 18:16:52 +02001400 stktable_touch(s->store[i].table, ts, 1);
Emeric Brun1d33b292010-01-04 15:47:17 +01001401 stksess_free(s->store[i].table, s->store[i].ts);
Emeric Brun1d33b292010-01-04 15:47:17 +01001402 }
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001403 else
Emeric Brun85e77c72010-09-23 18:16:52 +02001404 ts = stktable_store(s->store[i].table, s->store[i].ts, 1);
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001405
1406 s->store[i].ts = NULL;
Willy Tarreau13c29de2010-06-06 16:40:39 +02001407 ptr = stktable_data_ptr(s->store[i].table, ts, STKTABLE_DT_SERVER_ID);
Willy Tarreau827aee92011-03-10 16:55:02 +01001408 stktable_data_cast(ptr, server_id) = target_srv(&s->target)->puid;
Emeric Brun1d33b292010-01-04 15:47:17 +01001409 }
Willy Tarreau2a164ee2010-06-18 09:57:45 +02001410 s->store_count = 0; /* everything is stored */
Emeric Brun1d33b292010-01-04 15:47:17 +01001411
1412 rep->analysers &= ~an_bit;
1413 rep->analyse_exp = TICK_ETERNITY;
1414 return 1;
1415}
1416
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001417/* This macro is very specific to the function below. See the comments in
1418 * process_session() below to understand the logic and the tests.
1419 */
1420#define UPDATE_ANALYSERS(real, list, back, flag) { \
1421 list = (((list) & ~(flag)) | ~(back)) & (real); \
1422 back = real; \
1423 if (!(list)) \
1424 break; \
1425 if (((list) ^ ((list) & ((list) - 1))) < (flag)) \
1426 continue; \
1427}
1428
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001429/* Processes the client, server, request and response jobs of a session task,
1430 * then puts it back to the wait queue in a clean state, or cleans up its
1431 * resources if it must be deleted. Returns in <next> the date the task wants
1432 * to be woken up, or TICK_ETERNITY. In order not to call all functions for
1433 * nothing too many times, the request and response buffers flags are monitored
1434 * and each function is called only if at least another function has changed at
1435 * least one flag it is interested in.
1436 */
Willy Tarreau26c25062009-03-08 09:38:41 +01001437struct task *process_session(struct task *t)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001438{
Willy Tarreau827aee92011-03-10 16:55:02 +01001439 struct server *srv;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001440 struct session *s = t->context;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001441 unsigned int rqf_last, rpf_last;
Willy Tarreau815a9b22010-07-27 17:15:12 +02001442 unsigned int rq_prod_last, rq_cons_last;
1443 unsigned int rp_cons_last, rp_prod_last;
Willy Tarreau576507f2010-01-07 00:09:04 +01001444 unsigned int req_ana_back;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001445
1446 //DPRINTF(stderr, "%s:%d: cs=%d ss=%d(%d) rqf=0x%08x rpf=0x%08x\n", __FUNCTION__, __LINE__,
1447 // s->si[0].state, s->si[1].state, s->si[1].err_type, s->req->flags, s->rep->flags);
1448
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001449 /* this data may be no longer valid, clear it */
1450 memset(&s->txn.auth, 0, sizeof(s->txn.auth));
1451
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001452 /* This flag must explicitly be set every time */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001453 s->req->flags &= ~CF_READ_NOEXP;
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001454
1455 /* Keep a copy of req/rep flags so that we can detect shutdowns */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001456 rqf_last = s->req->flags & ~CF_MASK_ANALYSER;
1457 rpf_last = s->rep->flags & ~CF_MASK_ANALYSER;
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001458
Willy Tarreau89f7ef22009-09-05 20:57:35 +02001459 /* we don't want the stream interface functions to recursively wake us up */
1460 if (s->req->prod->owner == t)
1461 s->req->prod->flags |= SI_FL_DONT_WAKE;
1462 if (s->req->cons->owner == t)
1463 s->req->cons->flags |= SI_FL_DONT_WAKE;
1464
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001465 /* 1a: Check for low level timeouts if needed. We just set a flag on
1466 * stream interfaces when their timeouts have expired.
1467 */
1468 if (unlikely(t->state & TASK_WOKEN_TIMER)) {
1469 stream_int_check_timeouts(&s->si[0]);
1470 stream_int_check_timeouts(&s->si[1]);
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001471
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001472 /* check channel timeouts, and close the corresponding stream interfaces
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001473 * for future reads or writes. Note: this will also concern upper layers
1474 * but we do not touch any other flag. We must be careful and correctly
1475 * detect state changes when calling them.
1476 */
1477
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001478 channel_check_timeouts(s->req);
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001479
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001480 if (unlikely((s->req->flags & (CF_SHUTW|CF_WRITE_TIMEOUT)) == CF_WRITE_TIMEOUT)) {
Willy Tarreau14641402009-12-29 14:49:56 +01001481 s->req->cons->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001482 si_shutw(s->req->cons);
Willy Tarreau14641402009-12-29 14:49:56 +01001483 }
1484
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001485 if (unlikely((s->req->flags & (CF_SHUTR|CF_READ_TIMEOUT)) == CF_READ_TIMEOUT)) {
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02001486 if (s->req->prod->flags & SI_FL_NOHALF)
1487 s->req->prod->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001488 si_shutr(s->req->prod);
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02001489 }
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001490
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001491 channel_check_timeouts(s->rep);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001492
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001493 if (unlikely((s->rep->flags & (CF_SHUTW|CF_WRITE_TIMEOUT)) == CF_WRITE_TIMEOUT)) {
Willy Tarreau14641402009-12-29 14:49:56 +01001494 s->rep->cons->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001495 si_shutw(s->rep->cons);
Willy Tarreau14641402009-12-29 14:49:56 +01001496 }
1497
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001498 if (unlikely((s->rep->flags & (CF_SHUTR|CF_READ_TIMEOUT)) == CF_READ_TIMEOUT)) {
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02001499 if (s->rep->prod->flags & SI_FL_NOHALF)
1500 s->rep->prod->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001501 si_shutr(s->rep->prod);
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02001502 }
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001503 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001504
1505 /* 1b: check for low-level errors reported at the stream interface.
1506 * First we check if it's a retryable error (in which case we don't
1507 * want to tell the buffer). Otherwise we report the error one level
1508 * upper by setting flags into the buffers. Note that the side towards
1509 * the client cannot have connect (hence retryable) errors. Also, the
1510 * connection setup code must be able to deal with any type of abort.
1511 */
Willy Tarreau827aee92011-03-10 16:55:02 +01001512 srv = target_srv(&s->target);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001513 if (unlikely(s->si[0].flags & SI_FL_ERR)) {
1514 if (s->si[0].state == SI_ST_EST || s->si[0].state == SI_ST_DIS) {
Willy Tarreau73b013b2012-05-21 16:31:45 +02001515 si_shutr(&s->si[0]);
1516 si_shutw(&s->si[0]);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001517 stream_int_report_error(&s->si[0]);
Willy Tarreau05cb29b2008-12-14 11:44:04 +01001518 if (!(s->req->analysers) && !(s->rep->analysers)) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001519 s->be->be_counters.cli_aborts++;
1520 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001521 if (srv)
1522 srv->counters.cli_aborts++;
Willy Tarreau05cb29b2008-12-14 11:44:04 +01001523 if (!(s->flags & SN_ERR_MASK))
1524 s->flags |= SN_ERR_CLICL;
1525 if (!(s->flags & SN_FINST_MASK))
1526 s->flags |= SN_FINST_D;
1527 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001528 }
1529 }
1530
1531 if (unlikely(s->si[1].flags & SI_FL_ERR)) {
1532 if (s->si[1].state == SI_ST_EST || s->si[1].state == SI_ST_DIS) {
Willy Tarreau73b013b2012-05-21 16:31:45 +02001533 si_shutr(&s->si[1]);
1534 si_shutw(&s->si[1]);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001535 stream_int_report_error(&s->si[1]);
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001536 s->be->be_counters.failed_resp++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001537 if (srv)
1538 srv->counters.failed_resp++;
Willy Tarreau05cb29b2008-12-14 11:44:04 +01001539 if (!(s->req->analysers) && !(s->rep->analysers)) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001540 s->be->be_counters.srv_aborts++;
1541 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001542 if (srv)
1543 srv->counters.srv_aborts++;
Willy Tarreau05cb29b2008-12-14 11:44:04 +01001544 if (!(s->flags & SN_ERR_MASK))
1545 s->flags |= SN_ERR_SRVCL;
1546 if (!(s->flags & SN_FINST_MASK))
1547 s->flags |= SN_FINST_D;
1548 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001549 }
1550 /* note: maybe we should process connection errors here ? */
1551 }
1552
1553 if (s->si[1].state == SI_ST_CON) {
1554 /* we were trying to establish a connection on the server side,
1555 * maybe it succeeded, maybe it failed, maybe we timed out, ...
1556 */
1557 if (unlikely(!sess_update_st_con_tcp(s, &s->si[1])))
1558 sess_update_st_cer(s, &s->si[1]);
1559 else if (s->si[1].state == SI_ST_EST)
1560 sess_establish(s, &s->si[1]);
1561
1562 /* state is now one of SI_ST_CON (still in progress), SI_ST_EST
1563 * (established), SI_ST_DIS (abort), SI_ST_CLO (last error),
1564 * SI_ST_ASS/SI_ST_TAR/SI_ST_REQ for retryable errors.
1565 */
1566 }
1567
Willy Tarreau815a9b22010-07-27 17:15:12 +02001568 rq_prod_last = s->si[0].state;
1569 rq_cons_last = s->si[1].state;
1570 rp_cons_last = s->si[0].state;
1571 rp_prod_last = s->si[1].state;
1572
1573 resync_stream_interface:
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001574 /* Check for connection closure */
1575
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001576 DPRINTF(stderr,
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001577 "[%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 +01001578 now_ms, __FUNCTION__, __LINE__,
1579 t,
1580 s, s->flags,
1581 s->req, s->rep,
1582 s->req->rex, s->rep->wex,
1583 s->req->flags, s->rep->flags,
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001584 s->req->i, s->req->o, s->rep->i, s->rep->o, s->rep->cons->state, s->req->cons->state,
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001585 s->rep->cons->err_type, s->req->cons->err_type,
Willy Tarreauee28de02010-06-01 09:51:00 +02001586 s->req->cons->conn_retries);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001587
1588 /* nothing special to be done on client side */
1589 if (unlikely(s->req->prod->state == SI_ST_DIS))
1590 s->req->prod->state = SI_ST_CLO;
1591
1592 /* When a server-side connection is released, we have to count it and
1593 * check for pending connections on this server.
1594 */
1595 if (unlikely(s->req->cons->state == SI_ST_DIS)) {
1596 s->req->cons->state = SI_ST_CLO;
Willy Tarreau827aee92011-03-10 16:55:02 +01001597 srv = target_srv(&s->target);
1598 if (srv) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001599 if (s->flags & SN_CURR_SESS) {
1600 s->flags &= ~SN_CURR_SESS;
Willy Tarreau827aee92011-03-10 16:55:02 +01001601 srv->cur_sess--;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001602 }
1603 sess_change_server(s, NULL);
Willy Tarreau827aee92011-03-10 16:55:02 +01001604 if (may_dequeue_tasks(srv, s->be))
1605 process_srv_queue(srv);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001606 }
1607 }
1608
1609 /*
1610 * Note: of the transient states (REQ, CER, DIS), only REQ may remain
1611 * at this point.
1612 */
1613
Willy Tarreau0be0ef92009-03-08 19:20:25 +01001614 resync_request:
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001615 /* Analyse request */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001616 if (((s->req->flags & ~rqf_last) & CF_MASK_ANALYSER) ||
1617 ((s->req->flags ^ rqf_last) & CF_MASK_STATIC) ||
Willy Tarreau815a9b22010-07-27 17:15:12 +02001618 s->si[0].state != rq_prod_last ||
1619 s->si[1].state != rq_cons_last) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001620 unsigned int flags = s->req->flags;
1621
1622 if (s->req->prod->state >= SI_ST_EST) {
Willy Tarreaue34070e2010-01-08 00:32:27 +01001623 int max_loops = global.tune.maxpollevents;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001624 unsigned int ana_list;
1625 unsigned int ana_back;
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001626
Willy Tarreau90deb182010-01-07 00:20:41 +01001627 /* it's up to the analysers to stop new connections,
1628 * disable reading or closing. Note: if an analyser
1629 * disables any of these bits, it is responsible for
1630 * enabling them again when it disables itself, so
1631 * that other analysers are called in similar conditions.
1632 */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001633 channel_auto_read(s->req);
1634 channel_auto_connect(s->req);
1635 channel_auto_close(s->req);
Willy Tarreauedcf6682008-11-30 23:15:34 +01001636
1637 /* We will call all analysers for which a bit is set in
1638 * s->req->analysers, following the bit order from LSB
1639 * to MSB. The analysers must remove themselves from
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001640 * the list when not needed. Any analyser may return 0
1641 * to break out of the loop, either because of missing
1642 * data to take a decision, or because it decides to
1643 * kill the session. We loop at least once through each
1644 * analyser, and we may loop again if other analysers
1645 * are added in the middle.
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001646 *
1647 * We build a list of analysers to run. We evaluate all
1648 * of these analysers in the order of the lower bit to
1649 * the higher bit. This ordering is very important.
1650 * An analyser will often add/remove other analysers,
1651 * including itself. Any changes to itself have no effect
1652 * on the loop. If it removes any other analysers, we
1653 * want those analysers not to be called anymore during
1654 * this loop. If it adds an analyser that is located
1655 * after itself, we want it to be scheduled for being
1656 * processed during the loop. If it adds an analyser
1657 * which is located before it, we want it to switch to
1658 * it immediately, even if it has already been called
1659 * once but removed since.
1660 *
1661 * In order to achieve this, we compare the analyser
1662 * list after the call with a copy of it before the
1663 * call. The work list is fed with analyser bits that
1664 * appeared during the call. Then we compare previous
1665 * work list with the new one, and check the bits that
1666 * appeared. If the lowest of these bits is lower than
1667 * the current bit, it means we have enabled a previous
1668 * analyser and must immediately loop again.
Willy Tarreauedcf6682008-11-30 23:15:34 +01001669 */
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001670
1671 ana_list = ana_back = s->req->analysers;
Willy Tarreaue34070e2010-01-08 00:32:27 +01001672 while (ana_list && max_loops--) {
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001673 /* Warning! ensure that analysers are always placed in ascending order! */
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001674
Willy Tarreaufb356202010-08-03 14:02:05 +02001675 if (ana_list & AN_REQ_INSPECT_FE) {
1676 if (!tcp_inspect_request(s, s->req, AN_REQ_INSPECT_FE))
Willy Tarreauedcf6682008-11-30 23:15:34 +01001677 break;
Willy Tarreaufb356202010-08-03 14:02:05 +02001678 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_INSPECT_FE);
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001679 }
Willy Tarreauedcf6682008-11-30 23:15:34 +01001680
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001681 if (ana_list & AN_REQ_WAIT_HTTP) {
Willy Tarreau3a816292009-07-07 10:55:49 +02001682 if (!http_wait_for_request(s, s->req, AN_REQ_WAIT_HTTP))
Willy Tarreaud787e662009-07-07 10:14:51 +02001683 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001684 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_WAIT_HTTP);
Willy Tarreaud787e662009-07-07 10:14:51 +02001685 }
1686
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001687 if (ana_list & AN_REQ_HTTP_PROCESS_FE) {
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001688 if (!http_process_req_common(s, s->req, AN_REQ_HTTP_PROCESS_FE, s->fe))
1689 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001690 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_PROCESS_FE);
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001691 }
1692
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001693 if (ana_list & AN_REQ_SWITCHING_RULES) {
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001694 if (!process_switching_rules(s, s->req, AN_REQ_SWITCHING_RULES))
1695 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001696 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_SWITCHING_RULES);
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001697 }
1698
Willy Tarreaufb356202010-08-03 14:02:05 +02001699 if (ana_list & AN_REQ_INSPECT_BE) {
1700 if (!tcp_inspect_request(s, s->req, AN_REQ_INSPECT_BE))
1701 break;
1702 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_INSPECT_BE);
1703 }
1704
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001705 if (ana_list & AN_REQ_HTTP_PROCESS_BE) {
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001706 if (!http_process_req_common(s, s->req, AN_REQ_HTTP_PROCESS_BE, s->be))
1707 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001708 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_PROCESS_BE);
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001709 }
1710
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001711 if (ana_list & AN_REQ_HTTP_TARPIT) {
Willy Tarreau3a816292009-07-07 10:55:49 +02001712 if (!http_process_tarpit(s, s->req, AN_REQ_HTTP_TARPIT))
Willy Tarreau60b85b02008-11-30 23:28:40 +01001713 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001714 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_TARPIT);
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001715 }
Willy Tarreau60b85b02008-11-30 23:28:40 +01001716
Willy Tarreau4a5cade2012-04-05 21:09:48 +02001717 if (ana_list & AN_REQ_SRV_RULES) {
1718 if (!process_server_rules(s, s->req, AN_REQ_SRV_RULES))
1719 break;
1720 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_SRV_RULES);
1721 }
1722
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001723 if (ana_list & AN_REQ_HTTP_INNER) {
Willy Tarreauc465fd72009-08-31 00:17:18 +02001724 if (!http_process_request(s, s->req, AN_REQ_HTTP_INNER))
1725 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001726 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_INNER);
Willy Tarreauc465fd72009-08-31 00:17:18 +02001727 }
1728
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001729 if (ana_list & AN_REQ_HTTP_BODY) {
Willy Tarreau3a816292009-07-07 10:55:49 +02001730 if (!http_process_request_body(s, s->req, AN_REQ_HTTP_BODY))
Willy Tarreaud34af782008-11-30 23:36:37 +01001731 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001732 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_BODY);
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001733 }
Emeric Brun647caf12009-06-30 17:57:00 +02001734
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001735 if (ana_list & AN_REQ_PRST_RDP_COOKIE) {
Emeric Brun647caf12009-06-30 17:57:00 +02001736 if (!tcp_persist_rdp_cookie(s, s->req, AN_REQ_PRST_RDP_COOKIE))
1737 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001738 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_PRST_RDP_COOKIE);
Emeric Brun647caf12009-06-30 17:57:00 +02001739 }
Willy Tarreaud98cf932009-12-27 22:54:55 +01001740
Emeric Brun1d33b292010-01-04 15:47:17 +01001741 if (ana_list & AN_REQ_STICKING_RULES) {
1742 if (!process_sticking_rules(s, s->req, AN_REQ_STICKING_RULES))
1743 break;
1744 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_STICKING_RULES);
1745 }
1746
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001747 if (ana_list & AN_REQ_HTTP_XFER_BODY) {
Willy Tarreaud98cf932009-12-27 22:54:55 +01001748 if (!http_request_forward_body(s, s->req, AN_REQ_HTTP_XFER_BODY))
1749 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001750 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_XFER_BODY);
Willy Tarreaud98cf932009-12-27 22:54:55 +01001751 }
Willy Tarreaue34070e2010-01-08 00:32:27 +01001752 break;
1753 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001754 }
Willy Tarreau84455332009-03-15 22:34:05 +01001755
Willy Tarreau815a9b22010-07-27 17:15:12 +02001756 rq_prod_last = s->si[0].state;
1757 rq_cons_last = s->si[1].state;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001758 s->req->flags &= ~CF_WAKE_ONCE;
Willy Tarreau815a9b22010-07-27 17:15:12 +02001759 rqf_last = s->req->flags;
1760
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001761 if ((s->req->flags ^ flags) & CF_MASK_STATIC)
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001762 goto resync_request;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001763 }
1764
Willy Tarreau576507f2010-01-07 00:09:04 +01001765 /* we'll monitor the request analysers while parsing the response,
1766 * because some response analysers may indirectly enable new request
1767 * analysers (eg: HTTP keep-alive).
1768 */
1769 req_ana_back = s->req->analysers;
1770
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001771 resync_response:
1772 /* Analyse response */
1773
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001774 if (unlikely(s->rep->flags & CF_HIJACK)) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001775 /* In inject mode, we wake up everytime something has
1776 * happened on the write side of the buffer.
1777 */
1778 unsigned int flags = s->rep->flags;
1779
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001780 if ((s->rep->flags & (CF_WRITE_PARTIAL|CF_WRITE_ERROR|CF_SHUTW)) &&
Willy Tarreau3bf1b2b2012-08-27 20:46:07 +02001781 !channel_full(s->rep)) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001782 s->rep->hijacker(s, s->rep);
1783 }
1784
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001785 if ((s->rep->flags ^ flags) & CF_MASK_STATIC) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001786 rpf_last = s->rep->flags;
1787 goto resync_response;
1788 }
1789 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001790 else if (((s->rep->flags & ~rpf_last) & CF_MASK_ANALYSER) ||
1791 (s->rep->flags ^ rpf_last) & CF_MASK_STATIC ||
Willy Tarreau815a9b22010-07-27 17:15:12 +02001792 s->si[0].state != rp_cons_last ||
1793 s->si[1].state != rp_prod_last) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001794 unsigned int flags = s->rep->flags;
1795
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001796 if ((s->rep->flags & CF_MASK_ANALYSER) &&
Willy Tarreau0499e352010-12-17 07:13:42 +01001797 (s->rep->analysers & AN_REQ_WAIT_HTTP)) {
1798 /* Due to HTTP pipelining, the HTTP request analyser might be waiting
1799 * for some free space in the response buffer, so we might need to call
1800 * it when something changes in the response buffer, but still we pass
1801 * it the request buffer. Note that the SI state might very well still
1802 * be zero due to us returning a flow of redirects!
1803 */
1804 s->rep->analysers &= ~AN_REQ_WAIT_HTTP;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001805 s->req->flags |= CF_WAKE_ONCE;
Willy Tarreau0499e352010-12-17 07:13:42 +01001806 }
1807
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001808 if (s->rep->prod->state >= SI_ST_EST) {
Willy Tarreaue34070e2010-01-08 00:32:27 +01001809 int max_loops = global.tune.maxpollevents;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001810 unsigned int ana_list;
1811 unsigned int ana_back;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001812
Willy Tarreau90deb182010-01-07 00:20:41 +01001813 /* it's up to the analysers to stop disable reading or
1814 * closing. Note: if an analyser disables any of these
1815 * bits, it is responsible for enabling them again when
1816 * it disables itself, so that other analysers are called
1817 * in similar conditions.
1818 */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001819 channel_auto_read(s->rep);
1820 channel_auto_close(s->rep);
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001821
1822 /* We will call all analysers for which a bit is set in
1823 * s->rep->analysers, following the bit order from LSB
1824 * to MSB. The analysers must remove themselves from
1825 * the list when not needed. Any analyser may return 0
1826 * to break out of the loop, either because of missing
1827 * data to take a decision, or because it decides to
1828 * kill the session. We loop at least once through each
1829 * analyser, and we may loop again if other analysers
1830 * are added in the middle.
1831 */
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001832
1833 ana_list = ana_back = s->rep->analysers;
Willy Tarreaue34070e2010-01-08 00:32:27 +01001834 while (ana_list && max_loops--) {
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001835 /* Warning! ensure that analysers are always placed in ascending order! */
1836
Emeric Brun97679e72010-09-23 17:56:44 +02001837 if (ana_list & AN_RES_INSPECT) {
1838 if (!tcp_inspect_response(s, s->rep, AN_RES_INSPECT))
1839 break;
1840 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_INSPECT);
1841 }
1842
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001843 if (ana_list & AN_RES_WAIT_HTTP) {
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001844 if (!http_wait_for_response(s, s->rep, AN_RES_WAIT_HTTP))
1845 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001846 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_WAIT_HTTP);
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001847 }
1848
Emeric Brun1d33b292010-01-04 15:47:17 +01001849 if (ana_list & AN_RES_STORE_RULES) {
1850 if (!process_store_rules(s, s->rep, AN_RES_STORE_RULES))
1851 break;
1852 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_STORE_RULES);
1853 }
1854
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001855 if (ana_list & AN_RES_HTTP_PROCESS_BE) {
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001856 if (!http_process_res_common(s, s->rep, AN_RES_HTTP_PROCESS_BE, s->be))
1857 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001858 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_HTTP_PROCESS_BE);
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001859 }
Willy Tarreaud98cf932009-12-27 22:54:55 +01001860
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001861 if (ana_list & AN_RES_HTTP_XFER_BODY) {
Willy Tarreaud98cf932009-12-27 22:54:55 +01001862 if (!http_response_forward_body(s, s->rep, AN_RES_HTTP_XFER_BODY))
1863 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001864 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_HTTP_XFER_BODY);
Willy Tarreaud98cf932009-12-27 22:54:55 +01001865 }
Willy Tarreaue34070e2010-01-08 00:32:27 +01001866 break;
1867 }
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001868 }
1869
Willy Tarreau815a9b22010-07-27 17:15:12 +02001870 rp_cons_last = s->si[0].state;
1871 rp_prod_last = s->si[1].state;
1872 rpf_last = s->rep->flags;
1873
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001874 if ((s->rep->flags ^ flags) & CF_MASK_STATIC)
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001875 goto resync_response;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001876 }
1877
Willy Tarreau576507f2010-01-07 00:09:04 +01001878 /* maybe someone has added some request analysers, so we must check and loop */
1879 if (s->req->analysers & ~req_ana_back)
1880 goto resync_request;
1881
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001882 if ((s->req->flags & ~rqf_last) & CF_MASK_ANALYSER)
Willy Tarreau0499e352010-12-17 07:13:42 +01001883 goto resync_request;
1884
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001885 /* FIXME: here we should call protocol handlers which rely on
1886 * both buffers.
1887 */
1888
1889
1890 /*
Willy Tarreauae526782010-03-04 20:34:23 +01001891 * Now we propagate unhandled errors to the session. Normally
1892 * we're just in a data phase here since it means we have not
1893 * seen any analyser who could set an error status.
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001894 */
Willy Tarreau827aee92011-03-10 16:55:02 +01001895 srv = target_srv(&s->target);
Willy Tarreau2f976e12010-11-11 14:28:47 +01001896 if (unlikely(!(s->flags & SN_ERR_MASK))) {
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001897 if (s->req->flags & (CF_READ_ERROR|CF_READ_TIMEOUT|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001898 /* Report it if the client got an error or a read timeout expired */
Willy Tarreau84455332009-03-15 22:34:05 +01001899 s->req->analysers = 0;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001900 if (s->req->flags & CF_READ_ERROR) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001901 s->be->be_counters.cli_aborts++;
1902 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001903 if (srv)
1904 srv->counters.cli_aborts++;
Willy Tarreau84455332009-03-15 22:34:05 +01001905 s->flags |= SN_ERR_CLICL;
Willy Tarreauae526782010-03-04 20:34:23 +01001906 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001907 else if (s->req->flags & CF_READ_TIMEOUT) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001908 s->be->be_counters.cli_aborts++;
1909 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001910 if (srv)
1911 srv->counters.cli_aborts++;
Willy Tarreau84455332009-03-15 22:34:05 +01001912 s->flags |= SN_ERR_CLITO;
Willy Tarreauae526782010-03-04 20:34:23 +01001913 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001914 else if (s->req->flags & CF_WRITE_ERROR) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001915 s->be->be_counters.srv_aborts++;
1916 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001917 if (srv)
1918 srv->counters.srv_aborts++;
Willy Tarreau84455332009-03-15 22:34:05 +01001919 s->flags |= SN_ERR_SRVCL;
Willy Tarreauae526782010-03-04 20:34:23 +01001920 }
1921 else {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001922 s->be->be_counters.srv_aborts++;
1923 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001924 if (srv)
1925 srv->counters.srv_aborts++;
Willy Tarreau84455332009-03-15 22:34:05 +01001926 s->flags |= SN_ERR_SRVTO;
Willy Tarreauae526782010-03-04 20:34:23 +01001927 }
Willy Tarreau84455332009-03-15 22:34:05 +01001928 sess_set_term_flags(s);
1929 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001930 else if (s->rep->flags & (CF_READ_ERROR|CF_READ_TIMEOUT|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001931 /* Report it if the server got an error or a read timeout expired */
1932 s->rep->analysers = 0;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001933 if (s->rep->flags & CF_READ_ERROR) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001934 s->be->be_counters.srv_aborts++;
1935 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001936 if (srv)
1937 srv->counters.srv_aborts++;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001938 s->flags |= SN_ERR_SRVCL;
Willy Tarreauae526782010-03-04 20:34:23 +01001939 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001940 else if (s->rep->flags & CF_READ_TIMEOUT) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001941 s->be->be_counters.srv_aborts++;
1942 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001943 if (srv)
1944 srv->counters.srv_aborts++;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001945 s->flags |= SN_ERR_SRVTO;
Willy Tarreauae526782010-03-04 20:34:23 +01001946 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001947 else if (s->rep->flags & CF_WRITE_ERROR) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001948 s->be->be_counters.cli_aborts++;
1949 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001950 if (srv)
1951 srv->counters.cli_aborts++;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001952 s->flags |= SN_ERR_CLICL;
Willy Tarreauae526782010-03-04 20:34:23 +01001953 }
1954 else {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001955 s->be->be_counters.cli_aborts++;
1956 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001957 if (srv)
1958 srv->counters.cli_aborts++;
Willy Tarreauae526782010-03-04 20:34:23 +01001959 s->flags |= SN_ERR_CLITO;
1960 }
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001961 sess_set_term_flags(s);
1962 }
Willy Tarreau84455332009-03-15 22:34:05 +01001963 }
1964
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001965 /*
1966 * Here we take care of forwarding unhandled data. This also includes
1967 * connection establishments and shutdown requests.
1968 */
1969
1970
Willy Tarreau7c84bab2009-03-08 21:38:23 +01001971 /* If noone is interested in analysing data, it's time to forward
Willy Tarreau31971e52009-09-20 12:07:52 +02001972 * everything. We configure the buffer to forward indefinitely.
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001973 * Note that we're checking CF_SHUTR_NOW as an indication of a possible
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001974 * recent call to channel_abort().
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01001975 */
Willy Tarreau7c84bab2009-03-08 21:38:23 +01001976 if (!s->req->analysers &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001977 !(s->req->flags & (CF_HIJACK|CF_SHUTW|CF_SHUTR_NOW)) &&
Willy Tarreau31971e52009-09-20 12:07:52 +02001978 (s->req->prod->state >= SI_ST_EST) &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001979 (s->req->to_forward != CHN_INFINITE_FORWARD)) {
Willy Tarreau7c84bab2009-03-08 21:38:23 +01001980 /* This buffer is freewheeling, there's no analyser nor hijacker
1981 * attached to it. If any data are left in, we'll permit them to
1982 * move.
1983 */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001984 channel_auto_read(s->req);
1985 channel_auto_connect(s->req);
1986 channel_auto_close(s->req);
Willy Tarreaua75bcef2012-08-24 22:56:11 +02001987 buffer_flush(&s->req->buf);
Willy Tarreau5bd8c372009-01-19 00:32:22 +01001988
Willy Tarreauda4d9fe2010-11-07 20:26:56 +01001989 /* We'll let data flow between the producer (if still connected)
1990 * to the consumer (which might possibly not be connected yet).
Willy Tarreau7c84bab2009-03-08 21:38:23 +01001991 */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001992 if (!(s->req->flags & (CF_SHUTR|CF_SHUTW_NOW)))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001993 channel_forward(s->req, CHN_INFINITE_FORWARD);
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01001994 }
Willy Tarreauf890dc92008-12-13 21:12:26 +01001995
Willy Tarreau7c84bab2009-03-08 21:38:23 +01001996 /* check if it is wise to enable kernel splicing to forward request data */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001997 if (!(s->req->flags & (CF_KERN_SPLICING|CF_SHUTR)) &&
Willy Tarreau7c84bab2009-03-08 21:38:23 +01001998 s->req->to_forward &&
1999 (global.tune.options & GTUNE_USE_SPLICE) &&
Willy Tarreau93b0f4f2012-08-30 21:23:53 +02002000 (s->si[0].conn.data && s->si[0].conn.data->rcv_pipe && s->si[0].conn.data->snd_pipe) &&
2001 (s->si[1].conn.data && s->si[1].conn.data->rcv_pipe && s->si[1].conn.data->snd_pipe) &&
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002002 (pipes_used < global.maxpipes) &&
2003 (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_REQ) ||
2004 (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_AUT) &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002005 (s->req->flags & CF_STREAMER_FAST)))) {
2006 s->req->flags |= CF_KERN_SPLICING;
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002007 }
2008
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002009 /* reflect what the L7 analysers have seen last */
2010 rqf_last = s->req->flags;
2011
2012 /*
2013 * Now forward all shutdown requests between both sides of the buffer
2014 */
2015
Willy Tarreau520d95e2009-09-19 21:04:57 +02002016 /* first, let's check if the request buffer needs to shutdown(write), which may
2017 * happen either because the input is closed or because we want to force a close
Willy Tarreaue4599762010-03-21 23:25:09 +01002018 * once the server has begun to respond.
Willy Tarreau520d95e2009-09-19 21:04:57 +02002019 */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002020 if (unlikely((s->req->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_HIJACK|CF_AUTO_CLOSE|CF_SHUTR)) ==
2021 (CF_AUTO_CLOSE|CF_SHUTR)))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002022 channel_shutw_now(s->req);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002023
2024 /* shutdown(write) pending */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002025 if (unlikely((s->req->flags & (CF_SHUTW|CF_SHUTW_NOW)) == CF_SHUTW_NOW &&
Willy Tarreau8e21bb92012-08-24 22:40:29 +02002026 channel_is_empty(s->req)))
Willy Tarreau73b013b2012-05-21 16:31:45 +02002027 si_shutw(s->req->cons);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002028
2029 /* shutdown(write) done on server side, we must stop the client too */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002030 if (unlikely((s->req->flags & (CF_SHUTW|CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTW &&
Willy Tarreau3dbc6942008-12-07 13:05:04 +01002031 !s->req->analysers))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002032 channel_shutr_now(s->req);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002033
2034 /* shutdown(read) pending */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002035 if (unlikely((s->req->flags & (CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTR_NOW)) {
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02002036 if (s->req->prod->flags & SI_FL_NOHALF)
2037 s->req->prod->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02002038 si_shutr(s->req->prod);
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02002039 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002040
Willy Tarreau520d95e2009-09-19 21:04:57 +02002041 /* it's possible that an upper layer has requested a connection setup or abort.
2042 * There are 2 situations where we decide to establish a new connection :
2043 * - there are data scheduled for emission in the buffer
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002044 * - the CF_AUTO_CONNECT flag is set (active connection)
Willy Tarreau520d95e2009-09-19 21:04:57 +02002045 */
2046 if (s->req->cons->state == SI_ST_INI) {
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002047 if (!(s->req->flags & CF_SHUTW)) {
2048 if ((s->req->flags & CF_AUTO_CONNECT) || !channel_is_empty(s->req)) {
Willy Tarreaub24281b2011-02-13 13:16:36 +01002049 /* If we have an applet without a connect method, we immediately
Willy Tarreau85e7d002010-05-31 11:57:51 +02002050 * switch to the connected state, otherwise we perform a connection
2051 * request.
Willy Tarreau520d95e2009-09-19 21:04:57 +02002052 */
Willy Tarreau85e7d002010-05-31 11:57:51 +02002053 s->req->cons->state = SI_ST_REQ; /* new connection requested */
Willy Tarreau070ceb62010-06-01 10:36:43 +02002054 s->req->cons->conn_retries = s->be->conn_retries;
Willy Tarreau3cefd522012-08-30 15:49:18 +02002055 if (unlikely(s->req->cons->conn.target.type == TARG_TYPE_APPLET &&
Willy Tarreau73b013b2012-05-21 16:31:45 +02002056 !(si_ctrl(s->req->cons) && si_ctrl(s->req->cons)->connect))) {
Willy Tarreau520d95e2009-09-19 21:04:57 +02002057 s->req->cons->state = SI_ST_EST; /* connection established */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002058 s->rep->flags |= CF_READ_ATTACHED; /* producer is now attached */
Willy Tarreau85e7d002010-05-31 11:57:51 +02002059 s->req->wex = TICK_ETERNITY;
2060 }
Willy Tarreau520d95e2009-09-19 21:04:57 +02002061 }
Willy Tarreau73201222009-08-16 18:27:24 +02002062 }
Willy Tarreauf41ffdc2009-09-20 08:19:25 +02002063 else {
Willy Tarreau92795622009-03-06 12:51:23 +01002064 s->req->cons->state = SI_ST_CLO; /* shutw+ini = abort */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002065 channel_shutw_now(s->req); /* fix buffer flags upon abort */
2066 channel_shutr_now(s->rep);
Willy Tarreauf41ffdc2009-09-20 08:19:25 +02002067 }
Willy Tarreau92795622009-03-06 12:51:23 +01002068 }
2069
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002070
2071 /* we may have a pending connection request, or a connection waiting
2072 * for completion.
2073 */
2074 if (s->si[1].state >= SI_ST_REQ && s->si[1].state < SI_ST_CON) {
2075 do {
2076 /* nb: step 1 might switch from QUE to ASS, but we first want
2077 * to give a chance to step 2 to perform a redirect if needed.
2078 */
2079 if (s->si[1].state != SI_ST_REQ)
2080 sess_update_stream_int(s, &s->si[1]);
2081 if (s->si[1].state == SI_ST_REQ)
2082 sess_prepare_conn_req(s, &s->si[1]);
2083
Willy Tarreau827aee92011-03-10 16:55:02 +01002084 srv = target_srv(&s->target);
2085 if (s->si[1].state == SI_ST_ASS && srv && srv->rdr_len && (s->flags & SN_REDIRECTABLE))
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002086 perform_http_redirect(s, &s->si[1]);
2087 } while (s->si[1].state == SI_ST_ASS);
Mark Lamourinec2247f02012-01-04 13:02:01 -05002088
2089 /* Now we can add the server name to a header (if requested) */
2090 /* check for HTTP mode and proxy server_name_hdr_name != NULL */
Stathis Voukelatos09a030a2012-01-09 14:27:13 +01002091 if ((s->flags & SN_BE_ASSIGNED) &&
Willy Tarreau45c0d982012-03-09 12:11:57 +01002092 (s->be->mode == PR_MODE_HTTP) &&
2093 (s->be->server_id_hdr_name != NULL)) {
2094 http_send_name_header(&s->txn, s->be, target_srv(&s->target)->id);
Mark Lamourinec2247f02012-01-04 13:02:01 -05002095 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002096 }
2097
Willy Tarreau3deb3d02009-06-21 22:43:05 +02002098 /* Benchmarks have shown that it's optimal to do a full resync now */
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002099 if (s->req->prod->state == SI_ST_DIS || s->req->cons->state == SI_ST_DIS)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002100 goto resync_stream_interface;
2101
Willy Tarreau815a9b22010-07-27 17:15:12 +02002102 /* otherwise we want to check if we need to resync the req buffer or not */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002103 if ((s->req->flags ^ rqf_last) & CF_MASK_STATIC)
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002104 goto resync_request;
2105
Willy Tarreau3deb3d02009-06-21 22:43:05 +02002106 /* perform output updates to the response buffer */
Willy Tarreau84455332009-03-15 22:34:05 +01002107
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002108 /* If noone is interested in analysing data, it's time to forward
Willy Tarreau31971e52009-09-20 12:07:52 +02002109 * everything. We configure the buffer to forward indefinitely.
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002110 * Note that we're checking CF_SHUTR_NOW as an indication of a possible
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002111 * recent call to channel_abort().
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01002112 */
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002113 if (!s->rep->analysers &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002114 !(s->rep->flags & (CF_HIJACK|CF_SHUTW|CF_SHUTR_NOW)) &&
Willy Tarreau31971e52009-09-20 12:07:52 +02002115 (s->rep->prod->state >= SI_ST_EST) &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002116 (s->rep->to_forward != CHN_INFINITE_FORWARD)) {
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002117 /* This buffer is freewheeling, there's no analyser nor hijacker
2118 * attached to it. If any data are left in, we'll permit them to
2119 * move.
2120 */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002121 channel_auto_read(s->rep);
2122 channel_auto_close(s->rep);
Willy Tarreaua75bcef2012-08-24 22:56:11 +02002123 buffer_flush(&s->rep->buf);
Willy Tarreauda4d9fe2010-11-07 20:26:56 +01002124
2125 /* We'll let data flow between the producer (if still connected)
2126 * to the consumer.
2127 */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002128 if (!(s->rep->flags & (CF_SHUTR|CF_SHUTW_NOW)))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002129 channel_forward(s->rep, CHN_INFINITE_FORWARD);
Willy Tarreauce887fd2012-05-12 12:50:00 +02002130
2131 /* if we have no analyser anymore in any direction and have a
2132 * tunnel timeout set, use it now.
2133 */
2134 if (!s->req->analysers && s->be->timeout.tunnel) {
2135 s->req->rto = s->req->wto = s->rep->rto = s->rep->wto =
2136 s->be->timeout.tunnel;
2137 s->req->rex = s->req->wex = s->rep->rex = s->rep->wex =
2138 tick_add(now_ms, s->be->timeout.tunnel);
2139 }
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01002140 }
Willy Tarreauf890dc92008-12-13 21:12:26 +01002141
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002142 /* check if it is wise to enable kernel splicing to forward response data */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002143 if (!(s->rep->flags & (CF_KERN_SPLICING|CF_SHUTR)) &&
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002144 s->rep->to_forward &&
2145 (global.tune.options & GTUNE_USE_SPLICE) &&
Willy Tarreau93b0f4f2012-08-30 21:23:53 +02002146 (s->si[0].conn.data && s->si[0].conn.data->rcv_pipe && s->si[0].conn.data->snd_pipe) &&
2147 (s->si[1].conn.data && s->si[1].conn.data->rcv_pipe && s->si[1].conn.data->snd_pipe) &&
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002148 (pipes_used < global.maxpipes) &&
2149 (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_RTR) ||
2150 (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_AUT) &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002151 (s->rep->flags & CF_STREAMER_FAST)))) {
2152 s->rep->flags |= CF_KERN_SPLICING;
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002153 }
2154
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002155 /* reflect what the L7 analysers have seen last */
2156 rpf_last = s->rep->flags;
2157
2158 /*
2159 * Now forward all shutdown requests between both sides of the buffer
2160 */
2161
2162 /*
2163 * FIXME: this is probably where we should produce error responses.
2164 */
2165
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01002166 /* first, let's check if the response buffer needs to shutdown(write) */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002167 if (unlikely((s->rep->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_HIJACK|CF_AUTO_CLOSE|CF_SHUTR)) ==
2168 (CF_AUTO_CLOSE|CF_SHUTR)))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002169 channel_shutw_now(s->rep);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002170
2171 /* shutdown(write) pending */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002172 if (unlikely((s->rep->flags & (CF_SHUTW|CF_SHUTW_NOW)) == CF_SHUTW_NOW &&
Willy Tarreau8e21bb92012-08-24 22:40:29 +02002173 channel_is_empty(s->rep)))
Willy Tarreau73b013b2012-05-21 16:31:45 +02002174 si_shutw(s->rep->cons);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002175
2176 /* shutdown(write) done on the client side, we must stop the server too */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002177 if (unlikely((s->rep->flags & (CF_SHUTW|CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTW) &&
Willy Tarreau3dbc6942008-12-07 13:05:04 +01002178 !s->rep->analysers)
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002179 channel_shutr_now(s->rep);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002180
2181 /* shutdown(read) pending */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002182 if (unlikely((s->rep->flags & (CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTR_NOW)) {
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02002183 if (s->rep->prod->flags & SI_FL_NOHALF)
2184 s->rep->prod->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02002185 si_shutr(s->rep->prod);
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02002186 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002187
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002188 if (s->req->prod->state == SI_ST_DIS || s->req->cons->state == SI_ST_DIS)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002189 goto resync_stream_interface;
2190
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002191 if (s->req->flags != rqf_last)
2192 goto resync_request;
2193
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002194 if ((s->rep->flags ^ rpf_last) & CF_MASK_STATIC)
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002195 goto resync_response;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002196
Willy Tarreau89f7ef22009-09-05 20:57:35 +02002197 /* we're interested in getting wakeups again */
2198 s->req->prod->flags &= ~SI_FL_DONT_WAKE;
2199 s->req->cons->flags &= ~SI_FL_DONT_WAKE;
2200
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002201 /* This is needed only when debugging is enabled, to indicate
2202 * client-side or server-side close. Please note that in the unlikely
2203 * event where both sides would close at once, the sequence is reported
2204 * on the server side first.
2205 */
2206 if (unlikely((global.mode & MODE_DEBUG) &&
2207 (!(global.mode & MODE_QUIET) ||
2208 (global.mode & MODE_VERBOSE)))) {
2209 int len;
2210
2211 if (s->si[1].state == SI_ST_CLO &&
2212 s->si[1].prev_state == SI_ST_EST) {
2213 len = sprintf(trash, "%08x:%s.srvcls[%04x:%04x]\n",
2214 s->uniq_id, s->be->id,
Willy Tarreaufb7508a2012-05-21 16:47:54 +02002215 (unsigned short)si_fd(&s->si[0]),
2216 (unsigned short)si_fd(&s->si[1]));
Willy Tarreau21337822012-04-29 14:11:38 +02002217 if (write(1, trash, len) < 0) /* shut gcc warning */;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002218 }
2219
2220 if (s->si[0].state == SI_ST_CLO &&
2221 s->si[0].prev_state == SI_ST_EST) {
2222 len = sprintf(trash, "%08x:%s.clicls[%04x:%04x]\n",
2223 s->uniq_id, s->be->id,
Willy Tarreaufb7508a2012-05-21 16:47:54 +02002224 (unsigned short)si_fd(&s->si[0]),
2225 (unsigned short)si_fd(&s->si[1]));
Willy Tarreau21337822012-04-29 14:11:38 +02002226 if (write(1, trash, len) < 0) /* shut gcc warning */;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002227 }
2228 }
2229
2230 if (likely((s->rep->cons->state != SI_ST_CLO) ||
2231 (s->req->cons->state > SI_ST_INI && s->req->cons->state < SI_ST_CLO))) {
2232
2233 if ((s->fe->options & PR_O_CONTSTATS) && (s->flags & SN_BE_ASSIGNED))
2234 session_process_counters(s);
2235
Willy Tarreau3cefd522012-08-30 15:49:18 +02002236 if (s->rep->cons->state == SI_ST_EST && s->rep->cons->conn.target.type != TARG_TYPE_APPLET)
Willy Tarreau73b013b2012-05-21 16:31:45 +02002237 si_update(s->rep->cons);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002238
Willy Tarreau3cefd522012-08-30 15:49:18 +02002239 if (s->req->cons->state == SI_ST_EST && s->req->cons->conn.target.type != TARG_TYPE_APPLET)
Willy Tarreau73b013b2012-05-21 16:31:45 +02002240 si_update(s->req->cons);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002241
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002242 s->req->flags &= ~(CF_READ_NULL|CF_READ_PARTIAL|CF_WRITE_NULL|CF_WRITE_PARTIAL|CF_READ_ATTACHED);
2243 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 +01002244 s->si[0].prev_state = s->si[0].state;
2245 s->si[1].prev_state = s->si[1].state;
Willy Tarreaub0ef7352008-12-14 13:26:20 +01002246 s->si[0].flags &= ~(SI_FL_ERR|SI_FL_EXP);
2247 s->si[1].flags &= ~(SI_FL_ERR|SI_FL_EXP);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002248
2249 /* Trick: if a request is being waiting for the server to respond,
2250 * and if we know the server can timeout, we don't want the timeout
2251 * to expire on the client side first, but we're still interested
2252 * in passing data from the client to the server (eg: POST). Thus,
2253 * we can cancel the client's request timeout if the server's
2254 * request timeout is set and the server has not yet sent a response.
2255 */
2256
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002257 if ((s->rep->flags & (CF_AUTO_CLOSE|CF_SHUTR)) == 0 &&
Willy Tarreau86491c32008-12-14 09:04:47 +01002258 (tick_isset(s->req->wex) || tick_isset(s->rep->rex))) {
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002259 s->req->flags |= CF_READ_NOEXP;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002260 s->req->rex = TICK_ETERNITY;
Willy Tarreau86491c32008-12-14 09:04:47 +01002261 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002262
Willy Tarreau7a20aa62010-07-13 16:30:45 +02002263 /* Call the stream interfaces' I/O handlers when embedded.
Willy Tarreau1accfc02009-09-05 20:57:35 +02002264 * Note that this one may wake the task up again.
2265 */
Willy Tarreau3cefd522012-08-30 15:49:18 +02002266 if (s->req->cons->conn.target.type == TARG_TYPE_APPLET ||
2267 s->rep->cons->conn.target.type == TARG_TYPE_APPLET) {
2268 if (s->req->cons->conn.target.type == TARG_TYPE_APPLET)
2269 s->req->cons->conn.target.ptr.a->fct(s->req->cons);
2270 if (s->rep->cons->conn.target.type == TARG_TYPE_APPLET)
2271 s->rep->cons->conn.target.ptr.a->fct(s->rep->cons);
Willy Tarreau1accfc02009-09-05 20:57:35 +02002272 if (task_in_rq(t)) {
2273 /* If we woke up, we don't want to requeue the
2274 * task to the wait queue, but rather requeue
2275 * it into the runqueue ASAP.
2276 */
2277 t->expire = TICK_ETERNITY;
2278 return t;
2279 }
2280 }
2281
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002282 t->expire = tick_first(tick_first(s->req->rex, s->req->wex),
2283 tick_first(s->rep->rex, s->rep->wex));
2284 if (s->req->analysers)
2285 t->expire = tick_first(t->expire, s->req->analyse_exp);
2286
2287 if (s->si[0].exp)
2288 t->expire = tick_first(t->expire, s->si[0].exp);
2289
2290 if (s->si[1].exp)
2291 t->expire = tick_first(t->expire, s->si[1].exp);
2292
2293#ifdef DEBUG_FULL
Willy Tarreau127334e2009-03-28 10:47:26 +01002294 fprintf(stderr,
2295 "[%u] queuing with exp=%u req->rex=%u req->wex=%u req->ana_exp=%u"
2296 " rep->rex=%u rep->wex=%u, si[0].exp=%u, si[1].exp=%u, cs=%d, ss=%d\n",
2297 now_ms, t->expire, s->req->rex, s->req->wex, s->req->analyse_exp,
2298 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 +01002299#endif
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002300
2301#ifdef DEBUG_DEV
2302 /* this may only happen when no timeout is set or in case of an FSM bug */
Willy Tarreaud0a201b2009-03-08 15:53:06 +01002303 if (!tick_isset(t->expire))
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002304 ABORT_NOW();
2305#endif
Willy Tarreau26c25062009-03-08 09:38:41 +01002306 return t; /* nothing more to do */
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002307 }
2308
2309 s->fe->feconn--;
2310 if (s->flags & SN_BE_ASSIGNED)
2311 s->be->beconn--;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02002312 if (!(s->listener->options & LI_O_UNLIMITED))
2313 actconn--;
Willy Tarreauaf7ad002010-08-31 15:39:26 +02002314 jobs--;
Willy Tarreau6e6fb2b2009-08-16 18:20:44 +02002315 s->listener->nbconn--;
Willy Tarreau62793712011-07-24 19:23:38 +02002316 if (s->listener->state == LI_FULL)
2317 resume_listener(s->listener);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002318
Willy Tarreau08ceb102011-07-24 22:58:00 +02002319 /* Dequeues all of the listeners waiting for a resource */
2320 if (!LIST_ISEMPTY(&global_listener_queue))
2321 dequeue_all_listeners(&global_listener_queue);
2322
Willy Tarreaub32907b2011-07-25 08:37:44 +02002323 if (!LIST_ISEMPTY(&s->fe->listener_queue) &&
2324 (!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 +02002325 dequeue_all_listeners(&s->fe->listener_queue);
2326
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002327 if (unlikely((global.mode & MODE_DEBUG) &&
2328 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)))) {
2329 int len;
Willy Tarreauec22b2c2009-03-06 13:07:40 +01002330 len = sprintf(trash, "%08x:%s.closed[%04x:%04x]\n",
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002331 s->uniq_id, s->be->id,
Willy Tarreaufb7508a2012-05-21 16:47:54 +02002332 (unsigned short)si_fd(s->req->prod), (unsigned short)si_fd(s->req->cons));
Willy Tarreau21337822012-04-29 14:11:38 +02002333 if (write(1, trash, len) < 0) /* shut gcc warning */;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002334 }
2335
2336 s->logs.t_close = tv_ms_elapsed(&s->logs.tv_accept, &now);
2337 session_process_counters(s);
2338
Krzysztof Piotr Oledzkide71d162009-10-24 15:36:15 +02002339 if (s->txn.status) {
2340 int n;
2341
2342 n = s->txn.status / 100;
2343 if (n < 1 || n > 5)
2344 n = 0;
2345
2346 if (s->fe->mode == PR_MODE_HTTP)
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01002347 s->fe->fe_counters.p.http.rsp[n]++;
Krzysztof Piotr Oledzkide71d162009-10-24 15:36:15 +02002348
Willy Tarreau24657792010-02-26 10:30:28 +01002349 if ((s->flags & SN_BE_ASSIGNED) &&
Krzysztof Piotr Oledzkide71d162009-10-24 15:36:15 +02002350 (s->be->mode == PR_MODE_HTTP))
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01002351 s->be->be_counters.p.http.rsp[n]++;
Krzysztof Piotr Oledzkide71d162009-10-24 15:36:15 +02002352 }
2353
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002354 /* let's do a final log if we need it */
2355 if (s->logs.logwait &&
2356 !(s->flags & SN_MONITOR) &&
2357 (!(s->fe->options & PR_O_NULLNOLOG) || s->req->total)) {
Willy Tarreaua5555ec2008-11-30 19:02:32 +01002358 s->do_log(s);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002359 }
2360
2361 /* the task MUST not be in the run queue anymore */
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002362 session_free(s);
Willy Tarreau26c25062009-03-08 09:38:41 +01002363 task_delete(t);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002364 task_free(t);
Willy Tarreau26c25062009-03-08 09:38:41 +01002365 return NULL;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002366}
2367
Willy Tarreau7c669d72008-06-20 15:04:11 +02002368/*
2369 * This function adjusts sess->srv_conn and maintains the previous and new
2370 * server's served session counts. Setting newsrv to NULL is enough to release
2371 * current connection slot. This function also notifies any LB algo which might
2372 * expect to be informed about any change in the number of active sessions on a
2373 * server.
2374 */
2375void sess_change_server(struct session *sess, struct server *newsrv)
2376{
2377 if (sess->srv_conn == newsrv)
2378 return;
2379
2380 if (sess->srv_conn) {
2381 sess->srv_conn->served--;
2382 if (sess->srv_conn->proxy->lbprm.server_drop_conn)
2383 sess->srv_conn->proxy->lbprm.server_drop_conn(sess->srv_conn);
Simon Hormanaf514952011-06-21 14:34:57 +09002384 session_del_srv_conn(sess);
Willy Tarreau7c669d72008-06-20 15:04:11 +02002385 }
2386
2387 if (newsrv) {
2388 newsrv->served++;
2389 if (newsrv->proxy->lbprm.server_take_conn)
2390 newsrv->proxy->lbprm.server_take_conn(newsrv);
Simon Hormanaf514952011-06-21 14:34:57 +09002391 session_add_srv_conn(sess, newsrv);
Willy Tarreau7c669d72008-06-20 15:04:11 +02002392 }
2393}
2394
Willy Tarreau84455332009-03-15 22:34:05 +01002395/* Handle server-side errors for default protocols. It is called whenever a a
2396 * connection setup is aborted or a request is aborted in queue. It sets the
2397 * session termination flags so that the caller does not have to worry about
2398 * them. It's installed as ->srv_error for the server-side stream_interface.
2399 */
2400void default_srv_error(struct session *s, struct stream_interface *si)
2401{
2402 int err_type = si->err_type;
2403 int err = 0, fin = 0;
2404
2405 if (err_type & SI_ET_QUEUE_ABRT) {
2406 err = SN_ERR_CLICL;
2407 fin = SN_FINST_Q;
2408 }
2409 else if (err_type & SI_ET_CONN_ABRT) {
2410 err = SN_ERR_CLICL;
2411 fin = SN_FINST_C;
2412 }
2413 else if (err_type & SI_ET_QUEUE_TO) {
2414 err = SN_ERR_SRVTO;
2415 fin = SN_FINST_Q;
2416 }
2417 else if (err_type & SI_ET_QUEUE_ERR) {
2418 err = SN_ERR_SRVCL;
2419 fin = SN_FINST_Q;
2420 }
2421 else if (err_type & SI_ET_CONN_TO) {
2422 err = SN_ERR_SRVTO;
2423 fin = SN_FINST_C;
2424 }
2425 else if (err_type & SI_ET_CONN_ERR) {
2426 err = SN_ERR_SRVCL;
2427 fin = SN_FINST_C;
2428 }
2429 else /* SI_ET_CONN_OTHER and others */ {
2430 err = SN_ERR_INTERNAL;
2431 fin = SN_FINST_C;
2432 }
2433
2434 if (!(s->flags & SN_ERR_MASK))
2435 s->flags |= err;
2436 if (!(s->flags & SN_FINST_MASK))
2437 s->flags |= fin;
2438}
Willy Tarreau7c669d72008-06-20 15:04:11 +02002439
Willy Tarreaua2a64e92011-09-07 23:01:56 +02002440/* kill a session and set the termination flags to <why> (one of SN_ERR_*) */
2441void session_shutdown(struct session *session, int why)
2442{
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002443 if (session->req->flags & (CF_SHUTW|CF_SHUTW_NOW))
Willy Tarreaua2a64e92011-09-07 23:01:56 +02002444 return;
2445
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002446 channel_shutw_now(session->req);
2447 channel_shutr_now(session->rep);
Willy Tarreaua2a64e92011-09-07 23:01:56 +02002448 session->task->nice = 1024;
2449 if (!(session->flags & SN_ERR_MASK))
2450 session->flags |= why;
2451 task_wakeup(session->task, TASK_WOKEN_OTHER);
2452}
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02002453
Willy Tarreau8b22a712010-06-18 17:46:06 +02002454/************************************************************************/
2455/* All supported ACL keywords must be declared here. */
2456/************************************************************************/
2457
Willy Tarreaua5e37562011-12-16 17:06:15 +01002458/* set temp integer to the General Purpose Counter 0 value in the stksess entry <ts> */
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002459static int
Willy Tarreau37406352012-04-23 16:16:37 +02002460acl_fetch_get_gpc0(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002461{
Willy Tarreau37406352012-04-23 16:16:37 +02002462 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002463 smp->type = SMP_T_UINT;
2464 smp->data.uint = 0;
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002465 if (ts != NULL) {
2466 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_GPC0);
2467 if (!ptr)
2468 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002469 smp->data.uint = stktable_data_cast(ptr, gpc0);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002470 }
2471 return 1;
2472}
2473
Willy Tarreaua5e37562011-12-16 17:06:15 +01002474/* set temp integer to the General Purpose Counter 0 value from the session's tracked
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002475 * frontend counters.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002476 */
2477static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002478acl_fetch_sc1_get_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002479 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002480{
Willy Tarreau56123282010-08-06 19:06:56 +02002481 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002482 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002483 return acl_fetch_get_gpc0(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002484}
2485
Willy Tarreaua5e37562011-12-16 17:06:15 +01002486/* set temp integer to the General Purpose Counter 0 value from the session's tracked
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002487 * backend counters.
2488 */
2489static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002490acl_fetch_sc2_get_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002491 const struct arg *args, struct sample *smp)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002492{
Willy Tarreau56123282010-08-06 19:06:56 +02002493 if (!l4->stkctr2_entry)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002494 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002495 return acl_fetch_get_gpc0(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002496}
2497
Willy Tarreaua5e37562011-12-16 17:06:15 +01002498/* set temp integer to the General Purpose Counter 0 value from the session's source
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002499 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002500 * Accepts exactly 1 argument of type table.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002501 */
2502static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002503acl_fetch_src_get_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002504 const struct arg *args, struct sample *smp)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002505{
2506 struct stktable_key *key;
2507
Willy Tarreau64ee4912012-08-30 22:59:48 +02002508 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002509 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002510 return 0;
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002511
Willy Tarreau24e32d82012-04-23 23:55:44 +02002512 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002513 return acl_fetch_get_gpc0(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002514}
2515
2516/* Increment the General Purpose Counter 0 value in the stksess entry <ts> and
Willy Tarreaua5e37562011-12-16 17:06:15 +01002517 * return it into temp integer.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002518 */
2519static int
Willy Tarreau37406352012-04-23 16:16:37 +02002520acl_fetch_inc_gpc0(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002521{
Willy Tarreau37406352012-04-23 16:16:37 +02002522 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002523 smp->type = SMP_T_UINT;
2524 smp->data.uint = 0;
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002525 if (ts != NULL) {
2526 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_GPC0);
2527 if (!ptr)
2528 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002529 smp->data.uint = ++stktable_data_cast(ptr, gpc0);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002530 }
2531 return 1;
2532}
2533
2534/* Increment the General Purpose Counter 0 value from the session's tracked
Willy Tarreaua5e37562011-12-16 17:06:15 +01002535 * frontend counters and return it into temp integer.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002536 */
2537static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002538acl_fetch_sc1_inc_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002539 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002540{
Willy Tarreau56123282010-08-06 19:06:56 +02002541 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002542 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002543 return acl_fetch_inc_gpc0(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002544}
2545
2546/* Increment the General Purpose Counter 0 value from the session's tracked
Willy Tarreaua5e37562011-12-16 17:06:15 +01002547 * backend counters and return it into temp integer.
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002548 */
2549static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002550acl_fetch_sc2_inc_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002551 const struct arg *args, struct sample *smp)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002552{
Willy Tarreau56123282010-08-06 19:06:56 +02002553 if (!l4->stkctr2_entry)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002554 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002555 return acl_fetch_inc_gpc0(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002556}
2557
2558/* Increment the General Purpose Counter 0 value from the session's source
Willy Tarreaua5e37562011-12-16 17:06:15 +01002559 * address in the table pointed to by expr, and return it into temp integer.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002560 * Accepts exactly 1 argument of type table.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002561 */
2562static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002563acl_fetch_src_inc_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002564 const struct arg *args, struct sample *smp)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002565{
2566 struct stktable_key *key;
2567
Willy Tarreau64ee4912012-08-30 22:59:48 +02002568 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002569 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002570 return 0;
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002571
Willy Tarreau24e32d82012-04-23 23:55:44 +02002572 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002573 return acl_fetch_inc_gpc0(&px->table, smp, stktable_update_key(&px->table, key));
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002574}
2575
Willy Tarreauf73cd112011-08-13 01:45:16 +02002576/* Clear the General Purpose Counter 0 value in the stksess entry <ts> and
Willy Tarreaua5e37562011-12-16 17:06:15 +01002577 * return its previous value into temp integer.
Willy Tarreauf73cd112011-08-13 01:45:16 +02002578 */
2579static int
Willy Tarreau37406352012-04-23 16:16:37 +02002580acl_fetch_clr_gpc0(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauf73cd112011-08-13 01:45:16 +02002581{
Willy Tarreau37406352012-04-23 16:16:37 +02002582 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002583 smp->type = SMP_T_UINT;
2584 smp->data.uint = 0;
Willy Tarreauf73cd112011-08-13 01:45:16 +02002585 if (ts != NULL) {
2586 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_GPC0);
2587 if (!ptr)
2588 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002589 smp->data.uint = stktable_data_cast(ptr, gpc0);
Willy Tarreauf73cd112011-08-13 01:45:16 +02002590 stktable_data_cast(ptr, gpc0) = 0;
2591 }
2592 return 1;
2593}
2594
2595/* Clear the General Purpose Counter 0 value from the session's tracked
Willy Tarreaua5e37562011-12-16 17:06:15 +01002596 * frontend counters and return its previous value into temp integer.
Willy Tarreauf73cd112011-08-13 01:45:16 +02002597 */
2598static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002599acl_fetch_sc1_clr_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002600 const struct arg *args, struct sample *smp)
Willy Tarreauf73cd112011-08-13 01:45:16 +02002601{
2602 if (!l4->stkctr1_entry)
2603 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002604 return acl_fetch_clr_gpc0(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf73cd112011-08-13 01:45:16 +02002605}
2606
2607/* Clear the General Purpose Counter 0 value from the session's tracked
Willy Tarreaua5e37562011-12-16 17:06:15 +01002608 * backend counters and return its previous value into temp integer.
Willy Tarreauf73cd112011-08-13 01:45:16 +02002609 */
2610static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002611acl_fetch_sc2_clr_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002612 const struct arg *args, struct sample *smp)
Willy Tarreauf73cd112011-08-13 01:45:16 +02002613{
2614 if (!l4->stkctr2_entry)
2615 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002616 return acl_fetch_clr_gpc0(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauf73cd112011-08-13 01:45:16 +02002617}
2618
2619/* Clear the General Purpose Counter 0 value from the session's source address
Willy Tarreaua5e37562011-12-16 17:06:15 +01002620 * in the table pointed to by expr, and return its previous value into temp integer.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002621 * Accepts exactly 1 argument of type table.
Willy Tarreauf73cd112011-08-13 01:45:16 +02002622 */
2623static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002624acl_fetch_src_clr_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002625 const struct arg *args, struct sample *smp)
Willy Tarreauf73cd112011-08-13 01:45:16 +02002626{
2627 struct stktable_key *key;
2628
Willy Tarreau64ee4912012-08-30 22:59:48 +02002629 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauf73cd112011-08-13 01:45:16 +02002630 if (!key)
2631 return 0;
2632
Willy Tarreau24e32d82012-04-23 23:55:44 +02002633 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002634 return acl_fetch_clr_gpc0(&px->table, smp, stktable_update_key(&px->table, key));
Willy Tarreauf73cd112011-08-13 01:45:16 +02002635}
2636
Willy Tarreaua5e37562011-12-16 17:06:15 +01002637/* set temp integer to the cumulated number of connections in the stksess entry <ts> */
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002638static int
Willy Tarreau37406352012-04-23 16:16:37 +02002639acl_fetch_conn_cnt(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002640{
Willy Tarreau37406352012-04-23 16:16:37 +02002641 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002642 smp->type = SMP_T_UINT;
2643 smp->data.uint = 0;
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002644 if (ts != NULL) {
2645 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_CONN_CNT);
2646 if (!ptr)
2647 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002648 smp->data.uint = stktable_data_cast(ptr, conn_cnt);
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002649 }
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002650 return 1;
2651}
2652
Willy Tarreaua5e37562011-12-16 17:06:15 +01002653/* set temp integer to the cumulated number of connections from the session's tracked FE counters */
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002654static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002655acl_fetch_sc1_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002656 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002657{
Willy Tarreau56123282010-08-06 19:06:56 +02002658 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002659 return 0;
2660
Willy Tarreau37406352012-04-23 16:16:37 +02002661 return acl_fetch_conn_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002662}
2663
Willy Tarreaua5e37562011-12-16 17:06:15 +01002664/* set temp integer to the cumulated number of connections from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002665static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002666acl_fetch_sc2_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002667 const struct arg *args, struct sample *smp)
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002668{
Willy Tarreau56123282010-08-06 19:06:56 +02002669 if (!l4->stkctr2_entry)
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002670 return 0;
2671
Willy Tarreau37406352012-04-23 16:16:37 +02002672 return acl_fetch_conn_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002673}
2674
Willy Tarreaua5e37562011-12-16 17:06:15 +01002675/* set temp integer to the cumulated number of connections from the session's source
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002676 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002677 * Accepts exactly 1 argument of type table.
Willy Tarreau8b22a712010-06-18 17:46:06 +02002678 */
2679static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002680acl_fetch_src_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002681 const struct arg *args, struct sample *smp)
Willy Tarreau8b22a712010-06-18 17:46:06 +02002682{
Willy Tarreau8b22a712010-06-18 17:46:06 +02002683 struct stktable_key *key;
2684
Willy Tarreau64ee4912012-08-30 22:59:48 +02002685 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau8b22a712010-06-18 17:46:06 +02002686 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002687 return 0;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002688
Willy Tarreau24e32d82012-04-23 23:55:44 +02002689 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002690 return acl_fetch_conn_cnt(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau8b22a712010-06-18 17:46:06 +02002691}
2692
Willy Tarreaua5e37562011-12-16 17:06:15 +01002693/* set temp integer to the connection rate in the stksess entry <ts> over the configured period */
Willy Tarreau91c43d72010-06-20 11:19:22 +02002694static int
Willy Tarreau37406352012-04-23 16:16:37 +02002695acl_fetch_conn_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002696{
Willy Tarreau37406352012-04-23 16:16:37 +02002697 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002698 smp->type = SMP_T_UINT;
2699 smp->data.uint = 0;
Willy Tarreau91c43d72010-06-20 11:19:22 +02002700 if (ts != NULL) {
2701 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_CONN_RATE);
2702 if (!ptr)
2703 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002704 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, conn_rate),
Willy Tarreau91c43d72010-06-20 11:19:22 +02002705 table->data_arg[STKTABLE_DT_CONN_RATE].u);
2706 }
2707 return 1;
2708}
2709
Willy Tarreaua5e37562011-12-16 17:06:15 +01002710/* set temp integer to the connection rate from the session's tracked FE counters over
Willy Tarreau91c43d72010-06-20 11:19:22 +02002711 * the configured period.
2712 */
2713static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002714acl_fetch_sc1_conn_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002715 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002716{
Willy Tarreau56123282010-08-06 19:06:56 +02002717 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002718 return 0;
2719
Willy Tarreau37406352012-04-23 16:16:37 +02002720 return acl_fetch_conn_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002721}
2722
Willy Tarreaua5e37562011-12-16 17:06:15 +01002723/* set temp integer to the connection rate from the session's tracked BE counters over
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002724 * the configured period.
2725 */
2726static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002727acl_fetch_sc2_conn_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002728 const struct arg *args, struct sample *smp)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002729{
Willy Tarreau56123282010-08-06 19:06:56 +02002730 if (!l4->stkctr2_entry)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002731 return 0;
2732
Willy Tarreau37406352012-04-23 16:16:37 +02002733 return acl_fetch_conn_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau91c43d72010-06-20 11:19:22 +02002734}
2735
Willy Tarreaua5e37562011-12-16 17:06:15 +01002736/* set temp integer to the connection rate from the session's source address in the
Willy Tarreau91c43d72010-06-20 11:19:22 +02002737 * table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002738 * Accepts exactly 1 argument of type table.
Willy Tarreau91c43d72010-06-20 11:19:22 +02002739 */
2740static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002741acl_fetch_src_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 Tarreau91c43d72010-06-20 11:19:22 +02002743{
2744 struct stktable_key *key;
2745
Willy Tarreau64ee4912012-08-30 22:59:48 +02002746 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau91c43d72010-06-20 11:19:22 +02002747 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002748 return 0;
Willy Tarreau91c43d72010-06-20 11:19:22 +02002749
Willy Tarreau24e32d82012-04-23 23:55:44 +02002750 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002751 return acl_fetch_conn_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau91c43d72010-06-20 11:19:22 +02002752}
2753
Willy Tarreaua5e37562011-12-16 17:06:15 +01002754/* set temp integer to the number of connections from the session's source address
Willy Tarreau8b22a712010-06-18 17:46:06 +02002755 * in the table pointed to by expr, after updating it.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002756 * Accepts exactly 1 argument of type table.
Willy Tarreau8b22a712010-06-18 17:46:06 +02002757 */
2758static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002759acl_fetch_src_updt_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002760 const struct arg *args, struct sample *smp)
Willy Tarreau8b22a712010-06-18 17:46:06 +02002761{
2762 struct stksess *ts;
2763 struct stktable_key *key;
2764 void *ptr;
2765
Willy Tarreau64ee4912012-08-30 22:59:48 +02002766 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau8b22a712010-06-18 17:46:06 +02002767 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002768 return 0;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002769
Willy Tarreau24e32d82012-04-23 23:55:44 +02002770 px = args->data.prx;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002771
Willy Tarreau1f7e9252010-06-20 12:27:21 +02002772 if ((ts = stktable_update_key(&px->table, key)) == NULL)
2773 /* entry does not exist and could not be created */
2774 return 0;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002775
2776 ptr = stktable_data_ptr(&px->table, ts, STKTABLE_DT_CONN_CNT);
2777 if (!ptr)
2778 return 0; /* parameter not stored in this table */
2779
Willy Tarreauf853c462012-04-23 18:53:56 +02002780 smp->type = SMP_T_UINT;
2781 smp->data.uint = ++stktable_data_cast(ptr, conn_cnt);
Willy Tarreau37406352012-04-23 16:16:37 +02002782 smp->flags = SMP_F_VOL_TEST;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002783 return 1;
2784}
2785
Willy Tarreaua5e37562011-12-16 17:06:15 +01002786/* set temp integer to the number of concurrent connections in the stksess entry <ts> */
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002787static int
Willy Tarreau37406352012-04-23 16:16:37 +02002788acl_fetch_conn_cur(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002789{
Willy Tarreau37406352012-04-23 16:16:37 +02002790 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002791 smp->type = SMP_T_UINT;
2792 smp->data.uint = 0;
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002793
2794 if (ts != NULL) {
2795 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_CONN_CUR);
2796 if (!ptr)
2797 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002798 smp->data.uint = stktable_data_cast(ptr, conn_cur);
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002799 }
2800 return 1;
2801}
2802
Willy Tarreaua5e37562011-12-16 17:06:15 +01002803/* set temp integer to the number of concurrent connections from the session's tracked FE counters */
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002804static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002805acl_fetch_sc1_conn_cur(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002806 const struct arg *args, struct sample *smp)
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002807{
Willy Tarreau56123282010-08-06 19:06:56 +02002808 if (!l4->stkctr1_entry)
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002809 return 0;
2810
Willy Tarreau37406352012-04-23 16:16:37 +02002811 return acl_fetch_conn_cur(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002812}
2813
Willy Tarreaua5e37562011-12-16 17:06:15 +01002814/* set temp integer to the number of concurrent connections from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002815static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002816acl_fetch_sc2_conn_cur(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002817 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002818{
Willy Tarreau56123282010-08-06 19:06:56 +02002819 if (!l4->stkctr2_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002820 return 0;
2821
Willy Tarreau37406352012-04-23 16:16:37 +02002822 return acl_fetch_conn_cur(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002823}
2824
Willy Tarreaua5e37562011-12-16 17:06:15 +01002825/* set temp integer to the number of concurrent connections from the session's source
Willy Tarreau38285c12010-06-18 16:35:43 +02002826 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002827 * Accepts exactly 1 argument of type table.
Willy Tarreau38285c12010-06-18 16:35:43 +02002828 */
2829static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002830acl_fetch_src_conn_cur(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002831 const struct arg *args, struct sample *smp)
Willy Tarreau38285c12010-06-18 16:35:43 +02002832{
Willy Tarreau38285c12010-06-18 16:35:43 +02002833 struct stktable_key *key;
2834
Willy Tarreau64ee4912012-08-30 22:59:48 +02002835 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau38285c12010-06-18 16:35:43 +02002836 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002837 return 0;
Willy Tarreau38285c12010-06-18 16:35:43 +02002838
Willy Tarreau24e32d82012-04-23 23:55:44 +02002839 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002840 return acl_fetch_conn_cur(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau38285c12010-06-18 16:35:43 +02002841}
2842
Willy Tarreaua5e37562011-12-16 17:06:15 +01002843/* set temp integer to the cumulated number of sessions in the stksess entry <ts> */
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002844static int
Willy Tarreau37406352012-04-23 16:16:37 +02002845acl_fetch_sess_cnt(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002846{
Willy Tarreau37406352012-04-23 16:16:37 +02002847 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002848 smp->type = SMP_T_UINT;
2849 smp->data.uint = 0;
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002850 if (ts != NULL) {
2851 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_SESS_CNT);
2852 if (!ptr)
2853 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002854 smp->data.uint = stktable_data_cast(ptr, sess_cnt);
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002855 }
2856 return 1;
2857}
2858
Willy Tarreaua5e37562011-12-16 17:06:15 +01002859/* set temp integer to the cumulated number of sessions from the session's tracked FE counters */
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002860static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002861acl_fetch_sc1_sess_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002862 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002863{
Willy Tarreau56123282010-08-06 19:06:56 +02002864 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002865 return 0;
2866
Willy Tarreau37406352012-04-23 16:16:37 +02002867 return acl_fetch_sess_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002868}
2869
Willy Tarreaua5e37562011-12-16 17:06:15 +01002870/* set temp integer to the cumulated number of sessions from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002871static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002872acl_fetch_sc2_sess_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002873 const struct arg *args, struct sample *smp)
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002874{
Willy Tarreau56123282010-08-06 19:06:56 +02002875 if (!l4->stkctr2_entry)
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002876 return 0;
2877
Willy Tarreau37406352012-04-23 16:16:37 +02002878 return acl_fetch_sess_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002879}
2880
Willy Tarreaua5e37562011-12-16 17:06:15 +01002881/* set temp integer to the cumulated number of session from the session's source
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002882 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002883 * Accepts exactly 1 argument of type table.
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002884 */
2885static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002886acl_fetch_src_sess_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002887 const struct arg *args, struct sample *smp)
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002888{
2889 struct stktable_key *key;
2890
Willy Tarreau64ee4912012-08-30 22:59:48 +02002891 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002892 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002893 return 0;
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002894
Willy Tarreau24e32d82012-04-23 23:55:44 +02002895 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002896 return acl_fetch_sess_cnt(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002897}
2898
Willy Tarreaua5e37562011-12-16 17:06:15 +01002899/* set temp integer to the session rate in the stksess entry <ts> over the configured period */
Willy Tarreau91c43d72010-06-20 11:19:22 +02002900static int
Willy Tarreau37406352012-04-23 16:16:37 +02002901acl_fetch_sess_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002902{
Willy Tarreau37406352012-04-23 16:16:37 +02002903 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002904 smp->type = SMP_T_UINT;
2905 smp->data.uint = 0;
Willy Tarreau91c43d72010-06-20 11:19:22 +02002906 if (ts != NULL) {
2907 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_SESS_RATE);
2908 if (!ptr)
2909 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002910 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, sess_rate),
Willy Tarreau91c43d72010-06-20 11:19:22 +02002911 table->data_arg[STKTABLE_DT_SESS_RATE].u);
2912 }
2913 return 1;
2914}
2915
Willy Tarreaua5e37562011-12-16 17:06:15 +01002916/* set temp integer to the session rate from the session's tracked FE counters over
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002917 * the configured period.
2918 */
2919static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002920acl_fetch_sc1_sess_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002921 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002922{
Willy Tarreau56123282010-08-06 19:06:56 +02002923 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002924 return 0;
2925
Willy Tarreau37406352012-04-23 16:16:37 +02002926 return acl_fetch_sess_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002927}
2928
Willy Tarreaua5e37562011-12-16 17:06:15 +01002929/* set temp integer to the session rate from the session's tracked BE counters over
Willy Tarreau91c43d72010-06-20 11:19:22 +02002930 * the configured period.
2931 */
2932static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002933acl_fetch_sc2_sess_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002934 const struct arg *args, struct sample *smp)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002935{
Willy Tarreau56123282010-08-06 19:06:56 +02002936 if (!l4->stkctr2_entry)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002937 return 0;
2938
Willy Tarreau37406352012-04-23 16:16:37 +02002939 return acl_fetch_sess_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau91c43d72010-06-20 11:19:22 +02002940}
2941
Willy Tarreaua5e37562011-12-16 17:06:15 +01002942/* set temp integer to the session rate from the session's source address in the
Willy Tarreau91c43d72010-06-20 11:19:22 +02002943 * table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002944 * Accepts exactly 1 argument of type table.
Willy Tarreau91c43d72010-06-20 11:19:22 +02002945 */
2946static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002947acl_fetch_src_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 Tarreau91c43d72010-06-20 11:19:22 +02002949{
2950 struct stktable_key *key;
2951
Willy Tarreau64ee4912012-08-30 22:59:48 +02002952 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau91c43d72010-06-20 11:19:22 +02002953 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002954 return 0;
Willy Tarreau91c43d72010-06-20 11:19:22 +02002955
Willy Tarreau24e32d82012-04-23 23:55:44 +02002956 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002957 return acl_fetch_sess_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau91c43d72010-06-20 11:19:22 +02002958}
2959
Willy Tarreaua5e37562011-12-16 17:06:15 +01002960/* set temp integer to the cumulated number of sessions in the stksess entry <ts> */
Willy Tarreauda7ff642010-06-23 11:44:09 +02002961static int
Willy Tarreau37406352012-04-23 16:16:37 +02002962acl_fetch_http_req_cnt(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauda7ff642010-06-23 11:44:09 +02002963{
Willy Tarreau37406352012-04-23 16:16:37 +02002964 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002965 smp->type = SMP_T_UINT;
2966 smp->data.uint = 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02002967 if (ts != NULL) {
2968 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_HTTP_REQ_CNT);
2969 if (!ptr)
2970 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002971 smp->data.uint = stktable_data_cast(ptr, http_req_cnt);
Willy Tarreauda7ff642010-06-23 11:44:09 +02002972 }
2973 return 1;
2974}
2975
Willy Tarreaua5e37562011-12-16 17:06:15 +01002976/* set temp integer to the cumulated number of sessions from the session's tracked FE counters */
Willy Tarreauda7ff642010-06-23 11:44:09 +02002977static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002978acl_fetch_sc1_http_req_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002979 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002980{
Willy Tarreau56123282010-08-06 19:06:56 +02002981 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002982 return 0;
2983
Willy Tarreau37406352012-04-23 16:16:37 +02002984 return acl_fetch_http_req_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002985}
2986
Willy Tarreaua5e37562011-12-16 17:06:15 +01002987/* set temp integer to the cumulated number of sessions from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002988static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002989acl_fetch_sc2_http_req_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002990 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02002991{
Willy Tarreau56123282010-08-06 19:06:56 +02002992 if (!l4->stkctr2_entry)
Willy Tarreauda7ff642010-06-23 11:44:09 +02002993 return 0;
2994
Willy Tarreau37406352012-04-23 16:16:37 +02002995 return acl_fetch_http_req_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauda7ff642010-06-23 11:44:09 +02002996}
2997
Willy Tarreaua5e37562011-12-16 17:06:15 +01002998/* set temp integer to the cumulated number of session from the session's source
Willy Tarreauda7ff642010-06-23 11:44:09 +02002999 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003000 * Accepts exactly 1 argument of type table.
Willy Tarreauda7ff642010-06-23 11:44:09 +02003001 */
3002static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003003acl_fetch_src_http_req_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003004 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003005{
3006 struct stktable_key *key;
3007
Willy Tarreau64ee4912012-08-30 22:59:48 +02003008 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003009 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003010 return 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003011
Willy Tarreau24e32d82012-04-23 23:55:44 +02003012 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003013 return acl_fetch_http_req_cnt(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauda7ff642010-06-23 11:44:09 +02003014}
3015
Willy Tarreaua5e37562011-12-16 17:06:15 +01003016/* set temp integer to the session rate in the stksess entry <ts> over the configured period */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003017static int
Willy Tarreau37406352012-04-23 16:16:37 +02003018acl_fetch_http_req_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003019{
Willy Tarreau37406352012-04-23 16:16:37 +02003020 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003021 smp->type = SMP_T_UINT;
3022 smp->data.uint = 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003023 if (ts != NULL) {
3024 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_HTTP_REQ_RATE);
3025 if (!ptr)
3026 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003027 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, http_req_rate),
Willy Tarreauda7ff642010-06-23 11:44:09 +02003028 table->data_arg[STKTABLE_DT_HTTP_REQ_RATE].u);
3029 }
3030 return 1;
3031}
3032
Willy Tarreaua5e37562011-12-16 17:06:15 +01003033/* set temp integer to the session rate from the session's tracked FE counters over
Willy Tarreauda7ff642010-06-23 11:44:09 +02003034 * the configured period.
3035 */
3036static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003037acl_fetch_sc1_http_req_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003038 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003039{
Willy Tarreau56123282010-08-06 19:06:56 +02003040 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003041 return 0;
3042
Willy Tarreau37406352012-04-23 16:16:37 +02003043 return acl_fetch_http_req_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003044}
3045
Willy Tarreaua5e37562011-12-16 17:06:15 +01003046/* set temp integer to the session rate from the session's tracked BE counters over
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003047 * the configured period.
3048 */
3049static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003050acl_fetch_sc2_http_req_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003051 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003052{
Willy Tarreau56123282010-08-06 19:06:56 +02003053 if (!l4->stkctr2_entry)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003054 return 0;
3055
Willy Tarreau37406352012-04-23 16:16:37 +02003056 return acl_fetch_http_req_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003057}
3058
Willy Tarreaua5e37562011-12-16 17:06:15 +01003059/* set temp integer to the session rate from the session's source address in the
Willy Tarreauda7ff642010-06-23 11:44:09 +02003060 * table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003061 * Accepts exactly 1 argument of type table.
Willy Tarreauda7ff642010-06-23 11:44:09 +02003062 */
3063static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003064acl_fetch_src_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 Tarreauda7ff642010-06-23 11:44:09 +02003066{
3067 struct stktable_key *key;
3068
Willy Tarreau64ee4912012-08-30 22:59:48 +02003069 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003070 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003071 return 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003072
Willy Tarreau24e32d82012-04-23 23:55:44 +02003073 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003074 return acl_fetch_http_req_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauda7ff642010-06-23 11:44:09 +02003075}
3076
Willy Tarreaua5e37562011-12-16 17:06:15 +01003077/* set temp integer to the cumulated number of sessions in the stksess entry <ts> */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003078static int
Willy Tarreau37406352012-04-23 16:16:37 +02003079acl_fetch_http_err_cnt(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003080{
Willy Tarreau37406352012-04-23 16:16:37 +02003081 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003082 smp->type = SMP_T_UINT;
3083 smp->data.uint = 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003084 if (ts != NULL) {
3085 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_HTTP_ERR_CNT);
3086 if (!ptr)
3087 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003088 smp->data.uint = stktable_data_cast(ptr, http_err_cnt);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003089 }
3090 return 1;
3091}
3092
Willy Tarreaua5e37562011-12-16 17:06:15 +01003093/* set temp integer to the cumulated number of sessions from the session's tracked FE counters */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003094static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003095acl_fetch_sc1_http_err_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003096 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003097{
Willy Tarreau56123282010-08-06 19:06:56 +02003098 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003099 return 0;
3100
Willy Tarreau37406352012-04-23 16:16:37 +02003101 return acl_fetch_http_err_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003102}
3103
Willy Tarreaua5e37562011-12-16 17:06:15 +01003104/* set temp integer to the cumulated number of sessions from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003105static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003106acl_fetch_sc2_http_err_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003107 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003108{
Willy Tarreau56123282010-08-06 19:06:56 +02003109 if (!l4->stkctr2_entry)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003110 return 0;
3111
Willy Tarreau37406352012-04-23 16:16:37 +02003112 return acl_fetch_http_err_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003113}
3114
Willy Tarreaua5e37562011-12-16 17:06:15 +01003115/* set temp integer to the cumulated number of session from the session's source
Willy Tarreauda7ff642010-06-23 11:44:09 +02003116 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003117 * Accepts exactly 1 argument of type table.
Willy Tarreauda7ff642010-06-23 11:44:09 +02003118 */
3119static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003120acl_fetch_src_http_err_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003121 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003122{
3123 struct stktable_key *key;
3124
Willy Tarreau64ee4912012-08-30 22:59:48 +02003125 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003126 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003127 return 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003128
Willy Tarreau24e32d82012-04-23 23:55:44 +02003129 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003130 return acl_fetch_http_err_cnt(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauda7ff642010-06-23 11:44:09 +02003131}
3132
Willy Tarreaua5e37562011-12-16 17:06:15 +01003133/* set temp integer to the session rate in the stksess entry <ts> over the configured period */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003134static int
Willy Tarreau37406352012-04-23 16:16:37 +02003135acl_fetch_http_err_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003136{
Willy Tarreau37406352012-04-23 16:16:37 +02003137 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003138 smp->type = SMP_T_UINT;
3139 smp->data.uint = 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003140 if (ts != NULL) {
3141 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_HTTP_ERR_RATE);
3142 if (!ptr)
3143 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003144 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, http_err_rate),
Willy Tarreauda7ff642010-06-23 11:44:09 +02003145 table->data_arg[STKTABLE_DT_HTTP_ERR_RATE].u);
3146 }
3147 return 1;
3148}
3149
Willy Tarreaua5e37562011-12-16 17:06:15 +01003150/* set temp integer to the session rate from the session's tracked FE counters over
Willy Tarreauda7ff642010-06-23 11:44:09 +02003151 * the configured period.
3152 */
3153static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003154acl_fetch_sc1_http_err_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003155 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003156{
Willy Tarreau56123282010-08-06 19:06:56 +02003157 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003158 return 0;
3159
Willy Tarreau37406352012-04-23 16:16:37 +02003160 return acl_fetch_http_err_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003161}
3162
Willy Tarreaua5e37562011-12-16 17:06:15 +01003163/* set temp integer to the session rate from the session's tracked BE counters over
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003164 * the configured period.
3165 */
3166static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003167acl_fetch_sc2_http_err_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003168 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003169{
Willy Tarreau56123282010-08-06 19:06:56 +02003170 if (!l4->stkctr2_entry)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003171 return 0;
3172
Willy Tarreau37406352012-04-23 16:16:37 +02003173 return acl_fetch_http_err_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003174}
3175
Willy Tarreaua5e37562011-12-16 17:06:15 +01003176/* set temp integer to the session rate from the session's source address in the
Willy Tarreauda7ff642010-06-23 11:44:09 +02003177 * table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003178 * Accepts exactly 1 argument of type table.
Willy Tarreauda7ff642010-06-23 11:44:09 +02003179 */
3180static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003181acl_fetch_src_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 Tarreauda7ff642010-06-23 11:44:09 +02003183{
3184 struct stktable_key *key;
3185
Willy Tarreau64ee4912012-08-30 22:59:48 +02003186 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003187 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003188 return 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003189
Willy Tarreau24e32d82012-04-23 23:55:44 +02003190 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003191 return acl_fetch_http_err_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauda7ff642010-06-23 11:44:09 +02003192}
3193
Willy Tarreaua5e37562011-12-16 17:06:15 +01003194/* set temp integer to the number of kbytes received from clients matching the stksess entry <ts> */
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003195static int
Willy Tarreau37406352012-04-23 16:16:37 +02003196acl_fetch_kbytes_in(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003197{
Willy Tarreau37406352012-04-23 16:16:37 +02003198 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003199 smp->type = SMP_T_UINT;
3200 smp->data.uint = 0;
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003201
3202 if (ts != NULL) {
3203 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_BYTES_IN_CNT);
3204 if (!ptr)
3205 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003206 smp->data.uint = stktable_data_cast(ptr, bytes_in_cnt) >> 10;
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003207 }
3208 return 1;
3209}
3210
Willy Tarreaua5e37562011-12-16 17:06:15 +01003211/* set temp integer to the number of kbytes received from clients according to the
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003212 * session's tracked FE counters.
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003213 */
3214static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003215acl_fetch_sc1_kbytes_in(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003216 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003217{
Willy Tarreau56123282010-08-06 19:06:56 +02003218 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003219 return 0;
3220
Willy Tarreau37406352012-04-23 16:16:37 +02003221 return acl_fetch_kbytes_in(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003222}
3223
Willy Tarreaua5e37562011-12-16 17:06:15 +01003224/* set temp integer to the number of kbytes received from clients according to the
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003225 * session's tracked BE counters.
3226 */
3227static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003228acl_fetch_sc2_kbytes_in(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003229 const struct arg *args, struct sample *smp)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003230{
Willy Tarreau56123282010-08-06 19:06:56 +02003231 if (!l4->stkctr2_entry)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003232 return 0;
3233
Willy Tarreau37406352012-04-23 16:16:37 +02003234 return acl_fetch_kbytes_in(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003235}
3236
Willy Tarreaua5e37562011-12-16 17:06:15 +01003237/* set temp integer to the number of kbytes received from the session's source
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003238 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003239 * Accepts exactly 1 argument of type table.
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003240 */
3241static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003242acl_fetch_src_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 Tarreau855e4bb2010-06-18 18:33:32 +02003244{
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003245 struct stktable_key *key;
3246
Willy Tarreau64ee4912012-08-30 22:59:48 +02003247 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003248 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003249 return 0;
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003250
Willy Tarreau24e32d82012-04-23 23:55:44 +02003251 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003252 return acl_fetch_kbytes_in(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003253}
3254
Willy Tarreaua5e37562011-12-16 17:06:15 +01003255/* set temp integer to the bytes rate from clients in the stksess entry <ts> over the
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003256 * configured period.
3257 */
3258static int
Willy Tarreau37406352012-04-23 16:16:37 +02003259acl_fetch_bytes_in_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003260{
Willy Tarreau37406352012-04-23 16:16:37 +02003261 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003262 smp->type = SMP_T_UINT;
3263 smp->data.uint = 0;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003264 if (ts != NULL) {
3265 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_BYTES_IN_RATE);
3266 if (!ptr)
3267 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003268 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, bytes_in_rate),
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003269 table->data_arg[STKTABLE_DT_BYTES_IN_RATE].u);
3270 }
3271 return 1;
3272}
3273
Willy Tarreaua5e37562011-12-16 17:06:15 +01003274/* set temp integer to the bytes rate from clients from the session's tracked FE
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003275 * counters over the configured period.
3276 */
3277static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003278acl_fetch_sc1_bytes_in_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003279 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003280{
Willy Tarreau56123282010-08-06 19:06:56 +02003281 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003282 return 0;
3283
Willy Tarreau37406352012-04-23 16:16:37 +02003284 return acl_fetch_bytes_in_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003285}
3286
Willy Tarreaua5e37562011-12-16 17:06:15 +01003287/* set temp integer to the bytes rate from clients from the session's tracked BE
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003288 * counters over the configured period.
3289 */
3290static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003291acl_fetch_sc2_bytes_in_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003292 const struct arg *args, struct sample *smp)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003293{
Willy Tarreau56123282010-08-06 19:06:56 +02003294 if (!l4->stkctr2_entry)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003295 return 0;
3296
Willy Tarreau37406352012-04-23 16:16:37 +02003297 return acl_fetch_bytes_in_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003298}
3299
Willy Tarreaua5e37562011-12-16 17:06:15 +01003300/* set temp integer to the bytes rate from clients from the session's source address
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003301 * in the table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003302 * Accepts exactly 1 argument of type table.
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003303 */
3304static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003305acl_fetch_src_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 Tarreau6c59e0a2010-06-20 11:56:30 +02003307{
3308 struct stktable_key *key;
3309
Willy Tarreau64ee4912012-08-30 22:59:48 +02003310 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003311 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003312 return 0;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003313
Willy Tarreau24e32d82012-04-23 23:55:44 +02003314 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003315 return acl_fetch_bytes_in_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003316}
3317
Willy Tarreaua5e37562011-12-16 17:06:15 +01003318/* set temp integer to the number of kbytes sent to clients matching the stksess entry <ts> */
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003319static int
Willy Tarreau37406352012-04-23 16:16:37 +02003320acl_fetch_kbytes_out(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003321{
Willy Tarreau37406352012-04-23 16:16:37 +02003322 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003323 smp->type = SMP_T_UINT;
3324 smp->data.uint = 0;
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003325
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003326 if (ts != NULL) {
3327 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_BYTES_OUT_CNT);
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003328 if (!ptr)
3329 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003330 smp->data.uint = stktable_data_cast(ptr, bytes_out_cnt) >> 10;
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003331 }
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003332 return 1;
3333}
3334
Willy Tarreaua5e37562011-12-16 17:06:15 +01003335/* set temp integer to the number of kbytes sent to clients according to the session's
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003336 * tracked FE counters.
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003337 */
3338static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003339acl_fetch_sc1_kbytes_out(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003340 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003341{
Willy Tarreau56123282010-08-06 19:06:56 +02003342 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003343 return 0;
3344
Willy Tarreau37406352012-04-23 16:16:37 +02003345 return acl_fetch_kbytes_out(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003346}
3347
Willy Tarreaua5e37562011-12-16 17:06:15 +01003348/* set temp integer to the number of kbytes sent to clients according to the session's
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003349 * tracked BE counters.
3350 */
3351static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003352acl_fetch_sc2_kbytes_out(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003353 const struct arg *args, struct sample *smp)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003354{
Willy Tarreau56123282010-08-06 19:06:56 +02003355 if (!l4->stkctr2_entry)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003356 return 0;
3357
Willy Tarreau37406352012-04-23 16:16:37 +02003358 return acl_fetch_kbytes_out(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003359}
3360
Willy Tarreaua5e37562011-12-16 17:06:15 +01003361/* set temp integer to the number of kbytes sent to the session's source address in
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003362 * the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003363 * Accepts exactly 1 argument of type table.
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003364 */
3365static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003366acl_fetch_src_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 Tarreau855e4bb2010-06-18 18:33:32 +02003368{
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003369 struct stktable_key *key;
3370
Willy Tarreau64ee4912012-08-30 22:59:48 +02003371 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003372 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003373 return 0;
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003374
Willy Tarreau24e32d82012-04-23 23:55:44 +02003375 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003376 return acl_fetch_kbytes_out(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003377}
3378
Willy Tarreaua5e37562011-12-16 17:06:15 +01003379/* set temp integer to the bytes rate to clients in the stksess entry <ts> over the
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003380 * configured period.
3381 */
3382static int
Willy Tarreau37406352012-04-23 16:16:37 +02003383acl_fetch_bytes_out_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003384{
Willy Tarreau37406352012-04-23 16:16:37 +02003385 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003386 smp->type = SMP_T_UINT;
3387 smp->data.uint = 0;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003388 if (ts != NULL) {
3389 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_BYTES_OUT_RATE);
3390 if (!ptr)
3391 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003392 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, bytes_out_rate),
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003393 table->data_arg[STKTABLE_DT_BYTES_OUT_RATE].u);
3394 }
3395 return 1;
3396}
3397
Willy Tarreaua5e37562011-12-16 17:06:15 +01003398/* set temp integer to the bytes rate to clients from the session's tracked FE counters
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003399 * over the configured period.
3400 */
3401static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003402acl_fetch_sc1_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003403 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003404{
Willy Tarreau56123282010-08-06 19:06:56 +02003405 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003406 return 0;
3407
Willy Tarreau37406352012-04-23 16:16:37 +02003408 return acl_fetch_bytes_out_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003409}
3410
Willy Tarreaua5e37562011-12-16 17:06:15 +01003411/* set temp integer to the bytes rate to clients from the session's tracked BE counters
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003412 * over the configured period.
3413 */
3414static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003415acl_fetch_sc2_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003416 const struct arg *args, struct sample *smp)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003417{
Willy Tarreau56123282010-08-06 19:06:56 +02003418 if (!l4->stkctr2_entry)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003419 return 0;
3420
Willy Tarreau37406352012-04-23 16:16:37 +02003421 return acl_fetch_bytes_out_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003422}
3423
Willy Tarreaua5e37562011-12-16 17:06:15 +01003424/* set temp integer to the bytes rate to client from the session's source address in
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003425 * the table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003426 * Accepts exactly 1 argument of type table.
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003427 */
3428static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003429acl_fetch_src_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 Tarreau6c59e0a2010-06-20 11:56:30 +02003431{
3432 struct stktable_key *key;
3433
Willy Tarreau64ee4912012-08-30 22:59:48 +02003434 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003435 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003436 return 0;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003437
Willy Tarreau24e32d82012-04-23 23:55:44 +02003438 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003439 return acl_fetch_bytes_out_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003440}
3441
Willy Tarreau34db1082012-04-19 17:16:54 +02003442/* set temp integer to the number of used entries in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003443 * Accepts exactly 1 argument of type table.
Willy Tarreau34db1082012-04-19 17:16:54 +02003444 */
Willy Tarreauc735a072011-03-29 00:57:02 +02003445static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003446acl_fetch_table_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003447 const struct arg *args, struct sample *smp)
Willy Tarreauc735a072011-03-29 00:57:02 +02003448{
Willy Tarreau37406352012-04-23 16:16:37 +02003449 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003450 smp->type = SMP_T_UINT;
Willy Tarreau24e32d82012-04-23 23:55:44 +02003451 smp->data.uint = args->data.prx->table.current;
Willy Tarreauc735a072011-03-29 00:57:02 +02003452 return 1;
3453}
3454
Willy Tarreau34db1082012-04-19 17:16:54 +02003455/* set temp integer to the number of free entries in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003456 * Accepts exactly 1 argument of type table.
Willy Tarreau34db1082012-04-19 17:16:54 +02003457 */
Willy Tarreauc735a072011-03-29 00:57:02 +02003458static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003459acl_fetch_table_avl(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003460 const struct arg *args, struct sample *smp)
Willy Tarreauc735a072011-03-29 00:57:02 +02003461{
Willy Tarreau24e32d82012-04-23 23:55:44 +02003462 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003463 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003464 smp->type = SMP_T_UINT;
3465 smp->data.uint = px->table.size - px->table.current;
Willy Tarreauc735a072011-03-29 00:57:02 +02003466 return 1;
3467}
Willy Tarreau8b22a712010-06-18 17:46:06 +02003468
Willy Tarreau61612d42012-04-19 18:42:05 +02003469/* Note: must not be declared <const> as its list will be overwritten.
3470 * Please take care of keeping this list alphabetically sorted.
3471 */
Willy Tarreau8b22a712010-06-18 17:46:06 +02003472static struct acl_kw_list acl_kws = {{ },{
Willy Tarreau61612d42012-04-19 18:42:05 +02003473 { "sc1_bytes_in_rate", acl_parse_int, acl_fetch_sc1_bytes_in_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3474 { "sc1_bytes_out_rate", acl_parse_int, acl_fetch_sc1_bytes_out_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3475 { "sc1_clr_gpc0", acl_parse_int, acl_fetch_sc1_clr_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3476 { "sc1_conn_cnt", acl_parse_int, acl_fetch_sc1_conn_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3477 { "sc1_conn_cur", acl_parse_int, acl_fetch_sc1_conn_cur, acl_match_int, ACL_USE_NOTHING, 0 },
3478 { "sc1_conn_rate", acl_parse_int, acl_fetch_sc1_conn_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3479 { "sc1_get_gpc0", acl_parse_int, acl_fetch_sc1_get_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3480 { "sc1_http_err_cnt", acl_parse_int, acl_fetch_sc1_http_err_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3481 { "sc1_http_err_rate", acl_parse_int, acl_fetch_sc1_http_err_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3482 { "sc1_http_req_cnt", acl_parse_int, acl_fetch_sc1_http_req_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3483 { "sc1_http_req_rate", acl_parse_int, acl_fetch_sc1_http_req_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3484 { "sc1_inc_gpc0", acl_parse_int, acl_fetch_sc1_inc_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3485 { "sc1_kbytes_in", acl_parse_int, acl_fetch_sc1_kbytes_in, acl_match_int, ACL_USE_TCP4_VOLATILE, 0 },
3486 { "sc1_kbytes_out", acl_parse_int, acl_fetch_sc1_kbytes_out, acl_match_int, ACL_USE_TCP4_VOLATILE, 0 },
3487 { "sc1_sess_cnt", acl_parse_int, acl_fetch_sc1_sess_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3488 { "sc1_sess_rate", acl_parse_int, acl_fetch_sc1_sess_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3489 { "sc2_bytes_in_rate", acl_parse_int, acl_fetch_sc2_bytes_in_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3490 { "sc2_bytes_out_rate", acl_parse_int, acl_fetch_sc2_bytes_out_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3491 { "sc2_clr_gpc0", acl_parse_int, acl_fetch_sc2_clr_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3492 { "sc2_conn_cnt", acl_parse_int, acl_fetch_sc2_conn_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3493 { "sc2_conn_cur", acl_parse_int, acl_fetch_sc2_conn_cur, acl_match_int, ACL_USE_NOTHING, 0 },
3494 { "sc2_conn_rate", acl_parse_int, acl_fetch_sc2_conn_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3495 { "sc2_get_gpc0", acl_parse_int, acl_fetch_sc2_get_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3496 { "sc2_http_err_cnt", acl_parse_int, acl_fetch_sc2_http_err_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3497 { "sc2_http_err_rate", acl_parse_int, acl_fetch_sc2_http_err_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3498 { "sc2_http_req_cnt", acl_parse_int, acl_fetch_sc2_http_req_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3499 { "sc2_http_req_rate", acl_parse_int, acl_fetch_sc2_http_req_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3500 { "sc2_inc_gpc0", acl_parse_int, acl_fetch_sc2_inc_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3501 { "sc2_kbytes_in", acl_parse_int, acl_fetch_sc2_kbytes_in, acl_match_int, ACL_USE_TCP4_VOLATILE, 0 },
3502 { "sc2_kbytes_out", acl_parse_int, acl_fetch_sc2_kbytes_out, acl_match_int, ACL_USE_TCP4_VOLATILE, 0 },
3503 { "sc2_sess_cnt", acl_parse_int, acl_fetch_sc2_sess_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3504 { "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 +02003505 { "src_bytes_in_rate", acl_parse_int, acl_fetch_src_bytes_in_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3506 { "src_bytes_out_rate", acl_parse_int, acl_fetch_src_bytes_out_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3507 { "src_clr_gpc0", acl_parse_int, acl_fetch_src_clr_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3508 { "src_conn_cnt", acl_parse_int, acl_fetch_src_conn_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3509 { "src_conn_cur", acl_parse_int, acl_fetch_src_conn_cur, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3510 { "src_conn_rate", acl_parse_int, acl_fetch_src_conn_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3511 { "src_get_gpc0", acl_parse_int, acl_fetch_src_get_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3512 { "src_http_err_cnt", acl_parse_int, acl_fetch_src_http_err_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3513 { "src_http_err_rate", acl_parse_int, acl_fetch_src_http_err_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3514 { "src_http_req_cnt", acl_parse_int, acl_fetch_src_http_req_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3515 { "src_http_req_rate", acl_parse_int, acl_fetch_src_http_req_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3516 { "src_inc_gpc0", acl_parse_int, acl_fetch_src_inc_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3517 { "src_kbytes_in", acl_parse_int, acl_fetch_src_kbytes_in, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3518 { "src_kbytes_out", acl_parse_int, acl_fetch_src_kbytes_out, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3519 { "src_sess_cnt", acl_parse_int, acl_fetch_src_sess_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3520 { "src_sess_rate", acl_parse_int, acl_fetch_src_sess_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3521 { "src_updt_conn_cnt", acl_parse_int, acl_fetch_src_updt_conn_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3522 { "table_avl", acl_parse_int, acl_fetch_table_avl, acl_match_int, ACL_USE_NOTHING, ARG1(1,TAB) },
3523 { "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 +02003524 { NULL, NULL, NULL, NULL },
3525}};
3526
3527
Willy Tarreau56123282010-08-06 19:06:56 +02003528/* Parse a "track-sc[12]" line starting with "track-sc[12]" in args[arg-1].
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003529 * Returns the number of warnings emitted, or -1 in case of fatal errors. The
3530 * <prm> struct is fed with the table name if any. If unspecified, the caller
3531 * will assume that the current proxy's table is used.
3532 */
3533int parse_track_counters(char **args, int *arg,
3534 int section_type, struct proxy *curpx,
3535 struct track_ctr_prm *prm,
Willy Tarreau0a3dd742012-05-08 19:47:01 +02003536 struct proxy *defpx, char **err)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003537{
Willy Tarreau12785782012-04-27 21:37:17 +02003538 int sample_type = 0;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003539
Willy Tarreau56123282010-08-06 19:06:56 +02003540 /* parse the arguments of "track-sc[12]" before the condition in the
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003541 * following form :
Willy Tarreau56123282010-08-06 19:06:56 +02003542 * track-sc[12] src [ table xxx ] [ if|unless ... ]
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003543 */
3544 while (args[*arg]) {
3545 if (strcmp(args[*arg], "src") == 0) {
3546 prm->type = STKTABLE_TYPE_IP;
Willy Tarreau12785782012-04-27 21:37:17 +02003547 sample_type = 1;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003548 }
3549 else if (strcmp(args[*arg], "table") == 0) {
3550 if (!args[*arg + 1]) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02003551 memprintf(err, "missing table name");
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003552 return -1;
3553 }
3554 /* we copy the table name for now, it will be resolved later */
3555 prm->table.n = strdup(args[*arg + 1]);
3556 (*arg)++;
3557 }
3558 else {
3559 /* unhandled keywords are handled by the caller */
3560 break;
3561 }
3562 (*arg)++;
3563 }
3564
Willy Tarreau12785782012-04-27 21:37:17 +02003565 if (!sample_type) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02003566 memprintf(err,
3567 "tracking key not specified (found %s, only 'src' is supported)",
3568 quote_arg(args[*arg]));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003569 return -1;
3570 }
3571
3572 return 0;
3573}
3574
Willy Tarreau8b22a712010-06-18 17:46:06 +02003575__attribute__((constructor))
3576static void __session_init(void)
3577{
3578 acl_register_keywords(&acl_kws);
3579}
3580
Willy Tarreaubaaee002006-06-26 02:48:02 +02003581/*
3582 * Local variables:
3583 * c-indent-level: 8
3584 * c-basic-offset: 8
3585 * End:
3586 */