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
static inline int vcp_cmp(const struct conn_pool *a, const struct conn_pool *b);
51
52
/*--------------------------------------------------------------------
53
 */
54
55
struct pfd {
56
        unsigned                magic;
57
#define PFD_MAGIC               0x0c5e6593
58
        int                     fd;
59
        VTAILQ_ENTRY(pfd)       list;
60
        VCL_IP                  addr;
61
        uint8_t                 state;
62
        struct waited           waited[1];
63
        struct conn_pool        *conn_pool;
64
65
        pthread_cond_t          *cond;
66
};
67
68
/*--------------------------------------------------------------------
69
 */
70
71
typedef int cp_open_f(const struct conn_pool *, vtim_dur tmo, VCL_IP *ap);
72
typedef void cp_close_f(struct pfd *);
73
typedef void cp_name_f(const struct pfd *, char *, unsigned, char *, unsigned);
74
75
struct cp_methods {
76
        cp_open_f                               *open;
77
        cp_close_f                              *close;
78
        cp_name_f                               *local_name;
79
        cp_name_f                               *remote_name;
80
};
81
82
struct conn_pool {
83
        unsigned                                magic;
84
#define CONN_POOL_MAGIC                         0x85099bc3
85
86
        const struct cp_methods                 *methods;
87
88
        struct vrt_endpoint                     *endpoint;
89
        char                                    ident[VSHA256_DIGEST_LENGTH];
90
91
        VRBT_ENTRY(conn_pool)                   entry;
92
        int                                     refcnt;
93
        struct lock                             mtx;
94
95
        VTAILQ_HEAD(, pfd)                      connlist;
96
        int                                     n_conn;
97
98
        int                                     n_kill;
99
100
        int                                     n_used;
101
102
        vtim_mono                               holddown;
103
        int                                     holddown_errno;
104
};
105
106
static struct lock conn_pools_mtx;
107
static struct lock dead_pools_mtx;
108
109
VRBT_HEAD(vrb, conn_pool);
110 82
VRBT_GENERATE_REMOVE_COLOR(vrb, conn_pool, entry, static)
111 215
VRBT_GENERATE_REMOVE(vrb, conn_pool, entry, static)
112 7708
VRBT_GENERATE_FIND(vrb, conn_pool, entry, vcp_cmp, static)
113 1089
VRBT_GENERATE_INSERT_COLOR(vrb, conn_pool, entry, static)
114 5077
VRBT_GENERATE_INSERT_FINISH(vrb, conn_pool, entry, static)
115 6172
VRBT_GENERATE_INSERT(vrb, conn_pool, entry, vcp_cmp, static)
116 12
VRBT_GENERATE_NEXT(vrb, conn_pool, entry, static)
117 24
VRBT_GENERATE_MINMAX(vrb, conn_pool, entry, static)
118
119
static struct vrb conn_pools = VRBT_INITIALIZER(&conn_pools);
120
static struct vrb dead_pools = VRBT_INITIALIZER(&dying_cps);
121
122
/*--------------------------------------------------------------------
123
 */
124
125
unsigned
126 49957
PFD_State(const struct pfd *p)
127
{
128 49957
        CHECK_OBJ_NOTNULL(p, PFD_MAGIC);
129 49957
        return (p->state);
130
}
131
132
int *
133 21125
PFD_Fd(struct pfd *p)
134
{
135 21125
        CHECK_OBJ_NOTNULL(p, PFD_MAGIC);
136 21125
        return (&(p->fd));
137
}
138
139
void
140 10505
PFD_LocalName(const struct pfd *p, char *abuf, unsigned alen, char *pbuf,
141
              unsigned plen)
142
{
143 10505
        CHECK_OBJ_NOTNULL(p, PFD_MAGIC);
144 10505
        CHECK_OBJ_NOTNULL(p->conn_pool, CONN_POOL_MAGIC);
145 10505
        p->conn_pool->methods->local_name(p, abuf, alen, pbuf, plen);
146 10505
}
147
148
void
149 10505
PFD_RemoteName(const struct pfd *p, char *abuf, unsigned alen, char *pbuf,
150
               unsigned plen)
