varnish-cache/bin/varnishd/cache/cache_deliver_proc.c
1
/*-
2
 * Copyright (c) 2006 Verdens Gang AS
3
 * Copyright (c) 2006-2015 Varnish Software AS
4
 * All rights reserved.
5
 *
6
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
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 "cache_varnishd.h"
33
#include "cache_filter.h"
34
35
/* VDP_bytes
36
 *
37
 * Pushes len bytes at ptr down the delivery processor list.
38
 *
39
 * This function picks and calls the next delivery processor from the
40
 * list. The return value is the return value of the delivery
41
 * processor. Upon seeing a non-zero return value, that lowest value
42
 * observed is latched in ->retval and all subsequent calls to
43
 * VDP_bytes will return that value directly without calling the next
44
 * processor.
45
 *
46
 * Valid return values (of VDP_bytes and any VDP function):
47
 * r < 0:  Error, breaks out early on an error condition
48
 * r == 0: Continue
49
 * r > 0:  Stop, breaks out early without error condition
50
 */
51
int
52 6047
VDP_bytes(struct req *req, enum vdp_action act, const void *ptr, ssize_t len)
53
{
54
        int retval;
55
        struct vdp_entry *vdpe;
56
        struct vdp_ctx *vdc;
57
58 6047
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
59 6047
        vdc = req->vdc;
60 6047
        assert(act == VDP_NULL || act == VDP_FLUSH);
61 6047
        if (vdc->retval)
62 8
                return (vdc->retval);
63 6039
        vdpe = vdc->nxt;
64 6039
        CHECK_OBJ_NOTNULL(vdpe, VDP_ENTRY_MAGIC);
65 6039
        vdc->nxt = VTAILQ_NEXT(vdpe, list);
66
67 6039
        assert(act > VDP_NULL || len > 0);
68
        /* Call the present layer, while pointing to the next layer down */
69 6039
        retval = vdpe->vdp->func(req, act, &vdpe->priv, ptr, len);
70 6039
        if (retval && (vdc->retval == 0 || retval < vdc->retval))
71 49
                vdc->retval = retval; /* Latch error value */
72 6039
        vdc->nxt = vdpe;
73 6039
        return (vdc->retval);
74
}
75
76
void
77 2790
VDP_push(struct req *req, const struct vdp *vdp, void *priv, int bottom)
78
{
79
        struct vdp_entry *vdpe;
80
        struct vdp_ctx *vdc;
81
82 2790
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
83 2790
        vdc = req->vdc;
84 2790
        AN(vdp);
85 2790
        AN(vdp->name);
86 2790
        AN(vdp->func);
87
88 2790
        if (DO_DEBUG(DBG_PROCESSORS))
89 0
                VSLb(req->vsl, SLT_Debug, "VDP_push(%s)", vdp->name);
90
91 2790
        vdpe = WS_Alloc(req->ws, sizeof *vdpe);
92 2790
        if (vdpe == NULL)
93 2790
                return;
94 2790
        INIT_OBJ(vdpe, VDP_ENTRY_MAGIC);
95 2790
        vdpe->vdp = vdp;
96 2790
        vdpe->priv = priv;
97 2790
        if (bottom)
98 2590
                VTAILQ_INSERT_TAIL(&vdc->vdp, vdpe, list);
99
        else
100 200
                VTAILQ_INSERT_HEAD(&vdc->vdp, vdpe, list);
101 2790
        vdc->nxt = VTAILQ_FIRST(&vdc->vdp);
102
103 2790
        AZ(vdpe->vdp->func(req, VDP_INIT, &vdpe->priv, NULL, 0));
104
}
105
106
void
107 3761
VDP_close(struct req *req)
108
{
109
        struct vdp_entry *vdpe;
110
        struct vdp_ctx *vdc;
111
112 3761
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
113 3761
        vdc = req->vdc;
114 10312
        while (!VTAILQ_EMPTY(&vdc->vdp)) {
115 2791
                vdpe = VTAILQ_FIRST(&vdc->vdp);
116 2791
                CHECK_OBJ_NOTNULL(vdpe, VDP_ENTRY_MAGIC);
117 2791
                VTAILQ_REMOVE(&vdc->vdp, vdpe, list);
118 2791
                AZ(vdpe->vdp->func(req, VDP_FINI, &vdpe->priv, NULL, 0));
119 2790
                AZ(vdpe->priv);
120 2790
                vdc->nxt = VTAILQ_FIRST(&vdc->vdp);
121
        }
122 3760
}
123
124
/*--------------------------------------------------------------------*/
125
126
static int v_matchproto_(objiterate_f)
127 2972
vdp_objiterator(void *priv, int flush, const void *ptr, ssize_t len)
128
{
129 2972
        return (VDP_bytes(priv, flush ? VDP_FLUSH : VDP_NULL, ptr, len));
130
}
131
132
133
int
134 2486
VDP_DeliverObj(struct req *req)
135
{
136
        int r;
137
138 2486
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
139 2486
        r = ObjIterate(req->wrk, req->objcore, req, vdp_objiterator,
140 2486
            req->objcore->flags & OC_F_PRIVATE ? 1 : 0);
141 2487
        if (r < 0)
142 31
                return (r);
143 2456
        return (0);
144
}