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
108
static VRBT_HEAD(vrb, conn_pool) conn_pools = VRBT_INITIALIZER(&conn_pools);
109 659
VRBT_GENERATE_REMOVE_COLOR(vrb, conn_pool, entry, static)
110 1602
VRBT_GENERATE_REMOVE(vrb, conn_pool, entry, static)
111 61068
VRBT_GENERATE_FIND(vrb, conn_pool, entry, vcp_cmp, static)
112 8668
VRBT_GENERATE_INSERT_COLOR(vrb, conn_pool, entry, static)
113 40240
VRBT_GENERATE_INSERT_FINISH(vrb, conn_pool, entry, static)
114 48978
VRBT_GENERATE_INSERT(vrb, conn_pool, entry, vcp_cmp, static)
115
116
/*--------------------------------------------------------------------
117
 */
118
119
unsigned
120 397290
PFD_State(const struct pfd *p)
121
{
122 397290
        CHECK_OBJ_NOTNULL(p, PFD_MAGIC);
123 397290
        return (p->state);
124
}
125
126
int *
127 168035
PFD_Fd(struct pfd *p)
128
{
129 168035
        CHECK_OBJ_NOTNULL(p, PFD_MAGIC);
130 168035
        return (&(p->fd));
131
}
132
133
void
134 83560
PFD_LocalName(const struct pfd *p, char *abuf, unsigned alen, char *pbuf,
135
              unsigned plen)
136
{
137 83560
        CHECK_OBJ_NOTNULL(p, PFD_MAGIC);
138 83560
        CHECK_OBJ_NOTNULL(p->conn_pool, CONN_POOL_MAGIC);
139 83560
        p->conn_pool->methods->local_name(p, abuf, alen, pbuf, plen);
140 83560
}
141
142
void
143 83560
PFD_RemoteName(const struct pfd *p, char *abuf, unsigned alen, char *pbuf,
144
               unsigned plen)
145
{
146 83560
        CHECK_OBJ_NOTNULL(p, PFD_MAGIC);
147 83560
        CHECK_OBJ_NOTNULL(p->conn_pool, CONN_POOL_MAGIC);
148 83560
        p->conn_pool->methods->remote_name(p, abuf, alen, pbuf, plen);
149 83560
}
150
151
/*--------------------------------------------------------------------
152
 */
153
154
static inline int
155 29566
vcp_cmp(const struct conn_pool *a, const struct conn_pool *b)
156
{
157 29566
        return (memcmp(a->ident, b->ident, sizeof b->ident));
158
}
159
160
/*--------------------------------------------------------------------
161
 * Waiter-handler
162
 */
163
164
static void  v_matchproto_(waiter_handle_f)
165 67561
vcp_handle(struct waited *w, enum wait_event ev, vtim_real now)
166
{
167
        struct pfd *pfd;
168
        struct conn_pool *cp;
169
170 67561
        CHECK_OBJ_NOTNULL(w, WAITED_MAGIC);
171 67561
        CAST_OBJ_NOTNULL(pfd, w->priv1, PFD_MAGIC);
172 67561
        (void)ev;
173 67561
        (void)now;
174 67561
        CHECK_OBJ_NOTNULL(pfd->conn_pool, CONN_POOL_MAGIC);
175 67561
        cp = pfd->conn_pool;
176
177 67561
        Lck_Lock(&cp->mtx);
178
179 67561
        switch (pfd->state) {
180
        case PFD_STATE_STOLEN:
181 30797
                pfd->state = PFD_STATE_USED;
182 30797
                VTAILQ_REMOVE(&cp->connlist, pfd, list);
183 30797
                AN(pfd->cond);
184 30797
                PTOK(pthread_cond_signal(pfd->cond));
185 30797
                break;
186
        case PFD_STATE_AVAIL:
187 36604
                cp->methods->close(pfd);
188 36604
                VTAILQ_REMOVE(&cp->connlist, pfd, list);
189 36604
                cp->n_conn--;
190 36604
                FREE_OBJ(pfd);
191 36604
                break;
192
        case PFD_STATE_CLEANUP:
193 160
                cp->methods->close(pfd);
194 160
                cp->n_kill--;
195 160
                memset(pfd, 0x11, sizeof *pfd);
196 160
                free(pfd);
197 160
                break;
198
        default:
199 0
                WRONG("Wrong pfd state");
200 0
        }
201 67561
        Lck_Unlock(&cp->mtx);
202 67561
}
203
204
205
/*--------------------------------------------------------------------
206
 */
