varnish-cache/vmod/vmod_debug_obj.c
1
/*-
2
 * Copyright (c) 2013-2021 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@FreeBSD.org>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 */
30
31
#include "config.h"
32
33
#include <stdlib.h>
34
#include <string.h>
35
36
#include "cache/cache.h"
37
#include "vcl.h"
38
39
#include "vcc_debug_if.h"
40
41
// vmod_debug.c
42
extern void mylog(struct vsl_log *vsl, enum VSL_tag_e tag,
43
    const char *fmt, ...) v_printflike_(3,4);
44
45
struct xyzzy_debug_obj {
46
        unsigned                magic;
47
#define VMOD_DEBUG_OBJ_MAGIC    0xccbd9b77
48
        int                     foobar;
49
        const char              *string;
50
        const char              *number;
51
        VCL_STRING              vcl_name;
52
};
53
54
VCL_VOID
55 160
xyzzy_obj__init(VRT_CTX, struct xyzzy_debug_obj **op,
56
    const char *vcl_name, VCL_STRING s, VCL_ENUM e)
57
{
58
        struct xyzzy_debug_obj *o;
59
60 160
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
61 160
        AN(op);
62 160
        AZ(*op);
63 160
        ALLOC_OBJ(o, VMOD_DEBUG_OBJ_MAGIC);
64 160
        AN(o);
65 160
        *op = o;
66 160
        o->foobar = 42;
67 160
        o->string = s;
68 160
        o->number = e;
69 160
        o->vcl_name = vcl_name;
70 160
        AN(*op);
71 160
}
72
73
VCL_VOID v_matchproto_(td_xyzzy_obj__fini)
74 30
xyzzy_obj__fini(struct xyzzy_debug_obj **op)
75
{
76
        struct xyzzy_debug_obj *o;
77
78 30
        TAKE_OBJ_NOTNULL(o, op, VMOD_DEBUG_OBJ_MAGIC);
79 30
        FREE_OBJ(o);
80 30
}
81
82
VCL_VOID v_matchproto_(td_xyzzy_obj_enum)
83 10
xyzzy_obj_enum(VRT_CTX, struct xyzzy_debug_obj *o, VCL_ENUM e)
84
{
85
86 10
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
87 10
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
88 10
        assert(!strcmp(e, "martin"));
89 10
}
90
91
VCL_VOID v_matchproto_(td_xyzzy_obj_enum)
92 10
xyzzy_obj_obj(VRT_CTX, struct xyzzy_debug_obj *o)
93
{
94
95 10
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
96 10
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
97 10
}
98
99
VCL_STRING v_matchproto_()
100 10
xyzzy_obj_foo(VRT_CTX, struct xyzzy_debug_obj *o, VCL_STRING s)
101
{
102
103 10
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
104 10
        (void)s;
105 10
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
106 10
        assert(o->foobar == 42);
107 10
        return ("BOO");
108
}
109
110
VCL_TIME v_matchproto_()
111 10
xyzzy_obj_date(VRT_CTX, struct xyzzy_debug_obj *o)
112
{
113
114 10
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
115 10
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
116 10
        assert(o->foobar == 42);
117 10
        return (21.4);
118
}
119
120
VCL_STRING v_matchproto_()
121 60
xyzzy_obj_string(VRT_CTX, struct xyzzy_debug_obj *o)
122
{
123
124 60
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
125 60
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
126 60
        assert(o->foobar == 42);
127 60
        return (o->string);
128
}
129
130
VCL_STRING v_matchproto_()
131 60
xyzzy_obj_number(VRT_CTX, struct xyzzy_debug_obj *o)
132
{
133
134 60
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
135 60
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
136 60
        assert(o->foobar == 42);
137 60
        return (o->number);
138
}
139
140
VCL_VOID v_matchproto_()
141 10
xyzzy_obj_test_priv_call(VRT_CTX,
142
    struct xyzzy_debug_obj *o, struct vmod_priv *priv)
143
{
144 10
        (void)o;
145 10
        xyzzy_test_priv_call(ctx, priv);
146 10
}
147
148
VCL_VOID v_matchproto_()
149 10
xyzzy_obj_test_priv_vcl(VRT_CTX,
150
    struct xyzzy_debug_obj *o, struct vmod_priv *priv)
151
{
152 10
        (void)o;
153 10
        xyzzy_test_priv_vcl(ctx, priv);
154 10
}
155
156
#define PRIV_FINI(name)                                         \
157
static void v_matchproto_(vmod_priv_fini_f)                             \
158
obj_priv_ ## name ## _fini(VRT_CTX, void *ptr)                          \
159
{                                                                       \
160
        const char * const fmt = "obj_priv_" #name "_fini(%p)";         \
161
                                                                        \
162
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
163
        AN(ptr);                                                        \
164
        mylog(ctx->vsl, SLT_Debug, fmt, ptr);                           \
165
}                                                                       \
166
                                                                        \
