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 656
VRBT_GENERATE_REMOVE_COLOR(vrb, conn_pool, entry, static)
110 1612
VRBT_GENERATE_REMOVE(vrb, conn_pool, entry, static)
111 61125
VRBT_GENERATE_FIND(vrb, conn_pool, entry, vcp_cmp, static)
112 8654
VRBT_GENERATE_INSERT_COLOR(vrb, conn_pool, entry, static)
113 40280
VRBT_GENERATE_INSERT_FINISH(vrb, conn_pool, entry, static)
114 49016
VRBT_GENERATE_INSERT(vrb, conn_pool, entry, vcp_cmp, static)
115
116
/*--------------------------------------------------------------------
117
 */
118
119
unsigned
120 397480
PFD_State(const struct pfd *p)
121
{
122 397480
        CHECK_OBJ_NOTNULL(p, PFD_MAGIC);
123 397480
        return (p->state);
124
}
125
126
int *
127 168114
PFD_Fd(struct pfd *p)
128
{
129 168114
        CHECK_OBJ_NOTNULL(p, PFD_MAGIC);
130 168114
        return (&(p->fd));
131
}
132
133
void
134 83600
PFD_LocalName(const struct pfd *p, char *abuf, unsigned alen, char *pbuf,
135
              unsigned plen)
136
{
137 83600
        CHECK_OBJ_NOTNULL(p, PFD_MAGIC);
138 83600
        CHECK_OBJ_NOTNULL(p->conn_pool, CONN_POOL_MAGIC);
139 83600
        p->conn_pool->methods->local_name(p, abuf, alen, pbuf, plen);
140 83600
}
141
142
void
143 83599
PFD_RemoteName(const struct pfd *p, char *abuf, unsigned alen, char *pbuf,
144
               unsigned plen)
145
{
146 83599
        CHECK_OBJ_NOTNULL(p, PFD_MAGIC);
147 83599
        CHECK_OBJ_NOTNULL(p->conn_pool, CONN_POOL_MAGIC);
148 83599
        p->conn_pool->methods->remote_name(p, abuf, alen, pbuf, plen);
149 83599
}
150
151
/*--------------------------------------------------------------------
152
 */
