~ubuntu-branches/ubuntu/trusty/haproxy/trusty-backports

« back to all changes in this revision

Viewing changes to src/proxy.c

  • Committer: Bazaar Package Importer
  • Author(s): Arnaud Cornet
  • Date: 2009-06-26 00:11:01 UTC
  • mfrom: (1.1.6 upstream) (2.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090626001101-qo261ke2mjh3d8cn
* New Upstream Version (Closes: #534583).
* Add contrib directory in docs

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * Proxy variables and functions.
3
3
 *
4
 
 * Copyright 2000-2007 Willy Tarreau <w@1wt.eu>
 
4
 * Copyright 2000-2009 Willy Tarreau <w@1wt.eu>
5
5
 *
6
6
 * This program is free software; you can redistribute it and/or
7
7
 * modify it under the terms of the GNU General Public License
18
18
#include <sys/stat.h>
19
19
 
20
20
#include <common/defaults.h>
 
21
#include <common/cfgparse.h>
21
22
#include <common/compat.h>
22
23
#include <common/config.h>
23
24
#include <common/errors.h>
25
26
#include <common/time.h>
26
27
 
27
28
#include <types/global.h>
28
 
#include <types/polling.h>
29
29
 
30
30
#include <proto/client.h>
31
31
#include <proto/backend.h>
80
80
 * return zero, it may write an error message into the <err> buffer, for at
81
81
 * most <errlen> bytes, trailing zero included. The trailing '\n' must not
82
82
 * be written. The function must be called with <args> pointing to the first
83
 
 * word after "timeout", with <proxy> pointing to the proxy being parsed, and
 
83
 * command line word, with <proxy> pointing to the proxy being parsed, and
84
84
 * <defpx> to the default proxy or NULL. As a special case for compatibility
85
85
 * with older configs, it also accepts "{cli|srv|con}timeout" in args[0].
86
86
 */
87
 
int proxy_parse_timeout(const char **args, struct proxy *proxy,
88
 
                        struct proxy *defpx, char *err, int errlen)
 
87
static int proxy_parse_timeout(char **args, int section, struct proxy *proxy,
 
88
                               struct proxy *defpx, char *err, int errlen)
89
89
{
90
90
        unsigned timeout;
91
91
        int retval, cap;
92
92
        const char *res, *name;
93
 
        struct timeval *tv = NULL;
94
 
        struct timeval *td = NULL;
 
93
        int *tv = NULL;
 
94
        int *td = NULL;
95
95
 
96
96
        retval = 0;
 
97
 
 
98
        /* simply skip "timeout" but remain compatible with old form */
 
99
        if (strcmp(args[0], "timeout") == 0)
 
100
                args++;
 
101
 
97
102
        name = args[0];
98
103
        if (!strcmp(args[0], "client") || !strcmp(args[0], "clitimeout")) {
99
104
                name = "client";
145
150
 
146
151
        res = parse_time_err(args[1], &timeout, TIME_UNIT_MS);
147
152
        if (res) {
148
 
                snprintf(err, errlen, "unexpected character '%c' in %s timeout", *err, name);
 
153
                snprintf(err, errlen, "unexpected character '%c' in %s timeout", *res, name);
149
154
                return -1;
150
155
        }
151
156
 
155
160
                         (cap & PR_CAP_BE) ? "backend" : "frontend");
156
161
                retval = 1;
157
162
        }
158
 
        else if (defpx && !__tv_iseq(tv, td)) {
 
163
        else if (defpx && *tv != *td) {
159
164
                snprintf(err, errlen, "overwriting %s timeout which was already specified", name);
160
165
                retval = 1;
161
166
        }
162
167
 
163
 
        if (timeout)
164
 
                __tv_from_ms(tv, timeout);
165
 
        else
166
 
                tv_eternity(tv);
167
 
 
 
168
        *tv = MS_TO_TICKS(timeout);
 
169
        return retval;
 
170
}
 
171
 
 
172
/* This function parses a "rate-limit" statement in a proxy section. It returns
 
173
 * -1 if there is any error, 1 for a warning, otherwise zero. If it does not
 
174
 * return zero, it may write an error message into the <err> buffer, for at
 
175
 * most <errlen> bytes, trailing zero included. The trailing '\n' must not
 
176
 * be written. The function must be called with <args> pointing to the first
 
177
 * command line word, with <proxy> pointing to the proxy being parsed, and
 
178
 * <defpx> to the default proxy or NULL.
 
179
 */
 
180
static int proxy_parse_rate_limit(char **args, int section, struct proxy *proxy,
 
181
                                  struct proxy *defpx, char *err, int errlen)
 
182
{
 
183
        int retval, cap;
 
184
        char *res, *name;
 
185
        unsigned int *tv = NULL;
 
186
        unsigned int *td = NULL;
 
187
        unsigned int val;
 
188
 
 
189
        retval = 0;
 
190
 
 
191
        /* simply skip "rate-limit" */
 
192
        if (strcmp(args[0], "rate-limit") == 0)
 
193
                args++;
 
194
 
 
195
        name = args[0];
 
196
        if (!strcmp(args[0], "sessions")) {
 
197
                name = "sessions";
 
198
                tv = &proxy->fe_sps_lim;
 
199
                td = &defpx->fe_sps_lim;
 
200
                cap = PR_CAP_FE;
 
201
        } else {
 
202
                snprintf(err, errlen,
 
203
                         "%s '%s': must be 'sessions'",
 
204
                         "rate-limit", args[0]);
 
205
                return -1;
 
206
        }
 
207
 
 
208
        if (*args[1] == 0) {
 
209
                snprintf(err, errlen, "%s %s expects expects an integer value (in sessions/second)", "rate-limit", name);
 
210
                return -1;
 
211
        }
 
212
 
 
213
        val = strtoul(args[1], &res, 0);
 
214
        if (*res) {
 
215
                snprintf(err, errlen, "%s %s: unexpected character '%c' in integer value '%s'", "rate-limit", name, *res, args[1]);
 
216
                return -1;
 
217
        }
 
218
 
 
219
        if (!(proxy->cap & cap)) {
 
220
                snprintf(err, errlen, "%s %s will be ignored because %s '%s' has no %s capability",
 
221
                         "rate-limit", name, proxy_type_str(proxy), proxy->id,
 
222
                         (cap & PR_CAP_BE) ? "backend" : "frontend");
 
223
                retval = 1;
 
224
        }
 
225
        else if (defpx && *tv != *td) {
 
226
                snprintf(err, errlen, "overwriting %s %s which was already specified", "rate-limit", name);
 
227
                retval = 1;
 
228
        }
 
229
 
 
230
        *tv = val;
168
231
        return retval;
169
232
}
170
233
 
234
297
        return target;
235
298
}
236
299
 
 
300
/* This function checks that the designated proxy has no http directives
 
301
 * enabled. It will output a warning if there are, and will fix some of them.
 
302
 * It returns the number of fatal errors encountered. This should be called
 
303
 * at the end of the configuration parsing if the proxy is not in http mode.
 
304
 * The <file> argument is used to construct the error message.
 
305
 */
 
306
int proxy_cfg_ensure_no_http(struct proxy *curproxy, const char *file)
 
307
{
 
308
        if (curproxy->cookie_name != NULL) {
 
309
                Warning("parsing %s : cookie will be ignored for %s '%s' (needs 'mode http').\n",
 
310
                        file, proxy_type_str(curproxy), curproxy->id);
 
311
        }
 
312
        if (curproxy->rsp_exp != NULL) {
 
313
                Warning("parsing %s : server regular expressions will be ignored for %s '%s' (needs 'mode http').\n",
 
314
                        file, proxy_type_str(curproxy), curproxy->id);
 
315
        }
 
316
        if (curproxy->req_exp != NULL) {
 
317
                Warning("parsing %s : client regular expressions will be ignored for %s '%s' (needs 'mode http').\n",
 
318
                        file, proxy_type_str(curproxy), curproxy->id);
 
319
        }
 
320
        if (curproxy->monitor_uri != NULL) {
 
321
                Warning("parsing %s : monitor-uri will be ignored for %s '%s' (needs 'mode http').\n",
 
322
                        file, proxy_type_str(curproxy), curproxy->id);
 
323
        }
 
324
        if (curproxy->lbprm.algo & BE_LB_PROP_L7) {
 
325
                curproxy->lbprm.algo &= ~BE_LB_ALGO;
 
326
                curproxy->lbprm.algo |= BE_LB_ALGO_RR;
 
327
                Warning("parsing %s : Layer 7 hash not possible for %s '%s' (needs 'mode http'). Falling back to round robin.\n",
 
328
                        file, proxy_type_str(curproxy), curproxy->id);
 
329
        }
 
330
        return 0;
 
331
}
 
332
 
237
333
/*
238
334
 * This function creates all proxy sockets. It should be done very early,
239
335
 * typically before privileges are dropped. The sockets will be registered
300
396
/*
301
397
 * this function enables proxies when there are enough free sessions,
302
398
 * or stops them when the table is full. It is designed to be called from the
303
 
 * select_loop(). It returns the date of next expiration event during stop
304
 
 * time, ETERNITY otherwise.
 
399
 * select_loop(). It adjusts the date of next expiration event during stop
 
400
 * time if appropriate.
305
401
 */
306
 
void maintain_proxies(struct timeval *next)
 
402
void maintain_proxies(int *next)
307
403
{
308
404
        struct proxy *p;
309
405
        struct listener *l;
 
406
        unsigned int wait;
310
407
 
311
408
        p = proxy;
312
 
        tv_eternity(next);
313
409
 
314
410
        /* if there are enough free sessions, we'll activate proxies */
315
411
        if (actconn < global.maxconn) {
316
 
                while (p) {
317
 
                        if (!p->maxconn || p->feconn < p->maxconn) {
318
 
                                if (p->state == PR_STIDLE) {
319
 
                                        for (l = p->listen; l != NULL; l = l->next)
320
 
                                                enable_listener(l);
321
 
                                        p->state = PR_STRUN;
322
 
                                }
323
 
                        }
324
 
                        else {
325
 
                                if (p->state == PR_STRUN) {
326
 
                                        for (l = p->listen; l != NULL; l = l->next)
327
 
                                                disable_listener(l);
328
 
                                        p->state = PR_STIDLE;
329
 
                                }
330
 
                        }
331
 
                        p = p->next;
 
412
                for (; p; p = p->next) {
 
413
                        /* check the various reasons we may find to block the frontend */
 
414
                        if (p->feconn >= p->maxconn)
 
415
                                goto do_block;
 
416
 
 
417
                        if (p->fe_sps_lim &&
 
418
                            (wait = next_event_delay(&p->fe_sess_per_sec, p->fe_sps_lim, 0))) {
 
419
                                /* we're blocking because a limit was reached on the number of
 
420
                                 * requests/s on the frontend. We want to re-check ASAP, which
 
421
                                 * means in 1 ms before estimated expiration date, because the
 
422
                                 * timer will have settled down. Note that we may already be in
 
423
                                 * IDLE state here.
 
424
                                 */
 
425
                                *next = tick_first(*next, tick_add(now_ms, wait));
 
426
                                goto do_block;
 
427
                        }
 
428
 
 
429
                        /* OK we have no reason to block, so let's unblock if we were blocking */
 
430
                        if (p->state == PR_STIDLE) {
 
431
                                for (l = p->listen; l != NULL; l = l->next)
 
432
                                        enable_listener(l);
 
433
                                p->state = PR_STRUN;
 
434
                        }
 
435
                        continue;
 
436
 
 
437
                do_block:
 
438
                        if (p->state == PR_STRUN) {
 
439
                                for (l = p->listen; l != NULL; l = l->next)
 
440
                                        disable_listener(l);
 
441
                                p->state = PR_STIDLE;
 
442
                        }
332
443
                }
333
444
        }
334
445
        else {  /* block all proxies */
347
458
                while (p) {
348
459
                        if (p->state != PR_STSTOPPED) {
349
460
                                int t;
350
 
                                t = tv_ms_remain2(&now, &p->stop_time);
 
461
                                t = tick_remain(now_ms, p->stop_time);
351
462
                                if (t == 0) {
352
463
                                        Warning("Proxy %s stopped.\n", p->id);
353
464
                                        send_log(p, LOG_WARNING, "Proxy %s stopped.\n", p->id);
356
467
                                        pool_gc2();
357
468
                                }
358
469
                                else {
359
 
                                        tv_bound(next, &p->stop_time);
 
470
                                        *next = tick_first(*next, p->stop_time);
360
471
                                }
361
472
                        }
362
473
                        p = p->next;
377
488
 
378
489
        stopping = 1;
379
490
        p = proxy;
380
 
        tv_now(&now); /* else, the old time before select will be used */
 
491
        tv_update_date(0,1); /* else, the old time before select will be used */
381
492
        while (p) {
382
493
                if (p->state != PR_STSTOPPED) {
383
494
                        Warning("Stopping %s %s in %d ms.\n", proxy_cap_str(p->cap), p->id, p->grace);
384
495
                        send_log(p, LOG_WARNING, "Stopping %s %s in %d ms.\n", proxy_cap_str(p->cap), p->id, p->grace);
385
 
                        tv_ms_add(&p->stop_time, &now, p->grace);
 
496
                        p->stop_time = tick_add(now_ms, p->grace);
386
497
                }
387
498
                p = p->next;
388
499
        }
448
559
 
449
560
        err = 0;
450
561
        p = proxy;
451
 
        tv_now(&now); /* else, the old time before select will be used */
 
562
        tv_update_date(0,1); /* else, the old time before select will be used */
452
563
        while (p) {
453
564
                if (p->cap & PR_CAP_FE &&
454
565
                    p->state != PR_STERROR &&
484
595
        struct listener *l;
485
596
 
486
597
        p = proxy;
487
 
        tv_now(&now); /* else, the old time before select will be used */
 
598
        tv_update_date(0,1); /* else, the old time before select will be used */
488
599
        while (p) {
489
600
                if (p->state == PR_STPAUSED) {
490
601
                        Warning("Enabling %s %s.\n", proxy_cap_str(p->cap), p->id);
520
631
        }
521
632
}
522
633
 
 
634
static struct cfg_kw_list cfg_kws = {{ },{
 
635
        { CFG_LISTEN, "timeout", proxy_parse_timeout },
 
636
        { CFG_LISTEN, "clitimeout", proxy_parse_timeout },
 
637
        { CFG_LISTEN, "contimeout", proxy_parse_timeout },
 
638
        { CFG_LISTEN, "srvtimeout", proxy_parse_timeout },
 
639
        { CFG_LISTEN, "rate-limit", proxy_parse_rate_limit },
 
640
        { 0, NULL, NULL },
 
641
}};
 
642
 
 
643
__attribute__((constructor))
 
644
static void __proxy_module_init(void)
 
645
{
 
646
        cfg_register_keywords(&cfg_kws);
 
647
}
523
648
 
524
649
/*
525
650
 * Local variables: