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