151
{
152 10505
        CHECK_OBJ_NOTNULL(p, PFD_MAGIC);
153 10505
        CHECK_OBJ_NOTNULL(p->conn_pool, CONN_POOL_MAGIC);
154 10505
        p->conn_pool->methods->remote_name(p, abuf, alen, pbuf, plen);
155 10505
}
156
157
/*--------------------------------------------------------------------
158
 */
159
160
static inline int
161 3738
vcp_cmp(const struct conn_pool *a, const struct conn_pool *b)
162
{
163 3738
        return (memcmp(a->ident, b->ident, sizeof b->ident));
164
}
165
166
/*--------------------------------------------------------------------
167
 * Waiter-handler
168
 */
169
170
static void  v_matchproto_(waiter_handle_f)
171 8494
vcp_handle(struct waited *w, enum wait_event ev, vtim_real now)
172
{
173
        struct pfd *pfd;
174
        struct conn_pool *cp;
175
176 8494
        CHECK_OBJ_NOTNULL(w, WAITED_MAGIC);
177 8494
        CAST_OBJ_NOTNULL(pfd, w->priv1, PFD_MAGIC);
178 8494
        (void)ev;
179 8494
        (void)now;
180 8494
        CHECK_OBJ_NOTNULL(pfd->conn_pool, CONN_POOL_MAGIC);
181 8494
        cp = pfd->conn_pool;
182
183 8494
        Lck_Lock(&cp->mtx);
184
185 8494
        switch (pfd->state) {
186
        case PFD_STATE_STOLEN:
187 3874
                pfd->state = PFD_STATE_USED;
188 3874
                VTAILQ_REMOVE(&cp->connlist, pfd, list);
189 3874
                AN(pfd->cond);
190 3874
                PTOK(pthread_cond_signal(pfd->cond));
191 3874
                break;
192
        case PFD_STATE_AVAIL:
193 4600
                cp->methods->close(pfd);
194 4600
                VTAILQ_REMOVE(&cp->connlist, pfd, list);
195 4600
                cp->n_conn--;
196 4600
                FREE_OBJ(pfd);
197 4600
                break;
198
        case PFD_STATE_CLEANUP:
199 20
                cp->methods->close(pfd);
200 20
                cp->n_kill--;
201 20
                memset(pfd, 0x11, sizeof *pfd);
202 20
                free(pfd);
203 20
                break;
204
        default:
205 0
                WRONG("Wrong pfd state");
206 0
        }
207 8494
        Lck_Unlock(&cp->mtx);
208 8494
}
209
210
211
/*--------------------------------------------------------------------
212
 */
213
214
void
215 185
VCP_AddRef(struct conn_pool *cp)
216
{
217 185
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
218
219 185
        Lck_Lock(&conn_pools_mtx);
220 185
        assert(cp->refcnt > 0);
221 185
        cp->refcnt++;
222 185
        Lck_Unlock(&conn_pools_mtx);
223 185
}
224
225
/*--------------------------------------------------------------------
226
 */
227
228
static void
229 135
vcp_destroy(struct conn_pool **cpp)
230
{
231
        struct conn_pool *cp;
232
233 135
        TAKE_OBJ_NOTNULL(cp, cpp, CONN_POOL_MAGIC);
234 135
        AZ(cp->n_conn);
235 135
        AZ(cp->n_kill);
236 135
        Lck_Delete(&cp->mtx);
237 135
        free(cp->endpoint);
238 135
        FREE_OBJ(cp);
239 135
}
240
241
/*--------------------------------------------------------------------
242
 * Release Conn pool, destroy if last reference.
243
 */
