blob: 7c218bf80315f77d108d98a4a9e301966000b170 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
Willy Tarreau81f9aa32010-06-01 17:45:26 +02002 * Session management functions.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003 *
Willy Tarreaud28c3532012-04-19 19:28:33 +02004 * Copyright 2000-2012 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdlib.h>
Willy Tarreau81f9aa32010-06-01 17:45:26 +020014#include <unistd.h>
15#include <fcntl.h>
Willy Tarreaue3ba5f02006-06-29 18:54:54 +020016
17#include <common/config.h>
Willy Tarreau7c669d72008-06-20 15:04:11 +020018#include <common/debug.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020019#include <common/memory.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020020
Willy Tarreaubaaee002006-06-26 02:48:02 +020021#include <types/capture.h>
Willy Tarreau55a8d0e2008-11-30 18:47:21 +010022#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020023
Willy Tarreau1d0dfb12009-07-07 15:10:31 +020024#include <proto/acl.h>
Willy Tarreau61612d42012-04-19 18:42:05 +020025#include <proto/arg.h>
Willy Tarreau55a8d0e2008-11-30 18:47:21 +010026#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <proto/channel.h>
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +010028#include <proto/checks.h>
Willy Tarreaud2274c62012-07-06 14:29:45 +020029#include <proto/connection.h>
Willy Tarreau5ca791d2009-08-16 19:06:42 +020030#include <proto/dumpstats.h>
Willy Tarreaudd2f85e2012-09-02 22:34:23 +020031#include <proto/fd.h>
Willy Tarreau91c43d72010-06-20 11:19:22 +020032#include <proto/freq_ctr.h>
Willy Tarreau3041b9f2010-10-15 23:25:20 +020033#include <proto/frontend.h>
Willy Tarreau8d5d7f22007-01-21 19:16:41 +010034#include <proto/hdr_idx.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020035#include <proto/listener.h>
Willy Tarreau332f8bf2007-05-13 21:36:56 +020036#include <proto/log.h>
Willy Tarreaucbaaec42012-09-06 11:32:07 +020037#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038#include <proto/session.h>
Willy Tarreau3eba98a2009-01-25 13:56:13 +010039#include <proto/pipe.h>
Willy Tarreau55a8d0e2008-11-30 18:47:21 +010040#include <proto/proto_http.h>
41#include <proto/proto_tcp.h>
Willy Tarreau1d0dfb12009-07-07 15:10:31 +020042#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/queue.h>
Willy Tarreau7f062c42009-03-05 18:43:00 +010044#include <proto/server.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020045#include <proto/sample.h>
Emeric Brun1d33b292010-01-04 15:47:17 +010046#include <proto/stick_table.h>
Willy Tarreau55a8d0e2008-11-30 18:47:21 +010047#include <proto/stream_interface.h>
Willy Tarreau55a8d0e2008-11-30 18:47:21 +010048#include <proto/task.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049
Willy Tarreauc6ca1a02007-05-13 19:43:47 +020050struct pool_head *pool2_session;
Willy Tarreauf54f8bd2008-11-23 19:53:55 +010051struct list sessions;
Willy Tarreaubaaee002006-06-26 02:48:02 +020052
Willy Tarreau071e1372012-10-03 01:39:48 +020053static int conn_session_complete(struct connection *conn);
Willy Tarreau9683e9a2012-10-03 21:17:23 +020054static int conn_session_update(struct connection *conn);
Willy Tarreau2542b532012-08-31 16:01:23 +020055static struct task *expire_mini_session(struct task *t);
56int session_complete(struct session *s);
57
Willy Tarreau5e75e272012-10-02 21:21:20 +020058/* data layer callbacks for an embryonic session */
59struct data_cb sess_conn_cb = {
60 .recv = NULL,
61 .send = NULL,
Willy Tarreau9683e9a2012-10-03 21:17:23 +020062 .wake = conn_session_update,
Willy Tarreau071e1372012-10-03 01:39:48 +020063 .init = conn_session_complete,
Willy Tarreau5e75e272012-10-02 21:21:20 +020064};
65
Willy Tarreau2542b532012-08-31 16:01:23 +020066/* This function is called from the protocol layer accept() in order to
67 * instanciate a new embryonic session on behalf of a given listener and
68 * frontend. It returns a positive value upon success, 0 if the connection
69 * can be ignored, or a negative value upon critical failure. The accepted
70 * file descriptor is closed if we return <= 0.
Willy Tarreau81f9aa32010-06-01 17:45:26 +020071 */
72int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
73{
74 struct proxy *p = l->frontend;
75 struct session *s;
Willy Tarreau81f9aa32010-06-01 17:45:26 +020076 struct task *t;
Willy Tarreauabe8ea52010-11-11 10:56:04 +010077 int ret;
78
79
80 ret = -1; /* assume unrecoverable error by default */
Willy Tarreau81f9aa32010-06-01 17:45:26 +020081
Willy Tarreaufffe1322010-11-11 09:48:16 +010082 if (unlikely((s = pool_alloc2(pool2_session)) == NULL))
Willy Tarreau81f9aa32010-06-01 17:45:26 +020083 goto out_close;
Willy Tarreau81f9aa32010-06-01 17:45:26 +020084
Willy Tarreau2542b532012-08-31 16:01:23 +020085 /* minimum session initialization required for an embryonic session is
86 * fairly low. We need very little to execute L4 ACLs, then we need a
87 * task to make the client-side connection live on its own.
88 * - flags
89 * - stick-entry tracking
90 */
Willy Tarreau81f9aa32010-06-01 17:45:26 +020091 s->flags = 0;
92 s->logs.logwait = p->to_log;
Willy Tarreau56123282010-08-06 19:06:56 +020093 s->stkctr1_entry = NULL;
94 s->stkctr2_entry = NULL;
95 s->stkctr1_table = NULL;
96 s->stkctr2_table = NULL;
Willy Tarreau81f9aa32010-06-01 17:45:26 +020097
Willy Tarreau2542b532012-08-31 16:01:23 +020098 s->listener = l;
99 s->fe = p;
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100100
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200101 /* OK, we're keeping the session, so let's properly initialize the session */
Willy Tarreau96596ae2012-06-08 22:57:36 +0200102 s->si[0].conn.t.sock.fd = cfd;
103 s->si[0].conn.ctrl = l->proto;
Willy Tarreau2542b532012-08-31 16:01:23 +0200104 s->si[0].conn.flags = CO_FL_NONE;
Willy Tarreau986a9d22012-08-30 21:11:38 +0200105 s->si[0].conn.addr.from = *addr;
Willy Tarreau2542b532012-08-31 16:01:23 +0200106 set_target_client(&s->si[0].conn.target, l);
107
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200108 s->logs.accept_date = date; /* user-visible date for logging */
109 s->logs.tv_accept = now; /* corrected date for internal use */
110 s->uniq_id = totalconn;
Willy Tarreau2542b532012-08-31 16:01:23 +0200111 p->feconn++;
112 /* This session was accepted, count it now */
113 if (p->feconn > p->fe_counters.conn_max)
114 p->fe_counters.conn_max = p->feconn;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200115
Willy Tarreau2542b532012-08-31 16:01:23 +0200116 proxy_inc_fe_conn_ctr(l, p);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200117
118 /* now evaluate the tcp-request layer4 rules. Since we expect to be able
119 * to abort right here as soon as possible, we check the rules before
120 * even initializing the stream interfaces.
121 */
122 if ((l->options & LI_O_TCP_RULES) && !tcp_exec_req_rules(s)) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200123 /* let's do a no-linger now to close with a single RST. */
124 setsockopt(cfd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100125 ret = 0; /* successful termination */
Willy Tarreau2542b532012-08-31 16:01:23 +0200126 goto out_free_session;
127 }
128
Willy Tarreau1bc4aab2012-10-08 20:11:03 +0200129#ifndef USE_ACCEPT4
130 /* Adjust some socket options if the connection was accepted by a plain
131 * accept() syscall.
132 */
Willy Tarreau82569f92012-09-27 23:48:56 +0200133 if (unlikely(fcntl(cfd, F_SETFL, O_NONBLOCK) == -1))
134 goto out_free_session;
Willy Tarreau1bc4aab2012-10-08 20:11:03 +0200135#endif
Willy Tarreau82569f92012-09-27 23:48:56 +0200136
137 /* monitor-net and health mode are processed immediately after TCP
138 * connection rules. This way it's possible to block them, but they
139 * never use the lower data layers, they send directly over the socket,
140 * as they were designed for. We first flush the socket receive buffer
141 * in order to avoid emission of an RST by the system. We ignore any
142 * error.
143 */
144 if (unlikely((p->mode == PR_MODE_HEALTH) ||
145 ((l->options & LI_O_CHK_MONNET) &&
146 addr->ss_family == AF_INET &&
147 (((struct sockaddr_in *)addr)->sin_addr.s_addr & p->mon_mask.s_addr) == p->mon_net.s_addr))) {
148 /* we have 4 possibilities here :
149 * - HTTP mode, from monitoring address => send "HTTP/1.0 200 OK"
150 * - HEALTH mode with HTTP check => send "HTTP/1.0 200 OK"
151 * - HEALTH mode without HTTP check => just send "OK"
152 * - TCP mode from monitoring address => just close
153 */
Willy Tarreaue9909f42012-10-12 17:36:40 +0200154 recv(cfd, trash, trashlen, MSG_DONTWAIT);
Willy Tarreau82569f92012-09-27 23:48:56 +0200155 if (p->mode == PR_MODE_HTTP ||
156 (p->mode == PR_MODE_HEALTH && (p->options2 & PR_O2_CHK_ANY) == PR_O2_HTTP_CHK))
157 send(cfd, "HTTP/1.0 200 OK\r\n\r\n", 19, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_MORE);
158 else if (p->mode == PR_MODE_HEALTH)
159 send(cfd, "OK\n", 3, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_MORE);
160 ret = 0;
161 goto out_free_session;
162 }
163
164
Willy Tarreau22cda212012-08-31 17:43:29 +0200165 /* wait for a PROXY protocol header */
166 if (l->options & LI_O_ACC_PROXY) {
167 s->si[0].conn.flags |= CO_FL_ACCEPT_PROXY;
168 conn_sock_want_recv(&s->si[0].conn);
169 }
170
Willy Tarreau2542b532012-08-31 16:01:23 +0200171 if (unlikely((t = task_new()) == NULL))
172 goto out_free_session;
173
174 t->context = s;
175 t->nice = l->nice;
176 s->task = t;
177
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200178 /* Add the various callbacks. Right now the transport layer is present
179 * but not initialized. Also note we need to be careful as the stream
180 * int is not initialized yet.
Willy Tarreau2542b532012-08-31 16:01:23 +0200181 */
Willy Tarreau5e75e272012-10-02 21:21:20 +0200182 conn_prepare(&s->si[0].conn, &sess_conn_cb, l->proto, l->xprt, s);
Willy Tarreau2542b532012-08-31 16:01:23 +0200183
184 /* finish initialization of the accepted file descriptor */
185 fd_insert(cfd);
186 fdtab[cfd].owner = &s->si[0].conn;
Willy Tarreau2542b532012-08-31 16:01:23 +0200187 fdtab[cfd].iocb = conn_fd_handler;
188 conn_data_want_recv(&s->si[0].conn);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200189 if (conn_xprt_init(&s->si[0].conn) < 0)
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100190 goto out_free_task;
Willy Tarreau2542b532012-08-31 16:01:23 +0200191
192 /* OK, now either we have a pending handshake to execute with and
193 * then we must return to the I/O layer, or we can proceed with the
194 * end of the session initialization. In case of handshake, we also
195 * set the I/O timeout to the frontend's client timeout.
196 */
197
198 if (s->si[0].conn.flags & CO_FL_HANDSHAKE) {
199 t->process = expire_mini_session;
200 t->expire = tick_add_ifset(now_ms, p->timeout.client);
201 task_queue(t);
Willy Tarreau91083f52012-10-12 17:42:13 +0200202 s->si[0].conn.flags |= CO_FL_INIT_DATA | CO_FL_WAKE_DATA;
Willy Tarreau2542b532012-08-31 16:01:23 +0200203 return 1;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200204 }
205
Willy Tarreau2542b532012-08-31 16:01:23 +0200206 /* OK let's complete session initialization */
207 ret = session_complete(s);
208 if (ret > 0)
209 return ret;
210
211 /* Error unrolling */
212 out_free_task:
213 task_free(t);
214 out_free_session:
215 p->feconn--;
216 if (s->stkctr1_entry || s->stkctr2_entry)
217 session_store_counters(s);
218 pool_free2(pool2_session, s);
219 out_close:
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200220 if (ret < 0 && l->xprt == &raw_sock && p->mode == PR_MODE_HTTP) {
Willy Tarreau2542b532012-08-31 16:01:23 +0200221 /* critical error, no more memory, try to emit a 500 response */
Willy Tarreau783f2582012-09-04 12:19:04 +0200222 struct chunk *err_msg = http_error_message(s, HTTP_ERR_500);
Willy Tarreau2542b532012-08-31 16:01:23 +0200223 send(cfd, err_msg->str, err_msg->len, MSG_DONTWAIT|MSG_NOSIGNAL);
224 }
225
226 if (fdtab[cfd].owner)
227 fd_delete(cfd);
228 else
229 close(cfd);
230 return ret;
231}
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100232
Willy Tarreau2542b532012-08-31 16:01:23 +0200233/* This function kills an existing embryonic session. It stops the connection's
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200234 * transport layer, releases assigned resources, resumes the listener if it was
Willy Tarreau2542b532012-08-31 16:01:23 +0200235 * disabled and finally kills the file descriptor.
236 */
237static void kill_mini_session(struct session *s)
238{
239 /* kill the connection now */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200240 conn_xprt_close(&s->si[0].conn);
Willy Tarreau2542b532012-08-31 16:01:23 +0200241
242 s->fe->feconn--;
243 if (s->stkctr1_entry || s->stkctr2_entry)
244 session_store_counters(s);
245
246 if (!(s->listener->options & LI_O_UNLIMITED))
247 actconn--;
248 jobs--;
249 s->listener->nbconn--;
250 if (s->listener->state == LI_FULL)
251 resume_listener(s->listener);
252
253 /* Dequeues all of the listeners waiting for a resource */
254 if (!LIST_ISEMPTY(&global_listener_queue))
255 dequeue_all_listeners(&global_listener_queue);
256
257 if (!LIST_ISEMPTY(&s->fe->listener_queue) &&
258 (!s->fe->fe_sps_lim || freq_ctr_remain(&s->fe->fe_sess_per_sec, s->fe->fe_sps_lim, 0) > 0))
259 dequeue_all_listeners(&s->fe->listener_queue);
260
261 task_delete(s->task);
262 task_free(s->task);
263
264 if (fdtab[s->si[0].conn.t.sock.fd].owner)
265 fd_delete(s->si[0].conn.t.sock.fd);
266 else
267 close(s->si[0].conn.t.sock.fd);
268
269 pool_free2(pool2_session, s);
270}
271
Willy Tarreau22cda212012-08-31 17:43:29 +0200272/* Finish initializing a session from a connection, or kills it if the
273 * connection shows and error. Returns <0 if the connection was killed.
Willy Tarreau2542b532012-08-31 16:01:23 +0200274 */
Willy Tarreau071e1372012-10-03 01:39:48 +0200275static int conn_session_complete(struct connection *conn)
Willy Tarreau2542b532012-08-31 16:01:23 +0200276{
Willy Tarreau5e75e272012-10-02 21:21:20 +0200277 struct session *s = conn->owner;
Willy Tarreau2542b532012-08-31 16:01:23 +0200278
Willy Tarreau22cda212012-08-31 17:43:29 +0200279 if (!(conn->flags & CO_FL_ERROR) && (session_complete(s) > 0)) {
Willy Tarreau071e1372012-10-03 01:39:48 +0200280 conn->flags &= ~CO_FL_INIT_DATA;
Willy Tarreau2542b532012-08-31 16:01:23 +0200281 return 0;
282 }
283
284 /* kill the connection now */
285 kill_mini_session(s);
286 return -1;
287}
288
Willy Tarreau9683e9a2012-10-03 21:17:23 +0200289/* Update an embryonic session status. The connection is killed in case of
290 * error, and <0 will be returned. Otherwise it does nothing.
291 */
292static int conn_session_update(struct connection *conn)
293{
294 if (conn->flags & CO_FL_ERROR) {
295 kill_mini_session(conn->owner);
296 return -1;
297 }
298 return 0;
299}
300
Willy Tarreau2542b532012-08-31 16:01:23 +0200301/* Manages embryonic sessions timeout. It is only called when the timeout
302 * strikes and performs the required cleanup.
303 */
304static struct task *expire_mini_session(struct task *t)
305{
306 struct session *s = t->context;
307
308 if (!(t->state & TASK_WOKEN_TIMER))
309 return t;
310
311 kill_mini_session(s);
312 return NULL;
313}
314
315/* This function is called from the I/O handler which detects the end of
316 * handshake, in order to complete initialization of a valid session. It must
317 * be called with an embryonic session. It returns a positive value upon
318 * success, 0 if the connection can be ignored, or a negative value upon
319 * critical failure. The accepted file descriptor is closed if we return <= 0.
320 */
321int session_complete(struct session *s)
322{
323 struct listener *l = s->listener;
324 struct proxy *p = s->fe;
325 struct http_txn *txn;
326 struct task *t = s->task;
327 int ret;
328
329 ret = -1; /* assume unrecoverable error by default */
330
331 /* OK, we're keeping the session, so let's properly initialize the session */
332 LIST_ADDQ(&sessions, &s->list);
333 LIST_INIT(&s->back_refs);
Willy Tarreau5e75e272012-10-02 21:21:20 +0200334 si_takeover_conn(&s->si[0], l->proto, l->xprt);
Willy Tarreau2542b532012-08-31 16:01:23 +0200335 s->flags |= SN_INITIALIZED;
336
337 s->unique_id = NULL;
338 s->term_trace = 0;
339
340 t->process = l->handler;
341 t->context = s;
342 t->expire = TICK_ETERNITY;
343
344 /* Note: initially, the session's backend points to the frontend.
345 * This changes later when switching rules are executed or
346 * when the default backend is assigned.
347 */
348 s->be = s->fe;
349 s->req = s->rep = NULL; /* will be allocated later */
350
351 /* Let's count a session now */
Willy Tarreaub36b4242010-06-04 20:59:39 +0200352 proxy_inc_fe_sess_ctr(l, p);
Willy Tarreau56123282010-08-06 19:06:56 +0200353 if (s->stkctr1_entry) {
Willy Tarreau91c43d72010-06-20 11:19:22 +0200354 void *ptr;
355
Willy Tarreau56123282010-08-06 19:06:56 +0200356 ptr = stktable_data_ptr(s->stkctr1_table, s->stkctr1_entry, STKTABLE_DT_SESS_CNT);
Willy Tarreauf4d17d92010-06-18 22:10:12 +0200357 if (ptr)
358 stktable_data_cast(ptr, sess_cnt)++;
Willy Tarreau91c43d72010-06-20 11:19:22 +0200359
Willy Tarreau56123282010-08-06 19:06:56 +0200360 ptr = stktable_data_ptr(s->stkctr1_table, s->stkctr1_entry, STKTABLE_DT_SESS_RATE);
Willy Tarreau91c43d72010-06-20 11:19:22 +0200361 if (ptr)
362 update_freq_ctr_period(&stktable_data_cast(ptr, sess_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200363 s->stkctr1_table->data_arg[STKTABLE_DT_SESS_RATE].u, 1);
Willy Tarreauf4d17d92010-06-18 22:10:12 +0200364 }
Willy Tarreaub36b4242010-06-04 20:59:39 +0200365
Willy Tarreau56123282010-08-06 19:06:56 +0200366 if (s->stkctr2_entry) {
Willy Tarreau9e9879a2010-08-06 15:25:22 +0200367 void *ptr;
368
Willy Tarreau56123282010-08-06 19:06:56 +0200369 ptr = stktable_data_ptr(s->stkctr2_table, s->stkctr2_entry, STKTABLE_DT_SESS_CNT);
Willy Tarreau9e9879a2010-08-06 15:25:22 +0200370 if (ptr)
371 stktable_data_cast(ptr, sess_cnt)++;
372
Willy Tarreau56123282010-08-06 19:06:56 +0200373 ptr = stktable_data_ptr(s->stkctr2_table, s->stkctr2_entry, STKTABLE_DT_SESS_RATE);
Willy Tarreau9e9879a2010-08-06 15:25:22 +0200374 if (ptr)
375 update_freq_ctr_period(&stktable_data_cast(ptr, sess_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200376 s->stkctr2_table->data_arg[STKTABLE_DT_SESS_RATE].u, 1);
Willy Tarreau9e9879a2010-08-06 15:25:22 +0200377 }
378
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200379 /* this part should be common with other protocols */
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200380 s->si[0].owner = t;
381 s->si[0].state = s->si[0].prev_state = SI_ST_EST;
382 s->si[0].err_type = SI_ET_NONE;
383 s->si[0].err_loc = NULL;
Willy Tarreau0bd05ea2010-07-02 11:18:03 +0200384 s->si[0].release = NULL;
Willy Tarreau63e7fe32012-05-08 15:20:43 +0200385 s->si[0].send_proxy_ofs = 0;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200386 s->si[0].exp = TICK_ETERNITY;
387 s->si[0].flags = SI_FL_NONE;
388
389 if (likely(s->fe->options2 & PR_O2_INDEPSTR))
390 s->si[0].flags |= SI_FL_INDEP_STR;
391
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200392 /* pre-initialize the other side's stream interface to an INIT state. The
393 * callbacks will be initialized before attempting to connect.
394 */
Willy Tarreaufb7508a2012-05-21 16:47:54 +0200395 s->si[1].conn.t.sock.fd = -1; /* just to help with debugging */
Willy Tarreau505e34a2012-07-06 10:17:53 +0200396 s->si[1].conn.flags = CO_FL_NONE;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200397 s->si[1].owner = t;
398 s->si[1].state = s->si[1].prev_state = SI_ST_INI;
399 s->si[1].err_type = SI_ET_NONE;
Willy Tarreau0b3a4112011-03-27 19:16:56 +0200400 s->si[1].conn_retries = 0; /* used for logging too */
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200401 s->si[1].err_loc = NULL;
Willy Tarreau0bd05ea2010-07-02 11:18:03 +0200402 s->si[1].release = NULL;
Willy Tarreau63e7fe32012-05-08 15:20:43 +0200403 s->si[1].send_proxy_ofs = 0;
Willy Tarreau3cefd522012-08-30 15:49:18 +0200404 clear_target(&s->si[1].conn.target);
Willy Tarreauc5788912012-08-24 18:12:41 +0200405 si_prepare_embedded(&s->si[1]);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200406 s->si[1].exp = TICK_ETERNITY;
407 s->si[1].flags = SI_FL_NONE;
408
409 if (likely(s->fe->options2 & PR_O2_INDEPSTR))
410 s->si[1].flags |= SI_FL_INDEP_STR;
411
Willy Tarreau9bd0d742011-07-20 00:17:39 +0200412 session_init_srv_conn(s);
Willy Tarreau9e000c62011-03-10 14:03:36 +0100413 clear_target(&s->target);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200414 s->pend_pos = NULL;
415
416 /* init store persistence */
417 s->store_count = 0;
418
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200419 if (unlikely((s->req = pool_alloc2(pool2_channel)) == NULL))
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200420 goto out_free_task; /* no memory */
421
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200422 if (unlikely((s->rep = pool_alloc2(pool2_channel)) == NULL))
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200423 goto out_free_req; /* no memory */
424
425 /* initialize the request buffer */
Willy Tarreau572bf902012-07-02 17:01:20 +0200426 s->req->buf.size = global.tune.bufsize;
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200427 channel_init(s->req);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200428 s->req->prod = &s->si[0];
429 s->req->cons = &s->si[1];
430 s->si[0].ib = s->si[1].ob = s->req;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200431 s->req->flags |= CF_READ_ATTACHED; /* the producer is already connected */
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200432
433 /* activate default analysers enabled for this listener */
434 s->req->analysers = l->analysers;
435
436 s->req->wto = TICK_ETERNITY;
437 s->req->rto = TICK_ETERNITY;
438 s->req->rex = TICK_ETERNITY;
439 s->req->wex = TICK_ETERNITY;
440 s->req->analyse_exp = TICK_ETERNITY;
441
442 /* initialize response buffer */
Willy Tarreau572bf902012-07-02 17:01:20 +0200443 s->rep->buf.size = global.tune.bufsize;
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200444 channel_init(s->rep);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200445 s->rep->prod = &s->si[1];
446 s->rep->cons = &s->si[0];
447 s->si[0].ob = s->si[1].ib = s->rep;
448 s->rep->analysers = 0;
449
Willy Tarreau96e31212011-05-30 18:10:30 +0200450 if (s->fe->options2 & PR_O2_NODELAY) {
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200451 s->req->flags |= CF_NEVER_WAIT;
452 s->rep->flags |= CF_NEVER_WAIT;
Willy Tarreau96e31212011-05-30 18:10:30 +0200453 }
454
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200455 s->rep->rto = TICK_ETERNITY;
456 s->rep->wto = TICK_ETERNITY;
457 s->rep->rex = TICK_ETERNITY;
458 s->rep->wex = TICK_ETERNITY;
459 s->rep->analyse_exp = TICK_ETERNITY;
460
Willy Tarreau62f791e2012-03-09 11:32:30 +0100461 txn = &s->txn;
462 /* Those variables will be checked and freed if non-NULL in
463 * session.c:session_free(). It is important that they are
464 * properly initialized.
465 */
466 txn->sessid = NULL;
467 txn->srv_cookie = NULL;
468 txn->cli_cookie = NULL;
469 txn->uri = NULL;
470 txn->req.cap = NULL;
471 txn->rsp.cap = NULL;
472 txn->hdr_idx.v = NULL;
473 txn->hdr_idx.size = txn->hdr_idx.used = 0;
474 txn->req.flags = 0;
475 txn->rsp.flags = 0;
476 /* the HTTP messages need to know what buffer they're associated with */
477 txn->req.buf = s->req;
478 txn->rsp.buf = s->rep;
479
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200480 /* finish initialization of the accepted file descriptor */
Willy Tarreauf9dabec2012-08-17 17:33:53 +0200481 conn_data_want_recv(&s->si[0].conn);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200482
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100483 if (p->accept && (ret = p->accept(s)) <= 0) {
484 /* Either we had an unrecoverable error (<0) or work is
485 * finished (=0, eg: monitoring), in both situations,
486 * we can release everything and close.
487 */
488 goto out_free_rep;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200489 }
490
Willy Tarreau2542b532012-08-31 16:01:23 +0200491 /* we want the connection handler to notify the stream interface about updates. */
Willy Tarreau4aa36832012-10-02 20:07:22 +0200492 s->si[0].conn.flags |= CO_FL_WAKE_DATA;
Willy Tarreau2542b532012-08-31 16:01:23 +0200493
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200494 /* it is important not to call the wakeup function directly but to
495 * pass through task_wakeup(), because this one knows how to apply
496 * priorities to tasks.
497 */
498 task_wakeup(t, TASK_WOKEN_INIT);
499 return 1;
500
501 /* Error unrolling */
502 out_free_rep:
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200503 pool_free2(pool2_channel, s->rep);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200504 out_free_req:
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200505 pool_free2(pool2_channel, s->req);
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200506 out_free_task:
Willy Tarreauabe8ea52010-11-11 10:56:04 +0100507 return ret;
Willy Tarreau81f9aa32010-06-01 17:45:26 +0200508}
509
Willy Tarreaubaaee002006-06-26 02:48:02 +0200510/*
511 * frees the context associated to a session. It must have been removed first.
512 */
Simon Hormandec5be42011-06-08 09:19:07 +0900513static void session_free(struct session *s)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200514{
Willy Tarreau4dbc4a22007-03-03 16:23:22 +0100515 struct http_txn *txn = &s->txn;
Willy Tarreau632f5a72007-07-11 10:42:35 +0200516 struct proxy *fe = s->fe;
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100517 struct bref *bref, *back;
Willy Tarreaua4cda672010-06-06 18:28:49 +0200518 int i;
Willy Tarreau0f7562b2007-01-07 15:46:13 +0100519
Willy Tarreaubaaee002006-06-26 02:48:02 +0200520 if (s->pend_pos)
521 pendconn_free(s->pend_pos);
Willy Tarreau922a8062008-12-04 09:33:58 +0100522
Willy Tarreau827aee92011-03-10 16:55:02 +0100523 if (target_srv(&s->target)) { /* there may be requests left pending in queue */
Willy Tarreau1e62de62008-11-11 20:20:02 +0100524 if (s->flags & SN_CURR_SESS) {
525 s->flags &= ~SN_CURR_SESS;
Willy Tarreau827aee92011-03-10 16:55:02 +0100526 target_srv(&s->target)->cur_sess--;
Willy Tarreau1e62de62008-11-11 20:20:02 +0100527 }
Willy Tarreau827aee92011-03-10 16:55:02 +0100528 if (may_dequeue_tasks(target_srv(&s->target), s->be))
529 process_srv_queue(target_srv(&s->target));
Willy Tarreau1e62de62008-11-11 20:20:02 +0100530 }
Willy Tarreau922a8062008-12-04 09:33:58 +0100531
Willy Tarreau7c669d72008-06-20 15:04:11 +0200532 if (unlikely(s->srv_conn)) {
533 /* the session still has a reserved slot on a server, but
534 * it should normally be only the same as the one above,
535 * so this should not happen in fact.
536 */
537 sess_change_server(s, NULL);
538 }
539
Willy Tarreau3eba98a2009-01-25 13:56:13 +0100540 if (s->req->pipe)
541 put_pipe(s->req->pipe);
Willy Tarreau259de1b2009-01-18 21:56:21 +0100542
Willy Tarreau3eba98a2009-01-25 13:56:13 +0100543 if (s->rep->pipe)
544 put_pipe(s->rep->pipe);
Willy Tarreau259de1b2009-01-18 21:56:21 +0100545
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200546 pool_free2(pool2_channel, s->req);
547 pool_free2(pool2_channel, s->rep);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200548
Willy Tarreau46023632010-01-07 22:51:47 +0100549 http_end_txn(s);
550
Willy Tarreau1e954912012-10-12 17:50:05 +0200551 /* ensure the client-side transport layer is destroyed */
552 s->si[0].conn.flags &= ~CO_FL_XPRT_TRACKED;
553 conn_xprt_close(&s->si[0].conn);
554
Willy Tarreaua4cda672010-06-06 18:28:49 +0200555 for (i = 0; i < s->store_count; i++) {
556 if (!s->store[i].ts)
557 continue;
558 stksess_free(s->store[i].table, s->store[i].ts);
559 s->store[i].ts = NULL;
560 }
561
Willy Tarreau34eb6712011-10-24 18:15:04 +0200562 pool_free2(pool2_hdr_idx, txn->hdr_idx.v);
Willy Tarreau92fb9832007-10-16 17:34:28 +0200563 if (fe) {
Willy Tarreau46023632010-01-07 22:51:47 +0100564 pool_free2(fe->rsp_cap_pool, txn->rsp.cap);
565 pool_free2(fe->req_cap_pool, txn->req.cap);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200566 }
Willy Tarreau0937bc42009-12-22 15:03:09 +0100567
Willy Tarreau56123282010-08-06 19:06:56 +0200568 if (s->stkctr1_entry || s->stkctr2_entry)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +0200569 session_store_counters(s);
570
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100571 list_for_each_entry_safe(bref, back, &s->back_refs, users) {
Willy Tarreaufd3828e2009-02-22 15:17:24 +0100572 /* we have to unlink all watchers. We must not relink them if
573 * this session was the last one in the list.
574 */
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100575 LIST_DEL(&bref->users);
Willy Tarreaufd3828e2009-02-22 15:17:24 +0100576 LIST_INIT(&bref->users);
577 if (s->list.n != &sessions)
578 LIST_ADDQ(&LIST_ELEM(s->list.n, struct session *, list)->back_refs, &bref->users);
Willy Tarreau62e4f1d2008-12-07 20:16:23 +0100579 bref->ref = s->list.n;
580 }
Willy Tarreauf54f8bd2008-11-23 19:53:55 +0100581 LIST_DEL(&s->list);
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200582 pool_free2(pool2_session, s);
Willy Tarreau632f5a72007-07-11 10:42:35 +0200583
584 /* We may want to free the maximum amount of pools if the proxy is stopping */
Willy Tarreau92fb9832007-10-16 17:34:28 +0200585 if (fe && unlikely(fe->state == PR_STSTOPPED)) {
Willy Tarreau8263d2b2012-08-28 00:06:31 +0200586 pool_flush2(pool2_channel);
Willy Tarreau34eb6712011-10-24 18:15:04 +0200587 pool_flush2(pool2_hdr_idx);
Willy Tarreau48d63db2008-08-03 17:41:33 +0200588 pool_flush2(pool2_requri);
589 pool_flush2(pool2_capture);
590 pool_flush2(pool2_session);
591 pool_flush2(fe->req_cap_pool);
592 pool_flush2(fe->rsp_cap_pool);
Willy Tarreau632f5a72007-07-11 10:42:35 +0200593 }
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200594}
595
596
597/* perform minimal intializations, report 0 in case of error, 1 if OK. */
598int init_session()
599{
Willy Tarreauf54f8bd2008-11-23 19:53:55 +0100600 LIST_INIT(&sessions);
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200601 pool2_session = create_pool("session", sizeof(struct session), MEM_F_SHARED);
602 return pool2_session != NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200603}
604
Willy Tarreau30e71012007-11-26 20:15:35 +0100605void session_process_counters(struct session *s)
606{
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100607 unsigned long long bytes;
608
Willy Tarreau30e71012007-11-26 20:15:35 +0100609 if (s->req) {
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100610 bytes = s->req->total - s->logs.bytes_in;
Willy Tarreau30e71012007-11-26 20:15:35 +0100611 s->logs.bytes_in = s->req->total;
612 if (bytes) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100613 s->fe->fe_counters.bytes_in += bytes;
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100614
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100615 s->be->be_counters.bytes_in += bytes;
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100616
Willy Tarreau827aee92011-03-10 16:55:02 +0100617 if (target_srv(&s->target))
618 target_srv(&s->target)->counters.bytes_in += bytes;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200619
620 if (s->listener->counters)
621 s->listener->counters->bytes_in += bytes;
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200622
Willy Tarreau56123282010-08-06 19:06:56 +0200623 if (s->stkctr2_entry) {
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200624 void *ptr;
625
Willy Tarreau56123282010-08-06 19:06:56 +0200626 ptr = stktable_data_ptr(s->stkctr2_table,
627 s->stkctr2_entry,
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200628 STKTABLE_DT_BYTES_IN_CNT);
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200629 if (ptr)
630 stktable_data_cast(ptr, bytes_in_cnt) += bytes;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200631
Willy Tarreau56123282010-08-06 19:06:56 +0200632 ptr = stktable_data_ptr(s->stkctr2_table,
633 s->stkctr2_entry,
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200634 STKTABLE_DT_BYTES_IN_RATE);
635 if (ptr)
636 update_freq_ctr_period(&stktable_data_cast(ptr, bytes_in_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200637 s->stkctr2_table->data_arg[STKTABLE_DT_BYTES_IN_RATE].u, bytes);
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200638 }
639
Willy Tarreau56123282010-08-06 19:06:56 +0200640 if (s->stkctr1_entry) {
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200641 void *ptr;
642
Willy Tarreau56123282010-08-06 19:06:56 +0200643 ptr = stktable_data_ptr(s->stkctr1_table,
644 s->stkctr1_entry,
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200645 STKTABLE_DT_BYTES_IN_CNT);
646 if (ptr)
647 stktable_data_cast(ptr, bytes_in_cnt) += bytes;
648
Willy Tarreau56123282010-08-06 19:06:56 +0200649 ptr = stktable_data_ptr(s->stkctr1_table,
650 s->stkctr1_entry,
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200651 STKTABLE_DT_BYTES_IN_RATE);
652 if (ptr)
653 update_freq_ctr_period(&stktable_data_cast(ptr, bytes_in_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200654 s->stkctr1_table->data_arg[STKTABLE_DT_BYTES_IN_RATE].u, bytes);
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200655 }
Willy Tarreau30e71012007-11-26 20:15:35 +0100656 }
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100657 }
658
Willy Tarreau30e71012007-11-26 20:15:35 +0100659 if (s->rep) {
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100660 bytes = s->rep->total - s->logs.bytes_out;
Willy Tarreau30e71012007-11-26 20:15:35 +0100661 s->logs.bytes_out = s->rep->total;
662 if (bytes) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100663 s->fe->fe_counters.bytes_out += bytes;
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100664
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100665 s->be->be_counters.bytes_out += bytes;
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100666
Willy Tarreau827aee92011-03-10 16:55:02 +0100667 if (target_srv(&s->target))
668 target_srv(&s->target)->counters.bytes_out += bytes;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200669
670 if (s->listener->counters)
671 s->listener->counters->bytes_out += bytes;
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200672
Willy Tarreau56123282010-08-06 19:06:56 +0200673 if (s->stkctr2_entry) {
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200674 void *ptr;
675
Willy Tarreau56123282010-08-06 19:06:56 +0200676 ptr = stktable_data_ptr(s->stkctr2_table,
677 s->stkctr2_entry,
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200678 STKTABLE_DT_BYTES_OUT_CNT);
679 if (ptr)
680 stktable_data_cast(ptr, bytes_out_cnt) += bytes;
681
Willy Tarreau56123282010-08-06 19:06:56 +0200682 ptr = stktable_data_ptr(s->stkctr2_table,
683 s->stkctr2_entry,
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200684 STKTABLE_DT_BYTES_OUT_RATE);
685 if (ptr)
686 update_freq_ctr_period(&stktable_data_cast(ptr, bytes_out_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200687 s->stkctr2_table->data_arg[STKTABLE_DT_BYTES_OUT_RATE].u, bytes);
Willy Tarreauf059a0f2010-08-03 16:29:52 +0200688 }
689
Willy Tarreau56123282010-08-06 19:06:56 +0200690 if (s->stkctr1_entry) {
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200691 void *ptr;
692
Willy Tarreau56123282010-08-06 19:06:56 +0200693 ptr = stktable_data_ptr(s->stkctr1_table,
694 s->stkctr1_entry,
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200695 STKTABLE_DT_BYTES_OUT_CNT);
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200696 if (ptr)
697 stktable_data_cast(ptr, bytes_out_cnt) += bytes;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200698
Willy Tarreau56123282010-08-06 19:06:56 +0200699 ptr = stktable_data_ptr(s->stkctr1_table,
700 s->stkctr1_entry,
Willy Tarreau6c59e0a2010-06-20 11:56:30 +0200701 STKTABLE_DT_BYTES_OUT_RATE);
702 if (ptr)
703 update_freq_ctr_period(&stktable_data_cast(ptr, bytes_out_rate),
Willy Tarreau56123282010-08-06 19:06:56 +0200704 s->stkctr1_table->data_arg[STKTABLE_DT_BYTES_OUT_RATE].u, bytes);
Willy Tarreau855e4bb2010-06-18 18:33:32 +0200705 }
Willy Tarreau30e71012007-11-26 20:15:35 +0100706 }
Krzysztof Piotr Oledzki583bc962007-11-24 22:12:47 +0100707 }
708}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200709
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100710/* This function is called with (si->state == SI_ST_CON) meaning that a
711 * connection was attempted and that the file descriptor is already allocated.
712 * We must check for establishment, error and abort. Possible output states
713 * are SI_ST_EST (established), SI_ST_CER (error), SI_ST_DIS (abort), and
714 * SI_ST_CON (no change). The function returns 0 if it switches to SI_ST_CER,
715 * otherwise 1.
716 */
Simon Hormandec5be42011-06-08 09:19:07 +0900717static int sess_update_st_con_tcp(struct session *s, struct stream_interface *si)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100718{
Willy Tarreau7421efb2012-07-02 15:11:27 +0200719 struct channel *req = si->ob;
720 struct channel *rep = si->ib;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100721
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100722 /* If we got an error, or if nothing happened and the connection timed
723 * out, we must give up. The CER state handler will take care of retry
724 * attempts and error reports.
725 */
726 if (unlikely(si->flags & (SI_FL_EXP|SI_FL_ERR))) {
Willy Tarreau127334e2009-03-28 10:47:26 +0100727 si->exp = TICK_ETERNITY;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100728 si->state = SI_ST_CER;
Willy Tarreaufb7508a2012-05-21 16:47:54 +0200729 fd_delete(si_fd(si));
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100730
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200731 conn_xprt_close(&si->conn);
Willy Tarreau0bd05ea2010-07-02 11:18:03 +0200732 if (si->release)
733 si->release(si);
734
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100735 if (si->err_type)
736 return 0;
737
Willy Tarreau827aee92011-03-10 16:55:02 +0100738 si->err_loc = target_srv(&s->target);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100739 if (si->flags & SI_FL_ERR)
740 si->err_type = SI_ET_CONN_ERR;
741 else
742 si->err_type = SI_ET_CONN_TO;
743 return 0;
744 }
745
746 /* OK, maybe we want to abort */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200747 if (unlikely((rep->flags & CF_SHUTW) ||
748 ((req->flags & CF_SHUTW_NOW) && /* FIXME: this should not prevent a connection from establishing */
749 ((!(req->flags & CF_WRITE_ACTIVITY) && channel_is_empty(req)) ||
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100750 s->be->options & PR_O_ABRT_CLOSE)))) {
751 /* give up */
Willy Tarreau73b013b2012-05-21 16:31:45 +0200752 si_shutw(si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100753 si->err_type |= SI_ET_CONN_ABRT;
Willy Tarreau827aee92011-03-10 16:55:02 +0100754 si->err_loc = target_srv(&s->target);
Willy Tarreau84455332009-03-15 22:34:05 +0100755 if (s->srv_error)
756 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100757 return 1;
758 }
759
760 /* we need to wait a bit more if there was no activity either */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200761 if (!(req->flags & CF_WRITE_ACTIVITY))
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100762 return 1;
763
764 /* OK, this means that a connection succeeded. The caller will be
765 * responsible for handling the transition from CON to EST.
766 */
767 s->logs.t_connect = tv_ms_elapsed(&s->logs.tv_accept, &now);
Willy Tarreau127334e2009-03-28 10:47:26 +0100768 si->exp = TICK_ETERNITY;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100769 si->state = SI_ST_EST;
770 si->err_type = SI_ET_NONE;
771 si->err_loc = NULL;
772 return 1;
773}
774
775/* This function is called with (si->state == SI_ST_CER) meaning that a
776 * previous connection attempt has failed and that the file descriptor
777 * has already been released. Possible causes include asynchronous error
778 * notification and time out. Possible output states are SI_ST_CLO when
779 * retries are exhausted, SI_ST_TAR when a delay is wanted before a new
780 * connection attempt, SI_ST_ASS when it's wise to retry on the same server,
781 * and SI_ST_REQ when an immediate redispatch is wanted. The buffers are
782 * marked as in error state. It returns 0.
783 */
Simon Hormandec5be42011-06-08 09:19:07 +0900784static int sess_update_st_cer(struct session *s, struct stream_interface *si)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100785{
786 /* we probably have to release last session from the server */
Willy Tarreau827aee92011-03-10 16:55:02 +0100787 if (target_srv(&s->target)) {
788 health_adjust(target_srv(&s->target), HANA_STATUS_L4_ERR);
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +0100789
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100790 if (s->flags & SN_CURR_SESS) {
791 s->flags &= ~SN_CURR_SESS;
Willy Tarreau827aee92011-03-10 16:55:02 +0100792 target_srv(&s->target)->cur_sess--;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100793 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100794 }
795
796 /* ensure that we have enough retries left */
Willy Tarreauee28de02010-06-01 09:51:00 +0200797 si->conn_retries--;
798 if (si->conn_retries < 0) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100799 if (!si->err_type) {
800 si->err_type = SI_ET_CONN_ERR;
Willy Tarreau827aee92011-03-10 16:55:02 +0100801 si->err_loc = target_srv(&s->target);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100802 }
803
Willy Tarreau827aee92011-03-10 16:55:02 +0100804 if (target_srv(&s->target))
805 target_srv(&s->target)->counters.failed_conns++;
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100806 s->be->be_counters.failed_conns++;
Willy Tarreaub89cfca2010-12-29 14:32:28 +0100807 sess_change_server(s, NULL);
Willy Tarreau827aee92011-03-10 16:55:02 +0100808 if (may_dequeue_tasks(target_srv(&s->target), s->be))
809 process_srv_queue(target_srv(&s->target));
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100810
811 /* shutw is enough so stop a connecting socket */
Willy Tarreau73b013b2012-05-21 16:31:45 +0200812 si_shutw(si);
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200813 si->ob->flags |= CF_WRITE_ERROR;
814 si->ib->flags |= CF_READ_ERROR;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100815
816 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +0100817 if (s->srv_error)
818 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100819 return 0;
820 }
821
822 /* If the "redispatch" option is set on the backend, we are allowed to
823 * retry on another server for the last retry. In order to achieve this,
824 * we must mark the session unassigned, and eventually clear the DIRECT
825 * bit to ignore any persistence cookie. We won't count a retry nor a
826 * redispatch yet, because this will depend on what server is selected.
827 */
Willy Tarreau827aee92011-03-10 16:55:02 +0100828 if (target_srv(&s->target) && si->conn_retries == 0 &&
Willy Tarreau4de91492010-01-22 19:10:05 +0100829 s->be->options & PR_O_REDISP && !(s->flags & SN_FORCE_PRST)) {
Willy Tarreaub89cfca2010-12-29 14:32:28 +0100830 sess_change_server(s, NULL);
Willy Tarreau827aee92011-03-10 16:55:02 +0100831 if (may_dequeue_tasks(target_srv(&s->target), s->be))
832 process_srv_queue(target_srv(&s->target));
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100833
834 s->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100835 si->state = SI_ST_REQ;
836 } else {
Willy Tarreau827aee92011-03-10 16:55:02 +0100837 if (target_srv(&s->target))
838 target_srv(&s->target)->counters.retries++;
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100839 s->be->be_counters.retries++;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100840 si->state = SI_ST_ASS;
841 }
842
843 if (si->flags & SI_FL_ERR) {
844 /* The error was an asynchronous connection error, and we will
845 * likely have to retry connecting to the same server, most
846 * likely leading to the same result. To avoid this, we wait
847 * one second before retrying.
848 */
849
850 if (!si->err_type)
851 si->err_type = SI_ET_CONN_ERR;
852
853 si->state = SI_ST_TAR;
854 si->exp = tick_add(now_ms, MS_TO_TICKS(1000));
855 return 0;
856 }
857 return 0;
858}
859
860/*
861 * This function handles the transition between the SI_ST_CON state and the
Willy Tarreau85e7d002010-05-31 11:57:51 +0200862 * SI_ST_EST state. It must only be called after switching from SI_ST_CON (or
Willy Tarreau26d8c592012-05-07 18:12:14 +0200863 * SI_ST_INI) to SI_ST_EST, but only when a ->proto is defined.
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100864 */
Simon Hormandec5be42011-06-08 09:19:07 +0900865static void sess_establish(struct session *s, struct stream_interface *si)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100866{
Willy Tarreau7421efb2012-07-02 15:11:27 +0200867 struct channel *req = si->ob;
868 struct channel *rep = si->ib;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100869
Willy Tarreau827aee92011-03-10 16:55:02 +0100870 if (target_srv(&s->target))
871 health_adjust(target_srv(&s->target), HANA_STATUS_L4_OK);
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +0100872
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100873 if (s->be->mode == PR_MODE_TCP) { /* let's allow immediate data connection in this case */
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100874 /* if the user wants to log as soon as possible, without counting
875 * bytes from the server, then this is the right moment. */
876 if (s->fe->to_log && !(s->logs.logwait & LW_BYTES)) {
877 s->logs.t_close = s->logs.t_connect; /* to get a valid end date */
Willy Tarreaua5555ec2008-11-30 19:02:32 +0100878 s->do_log(s);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100879 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100880 }
881 else {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100882 s->txn.rsp.msg_state = HTTP_MSG_RPBEFORE;
883 /* reset hdr_idx which was already initialized by the request.
884 * right now, the http parser does it.
885 * hdr_idx_init(&s->txn.hdr_idx);
886 */
887 }
888
Willy Tarreau4e5b8282009-08-16 22:57:50 +0200889 rep->analysers |= s->fe->fe_rsp_ana | s->be->be_rsp_ana;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200890 rep->flags |= CF_READ_ATTACHED; /* producer is now attached */
Willy Tarreau73b013b2012-05-21 16:31:45 +0200891 if (si_ctrl(si)) {
Willy Tarreaud04e8582010-05-31 12:31:35 +0200892 /* real connections have timeouts */
893 req->wto = s->be->timeout.server;
894 rep->rto = s->be->timeout.server;
895 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100896 req->wex = TICK_ETERNITY;
897}
898
899/* Update stream interface status for input states SI_ST_ASS, SI_ST_QUE, SI_ST_TAR.
900 * Other input states are simply ignored.
901 * Possible output states are SI_ST_CLO, SI_ST_TAR, SI_ST_ASS, SI_ST_REQ, SI_ST_CON.
902 * Flags must have previously been updated for timeouts and other conditions.
903 */
Simon Hormandec5be42011-06-08 09:19:07 +0900904static void sess_update_stream_int(struct session *s, struct stream_interface *si)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100905{
Willy Tarreau827aee92011-03-10 16:55:02 +0100906 struct server *srv = target_srv(&s->target);
907
Willy Tarreau02d6cfc2012-03-01 18:19:58 +0100908 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 +0100909 now_ms, __FUNCTION__,
910 s,
911 s->req, s->rep,
912 s->req->rex, s->rep->wex,
913 s->req->flags, s->rep->flags,
Cyril Bonté3aaba442012-09-23 14:19:12 +0200914 s->req->buf.i, s->req->buf.o, s->rep->buf.i, s->rep->buf.o, s->rep->cons->state, s->req->cons->state);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100915
916 if (si->state == SI_ST_ASS) {
917 /* Server assigned to connection request, we have to try to connect now */
918 int conn_err;
919
920 conn_err = connect_server(s);
Willy Tarreau827aee92011-03-10 16:55:02 +0100921 srv = target_srv(&s->target);
922
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100923 if (conn_err == SN_ERR_NONE) {
924 /* state = SI_ST_CON now */
Willy Tarreau827aee92011-03-10 16:55:02 +0100925 if (srv)
926 srv_inc_sess_ctr(srv);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100927 return;
928 }
929
930 /* We have received a synchronous error. We might have to
931 * abort, retry immediately or redispatch.
932 */
933 if (conn_err == SN_ERR_INTERNAL) {
934 if (!si->err_type) {
935 si->err_type = SI_ET_CONN_OTHER;
Willy Tarreau827aee92011-03-10 16:55:02 +0100936 si->err_loc = srv;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100937 }
938
Willy Tarreau827aee92011-03-10 16:55:02 +0100939 if (srv)
940 srv_inc_sess_ctr(srv);
941 if (srv)
942 srv->counters.failed_conns++;
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100943 s->be->be_counters.failed_conns++;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100944
945 /* release other sessions waiting for this server */
Willy Tarreaub89cfca2010-12-29 14:32:28 +0100946 sess_change_server(s, NULL);
Willy Tarreau827aee92011-03-10 16:55:02 +0100947 if (may_dequeue_tasks(srv, s->be))
948 process_srv_queue(srv);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100949
950 /* Failed and not retryable. */
Willy Tarreau73b013b2012-05-21 16:31:45 +0200951 si_shutr(si);
952 si_shutw(si);
Willy Tarreau03cdb7c2012-08-27 23:14:58 +0200953 si->ob->flags |= CF_WRITE_ERROR;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100954
955 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
956
957 /* no session was ever accounted for this server */
958 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +0100959 if (s->srv_error)
960 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +0100961 return;
962 }
963
964 /* We are facing a retryable error, but we don't want to run a
965 * turn-around now, as the problem is likely a source port
966 * allocation problem, so we want to retry now.
967 */
968 si->state = SI_ST_CER;
969 si->flags &= ~SI_FL_ERR;
970 sess_update_st_cer(s, si);
971 /* now si->state is one of SI_ST_CLO, SI_ST_TAR, SI_ST_ASS, SI_ST_REQ */
972 return;
973 }
974 else if (si->state == SI_ST_QUE) {
975 /* connection request was queued, check for any update */
976 if (!s->pend_pos) {
977 /* The connection is not in the queue anymore. Either
978 * we have a server connection slot available and we
979 * go directly to the assigned state, or we need to
980 * load-balance first and go to the INI state.
981 */
982 si->exp = TICK_ETERNITY;
983 if (unlikely(!(s->flags & SN_ASSIGNED)))
984 si->state = SI_ST_REQ;
985 else {
986 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
987 si->state = SI_ST_ASS;
988 }
989 return;
990 }
991
992 /* Connection request still in queue... */
993 if (si->flags & SI_FL_EXP) {
994 /* ... and timeout expired */
995 si->exp = TICK_ETERNITY;
996 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
Willy Tarreau827aee92011-03-10 16:55:02 +0100997 if (srv)
998 srv->counters.failed_conns++;
Willy Tarreau7d0aaf32011-03-10 23:25:56 +0100999 s->be->be_counters.failed_conns++;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001000 si_shutr(si);
1001 si_shutw(si);
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001002 si->ob->flags |= CF_WRITE_TIMEOUT;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001003 if (!si->err_type)
1004 si->err_type = SI_ET_QUEUE_TO;
1005 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +01001006 if (s->srv_error)
1007 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001008 return;
1009 }
1010
1011 /* Connection remains in queue, check if we have to abort it */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001012 if ((si->ob->flags & (CF_READ_ERROR)) ||
1013 ((si->ob->flags & CF_SHUTW_NOW) && /* empty and client aborted */
Willy Tarreau8e21bb92012-08-24 22:40:29 +02001014 (channel_is_empty(si->ob) || s->be->options & PR_O_ABRT_CLOSE))) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001015 /* give up */
1016 si->exp = TICK_ETERNITY;
1017 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
Willy Tarreau73b013b2012-05-21 16:31:45 +02001018 si_shutr(si);
1019 si_shutw(si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001020 si->err_type |= SI_ET_QUEUE_ABRT;
1021 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +01001022 if (s->srv_error)
1023 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001024 return;
1025 }
1026
1027 /* Nothing changed */
1028 return;
1029 }
1030 else if (si->state == SI_ST_TAR) {
1031 /* Connection request might be aborted */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001032 if ((si->ob->flags & (CF_READ_ERROR)) ||
1033 ((si->ob->flags & CF_SHUTW_NOW) && /* empty and client aborted */
Willy Tarreau8e21bb92012-08-24 22:40:29 +02001034 (channel_is_empty(si->ob) || s->be->options & PR_O_ABRT_CLOSE))) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001035 /* give up */
1036 si->exp = TICK_ETERNITY;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001037 si_shutr(si);
1038 si_shutw(si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001039 si->err_type |= SI_ET_CONN_ABRT;
1040 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +01001041 if (s->srv_error)
1042 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001043 return;
1044 }
1045
1046 if (!(si->flags & SI_FL_EXP))
1047 return; /* still in turn-around */
1048
1049 si->exp = TICK_ETERNITY;
1050
1051 /* we keep trying on the same server as long as the session is
1052 * marked "assigned".
1053 * FIXME: Should we force a redispatch attempt when the server is down ?
1054 */
1055 if (s->flags & SN_ASSIGNED)
1056 si->state = SI_ST_ASS;
1057 else
1058 si->state = SI_ST_REQ;
1059 return;
1060 }
1061}
1062
Simon Hormandec5be42011-06-08 09:19:07 +09001063/* Set correct session termination flags in case no analyser has done it. It
1064 * also counts a failed request if the server state has not reached the request
1065 * stage.
1066 */
1067static void sess_set_term_flags(struct session *s)
1068{
1069 if (!(s->flags & SN_FINST_MASK)) {
1070 if (s->si[1].state < SI_ST_REQ) {
1071
1072 s->fe->fe_counters.failed_req++;
1073 if (s->listener->counters)
1074 s->listener->counters->failed_req++;
1075
1076 s->flags |= SN_FINST_R;
1077 }
1078 else if (s->si[1].state == SI_ST_QUE)
1079 s->flags |= SN_FINST_Q;
1080 else if (s->si[1].state < SI_ST_EST)
1081 s->flags |= SN_FINST_C;
1082 else if (s->si[1].state == SI_ST_EST || s->si[1].prev_state == SI_ST_EST)
1083 s->flags |= SN_FINST_D;
1084 else
1085 s->flags |= SN_FINST_L;
1086 }
1087}
1088
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001089/* This function initiates a server connection request on a stream interface
1090 * already in SI_ST_REQ state. Upon success, the state goes to SI_ST_ASS,
1091 * indicating that a server has been assigned. It may also return SI_ST_QUE,
1092 * or SI_ST_CLO upon error.
1093 */
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001094static void sess_prepare_conn_req(struct session *s, struct stream_interface *si)
1095{
1096 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 +01001097 now_ms, __FUNCTION__,
1098 s,
1099 s->req, s->rep,
1100 s->req->rex, s->rep->wex,
1101 s->req->flags, s->rep->flags,
Cyril Bonté3aaba442012-09-23 14:19:12 +02001102 s->req->buf.i, s->req->buf.o, s->rep->buf.i, s->rep->buf.o, s->rep->cons->state, s->req->cons->state);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001103
1104 if (si->state != SI_ST_REQ)
1105 return;
1106
1107 /* Try to assign a server */
1108 if (srv_redispatch_connect(s) != 0) {
1109 /* We did not get a server. Either we queued the
1110 * connection request, or we encountered an error.
1111 */
1112 if (si->state == SI_ST_QUE)
1113 return;
1114
1115 /* we did not get any server, let's check the cause */
Willy Tarreau73b013b2012-05-21 16:31:45 +02001116 si_shutr(si);
1117 si_shutw(si);
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001118 si->ob->flags |= CF_WRITE_ERROR;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001119 if (!si->err_type)
1120 si->err_type = SI_ET_CONN_OTHER;
1121 si->state = SI_ST_CLO;
Willy Tarreau0cac36f2008-11-30 20:44:17 +01001122 if (s->srv_error)
1123 s->srv_error(s, si);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001124 return;
1125 }
1126
1127 /* The server is assigned */
1128 s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
1129 si->state = SI_ST_ASS;
1130}
1131
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001132/* This stream analyser checks the switching rules and changes the backend
Willy Tarreau4de91492010-01-22 19:10:05 +01001133 * if appropriate. The default_backend rule is also considered, then the
1134 * target backend's forced persistence rules are also evaluated last if any.
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001135 * It returns 1 if the processing can continue on next analysers, or zero if it
1136 * either needs more data or wants to immediately abort the request.
1137 */
Willy Tarreau7421efb2012-07-02 15:11:27 +02001138static int process_switching_rules(struct session *s, struct channel *req, int an_bit)
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001139{
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001140 struct persist_rule *prst_rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01001141
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001142 req->analysers &= ~an_bit;
1143 req->analyse_exp = TICK_ETERNITY;
1144
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001145 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 +02001146 now_ms, __FUNCTION__,
1147 s,
1148 req,
1149 req->rex, req->wex,
1150 req->flags,
Cyril Bonté3aaba442012-09-23 14:19:12 +02001151 req->buf.i,
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001152 req->analysers);
1153
1154 /* now check whether we have some switching rules for this request */
1155 if (!(s->flags & SN_BE_ASSIGNED)) {
1156 struct switching_rule *rule;
1157
1158 list_for_each_entry(rule, &s->fe->switching_rules, list) {
1159 int ret;
1160
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001161 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 +02001162 ret = acl_pass(ret);
1163 if (rule->cond->pol == ACL_COND_UNLESS)
1164 ret = !ret;
1165
1166 if (ret) {
Willy Tarreaubedb9ba2009-07-12 08:27:39 +02001167 if (!session_set_backend(s, rule->be.backend))
1168 goto sw_failed;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001169 break;
1170 }
1171 }
1172
1173 /* To ensure correct connection accounting on the backend, we
1174 * have to assign one if it was not set (eg: a listen). This
1175 * measure also takes care of correctly setting the default
1176 * backend if any.
1177 */
1178 if (!(s->flags & SN_BE_ASSIGNED))
Willy Tarreaubedb9ba2009-07-12 08:27:39 +02001179 if (!session_set_backend(s, s->fe->defbe.be ? s->fe->defbe.be : s->be))
1180 goto sw_failed;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001181 }
1182
Willy Tarreaufb356202010-08-03 14:02:05 +02001183 /* we don't want to run the TCP or HTTP filters again if the backend has not changed */
1184 if (s->fe == s->be) {
1185 s->req->analysers &= ~AN_REQ_INSPECT_BE;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001186 s->req->analysers &= ~AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaufb356202010-08-03 14:02:05 +02001187 }
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001188
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001189 /* 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 +01001190 * persistence rule, and report that in the session.
1191 */
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001192 list_for_each_entry(prst_rule, &s->be->persist_rules, list) {
Willy Tarreau4de91492010-01-22 19:10:05 +01001193 int ret = 1;
1194
1195 if (prst_rule->cond) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001196 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 +01001197 ret = acl_pass(ret);
1198 if (prst_rule->cond->pol == ACL_COND_UNLESS)
1199 ret = !ret;
1200 }
1201
1202 if (ret) {
1203 /* no rule, or the rule matches */
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001204 if (prst_rule->type == PERSIST_TYPE_FORCE) {
1205 s->flags |= SN_FORCE_PRST;
1206 } else {
1207 s->flags |= SN_IGNORE_PRST;
1208 }
Willy Tarreau4de91492010-01-22 19:10:05 +01001209 break;
1210 }
1211 }
1212
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001213 return 1;
Willy Tarreaubedb9ba2009-07-12 08:27:39 +02001214
1215 sw_failed:
1216 /* immediately abort this request in case of allocation failure */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001217 channel_abort(s->req);
1218 channel_abort(s->rep);
Willy Tarreaubedb9ba2009-07-12 08:27:39 +02001219
1220 if (!(s->flags & SN_ERR_MASK))
1221 s->flags |= SN_ERR_RESOURCE;
1222 if (!(s->flags & SN_FINST_MASK))
1223 s->flags |= SN_FINST_R;
1224
1225 s->txn.status = 500;
1226 s->req->analysers = 0;
1227 s->req->analyse_exp = TICK_ETERNITY;
1228 return 0;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001229}
1230
Willy Tarreau4a5cade2012-04-05 21:09:48 +02001231/* This stream analyser works on a request. It applies all use-server rules on
1232 * it then returns 1. The data must already be present in the buffer otherwise
1233 * they won't match. It always returns 1.
1234 */
Willy Tarreau7421efb2012-07-02 15:11:27 +02001235static int process_server_rules(struct session *s, struct channel *req, int an_bit)
Willy Tarreau4a5cade2012-04-05 21:09:48 +02001236{
1237 struct proxy *px = s->be;
1238 struct server_rule *rule;
1239
1240 DPRINTF(stderr,"[%u] %s: session=%p b=%p, exp(r,w)=%u,%u bf=%08x bl=%d analysers=%02x\n",
1241 now_ms, __FUNCTION__,
1242 s,
1243 req,
1244 req->rex, req->wex,
1245 req->flags,
Cyril Bonté3aaba442012-09-23 14:19:12 +02001246 req->buf.i + req->buf.o,
Willy Tarreau4a5cade2012-04-05 21:09:48 +02001247 req->analysers);
1248
1249 if (!(s->flags & SN_ASSIGNED)) {
1250 list_for_each_entry(rule, &px->server_rules, list) {
1251 int ret;
1252
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001253 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 +02001254 ret = acl_pass(ret);
1255 if (rule->cond->pol == ACL_COND_UNLESS)
1256 ret = !ret;
1257
1258 if (ret) {
1259 struct server *srv = rule->srv.ptr;
1260
1261 if ((srv->state & SRV_RUNNING) ||
1262 (px->options & PR_O_PERSIST) ||
1263 (s->flags & SN_FORCE_PRST)) {
1264 s->flags |= SN_DIRECT | SN_ASSIGNED;
1265 set_target_server(&s->target, srv);
1266 break;
1267 }
1268 /* if the server is not UP, let's go on with next rules
1269 * just in case another one is suited.
1270 */
1271 }
1272 }
1273 }
1274
1275 req->analysers &= ~an_bit;
1276 req->analyse_exp = TICK_ETERNITY;
1277 return 1;
1278}
1279
Emeric Brun1d33b292010-01-04 15:47:17 +01001280/* This stream analyser works on a request. It applies all sticking rules on
1281 * it then returns 1. The data must already be present in the buffer otherwise
1282 * they won't match. It always returns 1.
1283 */
Willy Tarreau7421efb2012-07-02 15:11:27 +02001284static int process_sticking_rules(struct session *s, struct channel *req, int an_bit)
Emeric Brun1d33b292010-01-04 15:47:17 +01001285{
1286 struct proxy *px = s->be;
1287 struct sticking_rule *rule;
1288
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001289 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 +01001290 now_ms, __FUNCTION__,
1291 s,
1292 req,
1293 req->rex, req->wex,
1294 req->flags,
Cyril Bonté3aaba442012-09-23 14:19:12 +02001295 req->buf.i,
Emeric Brun1d33b292010-01-04 15:47:17 +01001296 req->analysers);
1297
1298 list_for_each_entry(rule, &px->sticking_rules, list) {
1299 int ret = 1 ;
1300 int i;
1301
1302 for (i = 0; i < s->store_count; i++) {
1303 if (rule->table.t == s->store[i].table)
1304 break;
1305 }
1306
1307 if (i != s->store_count)
1308 continue;
1309
1310 if (rule->cond) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001311 ret = acl_exec_cond(rule->cond, px, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
Emeric Brun1d33b292010-01-04 15:47:17 +01001312 ret = acl_pass(ret);
1313 if (rule->cond->pol == ACL_COND_UNLESS)
1314 ret = !ret;
1315 }
1316
1317 if (ret) {
1318 struct stktable_key *key;
1319
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001320 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 +01001321 if (!key)
1322 continue;
1323
1324 if (rule->flags & STK_IS_MATCH) {
1325 struct stksess *ts;
1326
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001327 if ((ts = stktable_lookup_key(rule->table.t, key)) != NULL) {
Emeric Brun1d33b292010-01-04 15:47:17 +01001328 if (!(s->flags & SN_ASSIGNED)) {
1329 struct eb32_node *node;
Willy Tarreau13c29de2010-06-06 16:40:39 +02001330 void *ptr;
Emeric Brun1d33b292010-01-04 15:47:17 +01001331
1332 /* srv found in table */
Willy Tarreau13c29de2010-06-06 16:40:39 +02001333 ptr = stktable_data_ptr(rule->table.t, ts, STKTABLE_DT_SERVER_ID);
1334 node = eb32_lookup(&px->conf.used_server_id, stktable_data_cast(ptr, server_id));
Emeric Brun1d33b292010-01-04 15:47:17 +01001335 if (node) {
1336 struct server *srv;
1337
1338 srv = container_of(node, struct server, conf.id);
Willy Tarreau4de91492010-01-22 19:10:05 +01001339 if ((srv->state & SRV_RUNNING) ||
1340 (px->options & PR_O_PERSIST) ||
1341 (s->flags & SN_FORCE_PRST)) {
Emeric Brun1d33b292010-01-04 15:47:17 +01001342 s->flags |= SN_DIRECT | SN_ASSIGNED;
Willy Tarreau9e000c62011-03-10 14:03:36 +01001343 set_target_server(&s->target, srv);
Emeric Brun1d33b292010-01-04 15:47:17 +01001344 }
1345 }
1346 }
Emeric Brun85e77c72010-09-23 18:16:52 +02001347 stktable_touch(rule->table.t, ts, 1);
Emeric Brun1d33b292010-01-04 15:47:17 +01001348 }
1349 }
1350 if (rule->flags & STK_IS_STORE) {
1351 if (s->store_count < (sizeof(s->store) / sizeof(s->store[0]))) {
1352 struct stksess *ts;
1353
1354 ts = stksess_new(rule->table.t, key);
1355 if (ts) {
1356 s->store[s->store_count].table = rule->table.t;
1357 s->store[s->store_count++].ts = ts;
1358 }
1359 }
1360 }
1361 }
1362 }
1363
1364 req->analysers &= ~an_bit;
1365 req->analyse_exp = TICK_ETERNITY;
1366 return 1;
1367}
1368
1369/* This stream analyser works on a response. It applies all store rules on it
1370 * then returns 1. The data must already be present in the buffer otherwise
1371 * they won't match. It always returns 1.
1372 */
Willy Tarreau7421efb2012-07-02 15:11:27 +02001373static int process_store_rules(struct session *s, struct channel *rep, int an_bit)
Emeric Brun1d33b292010-01-04 15:47:17 +01001374{
1375 struct proxy *px = s->be;
1376 struct sticking_rule *rule;
1377 int i;
1378
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001379 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 +01001380 now_ms, __FUNCTION__,
1381 s,
Willy Tarreau2e2b3eb2010-02-09 20:55:44 +01001382 rep,
1383 rep->rex, rep->wex,
1384 rep->flags,
Cyril Bonté3aaba442012-09-23 14:19:12 +02001385 rep->buf.i,
Willy Tarreau2e2b3eb2010-02-09 20:55:44 +01001386 rep->analysers);
Emeric Brun1d33b292010-01-04 15:47:17 +01001387
1388 list_for_each_entry(rule, &px->storersp_rules, list) {
1389 int ret = 1 ;
1390 int storereqidx = -1;
1391
1392 for (i = 0; i < s->store_count; i++) {
1393 if (rule->table.t == s->store[i].table) {
1394 if (!(s->store[i].flags))
1395 storereqidx = i;
1396 break;
1397 }
1398 }
1399
1400 if ((i != s->store_count) && (storereqidx == -1))
1401 continue;
1402
1403 if (rule->cond) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001404 ret = acl_exec_cond(rule->cond, px, s, &s->txn, SMP_OPT_DIR_RES|SMP_OPT_FINAL);
Emeric Brun1d33b292010-01-04 15:47:17 +01001405 ret = acl_pass(ret);
1406 if (rule->cond->pol == ACL_COND_UNLESS)
1407 ret = !ret;
1408 }
1409
1410 if (ret) {
1411 struct stktable_key *key;
1412
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001413 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 +01001414 if (!key)
1415 continue;
1416
1417 if (storereqidx != -1) {
Willy Tarreau393379c2010-06-06 12:11:37 +02001418 stksess_setkey(s->store[storereqidx].table, s->store[storereqidx].ts, key);
Emeric Brun1d33b292010-01-04 15:47:17 +01001419 s->store[storereqidx].flags = 1;
1420 }
1421 else if (s->store_count < (sizeof(s->store) / sizeof(s->store[0]))) {
1422 struct stksess *ts;
1423
1424 ts = stksess_new(rule->table.t, key);
1425 if (ts) {
1426 s->store[s->store_count].table = rule->table.t;
1427 s->store[s->store_count].flags = 1;
1428 s->store[s->store_count++].ts = ts;
1429 }
1430 }
1431 }
1432 }
1433
1434 /* process store request and store response */
1435 for (i = 0; i < s->store_count; i++) {
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001436 struct stksess *ts;
Willy Tarreau13c29de2010-06-06 16:40:39 +02001437 void *ptr;
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001438
Simon Hormanfa461682011-06-25 09:39:49 +09001439 if (target_srv(&s->target) && target_srv(&s->target)->state & SRV_NON_STICK) {
1440 stksess_free(s->store[i].table, s->store[i].ts);
1441 s->store[i].ts = NULL;
1442 continue;
1443 }
1444
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001445 ts = stktable_lookup(s->store[i].table, s->store[i].ts);
1446 if (ts) {
1447 /* the entry already existed, we can free ours */
Emeric Brun85e77c72010-09-23 18:16:52 +02001448 stktable_touch(s->store[i].table, ts, 1);
Emeric Brun1d33b292010-01-04 15:47:17 +01001449 stksess_free(s->store[i].table, s->store[i].ts);
Emeric Brun1d33b292010-01-04 15:47:17 +01001450 }
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001451 else
Emeric Brun85e77c72010-09-23 18:16:52 +02001452 ts = stktable_store(s->store[i].table, s->store[i].ts, 1);
Willy Tarreauf16d2b82010-06-06 15:38:59 +02001453
1454 s->store[i].ts = NULL;
Willy Tarreau13c29de2010-06-06 16:40:39 +02001455 ptr = stktable_data_ptr(s->store[i].table, ts, STKTABLE_DT_SERVER_ID);
Willy Tarreau827aee92011-03-10 16:55:02 +01001456 stktable_data_cast(ptr, server_id) = target_srv(&s->target)->puid;
Emeric Brun1d33b292010-01-04 15:47:17 +01001457 }
Willy Tarreau2a164ee2010-06-18 09:57:45 +02001458 s->store_count = 0; /* everything is stored */
Emeric Brun1d33b292010-01-04 15:47:17 +01001459
1460 rep->analysers &= ~an_bit;
1461 rep->analyse_exp = TICK_ETERNITY;
1462 return 1;
1463}
1464
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001465/* This macro is very specific to the function below. See the comments in
1466 * process_session() below to understand the logic and the tests.
1467 */
1468#define UPDATE_ANALYSERS(real, list, back, flag) { \
1469 list = (((list) & ~(flag)) | ~(back)) & (real); \
1470 back = real; \
1471 if (!(list)) \
1472 break; \
1473 if (((list) ^ ((list) & ((list) - 1))) < (flag)) \
1474 continue; \
1475}
1476
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001477/* Processes the client, server, request and response jobs of a session task,
1478 * then puts it back to the wait queue in a clean state, or cleans up its
1479 * resources if it must be deleted. Returns in <next> the date the task wants
1480 * to be woken up, or TICK_ETERNITY. In order not to call all functions for
1481 * nothing too many times, the request and response buffers flags are monitored
1482 * and each function is called only if at least another function has changed at
1483 * least one flag it is interested in.
1484 */
Willy Tarreau26c25062009-03-08 09:38:41 +01001485struct task *process_session(struct task *t)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001486{
Willy Tarreau827aee92011-03-10 16:55:02 +01001487 struct server *srv;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001488 struct session *s = t->context;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001489 unsigned int rqf_last, rpf_last;
Willy Tarreau815a9b22010-07-27 17:15:12 +02001490 unsigned int rq_prod_last, rq_cons_last;
1491 unsigned int rp_cons_last, rp_prod_last;
Willy Tarreau576507f2010-01-07 00:09:04 +01001492 unsigned int req_ana_back;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001493
1494 //DPRINTF(stderr, "%s:%d: cs=%d ss=%d(%d) rqf=0x%08x rpf=0x%08x\n", __FUNCTION__, __LINE__,
1495 // s->si[0].state, s->si[1].state, s->si[1].err_type, s->req->flags, s->rep->flags);
1496
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01001497 /* this data may be no longer valid, clear it */
1498 memset(&s->txn.auth, 0, sizeof(s->txn.auth));
1499
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001500 /* This flag must explicitly be set every time */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001501 s->req->flags &= ~CF_READ_NOEXP;
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001502
1503 /* Keep a copy of req/rep flags so that we can detect shutdowns */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001504 rqf_last = s->req->flags & ~CF_MASK_ANALYSER;
1505 rpf_last = s->rep->flags & ~CF_MASK_ANALYSER;
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001506
Willy Tarreau89f7ef22009-09-05 20:57:35 +02001507 /* we don't want the stream interface functions to recursively wake us up */
1508 if (s->req->prod->owner == t)
1509 s->req->prod->flags |= SI_FL_DONT_WAKE;
1510 if (s->req->cons->owner == t)
1511 s->req->cons->flags |= SI_FL_DONT_WAKE;
1512
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001513 /* 1a: Check for low level timeouts if needed. We just set a flag on
1514 * stream interfaces when their timeouts have expired.
1515 */
1516 if (unlikely(t->state & TASK_WOKEN_TIMER)) {
1517 stream_int_check_timeouts(&s->si[0]);
1518 stream_int_check_timeouts(&s->si[1]);
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001519
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001520 /* check channel timeouts, and close the corresponding stream interfaces
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001521 * for future reads or writes. Note: this will also concern upper layers
1522 * but we do not touch any other flag. We must be careful and correctly
1523 * detect state changes when calling them.
1524 */
1525
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001526 channel_check_timeouts(s->req);
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001527
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001528 if (unlikely((s->req->flags & (CF_SHUTW|CF_WRITE_TIMEOUT)) == CF_WRITE_TIMEOUT)) {
Willy Tarreau14641402009-12-29 14:49:56 +01001529 s->req->cons->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001530 si_shutw(s->req->cons);
Willy Tarreau14641402009-12-29 14:49:56 +01001531 }
1532
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001533 if (unlikely((s->req->flags & (CF_SHUTR|CF_READ_TIMEOUT)) == CF_READ_TIMEOUT)) {
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02001534 if (s->req->prod->flags & SI_FL_NOHALF)
1535 s->req->prod->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001536 si_shutr(s->req->prod);
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02001537 }
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001538
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001539 channel_check_timeouts(s->rep);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001540
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001541 if (unlikely((s->rep->flags & (CF_SHUTW|CF_WRITE_TIMEOUT)) == CF_WRITE_TIMEOUT)) {
Willy Tarreau14641402009-12-29 14:49:56 +01001542 s->rep->cons->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001543 si_shutw(s->rep->cons);
Willy Tarreau14641402009-12-29 14:49:56 +01001544 }
1545
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001546 if (unlikely((s->rep->flags & (CF_SHUTR|CF_READ_TIMEOUT)) == CF_READ_TIMEOUT)) {
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02001547 if (s->rep->prod->flags & SI_FL_NOHALF)
1548 s->rep->prod->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02001549 si_shutr(s->rep->prod);
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02001550 }
Willy Tarreaub67a9b82009-06-21 22:03:51 +02001551 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001552
1553 /* 1b: check for low-level errors reported at the stream interface.
1554 * First we check if it's a retryable error (in which case we don't
1555 * want to tell the buffer). Otherwise we report the error one level
1556 * upper by setting flags into the buffers. Note that the side towards
1557 * the client cannot have connect (hence retryable) errors. Also, the
1558 * connection setup code must be able to deal with any type of abort.
1559 */
Willy Tarreau827aee92011-03-10 16:55:02 +01001560 srv = target_srv(&s->target);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001561 if (unlikely(s->si[0].flags & SI_FL_ERR)) {
1562 if (s->si[0].state == SI_ST_EST || s->si[0].state == SI_ST_DIS) {
Willy Tarreau73b013b2012-05-21 16:31:45 +02001563 si_shutr(&s->si[0]);
1564 si_shutw(&s->si[0]);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001565 stream_int_report_error(&s->si[0]);
Willy Tarreau05cb29b2008-12-14 11:44:04 +01001566 if (!(s->req->analysers) && !(s->rep->analysers)) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001567 s->be->be_counters.cli_aborts++;
1568 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001569 if (srv)
1570 srv->counters.cli_aborts++;
Willy Tarreau05cb29b2008-12-14 11:44:04 +01001571 if (!(s->flags & SN_ERR_MASK))
1572 s->flags |= SN_ERR_CLICL;
1573 if (!(s->flags & SN_FINST_MASK))
1574 s->flags |= SN_FINST_D;
1575 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001576 }
1577 }
1578
1579 if (unlikely(s->si[1].flags & SI_FL_ERR)) {
1580 if (s->si[1].state == SI_ST_EST || s->si[1].state == SI_ST_DIS) {
Willy Tarreau73b013b2012-05-21 16:31:45 +02001581 si_shutr(&s->si[1]);
1582 si_shutw(&s->si[1]);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001583 stream_int_report_error(&s->si[1]);
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001584 s->be->be_counters.failed_resp++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001585 if (srv)
1586 srv->counters.failed_resp++;
Willy Tarreau05cb29b2008-12-14 11:44:04 +01001587 if (!(s->req->analysers) && !(s->rep->analysers)) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001588 s->be->be_counters.srv_aborts++;
1589 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001590 if (srv)
1591 srv->counters.srv_aborts++;
Willy Tarreau05cb29b2008-12-14 11:44:04 +01001592 if (!(s->flags & SN_ERR_MASK))
1593 s->flags |= SN_ERR_SRVCL;
1594 if (!(s->flags & SN_FINST_MASK))
1595 s->flags |= SN_FINST_D;
1596 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001597 }
1598 /* note: maybe we should process connection errors here ? */
1599 }
1600
1601 if (s->si[1].state == SI_ST_CON) {
1602 /* we were trying to establish a connection on the server side,
1603 * maybe it succeeded, maybe it failed, maybe we timed out, ...
1604 */
1605 if (unlikely(!sess_update_st_con_tcp(s, &s->si[1])))
1606 sess_update_st_cer(s, &s->si[1]);
1607 else if (s->si[1].state == SI_ST_EST)
1608 sess_establish(s, &s->si[1]);
1609
1610 /* state is now one of SI_ST_CON (still in progress), SI_ST_EST
1611 * (established), SI_ST_DIS (abort), SI_ST_CLO (last error),
1612 * SI_ST_ASS/SI_ST_TAR/SI_ST_REQ for retryable errors.
1613 */
1614 }
1615
Willy Tarreau815a9b22010-07-27 17:15:12 +02001616 rq_prod_last = s->si[0].state;
1617 rq_cons_last = s->si[1].state;
1618 rp_cons_last = s->si[0].state;
1619 rp_prod_last = s->si[1].state;
1620
1621 resync_stream_interface:
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001622 /* Check for connection closure */
1623
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001624 DPRINTF(stderr,
Willy Tarreau02d6cfc2012-03-01 18:19:58 +01001625 "[%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 +01001626 now_ms, __FUNCTION__, __LINE__,
1627 t,
1628 s, s->flags,
1629 s->req, s->rep,
1630 s->req->rex, s->rep->wex,
1631 s->req->flags, s->rep->flags,
Cyril Bonté3aaba442012-09-23 14:19:12 +02001632 s->req->buf.i, s->req->buf.o, s->rep->buf.i, s->rep->buf.o, s->rep->cons->state, s->req->cons->state,
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001633 s->rep->cons->err_type, s->req->cons->err_type,
Willy Tarreauee28de02010-06-01 09:51:00 +02001634 s->req->cons->conn_retries);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001635
1636 /* nothing special to be done on client side */
1637 if (unlikely(s->req->prod->state == SI_ST_DIS))
1638 s->req->prod->state = SI_ST_CLO;
1639
1640 /* When a server-side connection is released, we have to count it and
1641 * check for pending connections on this server.
1642 */
1643 if (unlikely(s->req->cons->state == SI_ST_DIS)) {
1644 s->req->cons->state = SI_ST_CLO;
Willy Tarreau827aee92011-03-10 16:55:02 +01001645 srv = target_srv(&s->target);
1646 if (srv) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001647 if (s->flags & SN_CURR_SESS) {
1648 s->flags &= ~SN_CURR_SESS;
Willy Tarreau827aee92011-03-10 16:55:02 +01001649 srv->cur_sess--;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001650 }
1651 sess_change_server(s, NULL);
Willy Tarreau827aee92011-03-10 16:55:02 +01001652 if (may_dequeue_tasks(srv, s->be))
1653 process_srv_queue(srv);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001654 }
1655 }
1656
1657 /*
1658 * Note: of the transient states (REQ, CER, DIS), only REQ may remain
1659 * at this point.
1660 */
1661
Willy Tarreau0be0ef92009-03-08 19:20:25 +01001662 resync_request:
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001663 /* Analyse request */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001664 if (((s->req->flags & ~rqf_last) & CF_MASK_ANALYSER) ||
1665 ((s->req->flags ^ rqf_last) & CF_MASK_STATIC) ||
Willy Tarreau815a9b22010-07-27 17:15:12 +02001666 s->si[0].state != rq_prod_last ||
1667 s->si[1].state != rq_cons_last) {
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001668 unsigned int flags = s->req->flags;
1669
1670 if (s->req->prod->state >= SI_ST_EST) {
Willy Tarreaue34070e2010-01-08 00:32:27 +01001671 int max_loops = global.tune.maxpollevents;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001672 unsigned int ana_list;
1673 unsigned int ana_back;
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001674
Willy Tarreau90deb182010-01-07 00:20:41 +01001675 /* it's up to the analysers to stop new connections,
1676 * disable reading or closing. Note: if an analyser
1677 * disables any of these bits, it is responsible for
1678 * enabling them again when it disables itself, so
1679 * that other analysers are called in similar conditions.
1680 */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001681 channel_auto_read(s->req);
1682 channel_auto_connect(s->req);
1683 channel_auto_close(s->req);
Willy Tarreauedcf6682008-11-30 23:15:34 +01001684
1685 /* We will call all analysers for which a bit is set in
1686 * s->req->analysers, following the bit order from LSB
1687 * to MSB. The analysers must remove themselves from
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001688 * the list when not needed. Any analyser may return 0
1689 * to break out of the loop, either because of missing
1690 * data to take a decision, or because it decides to
1691 * kill the session. We loop at least once through each
1692 * analyser, and we may loop again if other analysers
1693 * are added in the middle.
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001694 *
1695 * We build a list of analysers to run. We evaluate all
1696 * of these analysers in the order of the lower bit to
1697 * the higher bit. This ordering is very important.
1698 * An analyser will often add/remove other analysers,
1699 * including itself. Any changes to itself have no effect
1700 * on the loop. If it removes any other analysers, we
1701 * want those analysers not to be called anymore during
1702 * this loop. If it adds an analyser that is located
1703 * after itself, we want it to be scheduled for being
1704 * processed during the loop. If it adds an analyser
1705 * which is located before it, we want it to switch to
1706 * it immediately, even if it has already been called
1707 * once but removed since.
1708 *
1709 * In order to achieve this, we compare the analyser
1710 * list after the call with a copy of it before the
1711 * call. The work list is fed with analyser bits that
1712 * appeared during the call. Then we compare previous
1713 * work list with the new one, and check the bits that
1714 * appeared. If the lowest of these bits is lower than
1715 * the current bit, it means we have enabled a previous
1716 * analyser and must immediately loop again.
Willy Tarreauedcf6682008-11-30 23:15:34 +01001717 */
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001718
1719 ana_list = ana_back = s->req->analysers;
Willy Tarreaue34070e2010-01-08 00:32:27 +01001720 while (ana_list && max_loops--) {
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001721 /* Warning! ensure that analysers are always placed in ascending order! */
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001722
Willy Tarreaufb356202010-08-03 14:02:05 +02001723 if (ana_list & AN_REQ_INSPECT_FE) {
1724 if (!tcp_inspect_request(s, s->req, AN_REQ_INSPECT_FE))
Willy Tarreauedcf6682008-11-30 23:15:34 +01001725 break;
Willy Tarreaufb356202010-08-03 14:02:05 +02001726 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_INSPECT_FE);
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001727 }
Willy Tarreauedcf6682008-11-30 23:15:34 +01001728
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001729 if (ana_list & AN_REQ_WAIT_HTTP) {
Willy Tarreau3a816292009-07-07 10:55:49 +02001730 if (!http_wait_for_request(s, s->req, AN_REQ_WAIT_HTTP))
Willy Tarreaud787e662009-07-07 10:14:51 +02001731 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001732 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_WAIT_HTTP);
Willy Tarreaud787e662009-07-07 10:14:51 +02001733 }
1734
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001735 if (ana_list & AN_REQ_HTTP_PROCESS_FE) {
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001736 if (!http_process_req_common(s, s->req, AN_REQ_HTTP_PROCESS_FE, s->fe))
1737 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001738 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_PROCESS_FE);
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001739 }
1740
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001741 if (ana_list & AN_REQ_SWITCHING_RULES) {
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001742 if (!process_switching_rules(s, s->req, AN_REQ_SWITCHING_RULES))
1743 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001744 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_SWITCHING_RULES);
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001745 }
1746
Willy Tarreaufb356202010-08-03 14:02:05 +02001747 if (ana_list & AN_REQ_INSPECT_BE) {
1748 if (!tcp_inspect_request(s, s->req, AN_REQ_INSPECT_BE))
1749 break;
1750 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_INSPECT_BE);
1751 }
1752
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001753 if (ana_list & AN_REQ_HTTP_PROCESS_BE) {
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001754 if (!http_process_req_common(s, s->req, AN_REQ_HTTP_PROCESS_BE, s->be))
1755 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001756 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_PROCESS_BE);
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02001757 }
1758
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001759 if (ana_list & AN_REQ_HTTP_TARPIT) {
Willy Tarreau3a816292009-07-07 10:55:49 +02001760 if (!http_process_tarpit(s, s->req, AN_REQ_HTTP_TARPIT))
Willy Tarreau60b85b02008-11-30 23:28:40 +01001761 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001762 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_TARPIT);
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001763 }
Willy Tarreau60b85b02008-11-30 23:28:40 +01001764
Willy Tarreau4a5cade2012-04-05 21:09:48 +02001765 if (ana_list & AN_REQ_SRV_RULES) {
1766 if (!process_server_rules(s, s->req, AN_REQ_SRV_RULES))
1767 break;
1768 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_SRV_RULES);
1769 }
1770
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001771 if (ana_list & AN_REQ_HTTP_INNER) {
Willy Tarreauc465fd72009-08-31 00:17:18 +02001772 if (!http_process_request(s, s->req, AN_REQ_HTTP_INNER))
1773 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001774 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_INNER);
Willy Tarreauc465fd72009-08-31 00:17:18 +02001775 }
1776
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001777 if (ana_list & AN_REQ_HTTP_BODY) {
Willy Tarreau3a816292009-07-07 10:55:49 +02001778 if (!http_process_request_body(s, s->req, AN_REQ_HTTP_BODY))
Willy Tarreaud34af782008-11-30 23:36:37 +01001779 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001780 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_BODY);
Willy Tarreau1a52dbd2009-06-28 19:37:53 +02001781 }
Emeric Brun647caf12009-06-30 17:57:00 +02001782
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001783 if (ana_list & AN_REQ_PRST_RDP_COOKIE) {
Emeric Brun647caf12009-06-30 17:57:00 +02001784 if (!tcp_persist_rdp_cookie(s, s->req, AN_REQ_PRST_RDP_COOKIE))
1785 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001786 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_PRST_RDP_COOKIE);
Emeric Brun647caf12009-06-30 17:57:00 +02001787 }
Willy Tarreaud98cf932009-12-27 22:54:55 +01001788
Emeric Brun1d33b292010-01-04 15:47:17 +01001789 if (ana_list & AN_REQ_STICKING_RULES) {
1790 if (!process_sticking_rules(s, s->req, AN_REQ_STICKING_RULES))
1791 break;
1792 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_STICKING_RULES);
1793 }
1794
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001795 if (ana_list & AN_REQ_HTTP_XFER_BODY) {
Willy Tarreaud98cf932009-12-27 22:54:55 +01001796 if (!http_request_forward_body(s, s->req, AN_REQ_HTTP_XFER_BODY))
1797 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001798 UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_HTTP_XFER_BODY);
Willy Tarreaud98cf932009-12-27 22:54:55 +01001799 }
Willy Tarreaue34070e2010-01-08 00:32:27 +01001800 break;
1801 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01001802 }
Willy Tarreau84455332009-03-15 22:34:05 +01001803
Willy Tarreau815a9b22010-07-27 17:15:12 +02001804 rq_prod_last = s->si[0].state;
1805 rq_cons_last = s->si[1].state;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001806 s->req->flags &= ~CF_WAKE_ONCE;
Willy Tarreau815a9b22010-07-27 17:15:12 +02001807 rqf_last = s->req->flags;
1808
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001809 if ((s->req->flags ^ flags) & CF_MASK_STATIC)
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001810 goto resync_request;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001811 }
1812
Willy Tarreau576507f2010-01-07 00:09:04 +01001813 /* we'll monitor the request analysers while parsing the response,
1814 * because some response analysers may indirectly enable new request
1815 * analysers (eg: HTTP keep-alive).
1816 */
1817 req_ana_back = s->req->analysers;
1818
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001819 resync_response:
1820 /* Analyse response */
1821
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001822 if (unlikely(s->rep->flags & CF_HIJACK)) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001823 /* In inject mode, we wake up everytime something has
1824 * happened on the write side of the buffer.
1825 */
1826 unsigned int flags = s->rep->flags;
1827
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001828 if ((s->rep->flags & (CF_WRITE_PARTIAL|CF_WRITE_ERROR|CF_SHUTW)) &&
Willy Tarreau3bf1b2b2012-08-27 20:46:07 +02001829 !channel_full(s->rep)) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001830 s->rep->hijacker(s, s->rep);
1831 }
1832
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001833 if ((s->rep->flags ^ flags) & CF_MASK_STATIC) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001834 rpf_last = s->rep->flags;
1835 goto resync_response;
1836 }
1837 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001838 else if (((s->rep->flags & ~rpf_last) & CF_MASK_ANALYSER) ||
1839 (s->rep->flags ^ rpf_last) & CF_MASK_STATIC ||
Willy Tarreau815a9b22010-07-27 17:15:12 +02001840 s->si[0].state != rp_cons_last ||
1841 s->si[1].state != rp_prod_last) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001842 unsigned int flags = s->rep->flags;
1843
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001844 if ((s->rep->flags & CF_MASK_ANALYSER) &&
Willy Tarreau0499e352010-12-17 07:13:42 +01001845 (s->rep->analysers & AN_REQ_WAIT_HTTP)) {
1846 /* Due to HTTP pipelining, the HTTP request analyser might be waiting
1847 * for some free space in the response buffer, so we might need to call
1848 * it when something changes in the response buffer, but still we pass
1849 * it the request buffer. Note that the SI state might very well still
1850 * be zero due to us returning a flow of redirects!
1851 */
1852 s->rep->analysers &= ~AN_REQ_WAIT_HTTP;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001853 s->req->flags |= CF_WAKE_ONCE;
Willy Tarreau0499e352010-12-17 07:13:42 +01001854 }
1855
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001856 if (s->rep->prod->state >= SI_ST_EST) {
Willy Tarreaue34070e2010-01-08 00:32:27 +01001857 int max_loops = global.tune.maxpollevents;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001858 unsigned int ana_list;
1859 unsigned int ana_back;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001860
Willy Tarreau90deb182010-01-07 00:20:41 +01001861 /* it's up to the analysers to stop disable reading or
1862 * closing. Note: if an analyser disables any of these
1863 * bits, it is responsible for enabling them again when
1864 * it disables itself, so that other analysers are called
1865 * in similar conditions.
1866 */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02001867 channel_auto_read(s->rep);
1868 channel_auto_close(s->rep);
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001869
1870 /* We will call all analysers for which a bit is set in
1871 * s->rep->analysers, following the bit order from LSB
1872 * to MSB. The analysers must remove themselves from
1873 * the list when not needed. Any analyser may return 0
1874 * to break out of the loop, either because of missing
1875 * data to take a decision, or because it decides to
1876 * kill the session. We loop at least once through each
1877 * analyser, and we may loop again if other analysers
1878 * are added in the middle.
1879 */
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001880
1881 ana_list = ana_back = s->rep->analysers;
Willy Tarreaue34070e2010-01-08 00:32:27 +01001882 while (ana_list && max_loops--) {
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001883 /* Warning! ensure that analysers are always placed in ascending order! */
1884
Emeric Brun97679e72010-09-23 17:56:44 +02001885 if (ana_list & AN_RES_INSPECT) {
1886 if (!tcp_inspect_response(s, s->rep, AN_RES_INSPECT))
1887 break;
1888 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_INSPECT);
1889 }
1890
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001891 if (ana_list & AN_RES_WAIT_HTTP) {
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001892 if (!http_wait_for_response(s, s->rep, AN_RES_WAIT_HTTP))
1893 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001894 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_WAIT_HTTP);
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001895 }
1896
Emeric Brun1d33b292010-01-04 15:47:17 +01001897 if (ana_list & AN_RES_STORE_RULES) {
1898 if (!process_store_rules(s, s->rep, AN_RES_STORE_RULES))
1899 break;
1900 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_STORE_RULES);
1901 }
1902
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001903 if (ana_list & AN_RES_HTTP_PROCESS_BE) {
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001904 if (!http_process_res_common(s, s->rep, AN_RES_HTTP_PROCESS_BE, s->be))
1905 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001906 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_HTTP_PROCESS_BE);
Willy Tarreaub37c27e2009-10-18 22:53:08 +02001907 }
Willy Tarreaud98cf932009-12-27 22:54:55 +01001908
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001909 if (ana_list & AN_RES_HTTP_XFER_BODY) {
Willy Tarreaud98cf932009-12-27 22:54:55 +01001910 if (!http_response_forward_body(s, s->rep, AN_RES_HTTP_XFER_BODY))
1911 break;
Willy Tarreau1e0bbaf2010-01-06 23:53:24 +01001912 UPDATE_ANALYSERS(s->rep->analysers, ana_list, ana_back, AN_RES_HTTP_XFER_BODY);
Willy Tarreaud98cf932009-12-27 22:54:55 +01001913 }
Willy Tarreaue34070e2010-01-08 00:32:27 +01001914 break;
1915 }
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001916 }
1917
Willy Tarreau815a9b22010-07-27 17:15:12 +02001918 rp_cons_last = s->si[0].state;
1919 rp_prod_last = s->si[1].state;
1920 rpf_last = s->rep->flags;
1921
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001922 if ((s->rep->flags ^ flags) & CF_MASK_STATIC)
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001923 goto resync_response;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001924 }
1925
Willy Tarreau576507f2010-01-07 00:09:04 +01001926 /* maybe someone has added some request analysers, so we must check and loop */
1927 if (s->req->analysers & ~req_ana_back)
1928 goto resync_request;
1929
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001930 if ((s->req->flags & ~rqf_last) & CF_MASK_ANALYSER)
Willy Tarreau0499e352010-12-17 07:13:42 +01001931 goto resync_request;
1932
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001933 /* FIXME: here we should call protocol handlers which rely on
1934 * both buffers.
1935 */
1936
1937
1938 /*
Willy Tarreauae526782010-03-04 20:34:23 +01001939 * Now we propagate unhandled errors to the session. Normally
1940 * we're just in a data phase here since it means we have not
1941 * seen any analyser who could set an error status.
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001942 */
Willy Tarreau827aee92011-03-10 16:55:02 +01001943 srv = target_srv(&s->target);
Willy Tarreau2f976e12010-11-11 14:28:47 +01001944 if (unlikely(!(s->flags & SN_ERR_MASK))) {
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001945 if (s->req->flags & (CF_READ_ERROR|CF_READ_TIMEOUT|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001946 /* Report it if the client got an error or a read timeout expired */
Willy Tarreau84455332009-03-15 22:34:05 +01001947 s->req->analysers = 0;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001948 if (s->req->flags & CF_READ_ERROR) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001949 s->be->be_counters.cli_aborts++;
1950 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001951 if (srv)
1952 srv->counters.cli_aborts++;
Willy Tarreau84455332009-03-15 22:34:05 +01001953 s->flags |= SN_ERR_CLICL;
Willy Tarreauae526782010-03-04 20:34:23 +01001954 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001955 else if (s->req->flags & CF_READ_TIMEOUT) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001956 s->be->be_counters.cli_aborts++;
1957 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001958 if (srv)
1959 srv->counters.cli_aborts++;
Willy Tarreau84455332009-03-15 22:34:05 +01001960 s->flags |= SN_ERR_CLITO;
Willy Tarreauae526782010-03-04 20:34:23 +01001961 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001962 else if (s->req->flags & CF_WRITE_ERROR) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001963 s->be->be_counters.srv_aborts++;
1964 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001965 if (srv)
1966 srv->counters.srv_aborts++;
Willy Tarreau84455332009-03-15 22:34:05 +01001967 s->flags |= SN_ERR_SRVCL;
Willy Tarreauae526782010-03-04 20:34:23 +01001968 }
1969 else {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001970 s->be->be_counters.srv_aborts++;
1971 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001972 if (srv)
1973 srv->counters.srv_aborts++;
Willy Tarreau84455332009-03-15 22:34:05 +01001974 s->flags |= SN_ERR_SRVTO;
Willy Tarreauae526782010-03-04 20:34:23 +01001975 }
Willy Tarreau84455332009-03-15 22:34:05 +01001976 sess_set_term_flags(s);
1977 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001978 else if (s->rep->flags & (CF_READ_ERROR|CF_READ_TIMEOUT|CF_WRITE_ERROR|CF_WRITE_TIMEOUT)) {
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001979 /* Report it if the server got an error or a read timeout expired */
1980 s->rep->analysers = 0;
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001981 if (s->rep->flags & CF_READ_ERROR) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001982 s->be->be_counters.srv_aborts++;
1983 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001984 if (srv)
1985 srv->counters.srv_aborts++;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001986 s->flags |= SN_ERR_SRVCL;
Willy Tarreauae526782010-03-04 20:34:23 +01001987 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001988 else if (s->rep->flags & CF_READ_TIMEOUT) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001989 s->be->be_counters.srv_aborts++;
1990 s->fe->fe_counters.srv_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001991 if (srv)
1992 srv->counters.srv_aborts++;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02001993 s->flags |= SN_ERR_SRVTO;
Willy Tarreauae526782010-03-04 20:34:23 +01001994 }
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02001995 else if (s->rep->flags & CF_WRITE_ERROR) {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01001996 s->be->be_counters.cli_aborts++;
1997 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01001998 if (srv)
1999 srv->counters.cli_aborts++;
Willy Tarreau3deb3d02009-06-21 22:43:05 +02002000 s->flags |= SN_ERR_CLICL;
Willy Tarreauae526782010-03-04 20:34:23 +01002001 }
2002 else {
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01002003 s->be->be_counters.cli_aborts++;
2004 s->fe->fe_counters.cli_aborts++;
Willy Tarreau827aee92011-03-10 16:55:02 +01002005 if (srv)
2006 srv->counters.cli_aborts++;
Willy Tarreauae526782010-03-04 20:34:23 +01002007 s->flags |= SN_ERR_CLITO;
2008 }
Willy Tarreau3deb3d02009-06-21 22:43:05 +02002009 sess_set_term_flags(s);
2010 }
Willy Tarreau84455332009-03-15 22:34:05 +01002011 }
2012
Willy Tarreau3deb3d02009-06-21 22:43:05 +02002013 /*
2014 * Here we take care of forwarding unhandled data. This also includes
2015 * connection establishments and shutdown requests.
2016 */
2017
2018
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002019 /* If noone is interested in analysing data, it's time to forward
Willy Tarreau31971e52009-09-20 12:07:52 +02002020 * everything. We configure the buffer to forward indefinitely.
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002021 * Note that we're checking CF_SHUTR_NOW as an indication of a possible
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002022 * recent call to channel_abort().
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01002023 */
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002024 if (!s->req->analysers &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002025 !(s->req->flags & (CF_HIJACK|CF_SHUTW|CF_SHUTR_NOW)) &&
Willy Tarreau31971e52009-09-20 12:07:52 +02002026 (s->req->prod->state >= SI_ST_EST) &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002027 (s->req->to_forward != CHN_INFINITE_FORWARD)) {
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002028 /* This buffer is freewheeling, there's no analyser nor hijacker
2029 * attached to it. If any data are left in, we'll permit them to
2030 * move.
2031 */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002032 channel_auto_read(s->req);
2033 channel_auto_connect(s->req);
2034 channel_auto_close(s->req);
Willy Tarreaua75bcef2012-08-24 22:56:11 +02002035 buffer_flush(&s->req->buf);
Willy Tarreau5bd8c372009-01-19 00:32:22 +01002036
Willy Tarreauda4d9fe2010-11-07 20:26:56 +01002037 /* We'll let data flow between the producer (if still connected)
2038 * to the consumer (which might possibly not be connected yet).
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002039 */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002040 if (!(s->req->flags & (CF_SHUTR|CF_SHUTW_NOW)))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002041 channel_forward(s->req, CHN_INFINITE_FORWARD);
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01002042 }
Willy Tarreauf890dc92008-12-13 21:12:26 +01002043
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002044 /* check if it is wise to enable kernel splicing to forward request data */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002045 if (!(s->req->flags & (CF_KERN_SPLICING|CF_SHUTR)) &&
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002046 s->req->to_forward &&
2047 (global.tune.options & GTUNE_USE_SPLICE) &&
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002048 (s->si[0].conn.xprt && s->si[0].conn.xprt->rcv_pipe && s->si[0].conn.xprt->snd_pipe) &&
2049 (s->si[1].conn.xprt && s->si[1].conn.xprt->rcv_pipe && s->si[1].conn.xprt->snd_pipe) &&
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002050 (pipes_used < global.maxpipes) &&
2051 (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_REQ) ||
2052 (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_AUT) &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002053 (s->req->flags & CF_STREAMER_FAST)))) {
2054 s->req->flags |= CF_KERN_SPLICING;
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002055 }
2056
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002057 /* reflect what the L7 analysers have seen last */
2058 rqf_last = s->req->flags;
2059
2060 /*
2061 * Now forward all shutdown requests between both sides of the buffer
2062 */
2063
Willy Tarreau520d95e2009-09-19 21:04:57 +02002064 /* first, let's check if the request buffer needs to shutdown(write), which may
2065 * happen either because the input is closed or because we want to force a close
Willy Tarreaue4599762010-03-21 23:25:09 +01002066 * once the server has begun to respond.
Willy Tarreau520d95e2009-09-19 21:04:57 +02002067 */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002068 if (unlikely((s->req->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_HIJACK|CF_AUTO_CLOSE|CF_SHUTR)) ==
2069 (CF_AUTO_CLOSE|CF_SHUTR)))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002070 channel_shutw_now(s->req);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002071
2072 /* shutdown(write) pending */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002073 if (unlikely((s->req->flags & (CF_SHUTW|CF_SHUTW_NOW)) == CF_SHUTW_NOW &&
Willy Tarreau8e21bb92012-08-24 22:40:29 +02002074 channel_is_empty(s->req)))
Willy Tarreau73b013b2012-05-21 16:31:45 +02002075 si_shutw(s->req->cons);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002076
2077 /* shutdown(write) done on server side, we must stop the client too */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002078 if (unlikely((s->req->flags & (CF_SHUTW|CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTW &&
Willy Tarreau3dbc6942008-12-07 13:05:04 +01002079 !s->req->analysers))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002080 channel_shutr_now(s->req);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002081
2082 /* shutdown(read) pending */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002083 if (unlikely((s->req->flags & (CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTR_NOW)) {
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02002084 if (s->req->prod->flags & SI_FL_NOHALF)
2085 s->req->prod->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02002086 si_shutr(s->req->prod);
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02002087 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002088
Willy Tarreau520d95e2009-09-19 21:04:57 +02002089 /* it's possible that an upper layer has requested a connection setup or abort.
2090 * There are 2 situations where we decide to establish a new connection :
2091 * - there are data scheduled for emission in the buffer
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002092 * - the CF_AUTO_CONNECT flag is set (active connection)
Willy Tarreau520d95e2009-09-19 21:04:57 +02002093 */
2094 if (s->req->cons->state == SI_ST_INI) {
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002095 if (!(s->req->flags & CF_SHUTW)) {
2096 if ((s->req->flags & CF_AUTO_CONNECT) || !channel_is_empty(s->req)) {
Willy Tarreaub24281b2011-02-13 13:16:36 +01002097 /* If we have an applet without a connect method, we immediately
Willy Tarreau85e7d002010-05-31 11:57:51 +02002098 * switch to the connected state, otherwise we perform a connection
2099 * request.
Willy Tarreau520d95e2009-09-19 21:04:57 +02002100 */
Willy Tarreau85e7d002010-05-31 11:57:51 +02002101 s->req->cons->state = SI_ST_REQ; /* new connection requested */
Willy Tarreau070ceb62010-06-01 10:36:43 +02002102 s->req->cons->conn_retries = s->be->conn_retries;
Willy Tarreau3cefd522012-08-30 15:49:18 +02002103 if (unlikely(s->req->cons->conn.target.type == TARG_TYPE_APPLET &&
Willy Tarreau73b013b2012-05-21 16:31:45 +02002104 !(si_ctrl(s->req->cons) && si_ctrl(s->req->cons)->connect))) {
Willy Tarreau520d95e2009-09-19 21:04:57 +02002105 s->req->cons->state = SI_ST_EST; /* connection established */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002106 s->rep->flags |= CF_READ_ATTACHED; /* producer is now attached */
Willy Tarreau85e7d002010-05-31 11:57:51 +02002107 s->req->wex = TICK_ETERNITY;
2108 }
Willy Tarreau520d95e2009-09-19 21:04:57 +02002109 }
Willy Tarreau73201222009-08-16 18:27:24 +02002110 }
Willy Tarreauf41ffdc2009-09-20 08:19:25 +02002111 else {
Willy Tarreau92795622009-03-06 12:51:23 +01002112 s->req->cons->state = SI_ST_CLO; /* shutw+ini = abort */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002113 channel_shutw_now(s->req); /* fix buffer flags upon abort */
2114 channel_shutr_now(s->rep);
Willy Tarreauf41ffdc2009-09-20 08:19:25 +02002115 }
Willy Tarreau92795622009-03-06 12:51:23 +01002116 }
2117
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002118
2119 /* we may have a pending connection request, or a connection waiting
2120 * for completion.
2121 */
2122 if (s->si[1].state >= SI_ST_REQ && s->si[1].state < SI_ST_CON) {
2123 do {
2124 /* nb: step 1 might switch from QUE to ASS, but we first want
2125 * to give a chance to step 2 to perform a redirect if needed.
2126 */
2127 if (s->si[1].state != SI_ST_REQ)
2128 sess_update_stream_int(s, &s->si[1]);
2129 if (s->si[1].state == SI_ST_REQ)
2130 sess_prepare_conn_req(s, &s->si[1]);
2131
Willy Tarreau827aee92011-03-10 16:55:02 +01002132 srv = target_srv(&s->target);
2133 if (s->si[1].state == SI_ST_ASS && srv && srv->rdr_len && (s->flags & SN_REDIRECTABLE))
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002134 perform_http_redirect(s, &s->si[1]);
2135 } while (s->si[1].state == SI_ST_ASS);
Mark Lamourinec2247f02012-01-04 13:02:01 -05002136
2137 /* Now we can add the server name to a header (if requested) */
2138 /* check for HTTP mode and proxy server_name_hdr_name != NULL */
Stathis Voukelatos09a030a2012-01-09 14:27:13 +01002139 if ((s->flags & SN_BE_ASSIGNED) &&
Willy Tarreau45c0d982012-03-09 12:11:57 +01002140 (s->be->mode == PR_MODE_HTTP) &&
2141 (s->be->server_id_hdr_name != NULL)) {
2142 http_send_name_header(&s->txn, s->be, target_srv(&s->target)->id);
Mark Lamourinec2247f02012-01-04 13:02:01 -05002143 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002144 }
2145
Willy Tarreau3deb3d02009-06-21 22:43:05 +02002146 /* Benchmarks have shown that it's optimal to do a full resync now */
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002147 if (s->req->prod->state == SI_ST_DIS || s->req->cons->state == SI_ST_DIS)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002148 goto resync_stream_interface;
2149
Willy Tarreau815a9b22010-07-27 17:15:12 +02002150 /* otherwise we want to check if we need to resync the req buffer or not */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002151 if ((s->req->flags ^ rqf_last) & CF_MASK_STATIC)
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002152 goto resync_request;
2153
Willy Tarreau3deb3d02009-06-21 22:43:05 +02002154 /* perform output updates to the response buffer */
Willy Tarreau84455332009-03-15 22:34:05 +01002155
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002156 /* If noone is interested in analysing data, it's time to forward
Willy Tarreau31971e52009-09-20 12:07:52 +02002157 * everything. We configure the buffer to forward indefinitely.
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002158 * Note that we're checking CF_SHUTR_NOW as an indication of a possible
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002159 * recent call to channel_abort().
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01002160 */
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002161 if (!s->rep->analysers &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002162 !(s->rep->flags & (CF_HIJACK|CF_SHUTW|CF_SHUTR_NOW)) &&
Willy Tarreau31971e52009-09-20 12:07:52 +02002163 (s->rep->prod->state >= SI_ST_EST) &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002164 (s->rep->to_forward != CHN_INFINITE_FORWARD)) {
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002165 /* This buffer is freewheeling, there's no analyser nor hijacker
2166 * attached to it. If any data are left in, we'll permit them to
2167 * move.
2168 */
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002169 channel_auto_read(s->rep);
2170 channel_auto_close(s->rep);
Willy Tarreaua75bcef2012-08-24 22:56:11 +02002171 buffer_flush(&s->rep->buf);
Willy Tarreauda4d9fe2010-11-07 20:26:56 +01002172
2173 /* We'll let data flow between the producer (if still connected)
2174 * to the consumer.
2175 */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002176 if (!(s->rep->flags & (CF_SHUTR|CF_SHUTW_NOW)))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002177 channel_forward(s->rep, CHN_INFINITE_FORWARD);
Willy Tarreauce887fd2012-05-12 12:50:00 +02002178
2179 /* if we have no analyser anymore in any direction and have a
2180 * tunnel timeout set, use it now.
2181 */
2182 if (!s->req->analysers && s->be->timeout.tunnel) {
2183 s->req->rto = s->req->wto = s->rep->rto = s->rep->wto =
2184 s->be->timeout.tunnel;
2185 s->req->rex = s->req->wex = s->rep->rex = s->rep->wex =
2186 tick_add(now_ms, s->be->timeout.tunnel);
2187 }
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01002188 }
Willy Tarreauf890dc92008-12-13 21:12:26 +01002189
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002190 /* check if it is wise to enable kernel splicing to forward response data */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002191 if (!(s->rep->flags & (CF_KERN_SPLICING|CF_SHUTR)) &&
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002192 s->rep->to_forward &&
2193 (global.tune.options & GTUNE_USE_SPLICE) &&
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002194 (s->si[0].conn.xprt && s->si[0].conn.xprt->rcv_pipe && s->si[0].conn.xprt->snd_pipe) &&
2195 (s->si[1].conn.xprt && s->si[1].conn.xprt->rcv_pipe && s->si[1].conn.xprt->snd_pipe) &&
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002196 (pipes_used < global.maxpipes) &&
2197 (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_RTR) ||
2198 (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_AUT) &&
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002199 (s->rep->flags & CF_STREAMER_FAST)))) {
2200 s->rep->flags |= CF_KERN_SPLICING;
Willy Tarreau7c84bab2009-03-08 21:38:23 +01002201 }
2202
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002203 /* reflect what the L7 analysers have seen last */
2204 rpf_last = s->rep->flags;
2205
2206 /*
2207 * Now forward all shutdown requests between both sides of the buffer
2208 */
2209
2210 /*
2211 * FIXME: this is probably where we should produce error responses.
2212 */
2213
Willy Tarreau6b66f3e2008-12-14 17:31:54 +01002214 /* first, let's check if the response buffer needs to shutdown(write) */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002215 if (unlikely((s->rep->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_HIJACK|CF_AUTO_CLOSE|CF_SHUTR)) ==
2216 (CF_AUTO_CLOSE|CF_SHUTR)))
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002217 channel_shutw_now(s->rep);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002218
2219 /* shutdown(write) pending */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002220 if (unlikely((s->rep->flags & (CF_SHUTW|CF_SHUTW_NOW)) == CF_SHUTW_NOW &&
Willy Tarreau8e21bb92012-08-24 22:40:29 +02002221 channel_is_empty(s->rep)))
Willy Tarreau73b013b2012-05-21 16:31:45 +02002222 si_shutw(s->rep->cons);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002223
2224 /* shutdown(write) done on the client side, we must stop the server too */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002225 if (unlikely((s->rep->flags & (CF_SHUTW|CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTW) &&
Willy Tarreau3dbc6942008-12-07 13:05:04 +01002226 !s->rep->analysers)
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002227 channel_shutr_now(s->rep);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002228
2229 /* shutdown(read) pending */
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002230 if (unlikely((s->rep->flags & (CF_SHUTR|CF_SHUTR_NOW)) == CF_SHUTR_NOW)) {
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02002231 if (s->rep->prod->flags & SI_FL_NOHALF)
2232 s->rep->prod->flags |= SI_FL_NOLINGER;
Willy Tarreau73b013b2012-05-21 16:31:45 +02002233 si_shutr(s->rep->prod);
Willy Tarreau7bb68ab2012-05-13 14:48:59 +02002234 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002235
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002236 if (s->req->prod->state == SI_ST_DIS || s->req->cons->state == SI_ST_DIS)
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002237 goto resync_stream_interface;
2238
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002239 if (s->req->flags != rqf_last)
2240 goto resync_request;
2241
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002242 if ((s->rep->flags ^ rpf_last) & CF_MASK_STATIC)
Willy Tarreau0be0ef92009-03-08 19:20:25 +01002243 goto resync_response;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002244
Willy Tarreau89f7ef22009-09-05 20:57:35 +02002245 /* we're interested in getting wakeups again */
2246 s->req->prod->flags &= ~SI_FL_DONT_WAKE;
2247 s->req->cons->flags &= ~SI_FL_DONT_WAKE;
2248
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002249 /* This is needed only when debugging is enabled, to indicate
2250 * client-side or server-side close. Please note that in the unlikely
2251 * event where both sides would close at once, the sequence is reported
2252 * on the server side first.
2253 */
2254 if (unlikely((global.mode & MODE_DEBUG) &&
2255 (!(global.mode & MODE_QUIET) ||
2256 (global.mode & MODE_VERBOSE)))) {
2257 int len;
2258
2259 if (s->si[1].state == SI_ST_CLO &&
2260 s->si[1].prev_state == SI_ST_EST) {
2261 len = sprintf(trash, "%08x:%s.srvcls[%04x:%04x]\n",
2262 s->uniq_id, s->be->id,
Willy Tarreaufb7508a2012-05-21 16:47:54 +02002263 (unsigned short)si_fd(&s->si[0]),
2264 (unsigned short)si_fd(&s->si[1]));
Willy Tarreau21337822012-04-29 14:11:38 +02002265 if (write(1, trash, len) < 0) /* shut gcc warning */;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002266 }
2267
2268 if (s->si[0].state == SI_ST_CLO &&
2269 s->si[0].prev_state == SI_ST_EST) {
2270 len = sprintf(trash, "%08x:%s.clicls[%04x:%04x]\n",
2271 s->uniq_id, s->be->id,
Willy Tarreaufb7508a2012-05-21 16:47:54 +02002272 (unsigned short)si_fd(&s->si[0]),
2273 (unsigned short)si_fd(&s->si[1]));
Willy Tarreau21337822012-04-29 14:11:38 +02002274 if (write(1, trash, len) < 0) /* shut gcc warning */;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002275 }
2276 }
2277
2278 if (likely((s->rep->cons->state != SI_ST_CLO) ||
2279 (s->req->cons->state > SI_ST_INI && s->req->cons->state < SI_ST_CLO))) {
2280
2281 if ((s->fe->options & PR_O_CONTSTATS) && (s->flags & SN_BE_ASSIGNED))
2282 session_process_counters(s);
2283
Willy Tarreau3cefd522012-08-30 15:49:18 +02002284 if (s->rep->cons->state == SI_ST_EST && s->rep->cons->conn.target.type != TARG_TYPE_APPLET)
Willy Tarreau73b013b2012-05-21 16:31:45 +02002285 si_update(s->rep->cons);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002286
Willy Tarreau3cefd522012-08-30 15:49:18 +02002287 if (s->req->cons->state == SI_ST_EST && s->req->cons->conn.target.type != TARG_TYPE_APPLET)
Willy Tarreau73b013b2012-05-21 16:31:45 +02002288 si_update(s->req->cons);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002289
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002290 s->req->flags &= ~(CF_READ_NULL|CF_READ_PARTIAL|CF_WRITE_NULL|CF_WRITE_PARTIAL|CF_READ_ATTACHED);
2291 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 +01002292 s->si[0].prev_state = s->si[0].state;
2293 s->si[1].prev_state = s->si[1].state;
Willy Tarreaub0ef7352008-12-14 13:26:20 +01002294 s->si[0].flags &= ~(SI_FL_ERR|SI_FL_EXP);
2295 s->si[1].flags &= ~(SI_FL_ERR|SI_FL_EXP);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002296
2297 /* Trick: if a request is being waiting for the server to respond,
2298 * and if we know the server can timeout, we don't want the timeout
2299 * to expire on the client side first, but we're still interested
2300 * in passing data from the client to the server (eg: POST). Thus,
2301 * we can cancel the client's request timeout if the server's
2302 * request timeout is set and the server has not yet sent a response.
2303 */
2304
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002305 if ((s->rep->flags & (CF_AUTO_CLOSE|CF_SHUTR)) == 0 &&
Willy Tarreau86491c32008-12-14 09:04:47 +01002306 (tick_isset(s->req->wex) || tick_isset(s->rep->rex))) {
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002307 s->req->flags |= CF_READ_NOEXP;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002308 s->req->rex = TICK_ETERNITY;
Willy Tarreau86491c32008-12-14 09:04:47 +01002309 }
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002310
Willy Tarreau7a20aa62010-07-13 16:30:45 +02002311 /* Call the stream interfaces' I/O handlers when embedded.
Willy Tarreau1accfc02009-09-05 20:57:35 +02002312 * Note that this one may wake the task up again.
2313 */
Willy Tarreau3cefd522012-08-30 15:49:18 +02002314 if (s->req->cons->conn.target.type == TARG_TYPE_APPLET ||
2315 s->rep->cons->conn.target.type == TARG_TYPE_APPLET) {
2316 if (s->req->cons->conn.target.type == TARG_TYPE_APPLET)
2317 s->req->cons->conn.target.ptr.a->fct(s->req->cons);
2318 if (s->rep->cons->conn.target.type == TARG_TYPE_APPLET)
2319 s->rep->cons->conn.target.ptr.a->fct(s->rep->cons);
Willy Tarreau1accfc02009-09-05 20:57:35 +02002320 if (task_in_rq(t)) {
2321 /* If we woke up, we don't want to requeue the
2322 * task to the wait queue, but rather requeue
2323 * it into the runqueue ASAP.
2324 */
2325 t->expire = TICK_ETERNITY;
2326 return t;
2327 }
2328 }
2329
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002330 t->expire = tick_first(tick_first(s->req->rex, s->req->wex),
2331 tick_first(s->rep->rex, s->rep->wex));
2332 if (s->req->analysers)
2333 t->expire = tick_first(t->expire, s->req->analyse_exp);
2334
2335 if (s->si[0].exp)
2336 t->expire = tick_first(t->expire, s->si[0].exp);
2337
2338 if (s->si[1].exp)
2339 t->expire = tick_first(t->expire, s->si[1].exp);
2340
2341#ifdef DEBUG_FULL
Willy Tarreau127334e2009-03-28 10:47:26 +01002342 fprintf(stderr,
2343 "[%u] queuing with exp=%u req->rex=%u req->wex=%u req->ana_exp=%u"
2344 " rep->rex=%u rep->wex=%u, si[0].exp=%u, si[1].exp=%u, cs=%d, ss=%d\n",
2345 now_ms, t->expire, s->req->rex, s->req->wex, s->req->analyse_exp,
2346 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 +01002347#endif
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002348
2349#ifdef DEBUG_DEV
2350 /* this may only happen when no timeout is set or in case of an FSM bug */
Willy Tarreaud0a201b2009-03-08 15:53:06 +01002351 if (!tick_isset(t->expire))
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002352 ABORT_NOW();
2353#endif
Willy Tarreau26c25062009-03-08 09:38:41 +01002354 return t; /* nothing more to do */
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002355 }
2356
2357 s->fe->feconn--;
2358 if (s->flags & SN_BE_ASSIGNED)
2359 s->be->beconn--;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02002360 if (!(s->listener->options & LI_O_UNLIMITED))
2361 actconn--;
Willy Tarreauaf7ad002010-08-31 15:39:26 +02002362 jobs--;
Willy Tarreau6e6fb2b2009-08-16 18:20:44 +02002363 s->listener->nbconn--;
Willy Tarreau62793712011-07-24 19:23:38 +02002364 if (s->listener->state == LI_FULL)
2365 resume_listener(s->listener);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002366
Willy Tarreau08ceb102011-07-24 22:58:00 +02002367 /* Dequeues all of the listeners waiting for a resource */
2368 if (!LIST_ISEMPTY(&global_listener_queue))
2369 dequeue_all_listeners(&global_listener_queue);
2370
Willy Tarreaub32907b2011-07-25 08:37:44 +02002371 if (!LIST_ISEMPTY(&s->fe->listener_queue) &&
2372 (!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 +02002373 dequeue_all_listeners(&s->fe->listener_queue);
2374
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002375 if (unlikely((global.mode & MODE_DEBUG) &&
2376 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)))) {
2377 int len;
Willy Tarreauec22b2c2009-03-06 13:07:40 +01002378 len = sprintf(trash, "%08x:%s.closed[%04x:%04x]\n",
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002379 s->uniq_id, s->be->id,
Willy Tarreaufb7508a2012-05-21 16:47:54 +02002380 (unsigned short)si_fd(s->req->prod), (unsigned short)si_fd(s->req->cons));
Willy Tarreau21337822012-04-29 14:11:38 +02002381 if (write(1, trash, len) < 0) /* shut gcc warning */;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002382 }
2383
2384 s->logs.t_close = tv_ms_elapsed(&s->logs.tv_accept, &now);
2385 session_process_counters(s);
2386
Krzysztof Piotr Oledzkide71d162009-10-24 15:36:15 +02002387 if (s->txn.status) {
2388 int n;
2389
2390 n = s->txn.status / 100;
2391 if (n < 1 || n > 5)
2392 n = 0;
2393
2394 if (s->fe->mode == PR_MODE_HTTP)
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01002395 s->fe->fe_counters.p.http.rsp[n]++;
Krzysztof Piotr Oledzkide71d162009-10-24 15:36:15 +02002396
Willy Tarreau24657792010-02-26 10:30:28 +01002397 if ((s->flags & SN_BE_ASSIGNED) &&
Krzysztof Piotr Oledzkide71d162009-10-24 15:36:15 +02002398 (s->be->mode == PR_MODE_HTTP))
Willy Tarreau7d0aaf32011-03-10 23:25:56 +01002399 s->be->be_counters.p.http.rsp[n]++;
Krzysztof Piotr Oledzkide71d162009-10-24 15:36:15 +02002400 }
2401
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002402 /* let's do a final log if we need it */
2403 if (s->logs.logwait &&
2404 !(s->flags & SN_MONITOR) &&
2405 (!(s->fe->options & PR_O_NULLNOLOG) || s->req->total)) {
Willy Tarreaua5555ec2008-11-30 19:02:32 +01002406 s->do_log(s);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002407 }
2408
2409 /* the task MUST not be in the run queue anymore */
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002410 session_free(s);
Willy Tarreau26c25062009-03-08 09:38:41 +01002411 task_delete(t);
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002412 task_free(t);
Willy Tarreau26c25062009-03-08 09:38:41 +01002413 return NULL;
Willy Tarreau55a8d0e2008-11-30 18:47:21 +01002414}
2415
Willy Tarreau7c669d72008-06-20 15:04:11 +02002416/*
2417 * This function adjusts sess->srv_conn and maintains the previous and new
2418 * server's served session counts. Setting newsrv to NULL is enough to release
2419 * current connection slot. This function also notifies any LB algo which might
2420 * expect to be informed about any change in the number of active sessions on a
2421 * server.
2422 */
2423void sess_change_server(struct session *sess, struct server *newsrv)
2424{
2425 if (sess->srv_conn == newsrv)
2426 return;
2427
2428 if (sess->srv_conn) {
2429 sess->srv_conn->served--;
2430 if (sess->srv_conn->proxy->lbprm.server_drop_conn)
2431 sess->srv_conn->proxy->lbprm.server_drop_conn(sess->srv_conn);
Simon Hormanaf514952011-06-21 14:34:57 +09002432 session_del_srv_conn(sess);
Willy Tarreau7c669d72008-06-20 15:04:11 +02002433 }
2434
2435 if (newsrv) {
2436 newsrv->served++;
2437 if (newsrv->proxy->lbprm.server_take_conn)
2438 newsrv->proxy->lbprm.server_take_conn(newsrv);
Simon Hormanaf514952011-06-21 14:34:57 +09002439 session_add_srv_conn(sess, newsrv);
Willy Tarreau7c669d72008-06-20 15:04:11 +02002440 }
2441}
2442
Willy Tarreau84455332009-03-15 22:34:05 +01002443/* Handle server-side errors for default protocols. It is called whenever a a
2444 * connection setup is aborted or a request is aborted in queue. It sets the
2445 * session termination flags so that the caller does not have to worry about
2446 * them. It's installed as ->srv_error for the server-side stream_interface.
2447 */
2448void default_srv_error(struct session *s, struct stream_interface *si)
2449{
2450 int err_type = si->err_type;
2451 int err = 0, fin = 0;
2452
2453 if (err_type & SI_ET_QUEUE_ABRT) {
2454 err = SN_ERR_CLICL;
2455 fin = SN_FINST_Q;
2456 }
2457 else if (err_type & SI_ET_CONN_ABRT) {
2458 err = SN_ERR_CLICL;
2459 fin = SN_FINST_C;
2460 }
2461 else if (err_type & SI_ET_QUEUE_TO) {
2462 err = SN_ERR_SRVTO;
2463 fin = SN_FINST_Q;
2464 }
2465 else if (err_type & SI_ET_QUEUE_ERR) {
2466 err = SN_ERR_SRVCL;
2467 fin = SN_FINST_Q;
2468 }
2469 else if (err_type & SI_ET_CONN_TO) {
2470 err = SN_ERR_SRVTO;
2471 fin = SN_FINST_C;
2472 }
2473 else if (err_type & SI_ET_CONN_ERR) {
2474 err = SN_ERR_SRVCL;
2475 fin = SN_FINST_C;
2476 }
2477 else /* SI_ET_CONN_OTHER and others */ {
2478 err = SN_ERR_INTERNAL;
2479 fin = SN_FINST_C;
2480 }
2481
2482 if (!(s->flags & SN_ERR_MASK))
2483 s->flags |= err;
2484 if (!(s->flags & SN_FINST_MASK))
2485 s->flags |= fin;
2486}
Willy Tarreau7c669d72008-06-20 15:04:11 +02002487
Willy Tarreaua2a64e92011-09-07 23:01:56 +02002488/* kill a session and set the termination flags to <why> (one of SN_ERR_*) */
2489void session_shutdown(struct session *session, int why)
2490{
Willy Tarreau03cdb7c2012-08-27 23:14:58 +02002491 if (session->req->flags & (CF_SHUTW|CF_SHUTW_NOW))
Willy Tarreaua2a64e92011-09-07 23:01:56 +02002492 return;
2493
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002494 channel_shutw_now(session->req);
2495 channel_shutr_now(session->rep);
Willy Tarreaua2a64e92011-09-07 23:01:56 +02002496 session->task->nice = 1024;
2497 if (!(session->flags & SN_ERR_MASK))
2498 session->flags |= why;
2499 task_wakeup(session->task, TASK_WOKEN_OTHER);
2500}
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02002501
Willy Tarreau8b22a712010-06-18 17:46:06 +02002502/************************************************************************/
2503/* All supported ACL keywords must be declared here. */
2504/************************************************************************/
2505
Willy Tarreaua5e37562011-12-16 17:06:15 +01002506/* set temp integer to the General Purpose Counter 0 value in the stksess entry <ts> */
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002507static int
Willy Tarreau37406352012-04-23 16:16:37 +02002508acl_fetch_get_gpc0(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002509{
Willy Tarreau37406352012-04-23 16:16:37 +02002510 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002511 smp->type = SMP_T_UINT;
2512 smp->data.uint = 0;
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002513 if (ts != NULL) {
2514 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_GPC0);
2515 if (!ptr)
2516 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002517 smp->data.uint = stktable_data_cast(ptr, gpc0);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002518 }
2519 return 1;
2520}
2521
Willy Tarreaua5e37562011-12-16 17:06:15 +01002522/* set temp integer to the General Purpose Counter 0 value from the session's tracked
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002523 * frontend counters.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002524 */
2525static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002526acl_fetch_sc1_get_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002527 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002528{
Willy Tarreau56123282010-08-06 19:06:56 +02002529 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002530 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002531 return acl_fetch_get_gpc0(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002532}
2533
Willy Tarreaua5e37562011-12-16 17:06:15 +01002534/* set temp integer to the General Purpose Counter 0 value from the session's tracked
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002535 * backend counters.
2536 */
2537static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002538acl_fetch_sc2_get_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 Tarreauc3bd9722010-06-20 12:47:25 +02002540{
Willy Tarreau56123282010-08-06 19:06:56 +02002541 if (!l4->stkctr2_entry)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002542 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002543 return acl_fetch_get_gpc0(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002544}
2545
Willy Tarreaua5e37562011-12-16 17:06:15 +01002546/* set temp integer to the General Purpose Counter 0 value from the session's source
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002547 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002548 * Accepts exactly 1 argument of type table.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002549 */
2550static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002551acl_fetch_src_get_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002552 const struct arg *args, struct sample *smp)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002553{
2554 struct stktable_key *key;
2555
Willy Tarreau64ee4912012-08-30 22:59:48 +02002556 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002557 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002558 return 0;
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002559
Willy Tarreau24e32d82012-04-23 23:55:44 +02002560 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002561 return acl_fetch_get_gpc0(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002562}
2563
2564/* Increment the General Purpose Counter 0 value in the stksess entry <ts> and
Willy Tarreaua5e37562011-12-16 17:06:15 +01002565 * return it into temp integer.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002566 */
2567static int
Willy Tarreau37406352012-04-23 16:16:37 +02002568acl_fetch_inc_gpc0(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002569{
Willy Tarreau37406352012-04-23 16:16:37 +02002570 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002571 smp->type = SMP_T_UINT;
2572 smp->data.uint = 0;
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002573 if (ts != NULL) {
2574 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_GPC0);
2575 if (!ptr)
2576 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002577 smp->data.uint = ++stktable_data_cast(ptr, gpc0);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002578 }
2579 return 1;
2580}
2581
2582/* Increment the General Purpose Counter 0 value from the session's tracked
Willy Tarreaua5e37562011-12-16 17:06:15 +01002583 * frontend counters and return it into temp integer.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002584 */
2585static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002586acl_fetch_sc1_inc_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002587 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002588{
Willy Tarreau56123282010-08-06 19:06:56 +02002589 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002590 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002591 return acl_fetch_inc_gpc0(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002592}
2593
2594/* Increment the General Purpose Counter 0 value from the session's tracked
Willy Tarreaua5e37562011-12-16 17:06:15 +01002595 * backend counters and return it into temp integer.
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002596 */
2597static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002598acl_fetch_sc2_inc_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002599 const struct arg *args, struct sample *smp)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002600{
Willy Tarreau56123282010-08-06 19:06:56 +02002601 if (!l4->stkctr2_entry)
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002602 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002603 return acl_fetch_inc_gpc0(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002604}
2605
2606/* Increment the General Purpose Counter 0 value from the session's source
Willy Tarreaua5e37562011-12-16 17:06:15 +01002607 * address in the table pointed to by expr, and return it into temp integer.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002608 * Accepts exactly 1 argument of type table.
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002609 */
2610static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002611acl_fetch_src_inc_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 Tarreauc3bd9722010-06-20 12:47:25 +02002613{
2614 struct stktable_key *key;
2615
Willy Tarreau64ee4912012-08-30 22:59:48 +02002616 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002617 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002618 return 0;
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002619
Willy Tarreau24e32d82012-04-23 23:55:44 +02002620 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002621 return acl_fetch_inc_gpc0(&px->table, smp, stktable_update_key(&px->table, key));
Willy Tarreauc3bd9722010-06-20 12:47:25 +02002622}
2623
Willy Tarreauf73cd112011-08-13 01:45:16 +02002624/* Clear the General Purpose Counter 0 value in the stksess entry <ts> and
Willy Tarreaua5e37562011-12-16 17:06:15 +01002625 * return its previous value into temp integer.
Willy Tarreauf73cd112011-08-13 01:45:16 +02002626 */
2627static int
Willy Tarreau37406352012-04-23 16:16:37 +02002628acl_fetch_clr_gpc0(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauf73cd112011-08-13 01:45:16 +02002629{
Willy Tarreau37406352012-04-23 16:16:37 +02002630 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002631 smp->type = SMP_T_UINT;
2632 smp->data.uint = 0;
Willy Tarreauf73cd112011-08-13 01:45:16 +02002633 if (ts != NULL) {
2634 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_GPC0);
2635 if (!ptr)
2636 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002637 smp->data.uint = stktable_data_cast(ptr, gpc0);
Willy Tarreauf73cd112011-08-13 01:45:16 +02002638 stktable_data_cast(ptr, gpc0) = 0;
2639 }
2640 return 1;
2641}
2642
2643/* Clear the General Purpose Counter 0 value from the session's tracked
Willy Tarreaua5e37562011-12-16 17:06:15 +01002644 * frontend counters and return its previous value into temp integer.
Willy Tarreauf73cd112011-08-13 01:45:16 +02002645 */
2646static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002647acl_fetch_sc1_clr_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002648 const struct arg *args, struct sample *smp)
Willy Tarreauf73cd112011-08-13 01:45:16 +02002649{
2650 if (!l4->stkctr1_entry)
2651 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002652 return acl_fetch_clr_gpc0(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf73cd112011-08-13 01:45:16 +02002653}
2654
2655/* Clear the General Purpose Counter 0 value from the session's tracked
Willy Tarreaua5e37562011-12-16 17:06:15 +01002656 * backend counters and return its previous value into temp integer.
Willy Tarreauf73cd112011-08-13 01:45:16 +02002657 */
2658static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002659acl_fetch_sc2_clr_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002660 const struct arg *args, struct sample *smp)
Willy Tarreauf73cd112011-08-13 01:45:16 +02002661{
2662 if (!l4->stkctr2_entry)
2663 return 0;
Willy Tarreau37406352012-04-23 16:16:37 +02002664 return acl_fetch_clr_gpc0(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauf73cd112011-08-13 01:45:16 +02002665}
2666
2667/* Clear the General Purpose Counter 0 value from the session's source address
Willy Tarreaua5e37562011-12-16 17:06:15 +01002668 * in the table pointed to by expr, and return its previous value into temp integer.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002669 * Accepts exactly 1 argument of type table.
Willy Tarreauf73cd112011-08-13 01:45:16 +02002670 */
2671static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002672acl_fetch_src_clr_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002673 const struct arg *args, struct sample *smp)
Willy Tarreauf73cd112011-08-13 01:45:16 +02002674{
2675 struct stktable_key *key;
2676
Willy Tarreau64ee4912012-08-30 22:59:48 +02002677 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauf73cd112011-08-13 01:45:16 +02002678 if (!key)
2679 return 0;
2680
Willy Tarreau24e32d82012-04-23 23:55:44 +02002681 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002682 return acl_fetch_clr_gpc0(&px->table, smp, stktable_update_key(&px->table, key));
Willy Tarreauf73cd112011-08-13 01:45:16 +02002683}
2684
Willy Tarreaua5e37562011-12-16 17:06:15 +01002685/* set temp integer to the cumulated number of connections in the stksess entry <ts> */
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002686static int
Willy Tarreau37406352012-04-23 16:16:37 +02002687acl_fetch_conn_cnt(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002688{
Willy Tarreau37406352012-04-23 16:16:37 +02002689 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002690 smp->type = SMP_T_UINT;
2691 smp->data.uint = 0;
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002692 if (ts != NULL) {
2693 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_CONN_CNT);
2694 if (!ptr)
2695 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002696 smp->data.uint = stktable_data_cast(ptr, conn_cnt);
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002697 }
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002698 return 1;
2699}
2700
Willy Tarreaua5e37562011-12-16 17:06:15 +01002701/* set temp integer to the cumulated number of connections from the session's tracked FE counters */
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002702static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002703acl_fetch_sc1_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002704 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002705{
Willy Tarreau56123282010-08-06 19:06:56 +02002706 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002707 return 0;
2708
Willy Tarreau37406352012-04-23 16:16:37 +02002709 return acl_fetch_conn_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002710}
2711
Willy Tarreaua5e37562011-12-16 17:06:15 +01002712/* set temp integer to the cumulated number of connections from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002713static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002714acl_fetch_sc2_conn_cnt(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 Tarreau9a3f8492010-06-18 19:53:25 +02002716{
Willy Tarreau56123282010-08-06 19:06:56 +02002717 if (!l4->stkctr2_entry)
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002718 return 0;
2719
Willy Tarreau37406352012-04-23 16:16:37 +02002720 return acl_fetch_conn_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002721}
2722
Willy Tarreaua5e37562011-12-16 17:06:15 +01002723/* set temp integer to the cumulated number of connections from the session's source
Willy Tarreau9a3f8492010-06-18 19:53:25 +02002724 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002725 * Accepts exactly 1 argument of type table.
Willy Tarreau8b22a712010-06-18 17:46:06 +02002726 */
2727static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002728acl_fetch_src_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002729 const struct arg *args, struct sample *smp)
Willy Tarreau8b22a712010-06-18 17:46:06 +02002730{
Willy Tarreau8b22a712010-06-18 17:46:06 +02002731 struct stktable_key *key;
2732
Willy Tarreau64ee4912012-08-30 22:59:48 +02002733 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau8b22a712010-06-18 17:46:06 +02002734 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002735 return 0;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002736
Willy Tarreau24e32d82012-04-23 23:55:44 +02002737 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002738 return acl_fetch_conn_cnt(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau8b22a712010-06-18 17:46:06 +02002739}
2740
Willy Tarreaua5e37562011-12-16 17:06:15 +01002741/* set temp integer to the connection rate in the stksess entry <ts> over the configured period */
Willy Tarreau91c43d72010-06-20 11:19:22 +02002742static int
Willy Tarreau37406352012-04-23 16:16:37 +02002743acl_fetch_conn_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002744{
Willy Tarreau37406352012-04-23 16:16:37 +02002745 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002746 smp->type = SMP_T_UINT;
2747 smp->data.uint = 0;
Willy Tarreau91c43d72010-06-20 11:19:22 +02002748 if (ts != NULL) {
2749 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_CONN_RATE);
2750 if (!ptr)
2751 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002752 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, conn_rate),
Willy Tarreau91c43d72010-06-20 11:19:22 +02002753 table->data_arg[STKTABLE_DT_CONN_RATE].u);
2754 }
2755 return 1;
2756}
2757
Willy Tarreaua5e37562011-12-16 17:06:15 +01002758/* set temp integer to the connection rate from the session's tracked FE counters over
Willy Tarreau91c43d72010-06-20 11:19:22 +02002759 * the configured period.
2760 */
2761static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002762acl_fetch_sc1_conn_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002763 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002764{
Willy Tarreau56123282010-08-06 19:06:56 +02002765 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002766 return 0;
2767
Willy Tarreau37406352012-04-23 16:16:37 +02002768 return acl_fetch_conn_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002769}
2770
Willy Tarreaua5e37562011-12-16 17:06:15 +01002771/* set temp integer to the connection rate from the session's tracked BE counters over
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002772 * the configured period.
2773 */
2774static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002775acl_fetch_sc2_conn_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002776 const struct arg *args, struct sample *smp)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002777{
Willy Tarreau56123282010-08-06 19:06:56 +02002778 if (!l4->stkctr2_entry)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002779 return 0;
2780
Willy Tarreau37406352012-04-23 16:16:37 +02002781 return acl_fetch_conn_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau91c43d72010-06-20 11:19:22 +02002782}
2783
Willy Tarreaua5e37562011-12-16 17:06:15 +01002784/* set temp integer to the connection rate from the session's source address in the
Willy Tarreau91c43d72010-06-20 11:19:22 +02002785 * table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002786 * Accepts exactly 1 argument of type table.
Willy Tarreau91c43d72010-06-20 11:19:22 +02002787 */
2788static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002789acl_fetch_src_conn_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002790 const struct arg *args, struct sample *smp)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002791{
2792 struct stktable_key *key;
2793
Willy Tarreau64ee4912012-08-30 22:59:48 +02002794 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau91c43d72010-06-20 11:19:22 +02002795 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002796 return 0;
Willy Tarreau91c43d72010-06-20 11:19:22 +02002797
Willy Tarreau24e32d82012-04-23 23:55:44 +02002798 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002799 return acl_fetch_conn_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau91c43d72010-06-20 11:19:22 +02002800}
2801
Willy Tarreaua5e37562011-12-16 17:06:15 +01002802/* set temp integer to the number of connections from the session's source address
Willy Tarreau8b22a712010-06-18 17:46:06 +02002803 * in the table pointed to by expr, after updating it.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002804 * Accepts exactly 1 argument of type table.
Willy Tarreau8b22a712010-06-18 17:46:06 +02002805 */
2806static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002807acl_fetch_src_updt_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002808 const struct arg *args, struct sample *smp)
Willy Tarreau8b22a712010-06-18 17:46:06 +02002809{
2810 struct stksess *ts;
2811 struct stktable_key *key;
2812 void *ptr;
2813
Willy Tarreau64ee4912012-08-30 22:59:48 +02002814 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau8b22a712010-06-18 17:46:06 +02002815 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002816 return 0;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002817
Willy Tarreau24e32d82012-04-23 23:55:44 +02002818 px = args->data.prx;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002819
Willy Tarreau1f7e9252010-06-20 12:27:21 +02002820 if ((ts = stktable_update_key(&px->table, key)) == NULL)
2821 /* entry does not exist and could not be created */
2822 return 0;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002823
2824 ptr = stktable_data_ptr(&px->table, ts, STKTABLE_DT_CONN_CNT);
2825 if (!ptr)
2826 return 0; /* parameter not stored in this table */
2827
Willy Tarreauf853c462012-04-23 18:53:56 +02002828 smp->type = SMP_T_UINT;
2829 smp->data.uint = ++stktable_data_cast(ptr, conn_cnt);
Willy Tarreau37406352012-04-23 16:16:37 +02002830 smp->flags = SMP_F_VOL_TEST;
Willy Tarreau8b22a712010-06-18 17:46:06 +02002831 return 1;
2832}
2833
Willy Tarreaua5e37562011-12-16 17:06:15 +01002834/* set temp integer to the number of concurrent connections in the stksess entry <ts> */
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002835static int
Willy Tarreau37406352012-04-23 16:16:37 +02002836acl_fetch_conn_cur(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002837{
Willy Tarreau37406352012-04-23 16:16:37 +02002838 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002839 smp->type = SMP_T_UINT;
2840 smp->data.uint = 0;
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002841
2842 if (ts != NULL) {
2843 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_CONN_CUR);
2844 if (!ptr)
2845 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002846 smp->data.uint = stktable_data_cast(ptr, conn_cur);
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002847 }
2848 return 1;
2849}
2850
Willy Tarreaua5e37562011-12-16 17:06:15 +01002851/* set temp integer to the number of concurrent connections from the session's tracked FE counters */
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002852static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002853acl_fetch_sc1_conn_cur(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002854 const struct arg *args, struct sample *smp)
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002855{
Willy Tarreau56123282010-08-06 19:06:56 +02002856 if (!l4->stkctr1_entry)
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002857 return 0;
2858
Willy Tarreau37406352012-04-23 16:16:37 +02002859 return acl_fetch_conn_cur(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreau9b0ddcf2010-06-18 21:14:36 +02002860}
2861
Willy Tarreaua5e37562011-12-16 17:06:15 +01002862/* set temp integer to the number of concurrent connections from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002863static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002864acl_fetch_sc2_conn_cur(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002865 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002866{
Willy Tarreau56123282010-08-06 19:06:56 +02002867 if (!l4->stkctr2_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002868 return 0;
2869
Willy Tarreau37406352012-04-23 16:16:37 +02002870 return acl_fetch_conn_cur(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002871}
2872
Willy Tarreaua5e37562011-12-16 17:06:15 +01002873/* set temp integer to the number of concurrent connections from the session's source
Willy Tarreau38285c12010-06-18 16:35:43 +02002874 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002875 * Accepts exactly 1 argument of type table.
Willy Tarreau38285c12010-06-18 16:35:43 +02002876 */
2877static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002878acl_fetch_src_conn_cur(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002879 const struct arg *args, struct sample *smp)
Willy Tarreau38285c12010-06-18 16:35:43 +02002880{
Willy Tarreau38285c12010-06-18 16:35:43 +02002881 struct stktable_key *key;
2882
Willy Tarreau64ee4912012-08-30 22:59:48 +02002883 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau38285c12010-06-18 16:35:43 +02002884 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002885 return 0;
Willy Tarreau38285c12010-06-18 16:35:43 +02002886
Willy Tarreau24e32d82012-04-23 23:55:44 +02002887 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002888 return acl_fetch_conn_cur(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau38285c12010-06-18 16:35:43 +02002889}
2890
Willy Tarreaua5e37562011-12-16 17:06:15 +01002891/* set temp integer to the cumulated number of sessions in the stksess entry <ts> */
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002892static int
Willy Tarreau37406352012-04-23 16:16:37 +02002893acl_fetch_sess_cnt(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002894{
Willy Tarreau37406352012-04-23 16:16:37 +02002895 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002896 smp->type = SMP_T_UINT;
2897 smp->data.uint = 0;
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002898 if (ts != NULL) {
2899 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_SESS_CNT);
2900 if (!ptr)
2901 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002902 smp->data.uint = stktable_data_cast(ptr, sess_cnt);
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002903 }
2904 return 1;
2905}
2906
Willy Tarreaua5e37562011-12-16 17:06:15 +01002907/* set temp integer to the cumulated number of sessions from the session's tracked FE counters */
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002908static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002909acl_fetch_sc1_sess_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002910 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002911{
Willy Tarreau56123282010-08-06 19:06:56 +02002912 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002913 return 0;
2914
Willy Tarreau37406352012-04-23 16:16:37 +02002915 return acl_fetch_sess_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002916}
2917
Willy Tarreaua5e37562011-12-16 17:06:15 +01002918/* set temp integer to the cumulated number of sessions from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002919static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002920acl_fetch_sc2_sess_cnt(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 Tarreauf4d17d92010-06-18 22:10:12 +02002922{
Willy Tarreau56123282010-08-06 19:06:56 +02002923 if (!l4->stkctr2_entry)
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002924 return 0;
2925
Willy Tarreau37406352012-04-23 16:16:37 +02002926 return acl_fetch_sess_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002927}
2928
Willy Tarreaua5e37562011-12-16 17:06:15 +01002929/* set temp integer to the cumulated number of session from the session's source
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002930 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002931 * Accepts exactly 1 argument of type table.
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002932 */
2933static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002934acl_fetch_src_sess_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002935 const struct arg *args, struct sample *smp)
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002936{
2937 struct stktable_key *key;
2938
Willy Tarreau64ee4912012-08-30 22:59:48 +02002939 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002940 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01002941 return 0;
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002942
Willy Tarreau24e32d82012-04-23 23:55:44 +02002943 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02002944 return acl_fetch_sess_cnt(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauf4d17d92010-06-18 22:10:12 +02002945}
2946
Willy Tarreaua5e37562011-12-16 17:06:15 +01002947/* set temp integer to the session rate in the stksess entry <ts> over the configured period */
Willy Tarreau91c43d72010-06-20 11:19:22 +02002948static int
Willy Tarreau37406352012-04-23 16:16:37 +02002949acl_fetch_sess_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002950{
Willy Tarreau37406352012-04-23 16:16:37 +02002951 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02002952 smp->type = SMP_T_UINT;
2953 smp->data.uint = 0;
Willy Tarreau91c43d72010-06-20 11:19:22 +02002954 if (ts != NULL) {
2955 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_SESS_RATE);
2956 if (!ptr)
2957 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02002958 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, sess_rate),
Willy Tarreau91c43d72010-06-20 11:19:22 +02002959 table->data_arg[STKTABLE_DT_SESS_RATE].u);
2960 }
2961 return 1;
2962}
2963
Willy Tarreaua5e37562011-12-16 17:06:15 +01002964/* set temp integer to the session rate from the session's tracked FE counters over
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002965 * the configured period.
2966 */
2967static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002968acl_fetch_sc1_sess_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002969 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002970{
Willy Tarreau56123282010-08-06 19:06:56 +02002971 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002972 return 0;
2973
Willy Tarreau37406352012-04-23 16:16:37 +02002974 return acl_fetch_sess_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02002975}
2976
Willy Tarreaua5e37562011-12-16 17:06:15 +01002977/* set temp integer to the session rate from the session's tracked BE counters over
Willy Tarreau91c43d72010-06-20 11:19:22 +02002978 * the configured period.
2979 */
2980static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002981acl_fetch_sc2_sess_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002982 const struct arg *args, struct sample *smp)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002983{
Willy Tarreau56123282010-08-06 19:06:56 +02002984 if (!l4->stkctr2_entry)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002985 return 0;
2986
Willy Tarreau37406352012-04-23 16:16:37 +02002987 return acl_fetch_sess_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau91c43d72010-06-20 11:19:22 +02002988}
2989
Willy Tarreaua5e37562011-12-16 17:06:15 +01002990/* set temp integer to the session rate from the session's source address in the
Willy Tarreau91c43d72010-06-20 11:19:22 +02002991 * table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02002992 * Accepts exactly 1 argument of type table.
Willy Tarreau91c43d72010-06-20 11:19:22 +02002993 */
2994static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002995acl_fetch_src_sess_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02002996 const struct arg *args, struct sample *smp)
Willy Tarreau91c43d72010-06-20 11:19:22 +02002997{
2998 struct stktable_key *key;
2999
Willy Tarreau64ee4912012-08-30 22:59:48 +02003000 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau91c43d72010-06-20 11:19:22 +02003001 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003002 return 0;
Willy Tarreau91c43d72010-06-20 11:19:22 +02003003
Willy Tarreau24e32d82012-04-23 23:55:44 +02003004 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003005 return acl_fetch_sess_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau91c43d72010-06-20 11:19:22 +02003006}
3007
Willy Tarreaua5e37562011-12-16 17:06:15 +01003008/* set temp integer to the cumulated number of sessions in the stksess entry <ts> */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003009static int
Willy Tarreau37406352012-04-23 16:16:37 +02003010acl_fetch_http_req_cnt(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003011{
Willy Tarreau37406352012-04-23 16:16:37 +02003012 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003013 smp->type = SMP_T_UINT;
3014 smp->data.uint = 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003015 if (ts != NULL) {
3016 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_HTTP_REQ_CNT);
3017 if (!ptr)
3018 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003019 smp->data.uint = stktable_data_cast(ptr, http_req_cnt);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003020 }
3021 return 1;
3022}
3023
Willy Tarreaua5e37562011-12-16 17:06:15 +01003024/* set temp integer to the cumulated number of sessions from the session's tracked FE counters */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003025static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003026acl_fetch_sc1_http_req_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003027 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003028{
Willy Tarreau56123282010-08-06 19:06:56 +02003029 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003030 return 0;
3031
Willy Tarreau37406352012-04-23 16:16:37 +02003032 return acl_fetch_http_req_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003033}
3034
Willy Tarreaua5e37562011-12-16 17:06:15 +01003035/* set temp integer to the cumulated number of sessions from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003036static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003037acl_fetch_sc2_http_req_cnt(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 Tarreauda7ff642010-06-23 11:44:09 +02003039{
Willy Tarreau56123282010-08-06 19:06:56 +02003040 if (!l4->stkctr2_entry)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003041 return 0;
3042
Willy Tarreau37406352012-04-23 16:16:37 +02003043 return acl_fetch_http_req_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003044}
3045
Willy Tarreaua5e37562011-12-16 17:06:15 +01003046/* set temp integer to the cumulated number of session from the session's source
Willy Tarreauda7ff642010-06-23 11:44:09 +02003047 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003048 * Accepts exactly 1 argument of type table.
Willy Tarreauda7ff642010-06-23 11:44:09 +02003049 */
3050static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003051acl_fetch_src_http_req_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003052 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003053{
3054 struct stktable_key *key;
3055
Willy Tarreau64ee4912012-08-30 22:59:48 +02003056 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003057 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003058 return 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003059
Willy Tarreau24e32d82012-04-23 23:55:44 +02003060 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003061 return acl_fetch_http_req_cnt(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauda7ff642010-06-23 11:44:09 +02003062}
3063
Willy Tarreaua5e37562011-12-16 17:06:15 +01003064/* set temp integer to the session rate in the stksess entry <ts> over the configured period */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003065static int
Willy Tarreau37406352012-04-23 16:16:37 +02003066acl_fetch_http_req_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003067{
Willy Tarreau37406352012-04-23 16:16:37 +02003068 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003069 smp->type = SMP_T_UINT;
3070 smp->data.uint = 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003071 if (ts != NULL) {
3072 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_HTTP_REQ_RATE);
3073 if (!ptr)
3074 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003075 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, http_req_rate),
Willy Tarreauda7ff642010-06-23 11:44:09 +02003076 table->data_arg[STKTABLE_DT_HTTP_REQ_RATE].u);
3077 }
3078 return 1;
3079}
3080
Willy Tarreaua5e37562011-12-16 17:06:15 +01003081/* set temp integer to the session rate from the session's tracked FE counters over
Willy Tarreauda7ff642010-06-23 11:44:09 +02003082 * the configured period.
3083 */
3084static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003085acl_fetch_sc1_http_req_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003086 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003087{
Willy Tarreau56123282010-08-06 19:06:56 +02003088 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003089 return 0;
3090
Willy Tarreau37406352012-04-23 16:16:37 +02003091 return acl_fetch_http_req_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003092}
3093
Willy Tarreaua5e37562011-12-16 17:06:15 +01003094/* set temp integer to the session rate from the session's tracked BE counters over
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003095 * the configured period.
3096 */
3097static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003098acl_fetch_sc2_http_req_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003099 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003100{
Willy Tarreau56123282010-08-06 19:06:56 +02003101 if (!l4->stkctr2_entry)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003102 return 0;
3103
Willy Tarreau37406352012-04-23 16:16:37 +02003104 return acl_fetch_http_req_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003105}
3106
Willy Tarreaua5e37562011-12-16 17:06:15 +01003107/* set temp integer to the session rate from the session's source address in the
Willy Tarreauda7ff642010-06-23 11:44:09 +02003108 * table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003109 * Accepts exactly 1 argument of type table.
Willy Tarreauda7ff642010-06-23 11:44:09 +02003110 */
3111static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003112acl_fetch_src_http_req_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003113 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003114{
3115 struct stktable_key *key;
3116
Willy Tarreau64ee4912012-08-30 22:59:48 +02003117 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003118 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003119 return 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003120
Willy Tarreau24e32d82012-04-23 23:55:44 +02003121 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003122 return acl_fetch_http_req_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauda7ff642010-06-23 11:44:09 +02003123}
3124
Willy Tarreaua5e37562011-12-16 17:06:15 +01003125/* set temp integer to the cumulated number of sessions in the stksess entry <ts> */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003126static int
Willy Tarreau37406352012-04-23 16:16:37 +02003127acl_fetch_http_err_cnt(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003128{
Willy Tarreau37406352012-04-23 16:16:37 +02003129 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003130 smp->type = SMP_T_UINT;
3131 smp->data.uint = 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003132 if (ts != NULL) {
3133 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_HTTP_ERR_CNT);
3134 if (!ptr)
3135 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003136 smp->data.uint = stktable_data_cast(ptr, http_err_cnt);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003137 }
3138 return 1;
3139}
3140
Willy Tarreaua5e37562011-12-16 17:06:15 +01003141/* set temp integer to the cumulated number of sessions from the session's tracked FE counters */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003142static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003143acl_fetch_sc1_http_err_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003144 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003145{
Willy Tarreau56123282010-08-06 19:06:56 +02003146 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003147 return 0;
3148
Willy Tarreau37406352012-04-23 16:16:37 +02003149 return acl_fetch_http_err_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003150}
3151
Willy Tarreaua5e37562011-12-16 17:06:15 +01003152/* set temp integer to the cumulated number of sessions from the session's tracked BE counters */
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003153static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003154acl_fetch_sc2_http_err_cnt(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 Tarreauda7ff642010-06-23 11:44:09 +02003156{
Willy Tarreau56123282010-08-06 19:06:56 +02003157 if (!l4->stkctr2_entry)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003158 return 0;
3159
Willy Tarreau37406352012-04-23 16:16:37 +02003160 return acl_fetch_http_err_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003161}
3162
Willy Tarreaua5e37562011-12-16 17:06:15 +01003163/* set temp integer to the cumulated number of session from the session's source
Willy Tarreauda7ff642010-06-23 11:44:09 +02003164 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003165 * Accepts exactly 1 argument of type table.
Willy Tarreauda7ff642010-06-23 11:44:09 +02003166 */
3167static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003168acl_fetch_src_http_err_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003169 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003170{
3171 struct stktable_key *key;
3172
Willy Tarreau64ee4912012-08-30 22:59:48 +02003173 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003174 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003175 return 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003176
Willy Tarreau24e32d82012-04-23 23:55:44 +02003177 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003178 return acl_fetch_http_err_cnt(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauda7ff642010-06-23 11:44:09 +02003179}
3180
Willy Tarreaua5e37562011-12-16 17:06:15 +01003181/* set temp integer to the session rate in the stksess entry <ts> over the configured period */
Willy Tarreauda7ff642010-06-23 11:44:09 +02003182static int
Willy Tarreau37406352012-04-23 16:16:37 +02003183acl_fetch_http_err_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003184{
Willy Tarreau37406352012-04-23 16:16:37 +02003185 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003186 smp->type = SMP_T_UINT;
3187 smp->data.uint = 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003188 if (ts != NULL) {
3189 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_HTTP_ERR_RATE);
3190 if (!ptr)
3191 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003192 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, http_err_rate),
Willy Tarreauda7ff642010-06-23 11:44:09 +02003193 table->data_arg[STKTABLE_DT_HTTP_ERR_RATE].u);
3194 }
3195 return 1;
3196}
3197
Willy Tarreaua5e37562011-12-16 17:06:15 +01003198/* set temp integer to the session rate from the session's tracked FE counters over
Willy Tarreauda7ff642010-06-23 11:44:09 +02003199 * the configured period.
3200 */
3201static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003202acl_fetch_sc1_http_err_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003203 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003204{
Willy Tarreau56123282010-08-06 19:06:56 +02003205 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003206 return 0;
3207
Willy Tarreau37406352012-04-23 16:16:37 +02003208 return acl_fetch_http_err_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003209}
3210
Willy Tarreaua5e37562011-12-16 17:06:15 +01003211/* set temp integer to the session rate from the session's tracked BE counters over
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003212 * the configured period.
3213 */
3214static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003215acl_fetch_sc2_http_err_rate(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 Tarreauda7ff642010-06-23 11:44:09 +02003217{
Willy Tarreau56123282010-08-06 19:06:56 +02003218 if (!l4->stkctr2_entry)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003219 return 0;
3220
Willy Tarreau37406352012-04-23 16:16:37 +02003221 return acl_fetch_http_err_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003222}
3223
Willy Tarreaua5e37562011-12-16 17:06:15 +01003224/* set temp integer to the session rate from the session's source address in the
Willy Tarreauda7ff642010-06-23 11:44:09 +02003225 * table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003226 * Accepts exactly 1 argument of type table.
Willy Tarreauda7ff642010-06-23 11:44:09 +02003227 */
3228static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003229acl_fetch_src_http_err_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003230 const struct arg *args, struct sample *smp)
Willy Tarreauda7ff642010-06-23 11:44:09 +02003231{
3232 struct stktable_key *key;
3233
Willy Tarreau64ee4912012-08-30 22:59:48 +02003234 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreauda7ff642010-06-23 11:44:09 +02003235 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003236 return 0;
Willy Tarreauda7ff642010-06-23 11:44:09 +02003237
Willy Tarreau24e32d82012-04-23 23:55:44 +02003238 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003239 return acl_fetch_http_err_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreauda7ff642010-06-23 11:44:09 +02003240}
3241
Willy Tarreaua5e37562011-12-16 17:06:15 +01003242/* set temp integer to the number of kbytes received from clients matching the stksess entry <ts> */
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003243static int
Willy Tarreau37406352012-04-23 16:16:37 +02003244acl_fetch_kbytes_in(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003245{
Willy Tarreau37406352012-04-23 16:16:37 +02003246 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003247 smp->type = SMP_T_UINT;
3248 smp->data.uint = 0;
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003249
3250 if (ts != NULL) {
3251 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_BYTES_IN_CNT);
3252 if (!ptr)
3253 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003254 smp->data.uint = stktable_data_cast(ptr, bytes_in_cnt) >> 10;
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003255 }
3256 return 1;
3257}
3258
Willy Tarreaua5e37562011-12-16 17:06:15 +01003259/* set temp integer to the number of kbytes received from clients according to the
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003260 * session's tracked FE counters.
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003261 */
3262static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003263acl_fetch_sc1_kbytes_in(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003264 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003265{
Willy Tarreau56123282010-08-06 19:06:56 +02003266 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003267 return 0;
3268
Willy Tarreau37406352012-04-23 16:16:37 +02003269 return acl_fetch_kbytes_in(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003270}
3271
Willy Tarreaua5e37562011-12-16 17:06:15 +01003272/* set temp integer to the number of kbytes received from clients according to the
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003273 * session's tracked BE counters.
3274 */
3275static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003276acl_fetch_sc2_kbytes_in(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003277 const struct arg *args, struct sample *smp)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003278{
Willy Tarreau56123282010-08-06 19:06:56 +02003279 if (!l4->stkctr2_entry)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003280 return 0;
3281
Willy Tarreau37406352012-04-23 16:16:37 +02003282 return acl_fetch_kbytes_in(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003283}
3284
Willy Tarreaua5e37562011-12-16 17:06:15 +01003285/* set temp integer to the number of kbytes received from the session's source
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003286 * address in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003287 * Accepts exactly 1 argument of type table.
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003288 */
3289static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003290acl_fetch_src_kbytes_in(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003291 const struct arg *args, struct sample *smp)
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003292{
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003293 struct stktable_key *key;
3294
Willy Tarreau64ee4912012-08-30 22:59:48 +02003295 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003296 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003297 return 0;
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003298
Willy Tarreau24e32d82012-04-23 23:55:44 +02003299 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003300 return acl_fetch_kbytes_in(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003301}
3302
Willy Tarreaua5e37562011-12-16 17:06:15 +01003303/* set temp integer to the bytes rate from clients in the stksess entry <ts> over the
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003304 * configured period.
3305 */
3306static int
Willy Tarreau37406352012-04-23 16:16:37 +02003307acl_fetch_bytes_in_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003308{
Willy Tarreau37406352012-04-23 16:16:37 +02003309 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003310 smp->type = SMP_T_UINT;
3311 smp->data.uint = 0;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003312 if (ts != NULL) {
3313 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_BYTES_IN_RATE);
3314 if (!ptr)
3315 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003316 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, bytes_in_rate),
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003317 table->data_arg[STKTABLE_DT_BYTES_IN_RATE].u);
3318 }
3319 return 1;
3320}
3321
Willy Tarreaua5e37562011-12-16 17:06:15 +01003322/* set temp integer to the bytes rate from clients from the session's tracked FE
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003323 * counters over the configured period.
3324 */
3325static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003326acl_fetch_sc1_bytes_in_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003327 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003328{
Willy Tarreau56123282010-08-06 19:06:56 +02003329 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003330 return 0;
3331
Willy Tarreau37406352012-04-23 16:16:37 +02003332 return acl_fetch_bytes_in_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003333}
3334
Willy Tarreaua5e37562011-12-16 17:06:15 +01003335/* set temp integer to the bytes rate from clients from the session's tracked BE
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003336 * counters over the configured period.
3337 */
3338static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003339acl_fetch_sc2_bytes_in_rate(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 Tarreau6c59e0a2010-06-20 11:56:30 +02003341{
Willy Tarreau56123282010-08-06 19:06:56 +02003342 if (!l4->stkctr2_entry)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003343 return 0;
3344
Willy Tarreau37406352012-04-23 16:16:37 +02003345 return acl_fetch_bytes_in_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003346}
3347
Willy Tarreaua5e37562011-12-16 17:06:15 +01003348/* set temp integer to the bytes rate from clients from the session's source address
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003349 * in the table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003350 * Accepts exactly 1 argument of type table.
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003351 */
3352static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003353acl_fetch_src_bytes_in_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003354 const struct arg *args, struct sample *smp)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003355{
3356 struct stktable_key *key;
3357
Willy Tarreau64ee4912012-08-30 22:59:48 +02003358 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003359 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003360 return 0;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003361
Willy Tarreau24e32d82012-04-23 23:55:44 +02003362 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003363 return acl_fetch_bytes_in_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003364}
3365
Willy Tarreaua5e37562011-12-16 17:06:15 +01003366/* set temp integer to the number of kbytes sent to clients matching the stksess entry <ts> */
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003367static int
Willy Tarreau37406352012-04-23 16:16:37 +02003368acl_fetch_kbytes_out(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003369{
Willy Tarreau37406352012-04-23 16:16:37 +02003370 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003371 smp->type = SMP_T_UINT;
3372 smp->data.uint = 0;
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003373
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003374 if (ts != NULL) {
3375 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_BYTES_OUT_CNT);
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003376 if (!ptr)
3377 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003378 smp->data.uint = stktable_data_cast(ptr, bytes_out_cnt) >> 10;
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003379 }
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003380 return 1;
3381}
3382
Willy Tarreaua5e37562011-12-16 17:06:15 +01003383/* set temp integer to the number of kbytes sent to clients according to the session's
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003384 * tracked FE counters.
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003385 */
3386static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003387acl_fetch_sc1_kbytes_out(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003388 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003389{
Willy Tarreau56123282010-08-06 19:06:56 +02003390 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003391 return 0;
3392
Willy Tarreau37406352012-04-23 16:16:37 +02003393 return acl_fetch_kbytes_out(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003394}
3395
Willy Tarreaua5e37562011-12-16 17:06:15 +01003396/* set temp integer to the number of kbytes sent to clients according to the session's
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003397 * tracked BE counters.
3398 */
3399static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003400acl_fetch_sc2_kbytes_out(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003401 const struct arg *args, struct sample *smp)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003402{
Willy Tarreau56123282010-08-06 19:06:56 +02003403 if (!l4->stkctr2_entry)
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003404 return 0;
3405
Willy Tarreau37406352012-04-23 16:16:37 +02003406 return acl_fetch_kbytes_out(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau1aa006f2010-06-18 21:52:52 +02003407}
3408
Willy Tarreaua5e37562011-12-16 17:06:15 +01003409/* set temp integer to the number of kbytes sent to the session's source address in
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003410 * the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003411 * Accepts exactly 1 argument of type table.
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003412 */
3413static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003414acl_fetch_src_kbytes_out(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003415 const struct arg *args, struct sample *smp)
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003416{
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003417 struct stktable_key *key;
3418
Willy Tarreau64ee4912012-08-30 22:59:48 +02003419 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003420 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003421 return 0;
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003422
Willy Tarreau24e32d82012-04-23 23:55:44 +02003423 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003424 return acl_fetch_kbytes_out(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau855e4bb2010-06-18 18:33:32 +02003425}
3426
Willy Tarreaua5e37562011-12-16 17:06:15 +01003427/* set temp integer to the bytes rate to clients in the stksess entry <ts> over the
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003428 * configured period.
3429 */
3430static int
Willy Tarreau37406352012-04-23 16:16:37 +02003431acl_fetch_bytes_out_rate(struct stktable *table, struct sample *smp, struct stksess *ts)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003432{
Willy Tarreau37406352012-04-23 16:16:37 +02003433 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003434 smp->type = SMP_T_UINT;
3435 smp->data.uint = 0;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003436 if (ts != NULL) {
3437 void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_BYTES_OUT_RATE);
3438 if (!ptr)
3439 return 0; /* parameter not stored */
Willy Tarreauf853c462012-04-23 18:53:56 +02003440 smp->data.uint = read_freq_ctr_period(&stktable_data_cast(ptr, bytes_out_rate),
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003441 table->data_arg[STKTABLE_DT_BYTES_OUT_RATE].u);
3442 }
3443 return 1;
3444}
3445
Willy Tarreaua5e37562011-12-16 17:06:15 +01003446/* set temp integer to the bytes rate to clients from the session's tracked FE counters
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003447 * over the configured period.
3448 */
3449static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003450acl_fetch_sc1_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003451 const struct arg *args, struct sample *smp)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003452{
Willy Tarreau56123282010-08-06 19:06:56 +02003453 if (!l4->stkctr1_entry)
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003454 return 0;
3455
Willy Tarreau37406352012-04-23 16:16:37 +02003456 return acl_fetch_bytes_out_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003457}
3458
Willy Tarreaua5e37562011-12-16 17:06:15 +01003459/* set temp integer to the bytes rate to clients from the session's tracked BE counters
Willy Tarreauf059a0f2010-08-03 16:29:52 +02003460 * over the configured period.
3461 */
3462static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003463acl_fetch_sc2_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003464 const struct arg *args, struct sample *smp)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003465{
Willy Tarreau56123282010-08-06 19:06:56 +02003466 if (!l4->stkctr2_entry)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003467 return 0;
3468
Willy Tarreau37406352012-04-23 16:16:37 +02003469 return acl_fetch_bytes_out_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003470}
3471
Willy Tarreaua5e37562011-12-16 17:06:15 +01003472/* set temp integer to the bytes rate to client from the session's source address in
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003473 * the table pointed to by expr, over the configured period.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003474 * Accepts exactly 1 argument of type table.
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003475 */
3476static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003477acl_fetch_src_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003478 const struct arg *args, struct sample *smp)
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003479{
3480 struct stktable_key *key;
3481
Willy Tarreau64ee4912012-08-30 22:59:48 +02003482 key = addr_to_stktable_key(&l4->si[0].conn.addr.from);
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003483 if (!key)
David du Colombier4f92d322011-03-24 11:09:31 +01003484 return 0;
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003485
Willy Tarreau24e32d82012-04-23 23:55:44 +02003486 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003487 return acl_fetch_bytes_out_rate(&px->table, smp, stktable_lookup_key(&px->table, key));
Willy Tarreau6c59e0a2010-06-20 11:56:30 +02003488}
3489
Willy Tarreau34db1082012-04-19 17:16:54 +02003490/* set temp integer to the number of used entries in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003491 * Accepts exactly 1 argument of type table.
Willy Tarreau34db1082012-04-19 17:16:54 +02003492 */
Willy Tarreauc735a072011-03-29 00:57:02 +02003493static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003494acl_fetch_table_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003495 const struct arg *args, struct sample *smp)
Willy Tarreauc735a072011-03-29 00:57:02 +02003496{
Willy Tarreau37406352012-04-23 16:16:37 +02003497 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003498 smp->type = SMP_T_UINT;
Willy Tarreau24e32d82012-04-23 23:55:44 +02003499 smp->data.uint = args->data.prx->table.current;
Willy Tarreauc735a072011-03-29 00:57:02 +02003500 return 1;
3501}
3502
Willy Tarreau34db1082012-04-19 17:16:54 +02003503/* set temp integer to the number of free entries in the table pointed to by expr.
Willy Tarreau0146c2e2012-04-20 11:37:56 +02003504 * Accepts exactly 1 argument of type table.
Willy Tarreau34db1082012-04-19 17:16:54 +02003505 */
Willy Tarreauc735a072011-03-29 00:57:02 +02003506static int
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003507acl_fetch_table_avl(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
Willy Tarreau24e32d82012-04-23 23:55:44 +02003508 const struct arg *args, struct sample *smp)
Willy Tarreauc735a072011-03-29 00:57:02 +02003509{
Willy Tarreau24e32d82012-04-23 23:55:44 +02003510 px = args->data.prx;
Willy Tarreau37406352012-04-23 16:16:37 +02003511 smp->flags = SMP_F_VOL_TEST;
Willy Tarreauf853c462012-04-23 18:53:56 +02003512 smp->type = SMP_T_UINT;
3513 smp->data.uint = px->table.size - px->table.current;
Willy Tarreauc735a072011-03-29 00:57:02 +02003514 return 1;
3515}
Willy Tarreau8b22a712010-06-18 17:46:06 +02003516
Willy Tarreau61612d42012-04-19 18:42:05 +02003517/* Note: must not be declared <const> as its list will be overwritten.
3518 * Please take care of keeping this list alphabetically sorted.
3519 */
Willy Tarreau8b22a712010-06-18 17:46:06 +02003520static struct acl_kw_list acl_kws = {{ },{
Willy Tarreau61612d42012-04-19 18:42:05 +02003521 { "sc1_bytes_in_rate", acl_parse_int, acl_fetch_sc1_bytes_in_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3522 { "sc1_bytes_out_rate", acl_parse_int, acl_fetch_sc1_bytes_out_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3523 { "sc1_clr_gpc0", acl_parse_int, acl_fetch_sc1_clr_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3524 { "sc1_conn_cnt", acl_parse_int, acl_fetch_sc1_conn_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3525 { "sc1_conn_cur", acl_parse_int, acl_fetch_sc1_conn_cur, acl_match_int, ACL_USE_NOTHING, 0 },
3526 { "sc1_conn_rate", acl_parse_int, acl_fetch_sc1_conn_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3527 { "sc1_get_gpc0", acl_parse_int, acl_fetch_sc1_get_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3528 { "sc1_http_err_cnt", acl_parse_int, acl_fetch_sc1_http_err_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3529 { "sc1_http_err_rate", acl_parse_int, acl_fetch_sc1_http_err_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3530 { "sc1_http_req_cnt", acl_parse_int, acl_fetch_sc1_http_req_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3531 { "sc1_http_req_rate", acl_parse_int, acl_fetch_sc1_http_req_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3532 { "sc1_inc_gpc0", acl_parse_int, acl_fetch_sc1_inc_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3533 { "sc1_kbytes_in", acl_parse_int, acl_fetch_sc1_kbytes_in, acl_match_int, ACL_USE_TCP4_VOLATILE, 0 },
3534 { "sc1_kbytes_out", acl_parse_int, acl_fetch_sc1_kbytes_out, acl_match_int, ACL_USE_TCP4_VOLATILE, 0 },
3535 { "sc1_sess_cnt", acl_parse_int, acl_fetch_sc1_sess_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3536 { "sc1_sess_rate", acl_parse_int, acl_fetch_sc1_sess_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3537 { "sc2_bytes_in_rate", acl_parse_int, acl_fetch_sc2_bytes_in_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3538 { "sc2_bytes_out_rate", acl_parse_int, acl_fetch_sc2_bytes_out_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3539 { "sc2_clr_gpc0", acl_parse_int, acl_fetch_sc2_clr_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3540 { "sc2_conn_cnt", acl_parse_int, acl_fetch_sc2_conn_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3541 { "sc2_conn_cur", acl_parse_int, acl_fetch_sc2_conn_cur, acl_match_int, ACL_USE_NOTHING, 0 },
3542 { "sc2_conn_rate", acl_parse_int, acl_fetch_sc2_conn_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3543 { "sc2_get_gpc0", acl_parse_int, acl_fetch_sc2_get_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3544 { "sc2_http_err_cnt", acl_parse_int, acl_fetch_sc2_http_err_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3545 { "sc2_http_err_rate", acl_parse_int, acl_fetch_sc2_http_err_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3546 { "sc2_http_req_cnt", acl_parse_int, acl_fetch_sc2_http_req_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3547 { "sc2_http_req_rate", acl_parse_int, acl_fetch_sc2_http_req_rate, acl_match_int, ACL_USE_NOTHING, 0 },
3548 { "sc2_inc_gpc0", acl_parse_int, acl_fetch_sc2_inc_gpc0, acl_match_int, ACL_USE_NOTHING, 0 },
3549 { "sc2_kbytes_in", acl_parse_int, acl_fetch_sc2_kbytes_in, acl_match_int, ACL_USE_TCP4_VOLATILE, 0 },
3550 { "sc2_kbytes_out", acl_parse_int, acl_fetch_sc2_kbytes_out, acl_match_int, ACL_USE_TCP4_VOLATILE, 0 },
3551 { "sc2_sess_cnt", acl_parse_int, acl_fetch_sc2_sess_cnt, acl_match_int, ACL_USE_NOTHING, 0 },
3552 { "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 +02003553 { "src_bytes_in_rate", acl_parse_int, acl_fetch_src_bytes_in_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3554 { "src_bytes_out_rate", acl_parse_int, acl_fetch_src_bytes_out_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3555 { "src_clr_gpc0", acl_parse_int, acl_fetch_src_clr_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3556 { "src_conn_cnt", acl_parse_int, acl_fetch_src_conn_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3557 { "src_conn_cur", acl_parse_int, acl_fetch_src_conn_cur, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3558 { "src_conn_rate", acl_parse_int, acl_fetch_src_conn_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3559 { "src_get_gpc0", acl_parse_int, acl_fetch_src_get_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3560 { "src_http_err_cnt", acl_parse_int, acl_fetch_src_http_err_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3561 { "src_http_err_rate", acl_parse_int, acl_fetch_src_http_err_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3562 { "src_http_req_cnt", acl_parse_int, acl_fetch_src_http_req_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3563 { "src_http_req_rate", acl_parse_int, acl_fetch_src_http_req_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3564 { "src_inc_gpc0", acl_parse_int, acl_fetch_src_inc_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3565 { "src_kbytes_in", acl_parse_int, acl_fetch_src_kbytes_in, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3566 { "src_kbytes_out", acl_parse_int, acl_fetch_src_kbytes_out, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3567 { "src_sess_cnt", acl_parse_int, acl_fetch_src_sess_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3568 { "src_sess_rate", acl_parse_int, acl_fetch_src_sess_rate, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3569 { "src_updt_conn_cnt", acl_parse_int, acl_fetch_src_updt_conn_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE, ARG1(1,TAB) },
3570 { "table_avl", acl_parse_int, acl_fetch_table_avl, acl_match_int, ACL_USE_NOTHING, ARG1(1,TAB) },
3571 { "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 +02003572 { NULL, NULL, NULL, NULL },
3573}};
3574
3575
Willy Tarreau56123282010-08-06 19:06:56 +02003576/* Parse a "track-sc[12]" line starting with "track-sc[12]" in args[arg-1].
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003577 * Returns the number of warnings emitted, or -1 in case of fatal errors. The
3578 * <prm> struct is fed with the table name if any. If unspecified, the caller
3579 * will assume that the current proxy's table is used.
3580 */
3581int parse_track_counters(char **args, int *arg,
3582 int section_type, struct proxy *curpx,
3583 struct track_ctr_prm *prm,
Willy Tarreau0a3dd742012-05-08 19:47:01 +02003584 struct proxy *defpx, char **err)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003585{
Willy Tarreau12785782012-04-27 21:37:17 +02003586 int sample_type = 0;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003587
Willy Tarreau56123282010-08-06 19:06:56 +02003588 /* parse the arguments of "track-sc[12]" before the condition in the
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003589 * following form :
Willy Tarreau56123282010-08-06 19:06:56 +02003590 * track-sc[12] src [ table xxx ] [ if|unless ... ]
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003591 */
3592 while (args[*arg]) {
3593 if (strcmp(args[*arg], "src") == 0) {
3594 prm->type = STKTABLE_TYPE_IP;
Willy Tarreau12785782012-04-27 21:37:17 +02003595 sample_type = 1;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003596 }
3597 else if (strcmp(args[*arg], "table") == 0) {
3598 if (!args[*arg + 1]) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02003599 memprintf(err, "missing table name");
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003600 return -1;
3601 }
3602 /* we copy the table name for now, it will be resolved later */
3603 prm->table.n = strdup(args[*arg + 1]);
3604 (*arg)++;
3605 }
3606 else {
3607 /* unhandled keywords are handled by the caller */
3608 break;
3609 }
3610 (*arg)++;
3611 }
3612
Willy Tarreau12785782012-04-27 21:37:17 +02003613 if (!sample_type) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02003614 memprintf(err,
3615 "tracking key not specified (found %s, only 'src' is supported)",
3616 quote_arg(args[*arg]));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02003617 return -1;
3618 }
3619
3620 return 0;
3621}
3622
Willy Tarreau8b22a712010-06-18 17:46:06 +02003623__attribute__((constructor))
3624static void __session_init(void)
3625{
3626 acl_register_keywords(&acl_kws);
3627}
3628
Willy Tarreaubaaee002006-06-26 02:48:02 +02003629/*
3630 * Local variables:
3631 * c-indent-level: 8
3632 * c-basic-offset: 8
3633 * End:
3634 */