167
static const struct vmod_priv_methods                                   \
168
xyzzy_obj_test_priv_ ## name ## _methods[1] = {{                        \
169
                .magic = VMOD_PRIV_METHODS_MAGIC,                       \
170
                .type = "debug_obj_test_priv_" #name,                   \
171
                .fini = obj_priv_ ## name ## _fini                      \
172
        }};
173 130
PRIV_FINI(task)
174 40
PRIV_FINI(top)
175
#undef PRIV_FINI
176
177
VCL_STRING v_matchproto_()
178 520
xyzzy_obj_test_priv_task(VRT_CTX, struct xyzzy_debug_obj *o, VCL_STRING s)
179
{
180
        struct vmod_priv *p;
181
        struct vsl_log *vsl;
182
183 520
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
184
185 520
        if (ctx->method & VCL_MET_TASK_H)
186 70
                vsl = NULL;
187
        else
188 450
                vsl = ctx->vsl;
189
190 520
        if (s == NULL || *s == '\0') {
191 340
                p = VRT_priv_task_get(ctx, o);
192 340
                if (p == NULL) {
193 360
                        mylog(vsl, SLT_Debug, "%s.priv_task() = NULL",
194 180
                            o->vcl_name);
195 180
                        return ("");
196
                }
197 160
                assert(p->methods == xyzzy_obj_test_priv_task_methods);
198 320
                mylog(vsl, SLT_Debug,
199
                    "%s.priv_task() = %p .priv = %p (\"%s\")",
200 160
                    o->vcl_name, p, p->priv, (char *)p->priv);
201 160
                return (p->priv);
202
        }
203
204 180
        p = VRT_priv_task(ctx, o);
205
206 180
        if (p == NULL) {
207 0
                mylog(vsl, SLT_Debug, "%s.priv_task() = NULL [err]",
208 0
                    o->vcl_name);
209 0
                VRT_fail(ctx, "no priv task - out of ws?");
210 0
                return ("");
211
        }
212
213 360
        mylog(vsl, SLT_Debug,
214
            "%s.priv_task() = %p .priv = %p (\"%s\") [%s]",
215 180
            o->vcl_name, p, s, s, p->priv ? "update" : "new");
216
217 180
        if (p->priv == NULL)
218 130
                p->methods = xyzzy_obj_test_priv_task_methods;
219
        else
220 50
                assert(p->methods == xyzzy_obj_test_priv_task_methods);
221
222
        /* minimum scope of s and priv is the task - no need to copy */
223 180
        p->priv = TRUST_ME(s);
224
225 180
        return (p->priv);
226 520
}
227
228
VCL_STRING v_matchproto_()
229 170
xyzzy_obj_test_priv_top(VRT_CTX, struct xyzzy_debug_obj *o, VCL_STRING s)
230
{
231
        struct vmod_priv *p;
232
        struct req *req;
233
        struct ws *ws;
234
235 170
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
236
237 170
        req = ctx->req;
238 170
        if (req == NULL) {
239 20
                VRT_fail(ctx, "%s.priv_top() can only be used "
240 10
                    "in client VCL context", o->vcl_name);
241 10
                return ("");
242
        }
243 160
        CHECK_OBJ(req, REQ_MAGIC);
244
245 160
        if (s == NULL || *s == '\0') {
246 120
                p = VRT_priv_top_get(ctx, o);
247 120
                if (p == NULL) {
248 60
                        VSLb(ctx->vsl, SLT_Debug, "%s.priv_top() = NULL",
249 30
                            o->vcl_name);
250 30
                        return ("");
251
                }
252 90
                assert(p->methods == xyzzy_obj_test_priv_top_methods);
253 180
                VSLb(ctx->vsl, SLT_Debug,
254
                    "%s.priv_top() = %p .priv = %p (\"%s\")",
255 90
                     o->vcl_name, p, p->priv, (char *)p->priv);
256 90
                return (p->priv);
257
        }
258
259 40
        p = VRT_priv_top(ctx, o);
260 40
        if (p == NULL)
261 0
                VSLb(ctx->vsl, SLT_Debug, "%s.priv_top() = NULL [err]",
262 0
                    o->vcl_name);
263
264 40
        CHECK_OBJ_NOTNULL(req->top, REQTOP_MAGIC);
265 40
        req = req->top->topreq;
266 40
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
267 40
        ws = req->ws;
268
269
        /* copy to top req's workspace if need to */
270 40
        if (ctx->ws != ws && WS_Allocated(ctx->ws, s, -1))
271 10
                s = WS_Copy(ws, s, -1);
272
273 40
        if (p == NULL || s == NULL) {
274 0
                VRT_fail(ctx, "out of ws?");
275 0
                return ("");
276
        }
277
278 80
        VSLb(ctx->vsl, SLT_Debug,
279
            "%s.priv_top() = %p .priv = %p (\"%s\") [%s]",
280 40
            o->vcl_name, p, s, s, p->priv ? "update" : "new");
281
282 40
        if (p->priv == NULL)
283 40
                p->methods = xyzzy_obj_test_priv_top_methods;
284
        else
285 0
                assert(p->methods == xyzzy_obj_test_priv_top_methods);
286
287 40
        p->priv = TRUST_ME(s);
288
289 40
        return (p->priv);
290 170
}
291
292
/* ----------------------------------------------------------------------------
293
 * obj_opt (optional arguments and privs)
294
 */