244
245
void
246 429
VCP_Rel(struct conn_pool **cpp)
247
{
248
        struct conn_pool *cp;
249
        struct pfd *pfd, *pfd2;
250
251 429
        TAKE_OBJ_NOTNULL(cp, cpp, CONN_POOL_MAGIC);
252
253 429
        Lck_Lock(&conn_pools_mtx);
254 429
        assert(cp->refcnt > 0);
255 429
        if (--cp->refcnt > 0) {
256 294
                Lck_Unlock(&conn_pools_mtx);
257 294
                return;
258
        }
259 135
        AZ(cp->n_used);
260 135
        VRBT_REMOVE(vrb, &conn_pools, cp);
261 135
        Lck_Unlock(&conn_pools_mtx);
262
263 135
        Lck_Lock(&cp->mtx);
264 145
        VTAILQ_FOREACH_SAFE(pfd, &cp->connlist, list, pfd2) {
265 10
                VTAILQ_REMOVE(&cp->connlist, pfd, list);
266 10
                cp->n_conn--;
267 10
                assert(pfd->state == PFD_STATE_AVAIL);
268 10
                pfd->state = PFD_STATE_CLEANUP;
269 10
                (void)shutdown(pfd->fd, SHUT_RDWR);
270 10
                cp->n_kill++;
271 10
        }
272 135
        Lck_Unlock(&cp->mtx);
273 135
        if (cp->n_kill == 0) {
274 125
                vcp_destroy(&cp);
275 125
                return;
276
        }
277 10
        Lck_Lock(&dead_pools_mtx);
278
        /*
279
         * Here we reuse cp's entry but it will probably not be correctly
280
         * indexed because of the hack in VCP_RelPoll
281
         */
282 10
        VRBT_INSERT(vrb, &dead_pools, cp);
283 10
        Lck_Unlock(&dead_pools_mtx);
284 429
}
285
286
void
287 37604
VCP_RelPoll(void)
288
{
289
        struct vrb dead;
290
        struct conn_pool *cp, *cp2;
291
292 37604
        ASSERT_CLI();
293
294 37604
        Lck_Lock(&dead_pools_mtx);
295 37604
        if (VRBT_EMPTY(&dead_pools)) {
296 37592
                Lck_Unlock(&dead_pools_mtx);
297 37592
                return;
298
        }
299 12
        dead = dead_pools;
300 12
        VRBT_INIT(&dead_pools);
301 12
        Lck_Unlock(&dead_pools_mtx);
302
303 24
        VRBT_FOREACH_SAFE(cp, vrb, &dead, cp2) {
304 12
                CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
305 12
                if (cp->n_kill > 0)
306 2
                        continue;
307 10
                VRBT_REMOVE(vrb, &dead, cp);
308 10
                vcp_destroy(&cp);
309 10
        }
310
311 12
        if (VRBT_EMPTY(&dead))
312 10
                return;
313
314 2
        Lck_Lock(&dead_pools_mtx);
315
        /*
316
         * The following insertion will most likely result in an
317
         * unordered tree, but in this case it does not matter
318
         * as we just want to iterate over all the elements
319
         * in the tree in order to delete them.
320
         */
321 2
        VRBT_INSERT(vrb, &dead_pools, dead.rbh_root);
322 2
        Lck_Unlock(&dead_pools_mtx);
323 37604
}
324
325
/*--------------------------------------------------------------------
326
 * Recycle a connection.
327
 */
