blob: 2ae25c36f78776c118b32072583cce73e5b7d1fb [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Backend variables and functions.
3 *
Willy Tarreaud825eef2007-05-12 22:35:00 +02004 * Copyright 2000-2007 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 <errno.h>
14#include <fcntl.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <syslog.h>
Willy Tarreauf19cf372006-11-14 15:40:51 +010018#include <string.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020019
Willy Tarreau2dd0d472006-06-29 17:53:05 +020020#include <common/compat.h>
Willy Tarreaue3ba5f02006-06-29 18:54:54 +020021#include <common/config.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020022#include <common/time.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020023
24#include <types/buffers.h>
25#include <types/global.h>
26#include <types/polling.h>
27#include <types/proxy.h>
28#include <types/server.h>
29#include <types/session.h>
30
31#include <proto/backend.h>
Willy Tarreau14c8aac2007-05-08 19:46:30 +020032#include <proto/client.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020033#include <proto/fd.h>
Willy Tarreau80587432006-12-24 17:47:20 +010034#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035#include <proto/log.h>
36#include <proto/proto_http.h>
37#include <proto/queue.h>
38#include <proto/stream_sock.h>
39#include <proto/task.h>
40
Willy Tarreau77074d52006-11-12 23:57:19 +010041#ifdef CONFIG_HAP_CTTPROXY
42#include <import/ip_tproxy.h>
43#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020044
Willy Tarreau6d1a9882007-01-07 02:03:04 +010045#ifdef CONFIG_HAP_TCPSPLICE
46#include <libtcpsplice.h>
47#endif
48
Willy Tarreaubaaee002006-06-26 02:48:02 +020049/*
50 * This function recounts the number of usable active and backup servers for
51 * proxy <p>. These numbers are returned into the p->srv_act and p->srv_bck.
52 * This function also recomputes the total active and backup weights.
53 */
54void recount_servers(struct proxy *px)
55{
56 struct server *srv;
57
58 px->srv_act = 0; px->srv_bck = px->tot_wact = px->tot_wbck = 0;
59 for (srv = px->srv; srv != NULL; srv = srv->next) {
60 if (srv->state & SRV_RUNNING) {
61 if (srv->state & SRV_BACKUP) {
62 px->srv_bck++;
Willy Tarreau417fae02007-03-25 21:16:40 +020063 px->tot_wbck += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +020064 } else {
65 px->srv_act++;
Willy Tarreau417fae02007-03-25 21:16:40 +020066 px->tot_wact += srv->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +020067 }
68 }
69 }
70}
71
72/* This function recomputes the server map for proxy px. It
73 * relies on px->tot_wact and px->tot_wbck, so it must be
74 * called after recount_servers(). It also expects px->srv_map
75 * to be initialized to the largest value needed.
76 */
77void recalc_server_map(struct proxy *px)
78{
79 int o, tot, flag;
80 struct server *cur, *best;
81
82 if (px->srv_act) {
83 flag = SRV_RUNNING;
84 tot = px->tot_wact;
85 } else if (px->srv_bck) {
86 flag = SRV_RUNNING | SRV_BACKUP;
87 if (px->options & PR_O_USE_ALL_BK)
88 tot = px->tot_wbck;
89 else
90 tot = 1; /* the first server is enough */
91 } else {
92 px->srv_map_sz = 0;
Willy Tarreau5af3a692007-07-24 23:32:33 +020093 px->map_state &= ~PR_MAP_RECALC;
Willy Tarreaubaaee002006-06-26 02:48:02 +020094 return;
95 }
96
97 /* this algorithm gives priority to the first server, which means that
98 * it will respect the declaration order for equivalent weights, and
99 * that whatever the weights, the first server called will always be
100 * the first declard. This is an important asumption for the backup
101 * case, where we want the first server only.
102 */
103 for (cur = px->srv; cur; cur = cur->next)
104 cur->wscore = 0;
105
106 for (o = 0; o < tot; o++) {
107 int max = 0;
108 best = NULL;
109 for (cur = px->srv; cur; cur = cur->next) {
110 if ((cur->state & (SRV_RUNNING | SRV_BACKUP)) == flag) {
111 int v;
112
113 /* If we are forced to return only one server, we don't want to
114 * go further, because we would return the wrong one due to
115 * divide overflow.
116 */
117 if (tot == 1) {
118 best = cur;
119 break;
120 }
121
Willy Tarreau417fae02007-03-25 21:16:40 +0200122 cur->wscore += cur->eweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200123 v = (cur->wscore + tot) / tot; /* result between 0 and 3 */
124 if (best == NULL || v > max) {
125 max = v;
126 best = cur;
127 }
128 }
129 }
130 px->srv_map[o] = best;
131 best->wscore -= tot;
132 }
133 px->srv_map_sz = tot;
Willy Tarreau5af3a692007-07-24 23:32:33 +0200134 px->map_state &= ~PR_MAP_RECALC;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200135}
136
Willy Tarreau01732802007-11-01 22:48:15 +0100137/*
138 * This function tries to find a running server for the proxy <px> following
139 * the URL parameter hash method. It looks for a specific parameter in the
140 * URL and hashes it to compute the server ID. This is useful to optimize
141 * performance by avoiding bounces between servers in contexts where sessions
142 * are shared but cookies are not usable. If the parameter is not found, NULL
143 * is returned. If any server is found, it will be returned. If no valid server
144 * is found, NULL is returned.
145 *
146 */
147struct server *get_server_ph(struct proxy *px, const char *uri, int uri_len)
148{
149 unsigned long hash = 0;
150 char *p;
151 int plen;
152
153 if (px->map_state & PR_MAP_RECALC)
154 recalc_server_map(px);
155
156 if (px->srv_map_sz == 0)
157 return NULL;
158
159 p = memchr(uri, '?', uri_len);
160 if (!p)
161 return NULL;
162 p++;
163
164 uri_len -= (p - uri);
165 plen = px->url_param_len;
166
167 if (uri_len <= plen)
168 return NULL;
169
170 while (uri_len > plen) {
171 /* Look for the parameter name followed by an equal symbol */
172 if (p[plen] == '=') {
173 /* skip the equal symbol */
174 uri = p;
175 p += plen + 1;
176 uri_len -= plen + 1;
177 if (memcmp(uri, px->url_param_name, plen) == 0) {
178 /* OK, we have the parameter here at <uri>, and
179 * the value after the equal sign, at <p>
180 */
181 while (uri_len && *p != '&') {
182 hash = *p + (hash << 6) + (hash << 16) - hash;
183 uri_len--;
184 p++;
185 }
186 return px->srv_map[hash % px->srv_map_sz];
187 }
188 }
189
190 /* skip to next parameter */
191 uri = p;
192 p = memchr(uri, '&', uri_len);
193 if (!p)
194 return NULL;
195 p++;
196 uri_len -= (p - uri);
197 }
198 return NULL;
199}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200
201/*
202 * This function marks the session as 'assigned' in direct or dispatch modes,
203 * or tries to assign one in balance mode, according to the algorithm. It does
204 * nothing if the session had already been assigned a server.
205 *
206 * It may return :
207 * SRV_STATUS_OK if everything is OK. s->srv will be valid.
208 * SRV_STATUS_NOSRV if no server is available. s->srv = NULL.
209 * SRV_STATUS_FULL if all servers are saturated. s->srv = NULL.
210 * SRV_STATUS_INTERNAL for other unrecoverable errors.
211 *
212 * Upon successful return, the session flag SN_ASSIGNED to indicate that it does
213 * not need to be called anymore. This usually means that s->srv can be trusted
214 * in balance and direct modes. This flag is not cleared, so it's to the caller
215 * to clear it if required (eg: redispatch).
216 *
217 */
218
219int assign_server(struct session *s)
220{
221#ifdef DEBUG_FULL
222 fprintf(stderr,"assign_server : s=%p\n",s);
223#endif
224
225 if (s->pend_pos)
226 return SRV_STATUS_INTERNAL;
227
228 if (!(s->flags & SN_ASSIGNED)) {
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200229 if (s->be->options & PR_O_BALANCE) {
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100230 int len;
231
Willy Tarreau5d65bbb2007-01-21 12:47:26 +0100232 if (s->flags & SN_DIRECT) {
233 s->flags |= SN_ASSIGNED;
234 return SRV_STATUS_OK;
235 }
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100236
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200237 if (!s->be->srv_act && !s->be->srv_bck)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 return SRV_STATUS_NOSRV;
239
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100240 switch (s->be->options & PR_O_BALANCE) {
241 case PR_O_BALANCE_RR:
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200242 s->srv = get_server_rr_with_conns(s->be);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243 if (!s->srv)
244 return SRV_STATUS_FULL;
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100245 break;
246 case PR_O_BALANCE_SH:
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247 if (s->cli_addr.ss_family == AF_INET)
248 len = 4;
249 else if (s->cli_addr.ss_family == AF_INET6)
250 len = 16;
251 else /* unknown IP family */
252 return SRV_STATUS_INTERNAL;
253
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200254 s->srv = get_server_sh(s->be,
Willy Tarreaubaaee002006-06-26 02:48:02 +0200255 (void *)&((struct sockaddr_in *)&s->cli_addr)->sin_addr,
256 len);
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100257 break;
258 case PR_O_BALANCE_UH:
Willy Tarreau2fcb5002007-05-08 13:35:26 +0200259 /* URI hashing */
260 s->srv = get_server_uh(s->be,
261 s->txn.req.sol + s->txn.req.sl.rq.u,
262 s->txn.req.sl.rq.u_l);
Willy Tarreau01732802007-11-01 22:48:15 +0100263 break;
264 case PR_O_BALANCE_PH:
265 /* URL Parameter hashing */
266 s->srv = get_server_ph(s->be,
267 s->txn.req.sol + s->txn.req.sl.rq.u,
268 s->txn.req.sl.rq.u_l);
269 if (!s->srv) {
270 /* parameter not found, fall back to round robin */
271 s->srv = get_server_rr_with_conns(s->be);
272 if (!s->srv)
273 return SRV_STATUS_FULL;
274 }
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100275 break;
276 default:
277 /* unknown balancing algorithm */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200278 return SRV_STATUS_INTERNAL;
Willy Tarreau1a20a5d2007-11-01 21:08:19 +0100279 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200280 }
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200281 else if (!*(int *)&s->be->dispatch_addr.sin_addr &&
Willy Tarreau5d65bbb2007-01-21 12:47:26 +0100282 !(s->fe->options & PR_O_TRANSP)) {
Willy Tarreau1a1158b2007-01-20 11:07:46 +0100283 return SRV_STATUS_NOSRV;
Willy Tarreau5d65bbb2007-01-21 12:47:26 +0100284 }
285 s->flags |= SN_ASSIGNED;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200286 }
287 return SRV_STATUS_OK;
288}
289
290
291/*
292 * This function assigns a server address to a session, and sets SN_ADDR_SET.
293 * The address is taken from the currently assigned server, or from the
294 * dispatch or transparent address.
295 *
296 * It may return :
297 * SRV_STATUS_OK if everything is OK.
298 * SRV_STATUS_INTERNAL for other unrecoverable errors.
299 *
300 * Upon successful return, the session flag SN_ADDR_SET is set. This flag is
301 * not cleared, so it's to the caller to clear it if required.
302 *
303 */
304int assign_server_address(struct session *s)
305{
306#ifdef DEBUG_FULL
307 fprintf(stderr,"assign_server_address : s=%p\n",s);
308#endif
309
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200310 if ((s->flags & SN_DIRECT) || (s->be->options & PR_O_BALANCE)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200311 /* A server is necessarily known for this session */
312 if (!(s->flags & SN_ASSIGNED))
313 return SRV_STATUS_INTERNAL;
314
315 s->srv_addr = s->srv->addr;
316
317 /* if this server remaps proxied ports, we'll use
318 * the port the client connected to with an offset. */
319 if (s->srv->state & SRV_MAPPORTS) {
Willy Tarreau14c8aac2007-05-08 19:46:30 +0200320 if (!(s->fe->options & PR_O_TRANSP) && !(s->flags & SN_FRT_ADDR_SET))
321 get_frt_addr(s);
322 if (s->frt_addr.ss_family == AF_INET) {
323 s->srv_addr.sin_port = htons(ntohs(s->srv_addr.sin_port) +
324 ntohs(((struct sockaddr_in *)&s->frt_addr)->sin_port));
325 } else {
326 s->srv_addr.sin_port = htons(ntohs(s->srv_addr.sin_port) +
327 ntohs(((struct sockaddr_in6 *)&s->frt_addr)->sin6_port));
328 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200329 }
330 }
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200331 else if (*(int *)&s->be->dispatch_addr.sin_addr) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200332 /* connect to the defined dispatch addr */
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200333 s->srv_addr = s->be->dispatch_addr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200334 }
Willy Tarreau73de9892006-11-30 11:40:23 +0100335 else if (s->fe->options & PR_O_TRANSP) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200336 /* in transparent mode, use the original dest addr if no dispatch specified */
337 socklen_t salen = sizeof(s->srv_addr);
338
339 if (get_original_dst(s->cli_fd, &s->srv_addr, &salen) == -1) {
340 qfprintf(stderr, "Cannot get original server address.\n");
341 return SRV_STATUS_INTERNAL;
342 }
343 }
Willy Tarreau1a1158b2007-01-20 11:07:46 +0100344 else {
345 /* no server and no LB algorithm ! */
346 return SRV_STATUS_INTERNAL;
347 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200348
349 s->flags |= SN_ADDR_SET;
350 return SRV_STATUS_OK;
351}
352
353
354/* This function assigns a server to session <s> if required, and can add the
355 * connection to either the assigned server's queue or to the proxy's queue.
356 *
357 * Returns :
358 *
359 * SRV_STATUS_OK if everything is OK.
360 * SRV_STATUS_NOSRV if no server is available. s->srv = NULL.
361 * SRV_STATUS_QUEUED if the connection has been queued.
362 * SRV_STATUS_FULL if the server(s) is/are saturated and the
363 * connection could not be queued.
364 * SRV_STATUS_INTERNAL for other unrecoverable errors.
365 *
366 */
367int assign_server_and_queue(struct session *s)
368{
369 struct pendconn *p;
370 int err;
371
372 if (s->pend_pos)
373 return SRV_STATUS_INTERNAL;
374
375 if (s->flags & SN_ASSIGNED) {
Elijah Epifanovacafc5f2007-10-25 20:15:38 +0200376 if (s->srv && s->srv->maxqueue > 0 && s->srv->nbpend >= s->srv->maxqueue) {
377 s->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
378 s->srv = NULL;
379 http_flush_cookie_flags(&s->txn);
380 } else {
381 /* a server does not need to be assigned, perhaps because we're in
382 * direct mode, or in dispatch or transparent modes where the server
383 * is not needed.
384 */
385 if (s->srv &&
386 s->srv->maxconn && s->srv->cur_sess >= srv_dynamic_maxconn(s->srv)) {
387 p = pendconn_add(s);
388 if (p)
389 return SRV_STATUS_QUEUED;
390 else
391 return SRV_STATUS_FULL;
392 }
393 return SRV_STATUS_OK;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200394 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200395 }
396
397 /* a server needs to be assigned */
398 err = assign_server(s);
399 switch (err) {
400 case SRV_STATUS_OK:
401 /* in balance mode, we might have servers with connection limits */
402 if (s->srv &&
403 s->srv->maxconn && s->srv->cur_sess >= srv_dynamic_maxconn(s->srv)) {
404 p = pendconn_add(s);
405 if (p)
406 return SRV_STATUS_QUEUED;
407 else
408 return SRV_STATUS_FULL;
409 }
410 return SRV_STATUS_OK;
411
412 case SRV_STATUS_FULL:
413 /* queue this session into the proxy's queue */
414 p = pendconn_add(s);
415 if (p)
416 return SRV_STATUS_QUEUED;
417 else
418 return SRV_STATUS_FULL;
419
420 case SRV_STATUS_NOSRV:
421 case SRV_STATUS_INTERNAL:
422 return err;
423 default:
424 return SRV_STATUS_INTERNAL;
425 }
426}
427
428
429/*
430 * This function initiates a connection to the server assigned to this session
431 * (s->srv, s->srv_addr). It will assign a server if none is assigned yet.
432 * It can return one of :
433 * - SN_ERR_NONE if everything's OK
434 * - SN_ERR_SRVTO if there are no more servers
435 * - SN_ERR_SRVCL if the connection was refused by the server
436 * - SN_ERR_PRXCOND if the connection has been limited by the proxy (maxconn)
437 * - SN_ERR_RESOURCE if a system resource is lacking (eg: fd limits, ports, ...)
438 * - SN_ERR_INTERNAL for any other purely internal errors
439 * Additionnally, in the case of SN_ERR_RESOURCE, an emergency log will be emitted.
440 */
441int connect_server(struct session *s)
442{
443 int fd, err;
444
445 if (!(s->flags & SN_ADDR_SET)) {
446 err = assign_server_address(s);
447 if (err != SRV_STATUS_OK)
448 return SN_ERR_INTERNAL;
449 }
450
451 if ((fd = s->srv_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
452 qfprintf(stderr, "Cannot get a server socket.\n");
453
454 if (errno == ENFILE)
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200455 send_log(s->be, LOG_EMERG,
Willy Tarreaubaaee002006-06-26 02:48:02 +0200456 "Proxy %s reached system FD limit at %d. Please check system tunables.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200457 s->be->id, maxfd);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200458 else if (errno == EMFILE)
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200459 send_log(s->be, LOG_EMERG,
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460 "Proxy %s reached process FD limit at %d. Please check 'ulimit-n' and restart.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200461 s->be->id, maxfd);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462 else if (errno == ENOBUFS || errno == ENOMEM)
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200463 send_log(s->be, LOG_EMERG,
Willy Tarreaubaaee002006-06-26 02:48:02 +0200464 "Proxy %s reached system memory limit at %d sockets. Please check system tunables.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200465 s->be->id, maxfd);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466 /* this is a resource error */
467 return SN_ERR_RESOURCE;
468 }
469
470 if (fd >= global.maxsock) {
471 /* do not log anything there, it's a normal condition when this option
472 * is used to serialize connections to a server !
473 */
474 Alert("socket(): not enough free sockets. Raise -n argument. Giving up.\n");
475 close(fd);
476 return SN_ERR_PRXCOND; /* it is a configuration limit */
477 }
478
Willy Tarreau6d1a9882007-01-07 02:03:04 +0100479#ifdef CONFIG_HAP_TCPSPLICE
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200480 if ((s->fe->options & s->be->options) & PR_O_TCPSPLICE) {
Willy Tarreau6d1a9882007-01-07 02:03:04 +0100481 /* TCP splicing supported by both FE and BE */
482 tcp_splice_initfd(s->cli_fd, fd);
483 }
484#endif
485
Willy Tarreaubaaee002006-06-26 02:48:02 +0200486 if ((fcntl(fd, F_SETFL, O_NONBLOCK)==-1) ||
487 (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &one, sizeof(one)) == -1)) {
488 qfprintf(stderr,"Cannot set client socket to non blocking mode.\n");
489 close(fd);
490 return SN_ERR_INTERNAL;
491 }
492
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200493 if (s->be->options & PR_O_TCP_SRV_KA)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200494 setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(one));
495
Alexandre Cassen87ea5482007-10-11 20:48:58 +0200496 if (s->be->options & PR_O_TCP_NOLING)
497 setsockopt(fd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
498
Willy Tarreaubaaee002006-06-26 02:48:02 +0200499 /* allow specific binding :
500 * - server-specific at first
501 * - proxy-specific next
502 */
503 if (s->srv != NULL && s->srv->state & SRV_BIND_SRC) {
504 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one));
505 if (bind(fd, (struct sockaddr *)&s->srv->source_addr, sizeof(s->srv->source_addr)) == -1) {
506 Alert("Cannot bind to source address before connect() for server %s/%s. Aborting.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200507 s->be->id, s->srv->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200508 close(fd);
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200509 send_log(s->be, LOG_EMERG,
Willy Tarreaubaaee002006-06-26 02:48:02 +0200510 "Cannot bind to source address before connect() for server %s/%s.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200511 s->be->id, s->srv->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200512 return SN_ERR_RESOURCE;
513 }
Willy Tarreau77074d52006-11-12 23:57:19 +0100514#ifdef CONFIG_HAP_CTTPROXY
515 if (s->srv->state & SRV_TPROXY_MASK) {
516 struct in_tproxy itp1, itp2;
517 memset(&itp1, 0, sizeof(itp1));
518
519 itp1.op = TPROXY_ASSIGN;
520 switch (s->srv->state & SRV_TPROXY_MASK) {
521 case SRV_TPROXY_ADDR:
522 itp1.v.addr.faddr = s->srv->tproxy_addr.sin_addr;
523 itp1.v.addr.fport = s->srv->tproxy_addr.sin_port;
524 break;
525 case SRV_TPROXY_CLI:
526 itp1.v.addr.fport = ((struct sockaddr_in *)&s->cli_addr)->sin_port;
527 /* fall through */
528 case SRV_TPROXY_CIP:
529 /* FIXME: what can we do if the client connects in IPv6 ? */
530 itp1.v.addr.faddr = ((struct sockaddr_in *)&s->cli_addr)->sin_addr;
531 break;
532 }
533
534 /* set connect flag on socket */
535 itp2.op = TPROXY_FLAGS;
536 itp2.v.flags = ITP_CONNECT | ITP_ONCE;
537
538 if (setsockopt(fd, SOL_IP, IP_TPROXY, &itp1, sizeof(itp1)) == -1 ||
539 setsockopt(fd, SOL_IP, IP_TPROXY, &itp2, sizeof(itp2)) == -1) {
540 Alert("Cannot bind to tproxy source address before connect() for server %s/%s. Aborting.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200541 s->be->id, s->srv->id);
Willy Tarreau77074d52006-11-12 23:57:19 +0100542 close(fd);
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200543 send_log(s->be, LOG_EMERG,
Willy Tarreau77074d52006-11-12 23:57:19 +0100544 "Cannot bind to tproxy source address before connect() for server %s/%s.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200545 s->be->id, s->srv->id);
Willy Tarreau77074d52006-11-12 23:57:19 +0100546 return SN_ERR_RESOURCE;
547 }
548 }
549#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200550 }
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200551 else if (s->be->options & PR_O_BIND_SRC) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200552 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one));
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200553 if (bind(fd, (struct sockaddr *)&s->be->source_addr, sizeof(s->be->source_addr)) == -1) {
554 Alert("Cannot bind to source address before connect() for proxy %s. Aborting.\n", s->be->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200555 close(fd);
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200556 send_log(s->be, LOG_EMERG,
Willy Tarreaubaaee002006-06-26 02:48:02 +0200557 "Cannot bind to source address before connect() for server %s/%s.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200558 s->be->id, s->srv->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200559 return SN_ERR_RESOURCE;
560 }
Willy Tarreau77074d52006-11-12 23:57:19 +0100561#ifdef CONFIG_HAP_CTTPROXY
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200562 if (s->be->options & PR_O_TPXY_MASK) {
Willy Tarreau77074d52006-11-12 23:57:19 +0100563 struct in_tproxy itp1, itp2;
564 memset(&itp1, 0, sizeof(itp1));
565
566 itp1.op = TPROXY_ASSIGN;
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200567 switch (s->be->options & PR_O_TPXY_MASK) {
Willy Tarreau77074d52006-11-12 23:57:19 +0100568 case PR_O_TPXY_ADDR:
569 itp1.v.addr.faddr = s->srv->tproxy_addr.sin_addr;
570 itp1.v.addr.fport = s->srv->tproxy_addr.sin_port;
571 break;
572 case PR_O_TPXY_CLI:
573 itp1.v.addr.fport = ((struct sockaddr_in *)&s->cli_addr)->sin_port;
574 /* fall through */
575 case PR_O_TPXY_CIP:
576 /* FIXME: what can we do if the client connects in IPv6 ? */
577 itp1.v.addr.faddr = ((struct sockaddr_in *)&s->cli_addr)->sin_addr;
578 break;
579 }
580
581 /* set connect flag on socket */
582 itp2.op = TPROXY_FLAGS;
583 itp2.v.flags = ITP_CONNECT | ITP_ONCE;
584
585 if (setsockopt(fd, SOL_IP, IP_TPROXY, &itp1, sizeof(itp1)) == -1 ||
586 setsockopt(fd, SOL_IP, IP_TPROXY, &itp2, sizeof(itp2)) == -1) {
587 Alert("Cannot bind to tproxy source address before connect() for proxy %s. Aborting.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200588 s->be->id);
Willy Tarreau77074d52006-11-12 23:57:19 +0100589 close(fd);
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200590 send_log(s->be, LOG_EMERG,
Willy Tarreau77074d52006-11-12 23:57:19 +0100591 "Cannot bind to tproxy source address before connect() for server %s/%s.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200592 s->be->id, s->srv->id);
Willy Tarreau77074d52006-11-12 23:57:19 +0100593 return SN_ERR_RESOURCE;
594 }
595 }
596#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200597 }
598
599 if ((connect(fd, (struct sockaddr *)&s->srv_addr, sizeof(s->srv_addr)) == -1) &&
600 (errno != EINPROGRESS) && (errno != EALREADY) && (errno != EISCONN)) {
601
602 if (errno == EAGAIN || errno == EADDRINUSE) {
603 char *msg;
604 if (errno == EAGAIN) /* no free ports left, try again later */
605 msg = "no free ports";
606 else
607 msg = "local address already in use";
608
609 qfprintf(stderr,"Cannot connect: %s.\n",msg);
610 close(fd);
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200611 send_log(s->be, LOG_EMERG,
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612 "Connect() failed for server %s/%s: %s.\n",
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200613 s->be->id, s->srv->id, msg);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200614 return SN_ERR_RESOURCE;
615 } else if (errno == ETIMEDOUT) {
616 //qfprintf(stderr,"Connect(): ETIMEDOUT");
617 close(fd);
618 return SN_ERR_SRVTO;
619 } else {
620 // (errno == ECONNREFUSED || errno == ENETUNREACH || errno == EACCES || errno == EPERM)
621 //qfprintf(stderr,"Connect(): %d", errno);
622 close(fd);
623 return SN_ERR_SRVCL;
624 }
625 }
626
627 fdtab[fd].owner = s->task;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628 fdtab[fd].state = FD_STCONN; /* connection in progress */
Willy Tarreaud7971282006-07-29 18:36:34 +0200629 fdtab[fd].cb[DIR_RD].f = &stream_sock_read;
Willy Tarreau54469402006-07-29 16:59:06 +0200630 fdtab[fd].cb[DIR_RD].b = s->rep;
Willy Tarreauf8306d52006-07-29 19:01:31 +0200631 fdtab[fd].cb[DIR_WR].f = &stream_sock_write;
Willy Tarreau54469402006-07-29 16:59:06 +0200632 fdtab[fd].cb[DIR_WR].b = s->req;
Willy Tarreaue94ebd02007-10-09 17:14:37 +0200633
634 fdtab[fd].peeraddr = (struct sockaddr *)&s->srv_addr;
635 fdtab[fd].peerlen = sizeof(s->srv_addr);
636
Willy Tarreauf161a342007-04-08 16:59:42 +0200637 EV_FD_SET(fd, DIR_WR); /* for connect status */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200638
639 fd_insert(fd);
640 if (s->srv) {
641 s->srv->cur_sess++;
642 if (s->srv->cur_sess > s->srv->cur_sess_max)
643 s->srv->cur_sess_max = s->srv->cur_sess;
644 }
645
Willy Tarreaua8b55e32007-05-13 16:08:19 +0200646 if (!tv_add_ifset(&s->req->cex, &now, &s->be->contimeout))
Willy Tarreaud7971282006-07-29 18:36:34 +0200647 tv_eternity(&s->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200648 return SN_ERR_NONE; /* connection is OK */
649}
650
651
652/*
653 * This function checks the retry count during the connect() job.
654 * It updates the session's srv_state and retries, so that the caller knows
655 * what it has to do. It uses the last connection error to set the log when
656 * it expires. It returns 1 when it has expired, and 0 otherwise.
657 */
658int srv_count_retry_down(struct session *t, int conn_err)
659{
660 /* we are in front of a retryable error */
661 t->conn_retries--;
Krzysztof Oledzki1cf36ba2007-10-18 19:12:30 +0200662 if (t->srv)
663 t->srv->retries++;
664 t->be->retries++;
665
Willy Tarreaubaaee002006-06-26 02:48:02 +0200666 if (t->conn_retries < 0) {
667 /* if not retryable anymore, let's abort */
Willy Tarreaud7971282006-07-29 18:36:34 +0200668 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200669 srv_close_with_err(t, conn_err, SN_FINST_C,
Willy Tarreau80587432006-12-24 17:47:20 +0100670 503, error_message(t, HTTP_ERR_503));
Willy Tarreaubaaee002006-06-26 02:48:02 +0200671 if (t->srv)
672 t->srv->failed_conns++;
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200673 t->be->failed_conns++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200674
675 /* We used to have a free connection slot. Since we'll never use it,
676 * we have to inform the server that it may be used by another session.
677 */
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200678 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau96bcfd72007-04-29 10:41:56 +0200679 task_wakeup(t->srv->queue_mgt);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 return 1;
681 }
682 return 0;
683}
684
685
686/*
687 * This function performs the retryable part of the connect() job.
688 * It updates the session's srv_state and retries, so that the caller knows
689 * what it has to do. It returns 1 when it breaks out of the loop, or 0 if
690 * it needs to redispatch.
691 */
692int srv_retryable_connect(struct session *t)
693{
694 int conn_err;
695
696 /* This loop ensures that we stop before the last retry in case of a
697 * redispatchable server.
698 */
699 do {
700 /* initiate a connection to the server */
701 conn_err = connect_server(t);
702 switch (conn_err) {
703
704 case SN_ERR_NONE:
705 //fprintf(stderr,"0: c=%d, s=%d\n", c, s);
706 t->srv_state = SV_STCONN;
707 return 1;
708
709 case SN_ERR_INTERNAL:
Willy Tarreaud7971282006-07-29 18:36:34 +0200710 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200711 srv_close_with_err(t, SN_ERR_INTERNAL, SN_FINST_C,
Willy Tarreau80587432006-12-24 17:47:20 +0100712 500, error_message(t, HTTP_ERR_500));
Willy Tarreaubaaee002006-06-26 02:48:02 +0200713 if (t->srv)
714 t->srv->failed_conns++;
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200715 t->be->failed_conns++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200716 /* release other sessions waiting for this server */
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200717 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau96bcfd72007-04-29 10:41:56 +0200718 task_wakeup(t->srv->queue_mgt);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200719 return 1;
720 }
721 /* ensure that we have enough retries left */
722 if (srv_count_retry_down(t, conn_err)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200723 return 1;
724 }
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200725 } while (t->srv == NULL || t->conn_retries > 0 || !(t->be->options & PR_O_REDISP));
Willy Tarreaubaaee002006-06-26 02:48:02 +0200726
727 /* We're on our last chance, and the REDISP option was specified.
728 * We will ignore cookie and force to balance or use the dispatcher.
729 */
730 /* let's try to offer this slot to anybody */
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200731 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau96bcfd72007-04-29 10:41:56 +0200732 task_wakeup(t->srv->queue_mgt);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200733
734 if (t->srv)
735 t->srv->failed_conns++;
Krzysztof Oledzki1cf36ba2007-10-18 19:12:30 +0200736 t->be->redispatches++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200737
738 t->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
739 t->srv = NULL; /* it's left to the dispatcher to choose a server */
Willy Tarreau3d300592007-03-18 18:34:41 +0100740 http_flush_cookie_flags(&t->txn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200741 return 0;
742}
743
744
745/* This function performs the "redispatch" part of a connection attempt. It
746 * will assign a server if required, queue the connection if required, and
747 * handle errors that might arise at this level. It can change the server
748 * state. It will return 1 if it encounters an error, switches the server
749 * state, or has to queue a connection. Otherwise, it will return 0 indicating
750 * that the connection is ready to use.
751 */
752
753int srv_redispatch_connect(struct session *t)
754{
755 int conn_err;
756
757 /* We know that we don't have any connection pending, so we will
758 * try to get a new one, and wait in this state if it's queued
759 */
760 conn_err = assign_server_and_queue(t);
761 switch (conn_err) {
762 case SRV_STATUS_OK:
763 break;
764
765 case SRV_STATUS_NOSRV:
766 /* note: it is guaranteed that t->srv == NULL here */
Willy Tarreaud7971282006-07-29 18:36:34 +0200767 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200768 srv_close_with_err(t, SN_ERR_SRVTO, SN_FINST_C,
Willy Tarreau80587432006-12-24 17:47:20 +0100769 503, error_message(t, HTTP_ERR_503));
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770 if (t->srv)
771 t->srv->failed_conns++;
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200772 t->be->failed_conns++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200773
774 return 1;
775
776 case SRV_STATUS_QUEUED:
777 /* FIXME-20060503 : we should use the queue timeout instead */
Willy Tarreaua8b55e32007-05-13 16:08:19 +0200778 if (!tv_add_ifset(&t->req->cex, &now, &t->be->contimeout))
Willy Tarreaud7971282006-07-29 18:36:34 +0200779 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200780 t->srv_state = SV_STIDLE;
781 /* do nothing else and do not wake any other session up */
782 return 1;
783
784 case SRV_STATUS_FULL:
785 case SRV_STATUS_INTERNAL:
786 default:
Willy Tarreaud7971282006-07-29 18:36:34 +0200787 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200788 srv_close_with_err(t, SN_ERR_INTERNAL, SN_FINST_C,
Willy Tarreau80587432006-12-24 17:47:20 +0100789 500, error_message(t, HTTP_ERR_500));
Willy Tarreaubaaee002006-06-26 02:48:02 +0200790 if (t->srv)
791 t->srv->failed_conns++;
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200792 t->be->failed_conns++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200793
794 /* release other sessions waiting for this server */
Willy Tarreaue2e27a52007-04-01 00:01:37 +0200795 if (may_dequeue_tasks(t->srv, t->be))
Willy Tarreau96bcfd72007-04-29 10:41:56 +0200796 task_wakeup(t->srv->queue_mgt);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200797 return 1;
798 }
799 /* if we get here, it's because we got SRV_STATUS_OK, which also
800 * means that the connection has not been queued.
801 */
802 return 0;
803}
804
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200805int be_downtime(struct proxy *px) {
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200806 if ((px->srv_act || px->srv_bck) && px->last_change < now.tv_sec) // ignore negative time
807 return px->down_time;
808
809 return now.tv_sec - px->last_change + px->down_time;
810}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200811
Willy Tarreaua0cbda62007-11-01 21:39:54 +0100812/* This function parses a "balance" statement in a backend section describing
813 * <curproxy>. It returns -1 if there is any error, otherwise zero. If it
814 * returns -1, it may write an error message into ther <err> buffer, for at
815 * most <errlen> bytes, trailing zero included. The trailing '\n' will not be
816 * written. The function must be called with <args> pointing to the first word
817 * after "balance".
818 */
819int backend_parse_balance(const char **args, char *err, int errlen, struct proxy *curproxy)
820{
821 if (!*(args[0])) {
822 /* if no option is set, use round-robin by default */
823 curproxy->options &= ~PR_O_BALANCE;
824 curproxy->options |= PR_O_BALANCE_RR;
825 return 0;
826 }
827
828 if (!strcmp(args[0], "roundrobin")) {
829 curproxy->options &= ~PR_O_BALANCE;
830 curproxy->options |= PR_O_BALANCE_RR;
831 }
832 else if (!strcmp(args[0], "source")) {
833 curproxy->options &= ~PR_O_BALANCE;
834 curproxy->options |= PR_O_BALANCE_SH;
835 }
836 else if (!strcmp(args[0], "uri")) {
837 curproxy->options &= ~PR_O_BALANCE;
838 curproxy->options |= PR_O_BALANCE_UH;
839 }
Willy Tarreau01732802007-11-01 22:48:15 +0100840 else if (!strcmp(args[0], "url_param")) {
841 if (!*args[1]) {
842 snprintf(err, errlen, "'balance url_param' requires an URL parameter name.");
843 return -1;
844 }
845 curproxy->options &= ~PR_O_BALANCE;
846 curproxy->options |= PR_O_BALANCE_PH;
847 if (curproxy->url_param_name)
848 free(curproxy->url_param_name);
849 curproxy->url_param_name = strdup(args[1]);
850 curproxy->url_param_len = strlen(args[1]);
851 }
Willy Tarreaua0cbda62007-11-01 21:39:54 +0100852 else {
Willy Tarreau01732802007-11-01 22:48:15 +0100853 snprintf(err, errlen, "'balance' only supports 'roundrobin', 'source', 'uri' and 'url_param' options.");
Willy Tarreaua0cbda62007-11-01 21:39:54 +0100854 return -1;
855 }
856 return 0;
857}
858
Willy Tarreaubaaee002006-06-26 02:48:02 +0200859/*
860 * Local variables:
861 * c-indent-level: 8
862 * c-basic-offset: 8
863 * End:
864 */