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