328
329
void
330 8597
VCP_Recycle(const struct worker *wrk, struct pfd **pfdp)
331
{
332
        struct pfd *pfd;
333
        struct conn_pool *cp;
334 8597
        int i = 0;
335
336 8597
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
337 8597
        TAKE_OBJ_NOTNULL(pfd, pfdp, PFD_MAGIC);
338 8597
        cp = pfd->conn_pool;
339 8597
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
340
341 8597
        assert(pfd->state == PFD_STATE_USED);
342 8597
        assert(pfd->fd > 0);
343
344 8597
        Lck_Lock(&cp->mtx);
345 8597
        cp->n_used--;
346
347 8597
        pfd->waited->priv1 = pfd;
348 8597
        pfd->waited->fd = pfd->fd;
349 8597
        pfd->waited->idle = VTIM_real();
350 8597
        pfd->state = PFD_STATE_AVAIL;
351 8597
        pfd->waited->func = vcp_handle;
352 8597
        pfd->waited->tmo = cache_param->backend_idle_timeout;
353 8597
        if (Wait_Enter(wrk->pool->waiter, pfd->waited)) {
354 0
                cp->methods->close(pfd);
355 0
                memset(pfd, 0x33, sizeof *pfd);
356 0
                free(pfd);
357
                // XXX: stats
358 0
                pfd = NULL;
359 0
        } else {
360 8597
                VTAILQ_INSERT_HEAD(&cp->connlist, pfd, list);
361 8597
                i++;
362
        }
363
364 8597
        if (pfd != NULL)
365 8597
                cp->n_conn++;
366 8597
        Lck_Unlock(&cp->mtx);
367
368 8597
        if (i && DO_DEBUG(DBG_VTC_MODE)) {
369
                /*
370
                 * In varnishtest we do not have the luxury of using
371
                 * multiple backend connections, so whenever we end up
372
                 * in the "pending" case, take a short nap to let the
373
                 * waiter catch up and put the pfd back into circulations.
374
                 *
375
                 * In particular ESI:include related tests suffer random
376
                 * failures without this.
377
                 *
378
                 * In normal operation, the only effect is that we will
379
                 * have N+1 backend connections rather than N, which is
380
                 * entirely harmless.
381
                 */
382 8597
                (void)usleep(10000);
383 8597
        }
384 8597
}
385
386
/*--------------------------------------------------------------------
387
 * Open a new connection from pool.
388
 */
389
390
int
391 7763
VCP_Open(struct conn_pool *cp, vtim_dur tmo, VCL_IP *ap, int *err)
392
{
393
        int r;
394
        vtim_mono h;
395
396 7763
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
397 7763
        AN(err);
398
399 7763
        while (cp->holddown > 0) {
400 115
                Lck_Lock(&cp->mtx);
401 115
                if (cp->holddown == 0) {
402 0
                        Lck_Unlock(&cp->mtx);
403 0
                        break;
404
                }
405
406 115
                if (VTIM_mono() >= cp->holddown) {
407 16
                        cp->holddown = 0;
408 16
                        Lck_Unlock(&cp->mtx);
409 16
                        break;
410
                }
411
412 99
                *err = 0;
413 99
                errno = cp->holddown_errno;
414 99
                Lck_Unlock(&cp->mtx);
415 99
                return (-1);
416
        }
417
418 7664
        *err = errno = 0;
419 7664
        r = cp->methods->open(cp, tmo, ap);
420
421 7664
        if (r >= 0 && errno == 0 && cp->endpoint->preamble != NULL &&
422 45
             cp->endpoint->preamble->len > 0) {
423 135
                if (write(r, cp->endpoint->preamble->blob,
424 90
                    cp->endpoint->preamble->len) !=
425 45
                    cp->endpoint->preamble->len) {
426 0
                        *err = errno;
427 0
                        closefd(&r);
428 0
                }
429 45
        } else {
430 7619
                *err = errno;
431
        }
432
433 7664
        if (r >= 0)
434 7535
                return (r);
435
436 129
        h = 0;
437
438 129
        switch (errno) {
439
        case EACCES:
440
        case EPERM:
441 0
                h = cache_param->backend_local_error_holddown;
442 0
                break;
443
        case EADDRNOTAVAIL:
444 0
                h = cache_param->backend_local_error_holddown;
445 0
                break;
446
        case ECONNREFUSED:
447 129
                h = cache_param->backend_remote_error_holddown;
448 129
                break;
449
        case ENETUNREACH:
450 0
                h = cache_param->backend_remote_error_holddown;
451 0
                break;
452
        default:
453 0
                break;
454
        }
455
456 129
        if (h == 0)
457 0
                return (r);
458
459 129
        Lck_Lock(&cp->mtx);
460 129
        h += VTIM_mono();
461 129
        if (cp->holddown == 0 || h < cp->holddown) {
462 116
                cp->holddown = h;
463 116
                cp->holddown_errno = errno;
464 116
        }
465
466 129
        Lck_Unlock(&cp->mtx);
467
468 129
        return (r);
469 7763
}
470
471
/*--------------------------------------------------------------------
472
 * Close a connection.
473
 */