153
154
static inline int
155 29581
vcp_cmp(const struct conn_pool *a, const struct conn_pool *b)
156
{
157 29581
        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 67607
vcp_handle(struct waited *w, enum wait_event ev, vtim_real now)
166
{
167
        struct pfd *pfd;
168
        struct conn_pool *cp;
169
170 67607
        CHECK_OBJ_NOTNULL(w, WAITED_MAGIC);
171 67607
        CAST_OBJ_NOTNULL(pfd, w->priv1, PFD_MAGIC);
172 67607
        (void)ev;
173 67607
        (void)now;
174 67607
        CHECK_OBJ_NOTNULL(pfd->conn_pool, CONN_POOL_MAGIC);
175 67607
        cp = pfd->conn_pool;
176
177 67607
        Lck_Lock(&cp->mtx);
178
179 67607
        switch (pfd->state) {
180
        case PFD_STATE_STOLEN:
181 30800
                pfd->state = PFD_STATE_USED;
182 30800
                VTAILQ_REMOVE(&cp->connlist, pfd, list);
183 30800
                AN(pfd->cond);
184 30800
                PTOK(pthread_cond_signal(pfd->cond));
185 30800
                break;
186
        case PFD_STATE_AVAIL:
187 36647
                cp->methods->close(pfd);
188 36647
                VTAILQ_REMOVE(&cp->connlist, pfd, list);
189 36647
                cp->n_conn--;
190 36647
                FREE_OBJ(pfd);
191 36647
                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 67607
        Lck_Unlock(&cp->mtx);
202 67607
}
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 3461
VCP_Rel(struct conn_pool **cpp)
225
{
226
        struct conn_pool *cp;
227
        struct pfd *pfd, *pfd2;
228
229 3461
        TAKE_OBJ_NOTNULL(cp, cpp, CONN_POOL_MAGIC);
230
231 3461
        Lck_Lock(&conn_pools_mtx);
232 3461
        assert(cp->refcnt > 0);
233 3461
        if (--cp->refcnt > 0) {
234 2381
                Lck_Unlock(&conn_pools_mtx);
235 2381
                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 3461
}
262
263
/*--------------------------------------------------------------------
264
 * Recycle a connection.
265
 */
266
267
void
268 68365
VCP_Recycle(const struct worker *wrk, struct pfd **pfdp)
269
{
270
        struct pfd *pfd;
271
        struct conn_pool *cp;
272 68365
        int i = 0;
273
274 68365
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
275 68365
        TAKE_OBJ_NOTNULL(pfd, pfdp, PFD_MAGIC);
276 68365
        cp = pfd->conn_pool;
277 68365
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
278
279 68365
        assert(pfd->state == PFD_STATE_USED);
280 68365
        assert(pfd->fd > 0);
281
282 68365
        Lck_Lock(&cp->mtx);
283 68365
        cp->n_used--;
284
285 68365
        pfd->waited->priv1 = pfd;
286 68365
        pfd->waited->fd = pfd->fd;
287 68365
        pfd->waited->idle = VTIM_real();
288 68365
        pfd->state = PFD_STATE_AVAIL;
289 68365
        pfd->waited->func = vcp_handle;
290 68365
        pfd->waited->tmo = cache_param->backend_idle_timeout;
291 68365
        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 68365
                VTAILQ_INSERT_HEAD(&cp->connlist, pfd, list);
299 68365
                i++;
300
        }
301
302 68365
        if (pfd != NULL)
303 68365
                cp->n_conn++;
304 68365
        Lck_Unlock(&cp->mtx);
305
306 68365
        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 68365
                (void)usleep(10000);
321 68365
        }
322 68365
}
323
324
/*--------------------------------------------------------------------
325
 * Open a new connection from pool.
326
 */
327
328
int
329 61753
VCP_Open(struct conn_pool *cp, vtim_dur tmo, VCL_IP *ap, int *err)
330
{
331
        int r;
332
        vtim_mono h;
333
334 61753
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
335 61753
        AN(err);
336
337 61753
        while (cp->holddown > 0) {
338 866
                Lck_Lock(&cp->mtx);
339 866
                if (cp->holddown == 0) {
340 0
                        Lck_Unlock(&cp->mtx);
341 0
                        break;
342
                }
343
344 866
                if (VTIM_mono() >= cp->holddown) {
345 109
                        cp->holddown = 0;
346 109
                        Lck_Unlock(&cp->mtx);
347 109
                        break;
348
                }
349
350 757
                *err = 0;
351 757
                errno = cp->holddown_errno;
352 757
                Lck_Unlock(&cp->mtx);
353 757
                return (-1);
354
        }
355
356 60996
        *err = errno = 0;
357 60996
        r = cp->methods->open(cp, tmo, ap);
358
359 60996
        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 60636
                *err = errno;
369
        }
370
371 60996
        if (r >= 0)
372 60014
                return (r);
373
374 982
        h = 0;
375
376 982
        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 982
                h = cache_param->backend_remote_error_holddown;
386 982
                break;
387
        case ENETUNREACH:
388 0
                h = cache_param->backend_remote_error_holddown;
389 0
                break;
390
        default:
391 0
                break;
392
        }
393
394 982
        if (h == 0)
395 0
                return (r);
396
397 982
        Lck_Lock(&cp->mtx);
398 982
        h += VTIM_mono();
399 982
        if (cp->holddown == 0 || h < cp->holddown) {
400 884
                cp->holddown = h;
401 884
                cp->holddown_errno = errno;
402 884
        }
403
404 982
        Lck_Unlock(&cp->mtx);
405
406 982
        return (r);
407 61753
}
408
409
/*--------------------------------------------------------------------
410
 * Close a connection.
411
 */
