varnish-cache/bin/varnishd/cache/cache_conn_pool.c
0
/*-
1
 * Copyright (c) 2015 Varnish Software AS
2
 * All rights reserved.
3
 *
4
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
5
 *
6
 * SPDX-License-Identifier: BSD-2-Clause
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 *
29
 * (TCP|UDS) connection pools.
30
 *
31
 */
32
33
#include "config.h"
34
35
#include <stdlib.h>
36
37
#include "cache_varnishd.h"
38
39
#include "vsa.h"
40
#include "vsha256.h"
41
#include "vtcp.h"
42
#include "vus.h"
43
#include "vtim.h"
44
#include "waiter/waiter.h"
45
46
#include "cache_conn_pool.h"
47
#include "cache_pool.h"
48
49
struct conn_pool;
50
51
/*--------------------------------------------------------------------
52
 */
53
54
struct pfd {
55
        unsigned                magic;
56
#define PFD_MAGIC               0x0c5e6593
57
        int                     fd;
58
        VTAILQ_ENTRY(pfd)       list;
59
        VCL_IP                  addr;
60
        uint8_t                 state;
61
        struct waited           waited[1];
62
        struct conn_pool        *conn_pool;
63
64
        pthread_cond_t          *cond;
65
};
66
67
/*--------------------------------------------------------------------
68
 */
69
70
typedef int cp_open_f(const struct conn_pool *, vtim_dur tmo, VCL_IP *ap);
71
typedef void cp_close_f(struct pfd *);
72
typedef void cp_name_f(const struct pfd *, char *, unsigned, char *, unsigned);
73
74
struct cp_methods {
75
        cp_open_f                               *open;
76
        cp_close_f                              *close;
77
        cp_name_f                               *local_name;
78
        cp_name_f                               *remote_name;
79
};
80
81
struct conn_pool {
82
        unsigned                                magic;
83
#define CONN_POOL_MAGIC                         0x85099bc3
84
85
        const struct cp_methods                 *methods;
86
87
        struct vrt_endpoint                     *endpoint;
88
        char                                    ident[VSHA256_DIGEST_LENGTH];
89
90
        VTAILQ_ENTRY(conn_pool)                 list;
91
        int                                     refcnt;
92
        struct lock                             mtx;
93
94
        VTAILQ_HEAD(, pfd)                      connlist;
95
        int                                     n_conn;
96
97
        int                                     n_kill;
98
99
        int                                     n_used;
100
101
        vtim_mono                               holddown;
102
        int                                     holddown_errno;
103
};
104
105
static struct lock conn_pools_mtx;
106
107
static VTAILQ_HEAD(, conn_pool) conn_pools =
108
    VTAILQ_HEAD_INITIALIZER(conn_pools);
109
110
111
/*--------------------------------------------------------------------
112
 */
113
114
unsigned
115 244272
PFD_State(const struct pfd *p)
116
{
117 244272
        CHECK_OBJ_NOTNULL(p, PFD_MAGIC);
118 244272
        return (p->state);
119
}
120
121
int *
122 102848
PFD_Fd(struct pfd *p)
123
{
124 102848
        CHECK_OBJ_NOTNULL(p, PFD_MAGIC);
125 102848
        return (&(p->fd));
126
}
127
128
void
129 51150
PFD_LocalName(const struct pfd *p, char *abuf, unsigned alen, char *pbuf,
130
              unsigned plen)
131
{
132 51150
        CHECK_OBJ_NOTNULL(p, PFD_MAGIC);
133 51150
        CHECK_OBJ_NOTNULL(p->conn_pool, CONN_POOL_MAGIC);
134 51150
        p->conn_pool->methods->local_name(p, abuf, alen, pbuf, plen);
135 51150
}
136
137
void
138 51149
PFD_RemoteName(const struct pfd *p, char *abuf, unsigned alen, char *pbuf,
139
               unsigned plen)
140
{
141 51149
        CHECK_OBJ_NOTNULL(p, PFD_MAGIC);
142 51149
        CHECK_OBJ_NOTNULL(p->conn_pool, CONN_POOL_MAGIC);
143 51149
        p->conn_pool->methods->remote_name(p, abuf, alen, pbuf, plen);
144 51149
}
145
146
/*--------------------------------------------------------------------
147
 * Waiter-handler
148
 */
149
150
static void  v_matchproto_(waiter_handle_f)
151 41698
vcp_handle(struct waited *w, enum wait_event ev, vtim_real now)
152
{
153
        struct pfd *pfd;
154
        struct conn_pool *cp;
155
156 41698
        CHECK_OBJ_NOTNULL(w, WAITED_MAGIC);
157 41698
        CAST_OBJ_NOTNULL(pfd, w->priv1, PFD_MAGIC);
158 41698
        (void)ev;
159 41698
        (void)now;
160 41698
        CHECK_OBJ_NOTNULL(pfd->conn_pool, CONN_POOL_MAGIC);
161 41698
        cp = pfd->conn_pool;
162
163 41698
        Lck_Lock(&cp->mtx);
164
165 41698
        switch (pfd->state) {
166
        case PFD_STATE_STOLEN:
167 18772
                pfd->state = PFD_STATE_USED;
168 18772
                VTAILQ_REMOVE(&cp->connlist, pfd, list);
169 18772
                AN(pfd->cond);
170 18772
                PTOK(pthread_cond_signal(pfd->cond));
171 18772
                break;
172
        case PFD_STATE_AVAIL:
173 22851
                cp->methods->close(pfd);
174 22851
                VTAILQ_REMOVE(&cp->connlist, pfd, list);
175 22851
                cp->n_conn--;
176 22851
                FREE_OBJ(pfd);
177 22851
                break;
178
        case PFD_STATE_CLEANUP:
179 75
                cp->methods->close(pfd);
180 75
                cp->n_kill--;
181 75
                memset(pfd, 0x11, sizeof *pfd);
182 75
                free(pfd);
183 75
                break;
184
        default:
185 0
                WRONG("Wrong pfd state");
186 0
        }
187 41698
        Lck_Unlock(&cp->mtx);
188 41698
}
189
190
191
/*--------------------------------------------------------------------
192
 */
193
194
void
195 850
VCP_AddRef(struct conn_pool *cp)
196
{
197 850
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
198
199 850
        Lck_Lock(&conn_pools_mtx);
200 850
        assert(cp->refcnt > 0);
201 850
        cp->refcnt++;
202 850
        Lck_Unlock(&conn_pools_mtx);
203 850
}
204
205
/*--------------------------------------------------------------------
206
 * Release Conn pool, destroy if last reference.
207
 */
208
209
void
210 2096
VCP_Rel(struct conn_pool **cpp)
211
{
212
        struct conn_pool *cp;
213
        struct pfd *pfd, *pfd2;
214
215 2096
        TAKE_OBJ_NOTNULL(cp, cpp, CONN_POOL_MAGIC);
216
217 2096
        Lck_Lock(&conn_pools_mtx);
218 2096
        assert(cp->refcnt > 0);
219 2096
        if (--cp->refcnt > 0) {
220 1446
                Lck_Unlock(&conn_pools_mtx);
221 1446
                return;
222
        }
223 650
        AZ(cp->n_used);
224 650
        VTAILQ_REMOVE(&conn_pools, cp, list);
225 650
        Lck_Unlock(&conn_pools_mtx);
226
227 650
        Lck_Lock(&cp->mtx);
228 675
        VTAILQ_FOREACH_SAFE(pfd, &cp->connlist, list, pfd2) {
229 25
                VTAILQ_REMOVE(&cp->connlist, pfd, list);
230 25
                cp->n_conn--;
231 25
                assert(pfd->state == PFD_STATE_AVAIL);
232 25
                pfd->state = PFD_STATE_CLEANUP;
233 25
                (void)shutdown(pfd->fd, SHUT_WR);
234 25
                cp->n_kill++;
235 25
        }
236 675
        while (cp->n_kill) {
237 25
                Lck_Unlock(&cp->mtx);
238 25
                (void)usleep(20000);
239 25
                Lck_Lock(&cp->mtx);
240
        }
241 650
        Lck_Unlock(&cp->mtx);
242 650
        Lck_Delete(&cp->mtx);
243 650
        AZ(cp->n_conn);
244 650
        AZ(cp->n_kill);
245 650
        free(cp->endpoint);
246 650
        FREE_OBJ(cp);
247 2096
}
248
249
/*--------------------------------------------------------------------
250
 * Recycle a connection.
251
 */