474
475
void
476 1903
VCP_Close(struct pfd **pfdp)
477
{
478
        struct pfd *pfd;
479
        struct conn_pool *cp;
480
481 1903
        TAKE_OBJ_NOTNULL(pfd, pfdp, PFD_MAGIC);
482 1903
        cp = pfd->conn_pool;
483 1903
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
484
485 1903
        assert(pfd->fd > 0);
486
487 1903
        Lck_Lock(&cp->mtx);
488 1903
        assert(pfd->state == PFD_STATE_USED || pfd->state == PFD_STATE_STOLEN);
489 1903
        cp->n_used--;
490 1903
        if (pfd->state == PFD_STATE_STOLEN) {
491 10
                (void)shutdown(pfd->fd, SHUT_RDWR);
492 10
                VTAILQ_REMOVE(&cp->connlist, pfd, list);
493 10
                pfd->state = PFD_STATE_CLEANUP;
494 10
                cp->n_kill++;
495 10
        } else {
496 1893
                assert(pfd->state == PFD_STATE_USED);
497 1893
                cp->methods->close(pfd);
498 1893
                memset(pfd, 0x44, sizeof *pfd);
499 1893
                free(pfd);
500
        }
501 1903
        Lck_Unlock(&cp->mtx);
502 1903
}
503
504
/*--------------------------------------------------------------------
505
 * Get a connection, possibly recycled
506
 */
507
508
struct pfd *
509 10660
VCP_Get(struct conn_pool *cp, vtim_dur tmo, struct worker *wrk,
510
    unsigned force_fresh, int *err)
511
{
512
        struct pfd *pfd;
513
514 10660
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
515 10660
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
516 10660
        AN(err);
517
518 10660
        *err = 0;
519 10660
        Lck_Lock(&cp->mtx);
520 10660
        pfd = VTAILQ_FIRST(&cp->connlist);
521 10660
        CHECK_OBJ_ORNULL(pfd, PFD_MAGIC);
522 10660
        if (force_fresh || pfd == NULL || pfd->state == PFD_STATE_STOLEN) {
523 6776
                pfd = NULL;
524 6776
        } else {
525 3884
                assert(pfd->conn_pool == cp);
526 3884
                assert(pfd->state == PFD_STATE_AVAIL);
527 3884
                VTAILQ_REMOVE(&cp->connlist, pfd, list);
528 3884
                VTAILQ_INSERT_TAIL(&cp->connlist, pfd, list);
529 3884
                cp->n_conn--;
530 3884
                VSC_C_main->backend_reuse++;
531 3884
                pfd->state = PFD_STATE_STOLEN;
532 3884
                pfd->cond = &wrk->cond;
533
        }
534 10660
        cp->n_used++;                   // Opening mostly works
535 10660
        Lck_Unlock(&cp->mtx);
536
537 10660
        if (pfd != NULL)
538 3884
                return (pfd);
539
540 6776
        ALLOC_OBJ(pfd, PFD_MAGIC);
541 6776
        AN(pfd);
542 6776
        INIT_OBJ(pfd->waited, WAITED_MAGIC);
543 6776
        pfd->state = PFD_STATE_USED;
544 6776
        pfd->conn_pool = cp;
545 6776
        pfd->fd = VCP_Open(cp, tmo, &pfd->addr, err);
546 6776
        if (pfd->fd < 0) {
547 155
                FREE_OBJ(pfd);
548 155
                Lck_Lock(&cp->mtx);
549 155
                cp->n_used--;           // Nope, didn't work after all.
550 155
                Lck_Unlock(&cp->mtx);
551 155
        } else
552 6621
                VSC_C_main->backend_conn++;
553
554 6776
        return (pfd);
555 10660
}
556
557
/*--------------------------------------------------------------------
558
 */
