varnish-cache/vmod/vmod_debug_obj.c
0
/*-
1
 * Copyright (c) 2013-2021 Varnish Software AS
2
 * All rights reserved.
3
 *
4
 * Author: Poul-Henning Kamp <phk@FreeBSD.org>
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
30
#include "config.h"
31
32
#include <stdlib.h>
33
#include <string.h>
34
35
#include "cache/cache.h"
36
#include "vcl.h"
37
38
#include "vcc_debug_if.h"
39
40
// vmod_debug.c
41
extern void mylog(struct vsl_log *vsl, enum VSL_tag_e tag,
42
    const char *fmt, ...) v_printflike_(3,4);
43
44
struct xyzzy_debug_obj {
45
        unsigned                magic;
46
#define VMOD_DEBUG_OBJ_MAGIC    0xccbd9b77
47
        int                     foobar;
48
        const char              *string;
49
        const char              *number;
50
        VCL_STRING              vcl_name;
51
};
52
53
VCL_VOID
54 76
xyzzy_obj__init(VRT_CTX, struct xyzzy_debug_obj **op,
55
    const char *vcl_name, VCL_STRING s, VCL_ENUM e)
56
{
57
        struct xyzzy_debug_obj *o;
58
59 76
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
60 76
        AN(op);
61 76
        AZ(*op);
62
63 76
        if (! strcmp(s, "fail")) {
64 12
                VRT_fail(ctx, "failing as requested");
65 12
        }
66 76
        ALLOC_OBJ(o, VMOD_DEBUG_OBJ_MAGIC);
67 76
        AN(o);
68 76
        *op = o;
69 76
        o->foobar = 42;
70 76
        o->string = s;
71 76
        o->number = e;
72 76
        o->vcl_name = vcl_name;
73 76
        AN(*op);
74 76
}
75
76
VCL_VOID v_matchproto_(td_xyzzy_obj__fini)
77 24
xyzzy_obj__fini(struct xyzzy_debug_obj **op)
78
{
79
        struct xyzzy_debug_obj *o;
80
81 24
        TAKE_OBJ_NOTNULL(o, op, VMOD_DEBUG_OBJ_MAGIC);
82 24
        FREE_OBJ(o);
83 24
}
84
85
VCL_VOID v_matchproto_(td_xyzzy_obj_enum)
86 4
xyzzy_obj_enum(VRT_CTX, struct xyzzy_debug_obj *o, VCL_ENUM e)
87
{
88
89 4
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
90 4
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
91 4
        assert(!strcmp(e, "martin"));
92 4
}
93
94
VCL_VOID v_matchproto_(td_xyzzy_obj_enum)
95 4
xyzzy_obj_obj(VRT_CTX, struct xyzzy_debug_obj *o)
96
{
97
98 4
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
99 4
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
100 4
}
101
102
VCL_STRING v_matchproto_()
103 8
xyzzy_obj_foo(VRT_CTX, struct xyzzy_debug_obj *o, VCL_STRING s)
104
{
105
106 8
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
107 8
        (void)s;
108 8
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
109 8
        assert(o->foobar == 42);
110 8
        return ("BOO");
111
}
112
113
VCL_TIME v_matchproto_()
114 4
xyzzy_obj_date(VRT_CTX, struct xyzzy_debug_obj *o)
115
{
116
117 4
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
118 4
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
119 4
        assert(o->foobar == 42);
120 4
        return (21.4);
121
}
122
123
VCL_STRING v_matchproto_()
124 24
xyzzy_obj_string(VRT_CTX, struct xyzzy_debug_obj *o)
125
{
126
127 24
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
128 24
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
129 24
        assert(o->foobar == 42);
130 24
        return (o->string);
131
}
132
133
VCL_STRING v_matchproto_()
134 24
xyzzy_obj_number(VRT_CTX, struct xyzzy_debug_obj *o)
135
{
136
137 24
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
138 24
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
139 24
        assert(o->foobar == 42);
140 24
        return (o->number);
141
}
142
143
VCL_VOID v_matchproto_()
144 4
xyzzy_obj_test_priv_call(VRT_CTX,
145
    struct xyzzy_debug_obj *o, struct vmod_priv *priv)
146
{
147 4
        (void)o;
148 4
        xyzzy_test_priv_call(ctx, priv);
149 4
}
150
151
VCL_VOID v_matchproto_()
152 4
xyzzy_obj_test_priv_vcl(VRT_CTX,
153
    struct xyzzy_debug_obj *o, struct vmod_priv *priv)
154
{
155 4
        (void)o;
156 4
        xyzzy_test_priv_vcl(ctx, priv);
157 4
}
158
159
#define PRIV_FINI(name)                                         \
160
static void v_matchproto_(vmod_priv_fini_f)                             \
161
obj_priv_ ## name ## _fini(VRT_CTX, void *ptr)                          \
162
{                                                                       \
163
        const char * const fmt = "obj_priv_" #name "_fini(%p)";         \
164
                                                                        \
165
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
166
        AN(ptr);                                                        \
167
        mylog(ctx->vsl, SLT_Debug, fmt, ptr);                           \
168
}                                                                       \
169
                                                                        \
170
static const struct vmod_priv_methods                                   \
171
xyzzy_obj_test_priv_ ## name ## _methods[1] = {{                        \
172
                .magic = VMOD_PRIV_METHODS_MAGIC,                       \
173
                .type = "debug_obj_test_priv_" #name,                   \
174
                .fini = obj_priv_ ## name ## _fini                      \
175
        }};
176 52
PRIV_FINI(task)
177 12
PRIV_FINI(top)
178
#undef PRIV_FINI
179
180
VCL_STRING v_matchproto_()
181 208
xyzzy_obj_test_priv_task(VRT_CTX, struct xyzzy_debug_obj *o, VCL_STRING s)
182
{
183
        struct vmod_priv *p;
184
        struct vsl_log *vsl;
185
186 208
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
187
188 208
        if (ctx->method & VCL_MET_TASK_H)
189 28
                vsl = NULL;
190
        else
191 180
                vsl = ctx->vsl;
192
193 208
        if (s == NULL || *s == '\0') {
194 136
                p = VRT_priv_task_get(ctx, o);
195 136
                if (p == NULL) {
196 144
                        mylog(vsl, SLT_Debug, "%s.priv_task() = NULL",
197 72
                            o->vcl_name);
198 72
                        return ("");
199
                }
200 64
                assert(p->methods == xyzzy_obj_test_priv_task_methods);
201 128
                mylog(vsl, SLT_Debug,
202
                    "%s.priv_task() = %p .priv = %p (\"%s\")",
203 64
                    o->vcl_name, p, p->priv, (char *)p->priv);
204 64
                return (p->priv);
205
        }
206
207 72
        p = VRT_priv_task(ctx, o);
208
209 72
        if (p == NULL) {
210 0
                mylog(vsl, SLT_Debug, "%s.priv_task() = NULL [err]",
211 0
                    o->vcl_name);
212 0
                VRT_fail(ctx, "no priv task - out of ws?");
213 0
                return ("");
214
        }
215
216 144
        mylog(vsl, SLT_Debug,
217
            "%s.priv_task() = %p .priv = %p (\"%s\") [%s]",
218 72
            o->vcl_name, p, s, s, p->priv ? "update" : "new");
219
220 72
        if (p->priv == NULL)
221 52
                p->methods = xyzzy_obj_test_priv_task_methods;
222
        else
223 20
                assert(p->methods == xyzzy_obj_test_priv_task_methods);
224
225
        /* minimum scope of s and priv is the task - no need to copy */
