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