252
253
void
254 42070
VCP_Recycle(const struct worker *wrk, struct pfd **pfdp)
255
{
256
        struct pfd *pfd;
257
        struct conn_pool *cp;
258 42070
        int i = 0;
259
260 42070
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
261 42070
        TAKE_OBJ_NOTNULL(pfd, pfdp, PFD_MAGIC);
262 42070
        cp = pfd->conn_pool;
263 42070
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
264
265 42070
        assert(pfd->state == PFD_STATE_USED);
266 42070
        assert(pfd->fd > 0);
267
268 42070
        Lck_Lock(&cp->mtx);
269 42070
        cp->n_used--;
270
271 42070
        pfd->waited->priv1 = pfd;
272 42070
        pfd->waited->fd = pfd->fd;
273 42070
        pfd->waited->idle = VTIM_real();
274 42070
        pfd->state = PFD_STATE_AVAIL;
275 42070
        pfd->waited->func = vcp_handle;
276 42070
        pfd->waited->tmo = cache_param->backend_idle_timeout;
277 42070
        if (Wait_Enter(wrk->pool->waiter, pfd->waited)) {
278 0
                cp->methods->close(pfd);
279 0
                memset(pfd, 0x33, sizeof *pfd);
280 0
                free(pfd);
281
                // XXX: stats
282 0
                pfd = NULL;
283 0
        } else {
284 42070
                VTAILQ_INSERT_HEAD(&cp->connlist, pfd, list);
285 42070
                i++;
286
        }
287
288 42070
        if (pfd != NULL)
289 42070
                cp->n_conn++;
290 42070
        Lck_Unlock(&cp->mtx);
291
292 42070
        if (i && DO_DEBUG(DBG_VTC_MODE)) {
293
                /*
294
                 * In varnishtest we do not have the luxury of using
295
                 * multiple backend connections, so whenever we end up
296
                 * in the "pending" case, take a short nap to let the
297
                 * waiter catch up and put the pfd back into circulations.
298
                 *
299
                 * In particular ESI:include related tests suffer random
300
                 * failures without this.
301
                 *
302
                 * In normal operation, the only effect is that we will
303
                 * have N+1 backend connections rather than N, which is
304
                 * entirely harmless.
305
                 */
306 42070
                (void)usleep(10000);
307 42070
        }
308 42070
}
309
310
/*--------------------------------------------------------------------
311
 * Open a new connection from pool.
312
 */
313
314
int
315 37875
VCP_Open(struct conn_pool *cp, vtim_dur tmo, VCL_IP *ap, int *err)
316
{
317
        int r;
318
        vtim_mono h;
319
320 37875
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
321 37875
        AN(err);
322
323 37875
        while (cp->holddown > 0) {
324 534
                Lck_Lock(&cp->mtx);
325 534
                if (cp->holddown == 0) {
326 0
                        Lck_Unlock(&cp->mtx);
327 0
                        break;
328
                }
329
330 534
                if (VTIM_mono() >= cp->holddown) {
331 65
                        cp->holddown = 0;
332 65
                        Lck_Unlock(&cp->mtx);
333 65
                        break;
334
                }
335
336 469
                *err = 0;
337 469
                errno = cp->holddown_errno;
338 469
                Lck_Unlock(&cp->mtx);
339 469
                return (-1);
340
        }
341
342 37406
        *err = errno = 0;
343 37406
        r = cp->methods->open(cp, tmo, ap);
344
345 37406
        if (r >= 0 && errno == 0 && cp->endpoint->preamble != NULL &&
346 225
             cp->endpoint->preamble->len > 0) {
347 675
                if (write(r, cp->endpoint->preamble->blob,
348 450
                    cp->endpoint->preamble->len) !=
349 225
                    cp->endpoint->preamble->len) {
350 0
                        *err = errno;
351 0
                        closefd(&r);
352 0
                }
353 225
        } else {
354 37181
                *err = errno;
355
        }
356
357 37406
        if (r >= 0)
358 36796
                return (r);
359
360 610
        h = 0;
361
362 610
        switch (errno) {
363
        case EACCES:
364
        case EPERM:
365 0
                h = cache_param->backend_local_error_holddown;
366 0
                break;
367
        case EADDRNOTAVAIL:
368 0
                h = cache_param->backend_local_error_holddown;
369 0
                break;
370
        case ECONNREFUSED:
371 610
                h = cache_param->backend_remote_error_holddown;
372 610
                break;
373
        case ENETUNREACH:
374 0
                h = cache_param->backend_remote_error_holddown;
375 0
                break;
376
        default:
377 0
                break;
378
        }
379
380 610
        if (h == 0)
381 0
                return (r);
382
383 610
        Lck_Lock(&cp->mtx);
384 610
        h += VTIM_mono();
385 610
        if (cp->holddown == 0 || h < cp->holddown) {
386 550
                cp->holddown = h;
387 550
                cp->holddown_errno = errno;
388 550
        }
389
390 610
        Lck_Unlock(&cp->mtx);
391
392 610
        return (r);
393 37875
}
394
395
/*--------------------------------------------------------------------
396
 * Close a connection.
397
 */