412
413
void
414 15195
VCP_Close(struct pfd **pfdp)
415
{
416
        struct pfd *pfd;
417
        struct conn_pool *cp;
418
419 15195
        TAKE_OBJ_NOTNULL(pfd, pfdp, PFD_MAGIC);
420 15195
        cp = pfd->conn_pool;
421 15195
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
422
423 15195
        assert(pfd->fd > 0);
424
425 15195
        Lck_Lock(&cp->mtx);
426 15195
        assert(pfd->state == PFD_STATE_USED || pfd->state == PFD_STATE_STOLEN);
427 15195
        cp->n_used--;
428 15195
        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 15115
                assert(pfd->state == PFD_STATE_USED);
435 15115
                cp->methods->close(pfd);
436 15115
                memset(pfd, 0x44, sizeof *pfd);
437 15115
                free(pfd);
438
        }
439 15195
        Lck_Unlock(&cp->mtx);
440 15195
}
441
442
/*--------------------------------------------------------------------
443
 * Get a connection, possibly recycled
444
 */
445
446
struct pfd *
447 84840
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 84840
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
453 84840
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
454 84840
        AN(err);
455
456 84840
        *err = 0;
457 84840
        Lck_Lock(&cp->mtx);
458 84840
        pfd = VTAILQ_FIRST(&cp->connlist);
459 84840
        CHECK_OBJ_ORNULL(pfd, PFD_MAGIC);
460 84840
        if (force_fresh || pfd == NULL || pfd->state == PFD_STATE_STOLEN) {
461 53960
                pfd = NULL;
462 53960
        } else {
463 30880
                assert(pfd->conn_pool == cp);
464 30880
                assert(pfd->state == PFD_STATE_AVAIL);
465 30880
                VTAILQ_REMOVE(&cp->connlist, pfd, list);
466 30880
                VTAILQ_INSERT_TAIL(&cp->connlist, pfd, list);
467 30880
                cp->n_conn--;
468 30880
                VSC_C_main->backend_reuse++;
469 30880
                pfd->state = PFD_STATE_STOLEN;
470 30880
                pfd->cond = &wrk->cond;
471
        }
472 84840
        cp->n_used++;                   // Opening mostly works
473 84840
        Lck_Unlock(&cp->mtx);
474
475 84840
        if (pfd != NULL)
476 30880
                return (pfd);
477
478 53960
        ALLOC_OBJ(pfd, PFD_MAGIC);
479 53960
        AN(pfd);
480 53960
        INIT_OBJ(pfd->waited, WAITED_MAGIC);
481 53960
        pfd->state = PFD_STATE_USED;
482 53960
        pfd->conn_pool = cp;
483 53960
        pfd->fd = VCP_Open(cp, tmo, &pfd->addr, err);
484 53960
        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 52720
                VSC_C_main->backend_conn++;
491
492 53960
        return (pfd);
493 84840
}
494
495
/*--------------------------------------------------------------------
496
 */