295
struct xyzzy_debug_obj_opt {
296
        unsigned                        magic;
297
#define VMOD_DEBUG_OBJ_OPT_MAGIC        0xccbd9b78
298
        char                            *name;
299
        struct VARGS(obj_opt_meth_opt)  args;
300
        void                            *freeptr;
301
};
302
303
VCL_VOID v_matchproto_()
304 30
xyzzy_obj_opt__init(VRT_CTX,
305
    struct xyzzy_debug_obj_opt **op, const char *vcl_name,
306
    struct VARGS(obj_opt__init) *args)
307
{
308
        struct xyzzy_debug_obj_opt *o;
309
310 30
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
311 30
        AN(args);
312
313 30
        AN(args->arg1); // priv_call
314 30
        AN(args->arg2); // priv_vcl
315 30
        AN(args->arg3); // priv_task
316 30
        assert(args->arg1 != args->arg2);
317 30
        assert(args->arg2 != args->arg3);
318
319 30
        if (args->valid_s)
320 10
                AN(args->s);
321 30
        (void)args->valid_b;
322 30
        (void)args->b;
323
324 30
        AN(op);
325 30
        AZ(*op);
326 30
        ALLOC_OBJ(o, VMOD_DEBUG_OBJ_OPT_MAGIC);
327 30
        AN(o);
328 30
        *op = o;
329 30
        REPLACE(o->name, vcl_name);
330 30
        memcpy(&o->args, args, sizeof o->args);
331 30
        if (args->valid_s) {
332 10
                REPLACE(o->freeptr, args->s);
333 10
                o->args.s = o->freeptr;
334 10
        }
335 30
}
336
337
VCL_VOID v_matchproto_()
338 0
xyzzy_obj_opt__fini(struct xyzzy_debug_obj_opt **op)
339
{
340
        struct xyzzy_debug_obj_opt *o;
341
342 0
        TAKE_OBJ_NOTNULL(o, op, VMOD_DEBUG_OBJ_OPT_MAGIC);
343
344 0
        REPLACE(o->name, NULL);
345 0
        if (o->freeptr) {
346 0
                AN(o->args.valid_s);
347 0
                REPLACE(o->freeptr, NULL);
348 0
        }
349 0
        FREE_OBJ(o);
350 0
}
351
352
VCL_STRING v_matchproto_()
353 30
xyzzy_obj_opt_meth_opt(VRT_CTX,
354
    struct xyzzy_debug_obj_opt *o,
355
    struct VARGS(obj_opt_meth_opt) *args)
356
{
357 30
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
358 30
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_OPT_MAGIC);
359
360 30
        AN(args);
361 30
        AN(args->arg1); // priv_call
362 30
        AN(args->arg2); // priv_vcl
363 30
        AN(args->arg3); // priv_task
364 30
        assert(args->arg1 != args->arg2);
365 30
        assert(args->arg2 != args->arg3);
366
367 60
        return (WS_Printf(ctx->ws,
368
            "obj %s obj_s %s obj_b %s met_s %s met_b %s",
369 30
            o->name,
370 30
            (o->args.valid_s ? o->args.s : "*undef*"),
371 30
            (o->args.valid_b
372 10
                        ? (o->args.b ? "true" : "false" )
373
                        : "*undef*"),
374 30
            (args->valid_s ? args->s : "*undef*"),
375 30
            (args->valid_b
376 10
                        ? (args->b ? "true" : "false" )
377
                        : "*undef*")
378
        ));
379
}