398
399
void
400 9030
VCP_Close(struct pfd **pfdp)
401
{
402
        struct pfd *pfd;
403
        struct conn_pool *cp;
404
405 9030
        TAKE_OBJ_NOTNULL(pfd, pfdp, PFD_MAGIC);
406 9030
        cp = pfd->conn_pool;
407 9030
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
408
409 9030
        assert(pfd->fd > 0);
410
411 9030
        Lck_Lock(&cp->mtx);
412 9030
        assert(pfd->state == PFD_STATE_USED || pfd->state == PFD_STATE_STOLEN);
413 9030
        cp->n_used--;
414 9030
        if (pfd->state == PFD_STATE_STOLEN) {
415 50
                (void)shutdown(pfd->fd, SHUT_RDWR);
416 50
                VTAILQ_REMOVE(&cp->connlist, pfd, list);
417 50
                pfd->state = PFD_STATE_CLEANUP;
418 50
                cp->n_kill++;
419 50
        } else {
420 8980
                assert(pfd->state == PFD_STATE_USED);
421 8980
                cp->methods->close(pfd);
422 8980
                memset(pfd, 0x44, sizeof *pfd);
423 8980
                free(pfd);
424
        }
425 9030
        Lck_Unlock(&cp->mtx);
426 9030
}
427
428
/*--------------------------------------------------------------------
429
 * Get a connection, possibly recycled
430
 */
431
432
struct pfd *
433 51926
VCP_Get(struct conn_pool *cp, vtim_dur tmo, struct worker *wrk,
434
    unsigned force_fresh, int *err)
435
{
436
        struct pfd *pfd;
437
438 51926
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
439 51926
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
440 51926
        AN(err);
441
442 51926
        *err = 0;
443 51926
        Lck_Lock(&cp->mtx);
444 51926
        pfd = VTAILQ_FIRST(&cp->connlist);
445 51926
        CHECK_OBJ_ORNULL(pfd, PFD_MAGIC);
446 51926
        if (force_fresh || pfd == NULL || pfd->state == PFD_STATE_STOLEN) {
447 33104
                pfd = NULL;
448 33104
        } else {
449 18822
                assert(pfd->conn_pool == cp);
450 18822
                assert(pfd->state == PFD_STATE_AVAIL);
451 18822
                VTAILQ_REMOVE(&cp->connlist, pfd, list);
452 18822
                VTAILQ_INSERT_TAIL(&cp->connlist, pfd, list);
453 18822
                cp->n_conn--;
454 18822
                VSC_C_main->backend_reuse++;
455 18822
                pfd->state = PFD_STATE_STOLEN;
456 18822
                pfd->cond = &wrk->cond;
457
        }
458 51926
        cp->n_used++;                   // Opening mostly works
459 51926
        Lck_Unlock(&cp->mtx);
460
461 51926
        if (pfd != NULL)
462 18822
                return (pfd);
463
464 33104
        ALLOC_OBJ(pfd, PFD_MAGIC);
465 33104
        AN(pfd);
466 33104
        INIT_OBJ(pfd->waited, WAITED_MAGIC);
467 33104
        pfd->state = PFD_STATE_USED;
468 33104
        pfd->conn_pool = cp;
469 33104
        pfd->fd = VCP_Open(cp, tmo, &pfd->addr, err);
470 33104
        if (pfd->fd < 0) {
471 776
                FREE_OBJ(pfd);
472 776
                Lck_Lock(&cp->mtx);
473 776
                cp->n_used--;           // Nope, didn't work after all.
474 776
                Lck_Unlock(&cp->mtx);
475 776
        } else
476 32328
                VSC_C_main->backend_conn++;
477
478 33104
        return (pfd);
479 51926
}
480
481
/*--------------------------------------------------------------------
482
 */