559
560
int
561 3864
VCP_Wait(struct worker *wrk, struct pfd *pfd, vtim_real when)
562
{
563
        struct conn_pool *cp;
564
        int r;
565
566 3864
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
567 3864
        CHECK_OBJ_NOTNULL(pfd, PFD_MAGIC);
568 3864
        cp = pfd->conn_pool;
569 3864
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
570 3864
        assert(pfd->cond == &wrk->cond);
571 3864
        Lck_Lock(&cp->mtx);
572 7723
        while (pfd->state == PFD_STATE_STOLEN) {
573 3864
                r = Lck_CondWaitUntil(&wrk->cond, &cp->mtx, when);
574 3864
                if (r != 0) {
575 5
                        if (r == EINTR)
576 0
                                continue;
577 5
                        assert(r == ETIMEDOUT);
578 5
                        Lck_Unlock(&cp->mtx);
579 5
                        return (1);
580
                }
581
        }
582 3859
        assert(pfd->state == PFD_STATE_USED);
583 3859
        pfd->cond = NULL;
584 3859
        Lck_Unlock(&cp->mtx);
585
586 3859
        return (0);
587 3864
}
588
589
/*--------------------------------------------------------------------
590
 */
591
592
VCL_IP
593 5
VCP_GetIp(struct pfd *pfd)
594
{
595
596 5
        CHECK_OBJ_NOTNULL(pfd, PFD_MAGIC);
597 5
        return (pfd->addr);
598
}
599
600
/*--------------------------------------------------------------------*/
601
602
static void
603 30
vcp_panic_endpoint(struct vsb *vsb, const struct vrt_endpoint *vep)
604
{
605
        char h[VTCP_ADDRBUFSIZE];
606
        char p[VTCP_PORTBUFSIZE];
607
608 30
        if (PAN_dump_struct(vsb, vep, VRT_ENDPOINT_MAGIC, "vrt_endpoint"))
609 0
                return;
610 30
        if (vep->uds_path)
611 0
                VSB_printf(vsb, "uds_path = %s,\n", vep->uds_path);
612 30
        if (vep->ipv4 && VSA_Sane(vep->ipv4)) {
613 30
                VTCP_name(vep->ipv4, h, sizeof h, p, sizeof p);
614 30
                VSB_printf(vsb, "ipv4 = %s, ", h);
615 30
                VSB_printf(vsb, "port = %s,\n", p);
616 30
        }
617 30
        if (vep->ipv6 && VSA_Sane(vep->ipv6)) {
618 0
                VTCP_name(vep->ipv6, h, sizeof h, p, sizeof p);
619 0
                VSB_printf(vsb, "ipv6 = %s, ", h);
620 0
                VSB_printf(vsb, "port = %s,\n", p);
621 0
        }
622 30
        VSB_indent(vsb, -2);
623 30
        VSB_cat(vsb, "},\n");
624 30
}
625
626
void
627 30
VCP_Panic(struct vsb *vsb, struct conn_pool *cp)
628
{
629
630 30
        if (PAN_dump_struct(vsb, cp, CONN_POOL_MAGIC, "conn_pool"))
631 0
                return;
632 30
        VSB_cat(vsb, "ident = ");
633 30
        VSB_quote(vsb, cp->ident, VSHA256_DIGEST_LENGTH, VSB_QUOTE_HEX);
634 30
        VSB_cat(vsb, ",\n");
635 30
        vcp_panic_endpoint(vsb, cp->endpoint);
636 30
        VSB_indent(vsb, -2);
637 30
        VSB_cat(vsb, "},\n");
638 30
}
639
640
/*--------------------------------------------------------------------*/
641
642
void
643 4613
VCP_Init(void)
644
{
645 4613
        Lck_New(&conn_pools_mtx, lck_conn_pool);
646 4613
        Lck_New(&dead_pools_mtx, lck_dead_pool);
647 4613
}
648
649
/**********************************************************************/
650
651
static inline int
652 7669
tmo2msec(vtim_dur tmo)
653
{
654 7669
        return ((int)floor(tmo * 1000.0));
655
}
656
657
static int v_matchproto_(cp_open_f)
658 7066
vtp_open(const struct conn_pool *cp, vtim_dur tmo, VCL_IP *ap)
659
{
660
        int s;
661
        int msec;
662
663 7066
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
664
665 7066
        msec = tmo2msec(tmo);
666 7066
        if (cache_param->prefer_ipv6) {
667 0
                *ap = cp->endpoint->ipv6;
668 0
                s = VTCP_connect(*ap, msec);
669 0
                if (s >= 0)
670 0
                        return (s);
671 0
        }
672 7066
        *ap = cp->endpoint->ipv4;
673 7066
        s = VTCP_connect(*ap, msec);
674 7066
        if (s >= 0)
675 6926
                return (s);
676 140
        if (!cache_param->prefer_ipv6) {
677 140
                *ap = cp->endpoint->ipv6;
678 140
                s = VTCP_connect(*ap, msec);
679 140
        }
680 140
        return (s);
681 7066
}
682
683
684
/*--------------------------------------------------------------------*/
685
686
static void v_matchproto_(cp_close_f)
687 6512
vtp_close(struct pfd *pfd)
688
{
689
690 6512
        CHECK_OBJ_NOTNULL(pfd, PFD_MAGIC);
691 6512
        VTCP_close(&pfd->fd);
692 6512
}
693
694
static void v_matchproto_(cp_name_f)
695 9950
vtp_local_name(const struct pfd *pfd, char *addr, unsigned alen, char *pbuf,
696
               unsigned plen)
