varnish-cache/lib/libvmod_debug/vmod_debug_dyn.c
1
/*-
2
 * Copyright (c) 2015 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Dridi Boukelmoune <dridi@varnish-software.com>
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
20
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 * SUCH DAMAGE.
27
 */
28
29
#include "config.h"
30
31
#include <netdb.h>
32
#include <stdlib.h>
33
#include <string.h>
34
#include <sys/socket.h>
35
36
#include "cache/cache.h"
37
#include "cache/cache_director.h"
38
39
#include "vsa.h"
40
#include "vcc_if.h"
41
42
struct xyzzy_debug_dyn {
43
        unsigned                magic;
44
#define VMOD_DEBUG_DYN_MAGIC    0x9b77ccbd
45
        pthread_mutex_t         mtx;
46
        char                    *vcl_name;
47
        struct director         *dir;
48
};
49
50
static void
51 13
dyn_dir_init(VRT_CTX, struct xyzzy_debug_dyn *dyn,
52
    VCL_STRING addr, VCL_STRING port)
53
{
54 13
        struct addrinfo hints, *res = NULL;
55
        struct suckaddr *sa;
56
        struct director *dir, *dir2;
57
        struct vrt_backend vrt;
58
59 13
        CHECK_OBJ_NOTNULL(dyn, VMOD_DEBUG_DYN_MAGIC);
60 13
        XXXAN(addr);
61 13
        XXXAN(port);
62
63 13
        INIT_OBJ(&vrt, VRT_BACKEND_MAGIC);
64 13
        vrt.port = port;
65 13
        vrt.vcl_name = dyn->vcl_name;
66 13
        vrt.hosthdr = addr;
67
68 13
        memset(&hints, 0, sizeof(hints));
69 13
        hints.ai_family = AF_UNSPEC;
70 13
        hints.ai_socktype = SOCK_STREAM;
71 13
        AZ(getaddrinfo(addr, port, &hints, &res));
72 13
        XXXAZ(res->ai_next);
73
74 13
        sa = VSA_Malloc(res->ai_addr, res->ai_addrlen);
75 13
        AN(sa);
76 13
        if (VSA_Get_Proto(sa) == AF_INET) {
77 13
                vrt.ipv4_addr = addr;
78 13
                vrt.ipv4_suckaddr = sa;
79 0
        } else if (VSA_Get_Proto(sa) == AF_INET6) {
80 0
                vrt.ipv6_addr = addr;
81 0
                vrt.ipv6_suckaddr = sa;
82
        } else
83 0
                WRONG("Wrong proto family");
84
85 13
        freeaddrinfo(res);
86
87 13
        dir = VRT_new_backend(ctx, &vrt);
88 13
        AN(dir);
89
90
        /*
91
         * NB: A real dynamic backend should not replace the previous
92
         * instance if the new one is identical.  We do it here because
93
         * the d* tests requires a replacement.
94
         */
95 13
        AZ(pthread_mutex_lock(&dyn->mtx));
96 13
        dir2 = dyn->dir;
97 13
        dyn->dir = dir;
98 13
        AZ(pthread_mutex_unlock(&dyn->mtx));
99
100 13
        if (dir2 != NULL)
101 5
                VRT_delete_backend(ctx, &dir2);
102
103 13
        free(sa);
104 13
}
105
106
VCL_VOID
107 9
xyzzy_dyn__init(VRT_CTX, struct xyzzy_debug_dyn **dynp,
108
    const char *vcl_name, VCL_STRING addr, VCL_STRING port)
109
{
110
        struct xyzzy_debug_dyn *dyn;
111
112 9
        ASSERT_CLI();
113 9
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
114 9
        AN(dynp);
115 9
        AZ(*dynp);
116 9
        AN(vcl_name);
117
118 9
        if (*addr == '\0' || *port == '\0') {
119 1
                AN(ctx->handling);
120 1
                AZ(*ctx->handling);
121 1
                VRT_fail(ctx, "Missing dynamic backend address or port");
122 10
                return;
123
        }
124
125 8
        ALLOC_OBJ(dyn, VMOD_DEBUG_DYN_MAGIC);
126 8
        AN(dyn);
127 8
        REPLACE(dyn->vcl_name, vcl_name);
128
129 8
        AZ(pthread_mutex_init(&dyn->mtx, NULL));
130
131 8
        dyn_dir_init(ctx, dyn, addr, port);
132 8
        XXXAN(dyn->dir);
133 8
        *dynp = dyn;
134
}
135
136
VCL_VOID
137 2
xyzzy_dyn__fini(struct xyzzy_debug_dyn **dynp)
138
{
139
        struct xyzzy_debug_dyn *dyn;
140
141 2
        AN(dynp);
142 2
        if (*dynp == NULL)
143 3
                return; /* failed initialization */
144
145 1
        CAST_OBJ_NOTNULL(dyn, *dynp, VMOD_DEBUG_DYN_MAGIC);
146
        /* at this point all backends will be deleted by the vcl */
147 1
        free(dyn->vcl_name);
148 1
        AZ(pthread_mutex_destroy(&dyn->mtx));
149 1
        FREE_OBJ(dyn);
150 1
        *dynp = NULL;
151
}
152
153
VCL_BACKEND v_matchproto_()
154 13
xyzzy_dyn_backend(VRT_CTX, struct xyzzy_debug_dyn *dyn)
155
{
156 13
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
157 13
        CHECK_OBJ_NOTNULL(dyn, VMOD_DEBUG_DYN_MAGIC);
158 13
        AN(dyn->dir);
159 13
        return (dyn->dir);
160
}
161
162
VCL_VOID
163 5
xyzzy_dyn_refresh(VRT_CTX, struct xyzzy_debug_dyn *dyn,
164
    VCL_STRING addr, VCL_STRING port)
165
{
166 5
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
167 5
        CHECK_OBJ_NOTNULL(dyn, VMOD_DEBUG_DYN_MAGIC);
168 5
        dyn_dir_init(ctx, dyn, addr, port);
169 5
}