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 336
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 336
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
61 336
        AN(op);
62 336
        AZ(*op);
63 336
        ALLOC_OBJ(o, VMOD_DEBUG_OBJ_MAGIC);
64 336
        AN(o);
65 336
        *op = o;
66 336
        o->foobar = 42;
67 336
        o->string = s;
68 336
        o->number = e;
69 336
        o->vcl_name = vcl_name;
70 336
        AN(*op);
71 336
}
72
73
VCL_VOID v_matchproto_(td_xyzzy_obj__fini)
74 42
xyzzy_obj__fini(struct xyzzy_debug_obj **op)
75
{
76
        struct xyzzy_debug_obj *o;
77
78 42
        TAKE_OBJ_NOTNULL(o, op, VMOD_DEBUG_OBJ_MAGIC);
79 42
        FREE_OBJ(o);
80 42
}
81
82
VCL_VOID v_matchproto_(td_xyzzy_obj_enum)
83 21
xyzzy_obj_enum(VRT_CTX, struct xyzzy_debug_obj *o, VCL_ENUM e)
84
{
85
86 21
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
87 21
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
88 21
        assert(!strcmp(e, "martin"));
89 21
}
90
91
VCL_VOID v_matchproto_(td_xyzzy_obj_enum)
92 21
xyzzy_obj_obj(VRT_CTX, struct xyzzy_debug_obj *o)
93
{
94
95 21
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
96 21
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
97 21
}
98
99
VCL_STRING v_matchproto_()
100 21
xyzzy_obj_foo(VRT_CTX, struct xyzzy_debug_obj *o, VCL_STRING s)
101
{
102
103 21
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
104 21
        (void)s;
105 21
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
106 21
        assert(o->foobar == 42);
107 21
        return ("BOO");
108
}
109
110
VCL_TIME v_matchproto_()
111 21
xyzzy_obj_date(VRT_CTX, struct xyzzy_debug_obj *o)
112
{
113
114 21
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
115 21
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
116 21
        assert(o->foobar == 42);
117 21
        return (21.4);
118
}
119
120
VCL_STRING v_matchproto_()
121 126
xyzzy_obj_string(VRT_CTX, struct xyzzy_debug_obj *o)
122
{
123
124 126
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
125 126
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
126 126
        assert(o->foobar == 42);
127 126
        return (o->string);
128
}
129
130
VCL_STRING v_matchproto_()
131 126
xyzzy_obj_number(VRT_CTX, struct xyzzy_debug_obj *o)
132
{
133
134 126
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
135 126
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
136 126
        assert(o->foobar == 42);
137 126
        return (o->number);
138
}
139
140
VCL_VOID v_matchproto_()
141 21
xyzzy_obj_test_priv_call(VRT_CTX,
142
    struct xyzzy_debug_obj *o, struct vmod_priv *priv)
143
{
144 21
        (void)o;
145 21
        xyzzy_test_priv_call(ctx, priv);
146 21
}
147
148
VCL_VOID v_matchproto_()
149 21
xyzzy_obj_test_priv_vcl(VRT_CTX,
150
    struct xyzzy_debug_obj *o, struct vmod_priv *priv)
151
{
152 21
        (void)o;
153 21
        xyzzy_test_priv_vcl(ctx, priv);
154 21
}
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 273
PRIV_FINI(task)
174 84
PRIV_FINI(top)
175
#undef PRIV_FINI
176
177
VCL_STRING v_matchproto_()
178 1092
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 1092
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
184
185 1092
        if (ctx->method & VCL_MET_TASK_H)
186 147
                vsl = NULL;
187
        else
188 945
                vsl = ctx->vsl;
189
190 1092
        if (s == NULL || *s == '\0') {
191 714
                p = VRT_priv_task_get(ctx, o);
192 714
                if (p == NULL) {
193 756
                        mylog(vsl, SLT_Debug, "%s.priv_task() = NULL",
194 378
                            o->vcl_name);
195 378
                        return ("");
196
                }
197 336
                assert(p->methods == xyzzy_obj_test_priv_task_methods);
198 672
                mylog(vsl, SLT_Debug,
199
                    "%s.priv_task() = %p .priv = %p (\"%s\")",
200 336
                    o->vcl_name, p, p->priv, (char *)p->priv);
201 336
                return (p->priv);
202
        }
203
204 378
        p = VRT_priv_task(ctx, o);
205
206 378
        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 756
        mylog(vsl, SLT_Debug,
214
            "%s.priv_task() = %p .priv = %p (\"%s\") [%s]",
215 378
            o->vcl_name, p, s, s, p->priv ? "update" : "new");
216
217 378
        if (p->priv == NULL)
218 273
                p->methods = xyzzy_obj_test_priv_task_methods;
219
        else
220 105
                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 378
        p->priv = TRUST_ME(s);
224
225 378
        return (p->priv);
226 1092
}
227
228
VCL_STRING v_matchproto_()
229 357
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 357
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
236
237 357
        req = ctx->req;
238 357
        if (req == NULL) {
239 42
                VRT_fail(ctx, "%s.priv_top() can only be used "
240 21
                    "in client VCL context", o->vcl_name);
241 21
                return ("");
242
        }
243 336
        CHECK_OBJ(req, REQ_MAGIC);
244
245 336
        if (s == NULL || *s == '\0') {
246 252
                p = VRT_priv_top_get(ctx, o);
247 252
                if (p == NULL) {
248 126
                        VSLb(ctx->vsl, SLT_Debug, "%s.priv_top() = NULL",
249 63
                            o->vcl_name);
250 63
                        return ("");
251
                }
252 189
                assert(p->methods == xyzzy_obj_test_priv_top_methods);
253 378
                VSLb(ctx->vsl, SLT_Debug,
254
                    "%s.priv_top() = %p .priv = %p (\"%s\")",
255 189
                     o->vcl_name, p, p->priv, (char *)p->priv);
256 189
                return (p->priv);
257
        }
258
259 84
        p = VRT_priv_top(ctx, o);
260 84
        if (p == NULL)
261 0
                VSLb(ctx->vsl, SLT_Debug, "%s.priv_top() = NULL [err]",
262 0
                    o->vcl_name);
263
264 84
        CHECK_OBJ_NOTNULL(req->top, REQTOP_MAGIC);
265 84
        req = req->top->topreq;
266 84
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
267 84
        ws = req->ws;
268
269
        /* copy to top req's workspace if need to */
270 84
        if (ctx->ws != ws && WS_Inside(ctx->ws, s, NULL))
271 21
                s = WS_Copy(ws, s, -1);
272
273 84
        if (p == NULL || s == NULL) {
274 0
                VRT_fail(ctx, "out of ws?");
275 0
                return ("");
276
        }
277
278 168
        VSLb(ctx->vsl, SLT_Debug,
279
            "%s.priv_top() = %p .priv = %p (\"%s\") [%s]",
280 84
            o->vcl_name, p, s, s, p->priv ? "update" : "new");
281
282 84
        if (p->priv == NULL)
283 84
                p->methods = xyzzy_obj_test_priv_top_methods;
284
        else
285 0
                assert(p->methods == xyzzy_obj_test_priv_top_methods);
286
287 84
        p->priv = TRUST_ME(s);
288
289 84
        return (p->priv);
290 357
}
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 63
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 63
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
311 63
        AN(args);
312
313 63
        AN(args->arg1); // priv_call
314 63
        AN(args->arg2); // priv_vcl
315 63
        AN(args->arg3); // priv_task
316 63
        assert(args->arg1 != args->arg2);
317 63
        assert(args->arg2 != args->arg3);
318
319 63
        if (args->valid_s)
320 21
                AN(args->s);
321 63
        (void)args->valid_b;
322 63
        (void)args->b;
323
324 63
        AN(op);
325 63
        AZ(*op);
326 63
        ALLOC_OBJ(o, VMOD_DEBUG_OBJ_OPT_MAGIC);
327 63
        AN(o);
328 63
        *op = o;
329 63
        REPLACE(o->name, vcl_name);
330 63
        memcpy(&o->args, args, sizeof o->args);
331 63
        if (args->valid_s) {
332 21
                REPLACE(o->freeptr, args->s);
333 21
                o->args.s = o->freeptr;
334 21
        }
335 63
}
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
        AN(op);
343 0
        AN(*op);
344
345 0
        TAKE_OBJ_NOTNULL(o, op, VMOD_DEBUG_OBJ_OPT_MAGIC);
346
347 0
        REPLACE(o->name, NULL);
348 0
        if (o->freeptr) {
349 0
                AN(o->args.valid_s);
350 0
                REPLACE(o->freeptr, NULL);
351 0
        }
352 0
        FREE_OBJ(o);
353 0
        AZ(o);
354 0
}
355
356
VCL_STRING v_matchproto_()
357 63
xyzzy_obj_opt_meth_opt(VRT_CTX,
358
    struct xyzzy_debug_obj_opt *o,
359
    struct VARGS(obj_opt_meth_opt) *args)
360
{
361 63
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
362 63
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_OPT_MAGIC);
363
364 63
        AN(args);
365 63
        AN(args->arg1); // priv_call
366 63
        AN(args->arg2); // priv_vcl
367 63
        AN(args->arg3); // priv_task
368 63
        assert(args->arg1 != args->arg2);
369 63
        assert(args->arg2 != args->arg3);
370
371 126
        return (WS_Printf(ctx->ws,
372
            "obj %s obj_s %s obj_b %s met_s %s met_b %s",
373 63
            o->name,
374 63
            (o->args.valid_s ? o->args.s : "*undef*"),
375 63
            (o->args.valid_b
376 21
                        ? (o->args.b ? "true" : "false" )
377
                        : "*undef*"),
378 63
            (args->valid_s ? args->s : "*undef*"),
379 63
            (args->valid_b
380 21
                        ? (args->b ? "true" : "false" )
381
                        : "*undef*")
382
        ));
383
}