697
{
698 9950
        CHECK_OBJ_NOTNULL(pfd, PFD_MAGIC);
699 9950
        VTCP_myname(pfd->fd, addr, alen, pbuf, plen);
700 9950
}
701
702
static void v_matchproto_(cp_name_f)
703 9950
vtp_remote_name(const struct pfd *pfd, char *addr, unsigned alen, char *pbuf,
704
                unsigned plen)
705
{
706 9950
        CHECK_OBJ_NOTNULL(pfd, PFD_MAGIC);
707 9950
        VTCP_hisname(pfd->fd, addr, alen, pbuf, plen);
708 9950
}
709
710
static const struct cp_methods vtp_methods = {
711
        .open = vtp_open,
712
        .close = vtp_close,
713
        .local_name = vtp_local_name,
714
        .remote_name = vtp_remote_name,
715
};
716
717
/*--------------------------------------------------------------------
718
 */
719
720
static int v_matchproto_(cp_open_f)
721 598
vus_open(const struct conn_pool *cp, vtim_dur tmo, VCL_IP *ap)
722
{
723
        int s;
724
        int msec;
725
726 598
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
727 598
        AN(cp->endpoint->uds_path);
728
729 598
        msec = tmo2msec(tmo);
730 598
        *ap = bogo_ip;
731 598
        s = VUS_connect(cp->endpoint->uds_path, msec);
732 598
        return (s);
733
}
734
735
static void v_matchproto_(cp_name_f)
736 1110
vus_name(const struct pfd *pfd, char *addr, unsigned alen, char *pbuf,
737
         unsigned plen)
738
{
739 1110
        (void) pfd;
740 1110
        assert(alen > strlen("0.0.0.0"));
741 1110
        assert(plen > 1);
742 1110
        strcpy(addr, "0.0.0.0");
743 1110
        strcpy(pbuf, "0");
744 1110
}
745
746
static const struct cp_methods vus_methods = {
747
        .open = vus_open,
748
        .close = vtp_close,
749
        .local_name = vus_name,
750
        .remote_name = vus_name,
751
};
752
753
/*--------------------------------------------------------------------
754
 * Reference a TCP pool given by {ip4, ip6} pair or a UDS.  Create if
755
 * it doesn't exist already.
756
 */
