blob: 1813d34dee81480f90ef8def55cd188cd50bf256 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Backend variables and functions.
3 *
4 * Copyright 2000-2006 Willy Tarreau <w@1wt.eu>
5 *
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>
18
Willy Tarreau2dd0d472006-06-29 17:53:05 +020019#include <common/compat.h>
Willy Tarreaue3ba5f02006-06-29 18:54:54 +020020#include <common/config.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020021#include <common/time.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020022
23#include <types/buffers.h>
24#include <types/global.h>
25#include <types/polling.h>
26#include <types/proxy.h>
27#include <types/server.h>
28#include <types/session.h>
29
30#include <proto/backend.h>
31#include <proto/fd.h>
32#include <proto/log.h>
33#include <proto/proto_http.h>
34#include <proto/queue.h>
35#include <proto/stream_sock.h>
36#include <proto/task.h>
37
Willy Tarreau77074d52006-11-12 23:57:19 +010038#ifdef CONFIG_HAP_CTTPROXY
39#include <import/ip_tproxy.h>
40#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020041
42/*
43 * This function recounts the number of usable active and backup servers for
44 * proxy <p>. These numbers are returned into the p->srv_act and p->srv_bck.
45 * This function also recomputes the total active and backup weights.
46 */
47void recount_servers(struct proxy *px)
48{
49 struct server *srv;
50
51 px->srv_act = 0; px->srv_bck = px->tot_wact = px->tot_wbck = 0;
52 for (srv = px->srv; srv != NULL; srv = srv->next) {
53 if (srv->state & SRV_RUNNING) {
54 if (srv->state & SRV_BACKUP) {
55 px->srv_bck++;
56 px->tot_wbck += srv->eweight + 1;
57 } else {
58 px->srv_act++;
59 px->tot_wact += srv->eweight + 1;
60 }
61 }
62 }
63}
64
65/* This function recomputes the server map for proxy px. It
66 * relies on px->tot_wact and px->tot_wbck, so it must be
67 * called after recount_servers(). It also expects px->srv_map
68 * to be initialized to the largest value needed.
69 */
70void recalc_server_map(struct proxy *px)
71{
72 int o, tot, flag;
73 struct server *cur, *best;
74
75 if (px->srv_act) {
76 flag = SRV_RUNNING;
77 tot = px->tot_wact;
78 } else if (px->srv_bck) {
79 flag = SRV_RUNNING | SRV_BACKUP;
80 if (px->options & PR_O_USE_ALL_BK)
81 tot = px->tot_wbck;
82 else
83 tot = 1; /* the first server is enough */
84 } else {
85 px->srv_map_sz = 0;
86 return;
87 }
88
89 /* this algorithm gives priority to the first server, which means that
90 * it will respect the declaration order for equivalent weights, and
91 * that whatever the weights, the first server called will always be
92 * the first declard. This is an important asumption for the backup
93 * case, where we want the first server only.
94 */
95 for (cur = px->srv; cur; cur = cur->next)
96 cur->wscore = 0;
97
98 for (o = 0; o < tot; o++) {
99 int max = 0;
100 best = NULL;
101 for (cur = px->srv; cur; cur = cur->next) {
102 if ((cur->state & (SRV_RUNNING | SRV_BACKUP)) == flag) {
103 int v;
104
105 /* If we are forced to return only one server, we don't want to
106 * go further, because we would return the wrong one due to
107 * divide overflow.
108 */
109 if (tot == 1) {
110 best = cur;
111 break;
112 }
113
114 cur->wscore += cur->eweight + 1;
115 v = (cur->wscore + tot) / tot; /* result between 0 and 3 */
116 if (best == NULL || v > max) {
117 max = v;
118 best = cur;
119 }
120 }
121 }
122 px->srv_map[o] = best;
123 best->wscore -= tot;
124 }
125 px->srv_map_sz = tot;
126}
127
128
129/*
130 * This function marks the session as 'assigned' in direct or dispatch modes,
131 * or tries to assign one in balance mode, according to the algorithm. It does
132 * nothing if the session had already been assigned a server.
133 *
134 * It may return :
135 * SRV_STATUS_OK if everything is OK. s->srv will be valid.
136 * SRV_STATUS_NOSRV if no server is available. s->srv = NULL.
137 * SRV_STATUS_FULL if all servers are saturated. s->srv = NULL.
138 * SRV_STATUS_INTERNAL for other unrecoverable errors.
139 *
140 * Upon successful return, the session flag SN_ASSIGNED to indicate that it does
141 * not need to be called anymore. This usually means that s->srv can be trusted
142 * in balance and direct modes. This flag is not cleared, so it's to the caller
143 * to clear it if required (eg: redispatch).
144 *
145 */
146
147int assign_server(struct session *s)
148{
149#ifdef DEBUG_FULL
150 fprintf(stderr,"assign_server : s=%p\n",s);
151#endif
152
153 if (s->pend_pos)
154 return SRV_STATUS_INTERNAL;
155
156 if (!(s->flags & SN_ASSIGNED)) {
157 if ((s->proxy->options & PR_O_BALANCE) && !(s->flags & SN_DIRECT)) {
158 if (!s->proxy->srv_act && !s->proxy->srv_bck)
159 return SRV_STATUS_NOSRV;
160
161 if (s->proxy->options & PR_O_BALANCE_RR) {
162 s->srv = get_server_rr_with_conns(s->proxy);
163 if (!s->srv)
164 return SRV_STATUS_FULL;
165 }
166 else if (s->proxy->options & PR_O_BALANCE_SH) {
167 int len;
168
169 if (s->cli_addr.ss_family == AF_INET)
170 len = 4;
171 else if (s->cli_addr.ss_family == AF_INET6)
172 len = 16;
173 else /* unknown IP family */
174 return SRV_STATUS_INTERNAL;
175
176 s->srv = get_server_sh(s->proxy,
177 (void *)&((struct sockaddr_in *)&s->cli_addr)->sin_addr,
178 len);
179 }
180 else /* unknown balancing algorithm */
181 return SRV_STATUS_INTERNAL;
182 }
183 s->flags |= SN_ASSIGNED;
184 }
185 return SRV_STATUS_OK;
186}
187
188
189/*
190 * This function assigns a server address to a session, and sets SN_ADDR_SET.
191 * The address is taken from the currently assigned server, or from the
192 * dispatch or transparent address.
193 *
194 * It may return :
195 * SRV_STATUS_OK if everything is OK.
196 * SRV_STATUS_INTERNAL for other unrecoverable errors.
197 *
198 * Upon successful return, the session flag SN_ADDR_SET is set. This flag is
199 * not cleared, so it's to the caller to clear it if required.
200 *
201 */
202int assign_server_address(struct session *s)
203{
204#ifdef DEBUG_FULL
205 fprintf(stderr,"assign_server_address : s=%p\n",s);
206#endif
207
208 if (s->flags & SN_DIRECT || s->proxy->options & PR_O_BALANCE) {
209 /* A server is necessarily known for this session */
210 if (!(s->flags & SN_ASSIGNED))
211 return SRV_STATUS_INTERNAL;
212
213 s->srv_addr = s->srv->addr;
214
215 /* if this server remaps proxied ports, we'll use
216 * the port the client connected to with an offset. */
217 if (s->srv->state & SRV_MAPPORTS) {
218 struct sockaddr_in sockname;
219 socklen_t namelen = sizeof(sockname);
220
221 if (!(s->proxy->options & PR_O_TRANSP) ||
222 get_original_dst(s->cli_fd, (struct sockaddr_in *)&sockname, &namelen) == -1)
223 getsockname(s->cli_fd, (struct sockaddr *)&sockname, &namelen);
224 s->srv_addr.sin_port = htons(ntohs(s->srv_addr.sin_port) + ntohs(sockname.sin_port));
225 }
226 }
227 else if (*(int *)&s->proxy->dispatch_addr.sin_addr) {
228 /* connect to the defined dispatch addr */
229 s->srv_addr = s->proxy->dispatch_addr;
230 }
231 else if (s->proxy->options & PR_O_TRANSP) {
232 /* in transparent mode, use the original dest addr if no dispatch specified */
233 socklen_t salen = sizeof(s->srv_addr);
234
235 if (get_original_dst(s->cli_fd, &s->srv_addr, &salen) == -1) {
236 qfprintf(stderr, "Cannot get original server address.\n");
237 return SRV_STATUS_INTERNAL;
238 }
239 }
240
241 s->flags |= SN_ADDR_SET;
242 return SRV_STATUS_OK;
243}
244
245
246/* This function assigns a server to session <s> if required, and can add the
247 * connection to either the assigned server's queue or to the proxy's queue.
248 *
249 * Returns :
250 *
251 * SRV_STATUS_OK if everything is OK.
252 * SRV_STATUS_NOSRV if no server is available. s->srv = NULL.
253 * SRV_STATUS_QUEUED if the connection has been queued.
254 * SRV_STATUS_FULL if the server(s) is/are saturated and the
255 * connection could not be queued.
256 * SRV_STATUS_INTERNAL for other unrecoverable errors.
257 *
258 */
259int assign_server_and_queue(struct session *s)
260{
261 struct pendconn *p;
262 int err;
263
264 if (s->pend_pos)
265 return SRV_STATUS_INTERNAL;
266
267 if (s->flags & SN_ASSIGNED) {
268 /* a server does not need to be assigned, perhaps because we're in
269 * direct mode, or in dispatch or transparent modes where the server
270 * is not needed.
271 */
272 if (s->srv &&
273 s->srv->maxconn && s->srv->cur_sess >= srv_dynamic_maxconn(s->srv)) {
274 p = pendconn_add(s);
275 if (p)
276 return SRV_STATUS_QUEUED;
277 else
278 return SRV_STATUS_FULL;
279 }
280 return SRV_STATUS_OK;
281 }
282
283 /* a server needs to be assigned */
284 err = assign_server(s);
285 switch (err) {
286 case SRV_STATUS_OK:
287 /* in balance mode, we might have servers with connection limits */
288 if (s->srv &&
289 s->srv->maxconn && s->srv->cur_sess >= srv_dynamic_maxconn(s->srv)) {
290 p = pendconn_add(s);
291 if (p)
292 return SRV_STATUS_QUEUED;
293 else
294 return SRV_STATUS_FULL;
295 }
296 return SRV_STATUS_OK;
297
298 case SRV_STATUS_FULL:
299 /* queue this session into the proxy's queue */
300 p = pendconn_add(s);
301 if (p)
302 return SRV_STATUS_QUEUED;
303 else
304 return SRV_STATUS_FULL;
305
306 case SRV_STATUS_NOSRV:
307 case SRV_STATUS_INTERNAL:
308 return err;
309 default:
310 return SRV_STATUS_INTERNAL;
311 }
312}
313
314
315/*
316 * This function initiates a connection to the server assigned to this session
317 * (s->srv, s->srv_addr). It will assign a server if none is assigned yet.
318 * It can return one of :
319 * - SN_ERR_NONE if everything's OK
320 * - SN_ERR_SRVTO if there are no more servers
321 * - SN_ERR_SRVCL if the connection was refused by the server
322 * - SN_ERR_PRXCOND if the connection has been limited by the proxy (maxconn)
323 * - SN_ERR_RESOURCE if a system resource is lacking (eg: fd limits, ports, ...)
324 * - SN_ERR_INTERNAL for any other purely internal errors
325 * Additionnally, in the case of SN_ERR_RESOURCE, an emergency log will be emitted.
326 */
327int connect_server(struct session *s)
328{
329 int fd, err;
330
331 if (!(s->flags & SN_ADDR_SET)) {
332 err = assign_server_address(s);
333 if (err != SRV_STATUS_OK)
334 return SN_ERR_INTERNAL;
335 }
336
337 if ((fd = s->srv_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
338 qfprintf(stderr, "Cannot get a server socket.\n");
339
340 if (errno == ENFILE)
341 send_log(s->proxy, LOG_EMERG,
342 "Proxy %s reached system FD limit at %d. Please check system tunables.\n",
343 s->proxy->id, maxfd);
344 else if (errno == EMFILE)
345 send_log(s->proxy, LOG_EMERG,
346 "Proxy %s reached process FD limit at %d. Please check 'ulimit-n' and restart.\n",
347 s->proxy->id, maxfd);
348 else if (errno == ENOBUFS || errno == ENOMEM)
349 send_log(s->proxy, LOG_EMERG,
350 "Proxy %s reached system memory limit at %d sockets. Please check system tunables.\n",
351 s->proxy->id, maxfd);
352 /* this is a resource error */
353 return SN_ERR_RESOURCE;
354 }
355
356 if (fd >= global.maxsock) {
357 /* do not log anything there, it's a normal condition when this option
358 * is used to serialize connections to a server !
359 */
360 Alert("socket(): not enough free sockets. Raise -n argument. Giving up.\n");
361 close(fd);
362 return SN_ERR_PRXCOND; /* it is a configuration limit */
363 }
364
365 if ((fcntl(fd, F_SETFL, O_NONBLOCK)==-1) ||
366 (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &one, sizeof(one)) == -1)) {
367 qfprintf(stderr,"Cannot set client socket to non blocking mode.\n");
368 close(fd);
369 return SN_ERR_INTERNAL;
370 }
371
372 if (s->proxy->options & PR_O_TCP_SRV_KA)
373 setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(one));
374
375 /* allow specific binding :
376 * - server-specific at first
377 * - proxy-specific next
378 */
379 if (s->srv != NULL && s->srv->state & SRV_BIND_SRC) {
380 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one));
381 if (bind(fd, (struct sockaddr *)&s->srv->source_addr, sizeof(s->srv->source_addr)) == -1) {
382 Alert("Cannot bind to source address before connect() for server %s/%s. Aborting.\n",
383 s->proxy->id, s->srv->id);
384 close(fd);
385 send_log(s->proxy, LOG_EMERG,
386 "Cannot bind to source address before connect() for server %s/%s.\n",
387 s->proxy->id, s->srv->id);
388 return SN_ERR_RESOURCE;
389 }
Willy Tarreau77074d52006-11-12 23:57:19 +0100390#ifdef CONFIG_HAP_CTTPROXY
391 if (s->srv->state & SRV_TPROXY_MASK) {
392 struct in_tproxy itp1, itp2;
393 memset(&itp1, 0, sizeof(itp1));
394
395 itp1.op = TPROXY_ASSIGN;
396 switch (s->srv->state & SRV_TPROXY_MASK) {
397 case SRV_TPROXY_ADDR:
398 itp1.v.addr.faddr = s->srv->tproxy_addr.sin_addr;
399 itp1.v.addr.fport = s->srv->tproxy_addr.sin_port;
400 break;
401 case SRV_TPROXY_CLI:
402 itp1.v.addr.fport = ((struct sockaddr_in *)&s->cli_addr)->sin_port;
403 /* fall through */
404 case SRV_TPROXY_CIP:
405 /* FIXME: what can we do if the client connects in IPv6 ? */
406 itp1.v.addr.faddr = ((struct sockaddr_in *)&s->cli_addr)->sin_addr;
407 break;
408 }
409
410 /* set connect flag on socket */
411 itp2.op = TPROXY_FLAGS;
412 itp2.v.flags = ITP_CONNECT | ITP_ONCE;
413
414 if (setsockopt(fd, SOL_IP, IP_TPROXY, &itp1, sizeof(itp1)) == -1 ||
415 setsockopt(fd, SOL_IP, IP_TPROXY, &itp2, sizeof(itp2)) == -1) {
416 Alert("Cannot bind to tproxy source address before connect() for server %s/%s. Aborting.\n",
417 s->proxy->id, s->srv->id);
418 close(fd);
419 send_log(s->proxy, LOG_EMERG,
420 "Cannot bind to tproxy source address before connect() for server %s/%s.\n",
421 s->proxy->id, s->srv->id);
422 return SN_ERR_RESOURCE;
423 }
424 }
425#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200426 }
427 else if (s->proxy->options & PR_O_BIND_SRC) {
428 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one));
429 if (bind(fd, (struct sockaddr *)&s->proxy->source_addr, sizeof(s->proxy->source_addr)) == -1) {
430 Alert("Cannot bind to source address before connect() for proxy %s. Aborting.\n", s->proxy->id);
431 close(fd);
432 send_log(s->proxy, LOG_EMERG,
433 "Cannot bind to source address before connect() for server %s/%s.\n",
434 s->proxy->id, s->srv->id);
435 return SN_ERR_RESOURCE;
436 }
Willy Tarreau77074d52006-11-12 23:57:19 +0100437#ifdef CONFIG_HAP_CTTPROXY
438 if (s->proxy->options & PR_O_TPXY_MASK) {
439 struct in_tproxy itp1, itp2;
440 memset(&itp1, 0, sizeof(itp1));
441
442 itp1.op = TPROXY_ASSIGN;
443 switch (s->proxy->options & PR_O_TPXY_MASK) {
444 case PR_O_TPXY_ADDR:
445 itp1.v.addr.faddr = s->srv->tproxy_addr.sin_addr;
446 itp1.v.addr.fport = s->srv->tproxy_addr.sin_port;
447 break;
448 case PR_O_TPXY_CLI:
449 itp1.v.addr.fport = ((struct sockaddr_in *)&s->cli_addr)->sin_port;
450 /* fall through */
451 case PR_O_TPXY_CIP:
452 /* FIXME: what can we do if the client connects in IPv6 ? */
453 itp1.v.addr.faddr = ((struct sockaddr_in *)&s->cli_addr)->sin_addr;
454 break;
455 }
456
457 /* set connect flag on socket */
458 itp2.op = TPROXY_FLAGS;
459 itp2.v.flags = ITP_CONNECT | ITP_ONCE;
460
461 if (setsockopt(fd, SOL_IP, IP_TPROXY, &itp1, sizeof(itp1)) == -1 ||
462 setsockopt(fd, SOL_IP, IP_TPROXY, &itp2, sizeof(itp2)) == -1) {
463 Alert("Cannot bind to tproxy source address before connect() for proxy %s. Aborting.\n",
464 s->proxy->id);
465 close(fd);
466 send_log(s->proxy, LOG_EMERG,
467 "Cannot bind to tproxy source address before connect() for server %s/%s.\n",
468 s->proxy->id, s->srv->id);
469 return SN_ERR_RESOURCE;
470 }
471 }
472#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200473 }
474
475 if ((connect(fd, (struct sockaddr *)&s->srv_addr, sizeof(s->srv_addr)) == -1) &&
476 (errno != EINPROGRESS) && (errno != EALREADY) && (errno != EISCONN)) {
477
478 if (errno == EAGAIN || errno == EADDRINUSE) {
479 char *msg;
480 if (errno == EAGAIN) /* no free ports left, try again later */
481 msg = "no free ports";
482 else
483 msg = "local address already in use";
484
485 qfprintf(stderr,"Cannot connect: %s.\n",msg);
486 close(fd);
487 send_log(s->proxy, LOG_EMERG,
488 "Connect() failed for server %s/%s: %s.\n",
489 s->proxy->id, s->srv->id, msg);
490 return SN_ERR_RESOURCE;
491 } else if (errno == ETIMEDOUT) {
492 //qfprintf(stderr,"Connect(): ETIMEDOUT");
493 close(fd);
494 return SN_ERR_SRVTO;
495 } else {
496 // (errno == ECONNREFUSED || errno == ENETUNREACH || errno == EACCES || errno == EPERM)
497 //qfprintf(stderr,"Connect(): %d", errno);
498 close(fd);
499 return SN_ERR_SRVCL;
500 }
501 }
502
503 fdtab[fd].owner = s->task;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200504 fdtab[fd].state = FD_STCONN; /* connection in progress */
Willy Tarreaud7971282006-07-29 18:36:34 +0200505 fdtab[fd].cb[DIR_RD].f = &stream_sock_read;
Willy Tarreau54469402006-07-29 16:59:06 +0200506 fdtab[fd].cb[DIR_RD].b = s->rep;
Willy Tarreauf8306d52006-07-29 19:01:31 +0200507 fdtab[fd].cb[DIR_WR].f = &stream_sock_write;
Willy Tarreau54469402006-07-29 16:59:06 +0200508 fdtab[fd].cb[DIR_WR].b = s->req;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200509
Willy Tarreau2a429502006-10-15 14:52:29 +0200510 MY_FD_SET(fd, StaticWriteEvent); /* for connect status */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200511#if defined(DEBUG_FULL) && defined(ENABLE_EPOLL)
512 if (PrevReadEvent) {
Willy Tarreau2a429502006-10-15 14:52:29 +0200513 assert(!(MY_FD_ISSET(fd, PrevReadEvent)));
514 assert(!(MY_FD_ISSET(fd, PrevWriteEvent)));
Willy Tarreaubaaee002006-06-26 02:48:02 +0200515 }
516#endif
517
518 fd_insert(fd);
519 if (s->srv) {
520 s->srv->cur_sess++;
521 if (s->srv->cur_sess > s->srv->cur_sess_max)
522 s->srv->cur_sess_max = s->srv->cur_sess;
523 }
524
525 if (s->proxy->contimeout)
Willy Tarreaud7971282006-07-29 18:36:34 +0200526 tv_delayfrom(&s->req->cex, &now, s->proxy->contimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200527 else
Willy Tarreaud7971282006-07-29 18:36:34 +0200528 tv_eternity(&s->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200529 return SN_ERR_NONE; /* connection is OK */
530}
531
532
533/*
534 * This function checks the retry count during the connect() job.
535 * It updates the session's srv_state and retries, so that the caller knows
536 * what it has to do. It uses the last connection error to set the log when
537 * it expires. It returns 1 when it has expired, and 0 otherwise.
538 */
539int srv_count_retry_down(struct session *t, int conn_err)
540{
541 /* we are in front of a retryable error */
542 t->conn_retries--;
543 if (t->conn_retries < 0) {
544 /* if not retryable anymore, let's abort */
Willy Tarreaud7971282006-07-29 18:36:34 +0200545 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200546 srv_close_with_err(t, conn_err, SN_FINST_C,
547 503, t->proxy->errmsg.len503, t->proxy->errmsg.msg503);
548 if (t->srv)
549 t->srv->failed_conns++;
550 t->proxy->failed_conns++;
551
552 /* We used to have a free connection slot. Since we'll never use it,
553 * we have to inform the server that it may be used by another session.
554 */
555 if (may_dequeue_tasks(t->srv, t->proxy))
556 task_wakeup(&rq, t->srv->queue_mgt);
557 return 1;
558 }
559 return 0;
560}
561
562
563/*
564 * This function performs the retryable part of the connect() job.
565 * It updates the session's srv_state and retries, so that the caller knows
566 * what it has to do. It returns 1 when it breaks out of the loop, or 0 if
567 * it needs to redispatch.
568 */
569int srv_retryable_connect(struct session *t)
570{
571 int conn_err;
572
573 /* This loop ensures that we stop before the last retry in case of a
574 * redispatchable server.
575 */
576 do {
577 /* initiate a connection to the server */
578 conn_err = connect_server(t);
579 switch (conn_err) {
580
581 case SN_ERR_NONE:
582 //fprintf(stderr,"0: c=%d, s=%d\n", c, s);
583 t->srv_state = SV_STCONN;
584 return 1;
585
586 case SN_ERR_INTERNAL:
Willy Tarreaud7971282006-07-29 18:36:34 +0200587 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200588 srv_close_with_err(t, SN_ERR_INTERNAL, SN_FINST_C,
589 500, t->proxy->errmsg.len500, t->proxy->errmsg.msg500);
590 if (t->srv)
591 t->srv->failed_conns++;
592 t->proxy->failed_conns++;
593 /* release other sessions waiting for this server */
594 if (may_dequeue_tasks(t->srv, t->proxy))
595 task_wakeup(&rq, t->srv->queue_mgt);
596 return 1;
597 }
598 /* ensure that we have enough retries left */
599 if (srv_count_retry_down(t, conn_err)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200600 return 1;
601 }
602 } while (t->srv == NULL || t->conn_retries > 0 || !(t->proxy->options & PR_O_REDISP));
603
604 /* We're on our last chance, and the REDISP option was specified.
605 * We will ignore cookie and force to balance or use the dispatcher.
606 */
607 /* let's try to offer this slot to anybody */
608 if (may_dequeue_tasks(t->srv, t->proxy))
609 task_wakeup(&rq, t->srv->queue_mgt);
610
611 if (t->srv)
612 t->srv->failed_conns++;
613 t->proxy->failed_conns++;
614
615 t->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
616 t->srv = NULL; /* it's left to the dispatcher to choose a server */
617 if ((t->flags & SN_CK_MASK) == SN_CK_VALID) {
618 t->flags &= ~SN_CK_MASK;
619 t->flags |= SN_CK_DOWN;
620 }
621 return 0;
622}
623
624
625/* This function performs the "redispatch" part of a connection attempt. It
626 * will assign a server if required, queue the connection if required, and
627 * handle errors that might arise at this level. It can change the server
628 * state. It will return 1 if it encounters an error, switches the server
629 * state, or has to queue a connection. Otherwise, it will return 0 indicating
630 * that the connection is ready to use.
631 */
632
633int srv_redispatch_connect(struct session *t)
634{
635 int conn_err;
636
637 /* We know that we don't have any connection pending, so we will
638 * try to get a new one, and wait in this state if it's queued
639 */
640 conn_err = assign_server_and_queue(t);
641 switch (conn_err) {
642 case SRV_STATUS_OK:
643 break;
644
645 case SRV_STATUS_NOSRV:
646 /* note: it is guaranteed that t->srv == NULL here */
Willy Tarreaud7971282006-07-29 18:36:34 +0200647 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200648 srv_close_with_err(t, SN_ERR_SRVTO, SN_FINST_C,
649 503, t->proxy->errmsg.len503, t->proxy->errmsg.msg503);
650 if (t->srv)
651 t->srv->failed_conns++;
652 t->proxy->failed_conns++;
653
654 return 1;
655
656 case SRV_STATUS_QUEUED:
657 /* FIXME-20060503 : we should use the queue timeout instead */
658 if (t->proxy->contimeout)
Willy Tarreaud7971282006-07-29 18:36:34 +0200659 tv_delayfrom(&t->req->cex, &now, t->proxy->contimeout);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200660 else
Willy Tarreaud7971282006-07-29 18:36:34 +0200661 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200662 t->srv_state = SV_STIDLE;
663 /* do nothing else and do not wake any other session up */
664 return 1;
665
666 case SRV_STATUS_FULL:
667 case SRV_STATUS_INTERNAL:
668 default:
Willy Tarreaud7971282006-07-29 18:36:34 +0200669 tv_eternity(&t->req->cex);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 srv_close_with_err(t, SN_ERR_INTERNAL, SN_FINST_C,
671 500, t->proxy->errmsg.len500, t->proxy->errmsg.msg500);
672 if (t->srv)
673 t->srv->failed_conns++;
674 t->proxy->failed_conns++;
675
676 /* release other sessions waiting for this server */
677 if (may_dequeue_tasks(t->srv, t->proxy))
678 task_wakeup(&rq, t->srv->queue_mgt);
679 return 1;
680 }
681 /* if we get here, it's because we got SRV_STATUS_OK, which also
682 * means that the connection has not been queued.
683 */
684 return 0;
685}
686
687
688/*
689 * Local variables:
690 * c-indent-level: 8
691 * c-basic-offset: 8
692 * End:
693 */