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 760
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 760
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
60 760
        AN(op);
61 760
        AZ(*op);
62
63 760
        if (! strcmp(s, "fail")) {
64 120
                VRT_fail(ctx, "failing as requested");
65 120
        }
66 760
        ALLOC_OBJ(o, VMOD_DEBUG_OBJ_MAGIC);
67 760
        AN(o);
68 760
        *op = o;
69 760
        o->foobar = 42;
70 760
        o->string = s;
71 760
        o->number = e;
72 760
        o->vcl_name = vcl_name;
73 760
        AN(*op);
74 760
}
75
76
VCL_VOID v_matchproto_(td_xyzzy_obj__fini)
77 240
xyzzy_obj__fini(struct xyzzy_debug_obj **op)
78
{
79
        struct xyzzy_debug_obj *o;
80
81 240
        TAKE_OBJ_NOTNULL(o, op, VMOD_DEBUG_OBJ_MAGIC);
82 240
        FREE_OBJ(o);
83 240
}
84
85
VCL_VOID v_matchproto_(td_xyzzy_obj_enum)
86 40
xyzzy_obj_enum(VRT_CTX, struct xyzzy_debug_obj *o, VCL_ENUM e)
87
{
88
89 40
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
90 40
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
91 40
        assert(!strcmp(e, "martin"));
92 40
}
93
94
VCL_VOID v_matchproto_(td_xyzzy_obj_enum)
95 40
xyzzy_obj_obj(VRT_CTX, struct xyzzy_debug_obj *o)
96
{
97
98 40
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
99 40
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
100 40
}
101
102
VCL_STRING v_matchproto_()
103 80
xyzzy_obj_foo(VRT_CTX, struct xyzzy_debug_obj *o, VCL_STRING s)
104
{
105
106 80
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
107 80
        (void)s;
108 80
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
109 80
        assert(o->foobar == 42);
110 80
        return ("BOO");
111
}
112
113
VCL_TIME v_matchproto_()
114 40
xyzzy_obj_date(VRT_CTX, struct xyzzy_debug_obj *o)
115
{
116
117 40
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
118 40
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
119 40
        assert(o->foobar == 42);
120 40
        return (21.4);
121
}
122
123
VCL_STRING v_matchproto_()
124 240
xyzzy_obj_string(VRT_CTX, struct xyzzy_debug_obj *o)
125
{
126
127 240
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
128 240
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
129 240
        assert(o->foobar == 42);
130 240
        return (o->string);
131
}
132
133
VCL_STRING v_matchproto_()
134 240
xyzzy_obj_number(VRT_CTX, struct xyzzy_debug_obj *o)
135
{
136
137 240
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
138 240
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_MAGIC);
139 240
        assert(o->foobar == 42);
140 240
        return (o->number);
141
}
142
143
VCL_VOID v_matchproto_()
144 40
xyzzy_obj_test_priv_call(VRT_CTX,
145
    struct xyzzy_debug_obj *o, struct vmod_priv *priv)
146
{
147 40
        (void)o;
148 40
        xyzzy_test_priv_call(ctx, priv);
149 40
}
150
151
VCL_VOID v_matchproto_()
152 40
xyzzy_obj_test_priv_vcl(VRT_CTX,
153
    struct xyzzy_debug_obj *o, struct vmod_priv *priv)
154
{
155 40
        (void)o;
156 40
        xyzzy_test_priv_vcl(ctx, priv);
157 40
}
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 520
PRIV_FINI(task)
177 120
PRIV_FINI(top)
178
#undef PRIV_FINI
179
180
VCL_STRING v_matchproto_()
181 2080
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 2080
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
187
188 2080
        if (ctx->method & VCL_MET_TASK_H)
189 280
                vsl = NULL;
190
        else
191 1800
                vsl = ctx->vsl;
192
193 2080
        if (s == NULL || *s == '\0') {
194 1360
                p = VRT_priv_task_get(ctx, o);
195 1360
                if (p == NULL) {
196 1440
                        mylog(vsl, SLT_Debug, "%s.priv_task() = NULL",
197 720
                            o->vcl_name);
198 720
                        return ("");
199
                }
200 640
                assert(p->methods == xyzzy_obj_test_priv_task_methods);
201 1280
                mylog(vsl, SLT_Debug,
202
                    "%s.priv_task() = %p .priv = %p (\"%s\")",
203 640
                    o->vcl_name, p, p->priv, (char *)p->priv);
204 640
                return (p->priv);
205
        }
206
207 720
        p = VRT_priv_task(ctx, o);
208
209 720
        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 1440
        mylog(vsl, SLT_Debug,
217
            "%s.priv_task() = %p .priv = %p (\"%s\") [%s]",
218 720
            o->vcl_name, p, s, s, p->priv ? "update" : "new");