207
208
void
209 1480
VCP_AddRef(struct conn_pool *cp)
210
{
211 1480
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
212
213 1480
        Lck_Lock(&conn_pools_mtx);
214 1480
        assert(cp->refcnt > 0);
215 1480
        cp->refcnt++;
216 1480
        Lck_Unlock(&conn_pools_mtx);
217 1480
}
218
219
/*--------------------------------------------------------------------
220
 * Release Conn pool, destroy if last reference.
221
 */
222
223
void
224 3465
VCP_Rel(struct conn_pool **cpp)
225
{
226
        struct conn_pool *cp;
227
        struct pfd *pfd, *pfd2;
228
229 3465
        TAKE_OBJ_NOTNULL(cp, cpp, CONN_POOL_MAGIC);
230
231 3465
        Lck_Lock(&conn_pools_mtx);
232 3465
        assert(cp->refcnt > 0);
233 3465
        if (--cp->refcnt > 0) {
234 2385
                Lck_Unlock(&conn_pools_mtx);
235 2385
                return;
236
        }
237 1080
        AZ(cp->n_used);
238 1080
        VRBT_REMOVE(vrb, &conn_pools, cp);
239 1080
        Lck_Unlock(&conn_pools_mtx);
240
241 1080
        Lck_Lock(&cp->mtx);
242 1160
        VTAILQ_FOREACH_SAFE(pfd, &cp->connlist, list, pfd2) {
243 80
                VTAILQ_REMOVE(&cp->connlist, pfd, list);
244 80
                cp->n_conn--;
245 80
                assert(pfd->state == PFD_STATE_AVAIL);
246 80
                pfd->state = PFD_STATE_CLEANUP;
247 80
                (void)shutdown(pfd->fd, SHUT_RDWR);
248 80
                cp->n_kill++;
249 80
        }
250 1160
        while (cp->n_kill) {
251 80
                Lck_Unlock(&cp->mtx);
252 80
                (void)usleep(20000);
253 80
                Lck_Lock(&cp->mtx);
254
        }
255 1080
        Lck_Unlock(&cp->mtx);
256 1080
        Lck_Delete(&cp->mtx);
257 1080
        AZ(cp->n_conn);
258 1080
        AZ(cp->n_kill);
259 1080
        free(cp->endpoint);
260 1080
        FREE_OBJ(cp);
261 3465
}
262
263
/*--------------------------------------------------------------------
264
 * Recycle a connection.
265
 */
266
267
void
268 68316
VCP_Recycle(const struct worker *wrk, struct pfd **pfdp)
269
{
270
        struct pfd *pfd;
271
        struct conn_pool *cp;
272 68316
        int i = 0;
273
274 68316
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
275 68316
        TAKE_OBJ_NOTNULL(pfd, pfdp, PFD_MAGIC);
276 68316
        cp = pfd->conn_pool;
277 68316
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
278
279 68316
        assert(pfd->state == PFD_STATE_USED);
280 68316
        assert(pfd->fd > 0);
281
282 68316
        Lck_Lock(&cp->mtx);
283 68316
        cp->n_used--;
284
285 68316
        pfd->waited->priv1 = pfd;
286 68316
        pfd->waited->fd = pfd->fd;
287 68316
        pfd->waited->idle = VTIM_real();
288 68316
        pfd->state = PFD_STATE_AVAIL;
289 68316
        pfd->waited->func = vcp_handle;
290 68316
        pfd->waited->tmo = cache_param->backend_idle_timeout;
291 68316
        if (Wait_Enter(wrk->pool->waiter, pfd->waited)) {
292 0
                cp->methods->close(pfd);
293 0
                memset(pfd, 0x33, sizeof *pfd);
294 0
                free(pfd);
295
                // XXX: stats
296 0
                pfd = NULL;
297 0
        } else {
298 68316
                VTAILQ_INSERT_HEAD(&cp->connlist, pfd, list);
299 68316
                i++;
300
        }
301
302 68316
        if (pfd != NULL)
303 68315
                cp->n_conn++;
304 68316
        Lck_Unlock(&cp->mtx);
305
306 68316
        if (i && DO_DEBUG(DBG_VTC_MODE)) {
307
                /*
308
                 * In varnishtest we do not have the luxury of using
309
                 * multiple backend connections, so whenever we end up
310
                 * in the "pending" case, take a short nap to let the
311
                 * waiter catch up and put the pfd back into circulations.
312
                 *
313
                 * In particular ESI:include related tests suffer random
314
                 * failures without this.
315
                 *
316
                 * In normal operation, the only effect is that we will
317
                 * have N+1 backend connections rather than N, which is
318
                 * entirely harmless.
319
                 */
320 68316
                (void)usleep(10000);
321 68316
        }
322 68316
}
323
324
/*--------------------------------------------------------------------
325
 * Open a new connection from pool.
326
 */
327
328
int
329 61712
VCP_Open(struct conn_pool *cp, vtim_dur tmo, VCL_IP *ap, int *err)
330
{
331
        int r;
332
        vtim_mono h;
333
334 61712
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
335 61712
        AN(err);
336
337 61712
        while (cp->holddown > 0) {
338 853
                Lck_Lock(&cp->mtx);
339 853
                if (cp->holddown == 0) {
340 0
                        Lck_Unlock(&cp->mtx);
341 0
                        break;
342
                }
343
344 853
                if (VTIM_mono() >= cp->holddown) {
345 104
                        cp->holddown = 0;
346 104
                        Lck_Unlock(&cp->mtx);
347 104
                        break;
348
                }
349
350 749
                *err = 0;
351 749
                errno = cp->holddown_errno;
352 749
                Lck_Unlock(&cp->mtx);
353 749
                return (-1);
354
        }
355
356 60963
        *err = errno = 0;
357 60963
        r = cp->methods->open(cp, tmo, ap);
358
359 60963
        if (r >= 0 && errno == 0 && cp->endpoint->preamble != NULL &&
360 360
             cp->endpoint->preamble->len > 0) {
361 1080
                if (write(r, cp->endpoint->preamble->blob,
362 720
                    cp->endpoint->preamble->len) !=
363 360
                    cp->endpoint->preamble->len) {
364 0
                        *err = errno;
365 0
                        closefd(&r);
366 0
                }
367 360
        } else {
368 60603
                *err = errno;
369
        }
370
371 60963
        if (r >= 0)
372 59983
                return (r);
373
374 980
        h = 0;
375
376 980
        switch (errno) {
377
        case EACCES:
378
        case EPERM:
379 0
                h = cache_param->backend_local_error_holddown;
380 0
                break;
381
        case EADDRNOTAVAIL:
382 0
                h = cache_param->backend_local_error_holddown;
383 0
                break;
384
        case ECONNREFUSED:
385 980
                h = cache_param->backend_remote_error_holddown;
386 980
                break;
387
        case ENETUNREACH:
388 0
                h = cache_param->backend_remote_error_holddown;
389 0
                break;
390
        default:
391 0
                break;
392
        }
393
394 980
        if (h == 0)
395 0
                return (r);
396
397 980
        Lck_Lock(&cp->mtx);
398 980
        h += VTIM_mono();
399 980
        if (cp->holddown == 0 || h < cp->holddown) {
400 878
                cp->holddown = h;
401 878
                cp->holddown_errno = errno;
402 878
        }
403
404 980
        Lck_Unlock(&cp->mtx);
405
406 980
        return (r);
407 61712
}
408
409
/*--------------------------------------------------------------------
410
 * Close a connection.
411
 */
412
413
void
414 15204
VCP_Close(struct pfd **pfdp)
415
{
416
        struct pfd *pfd;
417
        struct conn_pool *cp;
418
419 15204
        TAKE_OBJ_NOTNULL(pfd, pfdp, PFD_MAGIC);
420 15204
        cp = pfd->conn_pool;
421 15204
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
422
423 15204
        assert(pfd->fd > 0);
424
425 15204
        Lck_Lock(&cp->mtx);
426 15204
        assert(pfd->state == PFD_STATE_USED || pfd->state == PFD_STATE_STOLEN);
427 15204
        cp->n_used--;
428 15204
        if (pfd->state == PFD_STATE_STOLEN) {
429 80
                (void)shutdown(pfd->fd, SHUT_RDWR);
430 80
                VTAILQ_REMOVE(&cp->connlist, pfd, list);
431 80
                pfd->state = PFD_STATE_CLEANUP;
432 80
                cp->n_kill++;
433 80
        } else {
434 15124
                assert(pfd->state == PFD_STATE_USED);
435 15124
                cp->methods->close(pfd);
436 15124
                memset(pfd, 0x44, sizeof *pfd);
437 15124
                free(pfd);
438
        }
439 15204
        Lck_Unlock(&cp->mtx);
440 15204
}
441
442
/*--------------------------------------------------------------------
443
 * Get a connection, possibly recycled
444
 */
445
446
struct pfd *
447 84800
VCP_Get(struct conn_pool *cp, vtim_dur tmo, struct worker *wrk,
448
    unsigned force_fresh, int *err)
449
{
450
        struct pfd *pfd;
451
452 84800
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
453 84800
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
454 84800
        AN(err);
455
456 84800
        *err = 0;
457 84800
        Lck_Lock(&cp->mtx);
458 84800
        pfd = VTAILQ_FIRST(&cp->connlist);
459 84800
        CHECK_OBJ_ORNULL(pfd, PFD_MAGIC);
460 84800
        if (force_fresh || pfd == NULL || pfd->state == PFD_STATE_STOLEN) {
461 53923
                pfd = NULL;
462 53923
        } else {
463 30877
                assert(pfd->conn_pool == cp);
464 30877
                assert(pfd->state == PFD_STATE_AVAIL);
465 30877
                VTAILQ_REMOVE(&cp->connlist, pfd, list);
466 30877
                VTAILQ_INSERT_TAIL(&cp->connlist, pfd, list);
467 30877
                cp->n_conn--;
468 30877
                VSC_C_main->backend_reuse++;
469 30877
                pfd->state = PFD_STATE_STOLEN;
470 30877
                pfd->cond = &wrk->cond;
471
        }
472 84800
        cp->n_used++;                   // Opening mostly works
473 84800
        Lck_Unlock(&cp->mtx);
474
475 84800
        if (pfd != NULL)
476 30877
                return (pfd);
477
478 53923
        ALLOC_OBJ(pfd, PFD_MAGIC);
479 53923
        AN(pfd);
480 53923
        INIT_OBJ(pfd->waited, WAITED_MAGIC);
481 53923
        pfd->state = PFD_STATE_USED;
482 53923
        pfd->conn_pool = cp;
483 53923
        pfd->fd = VCP_Open(cp, tmo, &pfd->addr, err);
484 53923
        if (pfd->fd < 0) {
485 1240
                FREE_OBJ(pfd);
486 1240
                Lck_Lock(&cp->mtx);
487 1240
                cp->n_used--;           // Nope, didn't work after all.
488 1240
                Lck_Unlock(&cp->mtx);
489 1240
        } else
490 52683
                VSC_C_main->backend_conn++;
491
492 53923
        return (pfd);
493 84800
}
494
495
/*--------------------------------------------------------------------
496
 */
497
498
int
499 30717
VCP_Wait(struct worker *wrk, struct pfd *pfd, vtim_real when)
500
{
501
        struct conn_pool *cp;
502
        int r;
503
504 30717
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
505 30717
        CHECK_OBJ_NOTNULL(pfd, PFD_MAGIC);
506 30717
        cp = pfd->conn_pool;
507 30717
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
508 30717
        assert(pfd->cond == &wrk->cond);
509 30717
        Lck_Lock(&cp->mtx);
510 61394
        while (pfd->state == PFD_STATE_STOLEN) {
511 30717
                r = Lck_CondWaitUntil(&wrk->cond, &cp->mtx, when);
512 30717
                if (r != 0) {
513 40
                        if (r == EINTR)
514 0
                                continue;
515 40
                        assert(r == ETIMEDOUT);
516 40
                        Lck_Unlock(&cp->mtx);
517 40
                        return (1);
518
                }
519
        }
520 30677
        assert(pfd->state == PFD_STATE_USED);
521 30677
        pfd->cond = NULL;
522 30677
        Lck_Unlock(&cp->mtx);
523
524 30677
        return (0);
525 30717
}
526
527
/*--------------------------------------------------------------------
528
 */
529
530
VCL_IP
531 40
VCP_GetIp(struct pfd *pfd)
532
{
533
534 40
        CHECK_OBJ_NOTNULL(pfd, PFD_MAGIC);
535 40
        return (pfd->addr);
536
}
537
538
/*--------------------------------------------------------------------*/
539
540
static void
541 240
vcp_panic_endpoint(struct vsb *vsb, const struct vrt_endpoint *vep)
542
{
543
        char h[VTCP_ADDRBUFSIZE];
544
        char p[VTCP_PORTBUFSIZE];
545
546 240
        if (PAN_dump_struct(vsb, vep, VRT_ENDPOINT_MAGIC, "vrt_endpoint"))
547 0
                return;
548 240
        if (vep->uds_path)
549 0
                VSB_printf(vsb, "uds_path = %s,\n", vep->uds_path);
550 240
        if (vep->ipv4 && VSA_Sane(vep->ipv4)) {
551 240
                VTCP_name(vep->ipv4, h, sizeof h, p, sizeof p);
552 240
                VSB_printf(vsb, "ipv4 = %s, ", h);
553 240
                VSB_printf(vsb, "port = %s,\n", p);
554 240
        }
555 240
        if (vep->ipv6 && VSA_Sane(vep->ipv6)) {
556 0
                VTCP_name(vep->ipv6, h, sizeof h, p, sizeof p);
557 0
                VSB_printf(vsb, "ipv6 = %s, ", h);
558 0
                VSB_printf(vsb, "port = %s,\n", p);
559 0
        }
560 240
        VSB_indent(vsb, -2);
561 240
        VSB_cat(vsb, "},\n");
562 240
}
563
564
void
565 240
VCP_Panic(struct vsb *vsb, struct conn_pool *cp)
566
{
567
568 240
        if (PAN_dump_struct(vsb, cp, CONN_POOL_MAGIC, "conn_pool"))
569 0
                return;
570 240
        VSB_cat(vsb, "ident = ");
571 240
        VSB_quote(vsb, cp->ident, VSHA256_DIGEST_LENGTH, VSB_QUOTE_HEX);
572 240
        VSB_cat(vsb, ",\n");
573 240
        vcp_panic_endpoint(vsb, cp->endpoint);
574 240
        VSB_indent(vsb, -2);
575 240
        VSB_cat(vsb, "},\n");
576 240
}
577
578
/*--------------------------------------------------------------------*/
579
580
void
581 36629
VCP_Init(void)
582
{
583 36629
        Lck_New(&conn_pools_mtx, lck_conn_pool);
584 36629
}
585
586
/**********************************************************************/
587
588
static inline int
589 61003
tmo2msec(vtim_dur tmo)
590
{
591 61003
        return ((int)floor(tmo * 1000.0));
592
}
593
594
static int v_matchproto_(cp_open_f)
595 56201
vtp_open(const struct conn_pool *cp, vtim_dur tmo, VCL_IP *ap)
596
{
597
        int s;
598
        int msec;
599
600 56201
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
601
602 56201
        msec = tmo2msec(tmo);
603 56201
        if (cache_param->prefer_ipv6) {
604 0
                *ap = cp->endpoint->ipv6;
605 0
                s = VTCP_connect(*ap, msec);
606 0
                if (s >= 0)
607 0
                        return (s);
608 0
        }
609 56201
        *ap = cp->endpoint->ipv4;
610 56201
        s = VTCP_connect(*ap, msec);
611 56201
        if (s >= 0)
612 55126
                return (s);
613 1075
        if (!cache_param->prefer_ipv6) {
614 1075
                *ap = cp->endpoint->ipv6;
615 1075
                s = VTCP_connect(*ap, msec);
616 1075
        }
617 1075
        return (s);
618 56201
}
619
620
621
/*--------------------------------------------------------------------*/
622
623
static void v_matchproto_(cp_close_f)
624 51886
vtp_close(struct pfd *pfd)
625
{
626
627 51886
        CHECK_OBJ_NOTNULL(pfd, PFD_MAGIC);
628 51886
        VTCP_close(&pfd->fd);
629 51886
}
630
631
static void v_matchproto_(cp_name_f)
632 79120
vtp_local_name(const struct pfd *pfd, char *addr, unsigned alen, char *pbuf,
633
               unsigned plen)