483
484
int
485 18722
VCP_Wait(struct worker *wrk, struct pfd *pfd, vtim_real when)
486
{
487
        struct conn_pool *cp;
488
        int r;
489
490 18722
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
491 18722
        CHECK_OBJ_NOTNULL(pfd, PFD_MAGIC);
492 18722
        cp = pfd->conn_pool;
493 18722
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
494 18722
        assert(pfd->cond == &wrk->cond);
495 18722
        Lck_Lock(&cp->mtx);
496 37419
        while (pfd->state == PFD_STATE_STOLEN) {
497 18722
                r = Lck_CondWaitUntil(&wrk->cond, &cp->mtx, when);
498 18722
                if (r != 0) {
499 25
                        if (r == EINTR)
500 0
                                continue;
501 25
                        assert(r == ETIMEDOUT);
502 25
                        Lck_Unlock(&cp->mtx);
503 25
                        return (1);
504
                }
505
        }
506 18697
        assert(pfd->state == PFD_STATE_USED);
507 18697
        pfd->cond = NULL;
508 18697
        Lck_Unlock(&cp->mtx);
509
510 18697
        return (0);
511 18722
}
512
513
/*--------------------------------------------------------------------
514
 */
515
516
VCL_IP
517 25
VCP_GetIp(struct pfd *pfd)
518
{
519
520 25
        CHECK_OBJ_NOTNULL(pfd, PFD_MAGIC);
521 25
        return (pfd->addr);
522
}
523
524
/*--------------------------------------------------------------------*/
525
526
static void
527 125
vcp_panic_endpoint(struct vsb *vsb, const struct vrt_endpoint *vep)
528
{
529
        char h[VTCP_ADDRBUFSIZE];
530
        char p[VTCP_PORTBUFSIZE];
531
532 125
        if (PAN_dump_struct(vsb, vep, VRT_ENDPOINT_MAGIC, "vrt_endpoint"))
533 0
                return;
534 125
        if (vep->uds_path)
535 0
                VSB_printf(vsb, "uds_path = %s,\n", vep->uds_path);
536 125
        if (vep->ipv4 && VSA_Sane(vep->ipv4)) {
537 125
                VTCP_name(vep->ipv4, h, sizeof h, p, sizeof p);
538 125
                VSB_printf(vsb, "ipv4 = %s, ", h);
539 125
                VSB_printf(vsb, "port = %s,\n", p);
540 125
        }
541 125
        if (vep->ipv6 && VSA_Sane(vep->ipv6)) {
542 0
                VTCP_name(vep->ipv6, h, sizeof h, p, sizeof p);
543 0
                VSB_printf(vsb, "ipv6 = %s, ", h);
544 0
                VSB_printf(vsb, "port = %s,\n", p);
545 0
        }
546 125
        VSB_indent(vsb, -2);
547 125
        VSB_cat(vsb, "},\n");
548 125
}
549
550
void
551 125
VCP_Panic(struct vsb *vsb, struct conn_pool *cp)
552
{
553
554 125
        if (PAN_dump_struct(vsb, cp, CONN_POOL_MAGIC, "conn_pool"))
555 0
                return;
556 125
        VSB_cat(vsb, "ident = ");
557 125
        VSB_quote(vsb, cp->ident, VSHA256_DIGEST_LENGTH, VSB_QUOTE_HEX);
558 125
        VSB_cat(vsb, ",\n");
559 125
        vcp_panic_endpoint(vsb, cp->endpoint);
560 125
        VSB_indent(vsb, -2);
561 125
        VSB_cat(vsb, "},\n");
562 125
}
563
564
/*--------------------------------------------------------------------*/
565
566
void
567 22197
VCP_Init(void)
568
{
569 22197
        Lck_New(&conn_pools_mtx, lck_conn_pool);
570 22197
}
571
572
/**********************************************************************/
573
574
static inline int
575 37431
tmo2msec(vtim_dur tmo)
576
{
577 37431
        return ((int)floor(tmo * 1000.0));
578
}
579
580
static int v_matchproto_(cp_open_f)
581 34454
vtp_open(const struct conn_pool *cp, vtim_dur tmo, VCL_IP *ap)
582
{
583
        int s;
584
        int msec;
585
586 34454
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
587
588 34454
        msec = tmo2msec(tmo);
589 34454
        if (cache_param->prefer_ipv6) {
590 0
                *ap = cp->endpoint->ipv6;
591 0
                s = VTCP_connect(*ap, msec);
592 0
                if (s >= 0)
593 0
                        return (s);
594 0
        }
595 34454
        *ap = cp->endpoint->ipv4;
596 34454
        s = VTCP_connect(*ap, msec);
597 34454
        if (s >= 0)
598 33785
                return (s);
599 669
        if (!cache_param->prefer_ipv6) {
600 669
                *ap = cp->endpoint->ipv6;
601 669
                s = VTCP_connect(*ap, msec);
602 669
        }
603 669
        return (s);
604 34454
}
605
606
607
/*--------------------------------------------------------------------*/
608
609
static void v_matchproto_(cp_close_f)
610 31905
vtp_close(struct pfd *pfd)
611
{
612
613 31905
        CHECK_OBJ_NOTNULL(pfd, PFD_MAGIC);
614 31905
        VTCP_close(&pfd->fd);
615 31905
}
616
617
static void v_matchproto_(cp_name_f)
618 48375
vtp_local_name(const struct pfd *pfd, char *addr, unsigned alen, char *pbuf,
619
               unsigned plen)