219
220 720
        if (p->priv == NULL)
221 520
                p->methods = xyzzy_obj_test_priv_task_methods;
222
        else
223 200
                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 720
        p->priv = TRUST_ME(s);
227
228 720
        return (p->priv);
229 2080
}
230
231
VCL_STRING v_matchproto_()
232 520
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 520
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
239
240 520
        req = ctx->req;
241 520
        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 520
        CHECK_OBJ(req, REQ_MAGIC);
247
248 520
        if (s == NULL || *s == '\0') {
249 400
                p = VRT_priv_top_get(ctx, o);
250 400
                if (p == NULL) {
251 160
                        VSLb(ctx->vsl, SLT_Debug, "%s.priv_top() = NULL",
252 80
                            o->vcl_name);
253 80
                        return ("");
254
                }
255 320
                assert(p->methods == xyzzy_obj_test_priv_top_methods);
256 640
                VSLb(ctx->vsl, SLT_Debug,
257
                    "%s.priv_top() = %p .priv = %p (\"%s\")",
258 320
                     o->vcl_name, p, p->priv, (char *)p->priv);
259 320
                return (p->priv);
260
        }
261
262 120
        p = VRT_priv_top(ctx, o);
263 120
        if (p == NULL)
264 0
                VSLb(ctx->vsl, SLT_Debug, "%s.priv_top() = NULL [err]",
265 0
                    o->vcl_name);
266
267 120
        CHECK_OBJ_NOTNULL(req->top, REQTOP_MAGIC);
268 120
        req = req->top->topreq;
269 120
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
270 120
        ws = req->ws;
271
272
        /* copy to top req's workspace if need to */
273 120
        if (ctx->ws != ws && WS_Allocated(ctx->ws, s, -1))
274 40
                s = WS_Copy(ws, s, -1);
275
276 120
        if (p == NULL || s == NULL) {
277 0
                VRT_fail(ctx, "out of ws?");
278 0
                return ("");
279
        }
280
281 240
        VSLb(ctx->vsl, SLT_Debug,
282
            "%s.priv_top() = %p .priv = %p (\"%s\") [%s]",
283 120
            o->vcl_name, p, s, s, p->priv ? "update" : "new");
284
285 120
        if (p->priv == NULL)
286 120
                p->methods = xyzzy_obj_test_priv_top_methods;
287
        else
288 0
                assert(p->methods == xyzzy_obj_test_priv_top_methods);
289
290 120
        p->priv = TRUST_ME(s);
291
292 120
        return (p->priv);
293 520
}
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 120
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 120
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
314 120
        AN(args);
315
316 120
        AN(args->arg1); // priv_call
317 120
        AN(args->arg2); // priv_vcl
318 120
        AN(args->arg3); // priv_task
319 120
        assert(args->arg1 != args->arg2);
320 120
        assert(args->arg2 != args->arg3);
321
322 120
        if (args->valid_s)
323 40
                AN(args->s);
324 120
        (void)args->valid_b;
325 120
        (void)args->b;
326
327 120
        AN(op);
328 120
        AZ(*op);
329 120
        ALLOC_OBJ(o, VMOD_DEBUG_OBJ_OPT_MAGIC);
330 120
        AN(o);
331 120
        *op = o;
332 120
        REPLACE(o->name, vcl_name);
333 120
        memcpy(&o->args, args, sizeof o->args);
334 120
        if (args->valid_s) {
335 40
                REPLACE(o->freeptr, args->s);
336 40
                o->args.s = o->freeptr;
337 40
        }
338 120
}
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 120
xyzzy_obj_opt_meth_opt(VRT_CTX,
357
    struct xyzzy_debug_obj_opt *o,
358
    struct VARGS(obj_opt_meth_opt) *args)
359
{
360 120
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
361 120
        CHECK_OBJ_NOTNULL(o, VMOD_DEBUG_OBJ_OPT_MAGIC);
362
363 120
        AN(args);
364 120
        AN(args->arg1); // priv_call
365 120
        AN(args->arg2); // priv_vcl
366 120
        AN(args->arg3); // priv_task
367 120
        assert(args->arg1 != args->arg2);
368 120
        assert(args->arg2 != args->arg3);
369
370 240
        return (WS_Printf(ctx->ws,
371
            "obj %s obj_s %s obj_b %s met_s %s met_b %s",
372 120
            o->name,
373 120
            (o->args.valid_s ? o->args.s : "*undef*"),
374 120
            (o->args.valid_b
375 40
                        ? (o->args.b ? "true" : "false" )
376
                        : "*undef*"),
377 120
            (args->valid_s ? args->s : "*undef*"),
378 120
            (args->valid_b
379 40
                        ? (args->b ? "true" : "false" )
380
                        : "*undef*")
381
        ));
382
}