634
{
635 79120
        CHECK_OBJ_NOTNULL(pfd, PFD_MAGIC);
636 79120
        VTCP_myname(pfd->fd, addr, alen, pbuf, plen);
637 79120
}
638
639
static void v_matchproto_(cp_name_f)
640 79120
vtp_remote_name(const struct pfd *pfd, char *addr, unsigned alen, char *pbuf,
641
                unsigned plen)
642
{
643 79120
        CHECK_OBJ_NOTNULL(pfd, PFD_MAGIC);
644 79120
        VTCP_hisname(pfd->fd, addr, alen, pbuf, plen);
645 79120
}
646
647
static const struct cp_methods vtp_methods = {
648
        .open = vtp_open,
649
        .close = vtp_close,
650
        .local_name = vtp_local_name,
651
        .remote_name = vtp_remote_name,
652
};
653
654
/*--------------------------------------------------------------------
655
 */
656
657
static int v_matchproto_(cp_open_f)
658 4761
vus_open(const struct conn_pool *cp, vtim_dur tmo, VCL_IP *ap)
659
{
660
        int s;
661
        int msec;
662
663 4761
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
664 4761
        AN(cp->endpoint->uds_path);
665
666 4761
        msec = tmo2msec(tmo);
667 4761
        *ap = bogo_ip;
668 4761
        s = VUS_connect(cp->endpoint->uds_path, msec);
669 4761
        return (s);
670
}
671
672
static void v_matchproto_(cp_name_f)
673 8880
vus_name(const struct pfd *pfd, char *addr, unsigned alen, char *pbuf,
674
         unsigned plen)
675
{
676 8880
        (void) pfd;
677 8880
        assert(alen > strlen("0.0.0.0"));
678 8880
        assert(plen > 1);
679 8880
        strcpy(addr, "0.0.0.0");
680 8880
        strcpy(pbuf, "0");
681 8880
}
682
683
static const struct cp_methods vus_methods = {
684
        .open = vus_open,
685
        .close = vtp_close,
686
        .local_name = vus_name,
687
        .remote_name = vus_name,
688
};
689
690
/*--------------------------------------------------------------------
691
 * Reference a TCP pool given by {ip4, ip6} pair or a UDS.  Create if
692
 * it doesn't exist already.
693
 */
