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