620
{
621 48375
        CHECK_OBJ_NOTNULL(pfd, PFD_MAGIC);
622 48375
        VTCP_myname(pfd->fd, addr, alen, pbuf, plen);
623 48375
}
624
625
static void v_matchproto_(cp_name_f)
626 48374
vtp_remote_name(const struct pfd *pfd, char *addr, unsigned alen, char *pbuf,
627
                unsigned plen)
628
{
629 48374
        CHECK_OBJ_NOTNULL(pfd, PFD_MAGIC);
630 48374
        VTCP_hisname(pfd->fd, addr, alen, pbuf, plen);
631 48374
}
632
633
static const struct cp_methods vtp_methods = {
634
        .open = vtp_open,
635
        .close = vtp_close,
636
        .local_name = vtp_local_name,
637
        .remote_name = vtp_remote_name,
638
};
639
640
/*--------------------------------------------------------------------
641
 */
642
643
static int v_matchproto_(cp_open_f)
644 2952
vus_open(const struct conn_pool *cp, vtim_dur tmo, VCL_IP *ap)
645
{
646
        int s;
647
        int msec;
648
649 2952
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
650 2952
        AN(cp->endpoint->uds_path);
651
652 2952
        msec = tmo2msec(tmo);
653 2952
        *ap = bogo_ip;
654 2952
        s = VUS_connect(cp->endpoint->uds_path, msec);
655 2952
        return (s);
656
}
657
658
static void v_matchproto_(cp_name_f)
659 5550
vus_name(const struct pfd *pfd, char *addr, unsigned alen, char *pbuf,
660
         unsigned plen)
661
{
662 5550
        (void) pfd;
663 5550
        assert(alen > strlen("0.0.0.0"));
664 5550
        assert(plen > 1);
665 5550
        strcpy(addr, "0.0.0.0");
666 5550
        strcpy(pbuf, "0");
667 5550
}
668
669
static const struct cp_methods vus_methods = {
670
        .open = vus_open,
671
        .close = vtp_close,
672
        .local_name = vus_name,
673
        .remote_name = vus_name,
674
};
675
676
/*--------------------------------------------------------------------
677
 * Reference a TCP pool given by {ip4, ip6} pair or a UDS.  Create if
678
 * it doesn't exist already.
679
 */