694
695
struct conn_pool *
696 51800
VCP_Ref(const struct vrt_endpoint *vep, const char *ident)
697
{
698
        struct conn_pool *cp, *cp2;
699
        struct VSHA256Context cx[1];
700
        unsigned char digest[VSHA256_DIGEST_LENGTH];
701
702 51800
        CHECK_OBJ_NOTNULL(vep, VRT_ENDPOINT_MAGIC);
703 51800
        AN(ident);
704 51800
        VSHA256_Init(cx);
705 51800
        VSHA256_Update(cx, ident, strlen(ident) + 1); // include \0
706 51800
        if (vep->uds_path != NULL) {
707 1840
                AZ(vep->ipv4);
708 1840
                AZ(vep->ipv6);
709 1840
                VSHA256_Update(cx, "UDS", 4); // include \0
710 1840
                VSHA256_Update(cx, vep->uds_path, strlen(vep->uds_path));
711 1840
        } else {
712 49960
                assert(vep->ipv4 != NULL || vep->ipv6 != NULL);
713 49960
                if (vep->ipv4 != NULL) {
714 49840
                        assert(VSA_Sane(vep->ipv4));
715 49840
                        VSHA256_Update(cx, "IP4", 4); // include \0
716 49840
                        VSHA256_Update(cx, vep->ipv4, vsa_suckaddr_len);
717 49840
                }
718 49960
                if (vep->ipv6 != NULL) {
719 160
                        assert(VSA_Sane(vep->ipv6));
720 160
                        VSHA256_Update(cx, "IP6", 4); // include \0
721 160
                        VSHA256_Update(cx, vep->ipv6, vsa_suckaddr_len);
722 160
                }
723
        }
724 51800
        if (vep->preamble != NULL && vep->preamble->len > 0) {
725 360
                VSHA256_Update(cx, "PRE", 4); // include \0
726 360
                VSHA256_Update(cx, vep->preamble->blob, vep->preamble->len);
727 360
        }
728 51800
        VSHA256_Final(digest, cx);
729
730 51800
        ALLOC_OBJ(cp, CONN_POOL_MAGIC);
731 51800
        AN(cp);
732 51800
        cp->refcnt = 1;
733 51800
        cp->holddown = 0;
734 51800
        cp->endpoint = VRT_Endpoint_Clone(vep);
735 51800
        CHECK_OBJ_NOTNULL(cp->endpoint, VRT_ENDPOINT_MAGIC);
736 51800
        memcpy(cp->ident, digest, sizeof cp->ident);
737 51800
        if (vep->uds_path != NULL)
738 1840
                cp->methods = &vus_methods;
739
        else
740 49960
                cp->methods = &vtp_methods;
741 51800
        Lck_New(&cp->mtx, lck_conn_pool);
742 51800
        VTAILQ_INIT(&cp->connlist);
743
744 51800
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
745 51800
        Lck_Lock(&conn_pools_mtx);
746 51800
        cp2 = VRBT_FIND(vrb, &conn_pools, cp);
747 51800
        if (cp2 == NULL)
748 40240
                AZ(VRBT_INSERT(vrb, &conn_pools, cp));
749
        else {
750 11560
                CHECK_OBJ(cp2, CONN_POOL_MAGIC);
751 11560
                assert(cp2->refcnt > 0);
752 11560
                cp2->refcnt++;
753
        }
754 51800
        Lck_Unlock(&conn_pools_mtx);
755
756 51800
        if (cp2 == NULL) {
757 40240
                CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
758 40240
                return (cp);
759
        }
760
761 11560
        Lck_Delete(&cp->mtx);
762 11560
        AZ(cp->n_conn);
763 11560
        AZ(cp->n_kill);
764 11560
        FREE_OBJ(cp->endpoint);
765 11560
        FREE_OBJ(cp);
766 11560
        CHECK_OBJ_NOTNULL(cp2, CONN_POOL_MAGIC);
767 11560
        return (cp2);
768 51800
}