226 72
        p->priv = TRUST_ME(s);
227
228 72
        return (p->priv);
229 208
}
230
231
VCL_STRING v_matchproto_()
232 52
xyzzy_obj_test_priv_top(VRT_CTX, struct xyzzy_debug_obj *o, VCL_STRING s)
233
{
234
        struct vmod_priv *p;
235
        struct req *req;
236
        struct ws *ws;
237
238 52
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
239
240 52
        req = ctx->req;
241 52
        if (req == NULL) {
242 0
                VRT_fail(ctx, "%s.priv_top() can only be used "
243 0
                    "in client VCL context", o->vcl_name);
244 0
                return ("");
245
        }
246 52
        CHECK_OBJ(req, REQ_MAGIC);
247
248 52
        if (s == NULL || *s == '\0') {
249 40
                p = VRT_priv_top_get(ctx, o);
250 40
                if (p == NULL) {
251 16
                        VSLb(ctx->vsl, SLT_Debug, "%s.priv_top() = NULL",
252 8
                            o->vcl_name);
253 8
                        return ("");
254
                }
255 32
                assert(p->methods == xyzzy_obj_test_priv_top_methods);
256 64
                VSLb(ctx->vsl, SLT_Debug,
257
                    "%s.priv_top() = %p .priv = %p (\"%s\")",
258 32
                     o->vcl_name, p, p->priv, (char *)p->priv);
259 32
                return (p->priv);
260
        }
261
262 12
        p = VRT_priv_top(ctx, o);
263 12
        if (p == NULL)
264 0
                VSLb(ctx->vsl, SLT_Debug, "%s.priv_top() = NULL [err]",
265 0
                    o->vcl_name);
266
267 12
        CHECK_OBJ_NOTNULL(req->top, REQTOP_MAGIC);
268 12
        req = req->top->topreq;
269 12
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
270 12
        ws = req->ws;
271
272
        /* copy to top req's workspace if need to */
273 12
        if (ctx->ws != ws && WS_Allocated(ctx->ws, s, -1))
274 4
                s = WS_Copy(ws, s, -1);
275
276 12
        if (p == NULL || s == NULL) {
277 0
                VRT_fail(ctx, "out of ws?");
278 0
                return ("");
279
        }
280
281 24
        VSLb(ctx->vsl, SLT_Debug,
282
            "%s.priv_top() = %p .priv = %p (\"%s\") [%s]",
283 12
            o->vcl_name, p, s, s, p->priv ? "update" : "new");
284
285 12
        if (p->priv == NULL)
286 12
                p->methods = xyzzy_obj_test_priv_top_methods;
287
        else
288 0
                assert(p->methods == xyzzy_obj_test_priv_top_methods);
289
290 12
        p->priv = TRUST_ME(s);
291
292 12
        return (p->priv);
293 52
}
294
295
/* ----------------------------------------------------------------------------
296
 * obj_opt (optional arguments and privs)
297
 */