680
681
struct conn_pool *
682 31625
VCP_Ref(const struct vrt_endpoint *vep, const char *ident)
683
{
684
        struct conn_pool *cp, *cp2;
685
        struct VSHA256Context cx[1];
686
        unsigned char digest[VSHA256_DIGEST_LENGTH];
687
688 31625
        CHECK_OBJ_NOTNULL(vep, VRT_ENDPOINT_MAGIC);
689 31625
        AN(ident);
690 31625
        VSHA256_Init(cx);
691 31625
        VSHA256_Update(cx, ident, strlen(ident) + 1); // include \0
692 31625
        if (vep->uds_path != NULL) {
693 1150
                AZ(vep->ipv4);
694 1150
                AZ(vep->ipv6);
695 1150
                VSHA256_Update(cx, "UDS", 4); // include \0
696 1150
                VSHA256_Update(cx, vep->uds_path, strlen(vep->uds_path));
697 1150
        } else {
698 30475
                assert(vep->ipv4 != NULL || vep->ipv6 != NULL);
699 30475
                if (vep->ipv4 != NULL) {
700 30400
                        assert(VSA_Sane(vep->ipv4));
701 30400
                        VSHA256_Update(cx, "IP4", 4); // include \0
702 30400
                        VSHA256_Update(cx, vep->ipv4, vsa_suckaddr_len);
703 30400
                }
704 30475
                if (vep->ipv6 != NULL) {
705 100
                        assert(VSA_Sane(vep->ipv6));
706 100
                        VSHA256_Update(cx, "IP6", 4); // include \0
707 100
                        VSHA256_Update(cx, vep->ipv6, vsa_suckaddr_len);
708 100
                }
709
        }
710 31625
        if (vep->preamble != NULL && vep->preamble->len > 0) {
711 200
                VSHA256_Update(cx, "PRE", 4); // include \0
712 200
                VSHA256_Update(cx, vep->preamble->blob, vep->preamble->len);
713 200
        }
714 31625
        VSHA256_Final(digest, cx);
715
716
        /*
717
         * In heavy use of dynamic backends, traversing this list
718
         * can become expensive.  In order to not do so twice we
719
         * pessimistically create the necessary pool, and discard
720
         * it on a hit. (XXX: Consider hash or tree ?)
721
         */
722
723 31625
        ALLOC_OBJ(cp, CONN_POOL_MAGIC);
724 31625
        AN(cp);
725 31625
        cp->refcnt = 1;
726 31625
        cp->holddown = 0;
727 31625
        cp->endpoint = VRT_Endpoint_Clone(vep);
728 31625
        CHECK_OBJ_NOTNULL(cp->endpoint, VRT_ENDPOINT_MAGIC);
729 31625
        memcpy(cp->ident, digest, sizeof cp->ident);
730 31625
        if (vep->uds_path != NULL)
731 1150
                cp->methods = &vus_methods;
732
        else
733 30475
                cp->methods = &vtp_methods;
734 31625
        Lck_New(&cp->mtx, lck_conn_pool);
735 31625
        VTAILQ_INIT(&cp->connlist);
736
737 31625
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
738 31625
        Lck_Lock(&conn_pools_mtx);
739 38400
        VTAILQ_FOREACH(cp2, &conn_pools, list) {
740 13825
                CHECK_OBJ_NOTNULL(cp2, CONN_POOL_MAGIC);
741 13825
                assert(cp2->refcnt > 0);
742 13825
                if (!memcmp(digest, cp2->ident, sizeof cp2->ident))
743 7050
                        break;
744 6775
        }
745 31625
        if (cp2 == NULL)
746 24575
                VTAILQ_INSERT_HEAD(&conn_pools, cp, list);
747
        else
748 7050
                cp2->refcnt++;
749 31625
        Lck_Unlock(&conn_pools_mtx);
750
751 31625
        if (cp2 == NULL) {
752 24575
                CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
753 24575
                return (cp);
754
        }
755
756 7050
        Lck_Delete(&cp->mtx);
757 7050
        AZ(cp->n_conn);
758 7050
        AZ(cp->n_kill);
759 7050
        FREE_OBJ(cp->endpoint);
760 7050
        FREE_OBJ(cp);
761 7050
        CHECK_OBJ_NOTNULL(cp2, CONN_POOL_MAGIC);
762 7050
        return (cp2);
763 31625
}