757
758
struct conn_pool *
759 6540
VCP_Ref(const struct vrt_endpoint *vep, const char *ident)
760
{
761
        struct conn_pool *cp, *cp2;
762
        struct VSHA256Context cx[1];
763
        unsigned char digest[VSHA256_DIGEST_LENGTH];
764
765 6540
        CHECK_OBJ_NOTNULL(vep, VRT_ENDPOINT_MAGIC);
766 6540
        AN(ident);
767 6540
        VSHA256_Init(cx);
768 6540
        VSHA256_Update(cx, ident, strlen(ident) + 1); // include \0
769 6540
        if (vep->uds_path != NULL) {
770 230
                AZ(vep->ipv4);
771 230
                AZ(vep->ipv6);
772 230
                VSHA256_Update(cx, "UDS", 4); // include \0
773 230
                VSHA256_Update(cx, vep->uds_path, strlen(vep->uds_path));
774 230
        } else {
775 6310
                assert(vep->ipv4 != NULL || vep->ipv6 != NULL);
776 6310
                if (vep->ipv4 != NULL) {
777 6295
                        assert(VSA_Sane(vep->ipv4));
778 6295
                        VSHA256_Update(cx, "IP4", 4); // include \0
779 6295
                        VSHA256_Update(cx, vep->ipv4, vsa_suckaddr_len);
780 6295
                }
781 6310
                if (vep->ipv6 != NULL) {
782 20
                        assert(VSA_Sane(vep->ipv6));
783 20
                        VSHA256_Update(cx, "IP6", 4); // include \0
784 20
                        VSHA256_Update(cx, vep->ipv6, vsa_suckaddr_len);
785 20
                }
786
        }
787 6540
        if (vep->preamble != NULL && vep->preamble->len > 0) {
788 45
                VSHA256_Update(cx, "PRE", 4); // include \0
789 45
                VSHA256_Update(cx, vep->preamble->blob, vep->preamble->len);
790 45
        }
791 6540
        VSHA256_Final(digest, cx);
792
793 6540
        ALLOC_OBJ(cp, CONN_POOL_MAGIC);
794 6540
        AN(cp);
795 6540
        cp->refcnt = 1;
796 6540
        cp->holddown = 0;
797 6540
        cp->endpoint = VRT_Endpoint_Clone(vep);
798 6540
        CHECK_OBJ_NOTNULL(cp->endpoint, VRT_ENDPOINT_MAGIC);
799 6540
        memcpy(cp->ident, digest, sizeof cp->ident);
800 6540
        if (vep->uds_path != NULL)
801 230
                cp->methods = &vus_methods;
802
        else
803 6310
                cp->methods = &vtp_methods;
804 6540
        Lck_New(&cp->mtx, lck_conn_pool);
805 6540
        VTAILQ_INIT(&cp->connlist);
806
807 6540
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
808 6540
        Lck_Lock(&conn_pools_mtx);
809 6540
        cp2 = VRBT_FIND(vrb, &conn_pools, cp);
810 6540
        if (cp2 == NULL)
811 5065
                AZ(VRBT_INSERT(vrb, &conn_pools, cp));
812
        else {
813 1475
                CHECK_OBJ(cp2, CONN_POOL_MAGIC);
814 1475
                assert(cp2->refcnt > 0);
815 1475
                cp2->refcnt++;
816
        }
817 6540
        Lck_Unlock(&conn_pools_mtx);
818
819 6540
        if (cp2 == NULL) {
820 5065
                CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
821 5065
                return (cp);
822
        }
823
824 1475
        Lck_Delete(&cp->mtx);
825 1475
        AZ(cp->n_conn);
826 1475
        AZ(cp->n_kill);
827 1475
        FREE_OBJ(cp->endpoint);
828 1475
        FREE_OBJ(cp);
829 1475
        CHECK_OBJ_NOTNULL(cp2, CONN_POOL_MAGIC);
830 1475
        return (cp2);
831 6540
}