298
struct xyzzy_debug_obj_opt {
299
        unsigned                        magic;
300
#define VMOD_DEBUG_OBJ_OPT_MAGIC        0xccbd9b78
301
        char                            *name;
302
        struct VARGS(obj_opt_meth_opt)  args;
303
        void                            *freeptr;
304
};
305
306
VCL_VOID v_matchproto_()
307 12
xyzzy_obj_opt__init(VRT_CTX,
308
    struct xyzzy_debug_obj_opt **op, const char *vcl_name,
309
    struct VARGS(obj_opt__init) *args)
310
{
311
        struct xyzzy_debug_obj_opt *o;
312
313 12
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
314 12
        AN(args);
315
316 12
        AN(args->arg1); // priv_call
317 12
        AN(args->arg2); // priv_vcl
318 12
        AN(args->arg3); // priv_task
319 12
        assert(args->arg1 != args->arg2);
320 12
        assert(args->arg2 != args->arg3);
321
322 12
        if (args->valid_s)
323 4
                AN(args->s);
324 12
        (void)args->valid_b;
325 12
        (void)args->b;
326
327 12
        AN(op);
328 12
        AZ(*op);
329 12
        ALLOC_OBJ(o, VMOD_DEBUG_OBJ_OPT_MAGIC);
330 12
        AN(o);
331 12
        *op = o;
332 12
        REPLACE(o->name, vcl_name);
333 12
        memcpy(&o->args, args, sizeof o->args);
334 12
        if (args->valid_s) {
335 4
                REPLACE(o->freeptr, args->s);
336 4
                o->args.s = o->freeptr;
337 4
        }
338 12
}
339
340
VCL_VOID v_matchproto_()
341 0
xyzzy_obj_opt__fini(struct xyzzy_debug_obj_opt **op)
342
{
343
        struct xyzzy_debug_obj_opt *o;
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
}
354
355
VCL_STRING v_matchproto_()
356 12
xyzzy_obj_opt_meth_opt(VRT_CTX,
357
    struct xyzzy_debug_obj_opt *o,
358
    struct VARGS(obj_opt_meth_opt) *args)
359
{
360 12
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
361 12
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_OPT_MAGIC);
362
363 12
        AN(args);
364 12
        AN(args->arg1); // priv_call
365 12
        AN(args->arg2); // priv_vcl
366 12
        AN(args->arg3); // priv_task
367 12
        assert(args->arg1 != args->arg2);
368 12
        assert(args->arg2 != args->arg3);
369
370 24
        return (WS_Printf(ctx->ws,
371
            "obj %s obj_s %s obj_b %s met_s %s met_b %s",
372 12
            o->name,
373 12
            (o->args.valid_s ? o->args.s : "*undef*"),
374 12
            (o->args.valid_b
375 4
                        ? (o->args.b ? "true" : "false" )
376
                        : "*undef*"),
377 12
            (args->valid_s ? args->s : "*undef*"),
378 12
            (args->valid_b
379 4
                        ? (args->b ? "true" : "false" )
380
                        : "*undef*")
381
        ));
382
}