497
498
int
499 30720
VCP_Wait(struct worker *wrk, struct pfd *pfd, vtim_real when)
500
{
501
        struct conn_pool *cp;
502
        int r;
503
504 30720
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
505 30720
        CHECK_OBJ_NOTNULL(pfd, PFD_MAGIC);
506 30720
        cp = pfd->conn_pool;
507 30720
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
508 30720
        assert(pfd->cond == &wrk->cond);
509 30720
        Lck_Lock(&cp->mtx);
510 61400
        while (pfd->state == PFD_STATE_STOLEN) {
511 30720
                r = Lck_CondWaitUntil(&wrk->cond, &cp->mtx, when);
512 30720
                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 30680
        assert(pfd->state == PFD_STATE_USED);
521 30680
        pfd->cond = NULL;
522 30680
        Lck_Unlock(&cp->mtx);
523
524 30680
        return (0);
525 30720
}
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 36676
VCP_Init(void)
582
{
583 36676
        Lck_New(&conn_pools_mtx, lck_conn_pool);
584 36676
}
585
586
/**********************************************************************/
587
588
static inline int
589 61036
tmo2msec(vtim_dur tmo)
590
{
591 61036
        return ((int)floor(tmo * 1000.0));
592
}
593
594
static int v_matchproto_(cp_open_f)
595 56237
vtp_open(const struct conn_pool *cp, vtim_dur tmo, VCL_IP *ap)
596
{
597
        int s;
598
        int msec;
599
600 56237
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
601
602 56237
        msec = tmo2msec(tmo);
603 56237
        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 56237
        *ap = cp->endpoint->ipv4;
610 56237
        s = VTCP_connect(*ap, msec);
611 56237
        if (s >= 0)
612 55159
                return (s);
613 1078
        if (!cache_param->prefer_ipv6) {
614 1078
                *ap = cp->endpoint->ipv6;
615 1078
                s = VTCP_connect(*ap, msec);
616 1078
        }
617 1078
        return (s);
618 56237
}
619
620
621
/*--------------------------------------------------------------------*/
622
623
static void v_matchproto_(cp_close_f)
624 51922
vtp_close(struct pfd *pfd)
625
{
626
627 51922
        CHECK_OBJ_NOTNULL(pfd, PFD_MAGIC);
628 51922
        VTCP_close(&pfd->fd);
629 51922
}
630
631
static void v_matchproto_(cp_name_f)
632 79160
vtp_local_name(const struct pfd *pfd, char *addr, unsigned alen, char *pbuf,
633
               unsigned plen)
634
{
635 79160
        CHECK_OBJ_NOTNULL(pfd, PFD_MAGIC);
636 79160
        VTCP_myname(pfd->fd, addr, alen, pbuf, plen);
637 79160
}
638
639
static void v_matchproto_(cp_name_f)
640 79159
vtp_remote_name(const struct pfd *pfd, char *addr, unsigned alen, char *pbuf,
641
                unsigned plen)
642
{
643 79159
        CHECK_OBJ_NOTNULL(pfd, PFD_MAGIC);
644 79159
        VTCP_hisname(pfd->fd, addr, alen, pbuf, plen);
645 79159
}
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 4759
vus_open(const struct conn_pool *cp, vtim_dur tmo, VCL_IP *ap)
659
{
660
        int s;
661
        int msec;
662
663 4759
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
664 4759
        AN(cp->endpoint->uds_path);
665
666 4759
        msec = tmo2msec(tmo);
667 4759
        *ap = bogo_ip;
668 4759
        s = VUS_connect(cp->endpoint->uds_path, msec);
669 4759
        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 51840
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 51840
        CHECK_OBJ_NOTNULL(vep, VRT_ENDPOINT_MAGIC);
703 51840
        AN(ident);
704 51840
        VSHA256_Init(cx);
705 51840
        VSHA256_Update(cx, ident, strlen(ident) + 1); // include \0
706 51840
        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 50000
                assert(vep->ipv4 != NULL || vep->ipv6 != NULL);
713 50000
                if (vep->ipv4 != NULL) {
714 49880
                        assert(VSA_Sane(vep->ipv4));
715 49880
                        VSHA256_Update(cx, "IP4", 4); // include \0
716 49880
                        VSHA256_Update(cx, vep->ipv4, vsa_suckaddr_len);
717 49880
                }
718 50000
                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 51840
        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 51840
        VSHA256_Final(digest, cx);
729
730 51840
        ALLOC_OBJ(cp, CONN_POOL_MAGIC);
731 51840
        AN(cp);
732 51840
        cp->refcnt = 1;
733 51840
        cp->holddown = 0;
734 51840
        cp->endpoint = VRT_Endpoint_Clone(vep);
735 51840
        CHECK_OBJ_NOTNULL(cp->endpoint, VRT_ENDPOINT_MAGIC);
736 51840
        memcpy(cp->ident, digest, sizeof cp->ident);
737 51840
        if (vep->uds_path != NULL)
738 1840
                cp->methods = &vus_methods;
739
        else
740 50000
                cp->methods = &vtp_methods;
741 51840
        Lck_New(&cp->mtx, lck_conn_pool);
742 51840
        VTAILQ_INIT(&cp->connlist);
743
744 51840
        CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
745 51840
        Lck_Lock(&conn_pools_mtx);
746 51840
        cp2 = VRBT_FIND(vrb, &conn_pools, cp);
747 51840
        if (cp2 == NULL)
748 40280
                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 51840
        Lck_Unlock(&conn_pools_mtx);
755
756 51840
        if (cp2 == NULL) {
757 40280
                CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
758 40280
                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 51840
}