vinyl-cache/bin/vinyld/cache/cache_req_body.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2015 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
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
32
#include "config.h"
33
34
#include <stdlib.h>
35
36
#include "cache_int.h"
37
#include "cache_filter.h"
38
#include "cache_objhead.h"
39
#include "cache_transport.h"
40
41
#include "vtim.h"
42
#include "storage/storage.h"
43
44
/*----------------------------------------------------------------------
45
 * Pull the req.body in via/into a objcore
46
 *
47
 * This can be called only once per request
48
 *
49
 */
50
51
static ssize_t
52 504
vrb_pull(struct req *req, ssize_t maxsize, objiterate_f *func, void *priv)
53
{
54 504
        ssize_t l, r = 0, yet;
55
        struct vrt_ctx ctx[1];
56
        struct vfp_ctx *vfc;
57
        uint8_t *ptr;
58 504
        enum vfp_status vfps = VFP_ERROR;
59
        const struct stevedore *stv;
60 504
        ssize_t req_bodybytes = 0;
61 504
        unsigned flush = OBJ_ITER_FLUSH;
62
63 504
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
64
65 504
        CHECK_OBJ_NOTNULL(req->htc, HTTP_CONN_MAGIC);
66 504
        CHECK_OBJ_NOTNULL(req->vfc, VFP_CTX_MAGIC);
67 504
        vfc = req->vfc;
68
69 504
        req->body_oc = HSH_Private(req->wrk);
70 504
        AN(req->body_oc);
71
72 504
        if (req->storage != NULL)
73 24
                stv = req->storage;
74
        else
75 480
                stv = stv_transient;
76
77 504
        req->storage = NULL;
78
79 504
        if (STV_NewObject(req->wrk, req->body_oc, stv, 0) == 0) {
80 8
                req->req_body_status = BS_ERROR;
81 8
                HSH_DerefBoc(req->wrk, req->body_oc);
82 8
                AZ(HSH_DerefObjCore(req->wrk, &req->body_oc));
83 16
                (void)VFP_Error(vfc, "Object allocation failed:"
84 8
                    " Ran out of space in %s", stv->vclname);
85 8
                return (-1);
86
        }
87
88 496
        vfc->oc = req->body_oc;
89
90 496
        INIT_OBJ(ctx, VRT_CTX_MAGIC);
91 496
        VCL_Req2Ctx(ctx, req);
92
93 496
        if (req->vfp_filter_list != NULL &&
94 32
            VCL_StackVFP(vfc, req->vcl, req->vfp_filter_list)) {
95 0
                (void)VFP_Error(vfc, "req.body filters failed");
96 0
                req->req_body_status = BS_ERROR;
97 0
                HSH_DerefBoc(req->wrk, req->body_oc);
98 0
                AZ(HSH_DerefObjCore(req->wrk, &req->body_oc));
99 0
                return (-1);
100
        }
101
102
103 496
        if (VFP_Open(ctx, vfc) < 0) {
104 0
                req->req_body_status = BS_ERROR;
105 0
                HSH_DerefBoc(req->wrk, req->body_oc);
106 0
                AZ(HSH_DerefObjCore(req->wrk, &req->body_oc));
107 0
                return (-1);
108
        }
109
110 496
        AN(req->htc);
111 496
        yet = req->htc->content_length;
112 496
        if (yet != 0 && req->want100cont) {
113 12
                req->want100cont = 0;
114 12
                (void)req->transport->minimal_response(req, 100);
115 12
        }
116 496
        yet = vmax_t(ssize_t, yet, 0);
117 496
        do {
118 892
                AZ(vfc->failed);
119 892
                if (maxsize >= 0 && req_bodybytes > maxsize) {
120 4
                        (void)VFP_Error(vfc, "Request body too big to cache");
121 4
                        break;
122
                }
123
                /* NB: only attempt a full allocation when caching. */
124 888
                l = maxsize > 0 ? yet : 0;
125 888
                if (VFP_GetStorage(vfc, &l, &ptr) != VFP_OK)
126 0
                        break;
127 888
                AZ(vfc->failed);
128 888
                AN(ptr);
129 888
                AN(l);
130 888
                vfps = VFP_Suck(vfc, ptr, &l);
131 888
                if (l > 0 && vfps != VFP_ERROR) {
132 755
                        req_bodybytes += l;
133 755
                        if (yet >= l)
134 459
                                yet -= l;
135 296
                        else if (yet > 0)
136 0
                                yet = 0;
137 755
                        if (func != NULL) {
138 512
                                if (vfps == VFP_END)
139 257
                                        flush |= OBJ_ITER_END;
140 512
                                r = func(priv, flush, ptr, l);
141
                                // ending delivery early is not an error,
142
                                // continue sucking
143 512
                                if (r > 0)
144 12
                                        func = NULL;
145 500
                                else if (r)
146 0
                                        break;
147 512
                        } else {
148 486
                                ObjExtend(req->wrk, req->body_oc, l,
149 243
                                    vfps == VFP_END ? 1 : 0);
150
                        }
151 755
                }
152
153 888
        } while (vfps == VFP_OK);
154 496
        req->acct.req_bodybytes += VFP_Close(vfc);
155 496
        VSLb_ts_req(req, "ReqBody", VTIM_real());
156 496
        if (func != NULL || r > 0) {
157 364
                HSH_DerefBoc(req->wrk, req->body_oc);
158 364
                AZ(HSH_DerefObjCore(req->wrk, &req->body_oc));
159 364
                if (r > 0)
160 12
                        return (r);
161 352
                AN(func);
162 352
                if (vfps == VFP_END && r == 0 && (flush & OBJ_ITER_END) == 0)
163 16
                        r = func(priv, flush | OBJ_ITER_END, NULL, 0);
164 352
                if (vfps != VFP_END) {
165 80
                        req->req_body_status = BS_ERROR;
166 80
                        if (r == 0)
167 80
                                r = -1;
168 80
                }
169 352
                return (r);
170
        }
171
172 132
        AZ(ObjSetU64(req->wrk, req->body_oc, OA_LEN, req_bodybytes));
173 132
        HSH_DerefBoc(req->wrk, req->body_oc);
174
175 132
        if (vfps != VFP_END) {
176 12
                req->req_body_status = BS_ERROR;
177 12
                AZ(HSH_DerefObjCore(req->wrk, &req->body_oc));
178 12
                return (-1);
179
        }
180
181 120
        assert(req_bodybytes >= 0);
182 120
        if (req_bodybytes != req->htc->content_length) {
183
                /* We must update also the "pristine" req.* copy */
184 32
                http_Unset(req->http0, H_Content_Length);
185 32
                http_Unset(req->http0, H_Transfer_Encoding);
186 64
                http_PrintfHeader(req->http0, "Content-Length: %ju",
187 32
                    (uintmax_t)req_bodybytes);
188
189 32
                http_Unset(req->http, H_Content_Length);
190 32
                http_Unset(req->http, H_Transfer_Encoding);
191 64
                http_PrintfHeader(req->http, "Content-Length: %ju",
192 32
                    (uintmax_t)req_bodybytes);
193 32
        }
194
195 120
        req->req_body_status = BS_CACHED;
196 120
        return (req_bodybytes);
197 504
}
198
199
/*----------------------------------------------------------------------
200
 * Iterate over the req.body.
201
 *
202
 * This can be done exactly once if uncached, and multiple times if the
203
 * req.body is cached.
204
 *
205
 * return length or -1 on error
206
 */
207
208
ssize_t
209 488
VRB_Iterate(struct worker *wrk, struct vsl_log *vsl,
210
    struct req *req, objiterate_f *func, void *priv)
211
{
212
        int i;
213
214 488
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
215 488
        AN(func);
216
217 488
        if (req->req_body_status == BS_CACHED) {
218 124
                AN(req->body_oc);
219 124
                if (ObjIterate(wrk, req->body_oc, priv, func, 0))
220 0
                        return (-1);
221 124
                return (0);
222
        }
223 364
        if (req->req_body_status == BS_NONE)
224 0
                return (0);
225 364
        if (req->req_body_status == BS_TAKEN) {
226 0
                VSLb(vsl, SLT_VCL_Error,
227
                    "Uncached req.body can only be consumed once.");
228 0
                return (-1);
229
        }
230 364
        if (req->req_body_status == BS_ERROR) {
231 0
                VSLb(vsl, SLT_FetchError,
232
                    "Had failed reading req.body before.");
233 0
                return (-1);
234
        }
235 364
        Lck_Lock(&req->sp->mtx);
236 364
        if (req->req_body_status->avail > 0) {
237 364
                req->req_body_status = BS_TAKEN;
238 364
                i = 0;
239 364
        } else
240 0
                i = -1;
241 364
        Lck_Unlock(&req->sp->mtx);
242 364
        if (i) {
243 0
                VSLb(vsl, SLT_VCL_Error,
244
                    "Multiple attempts to access non-cached req.body");
245 0
                return (i);
246
        }
247 364
        return (vrb_pull(req, -1, func, priv));
248 488
}
249
250
/*----------------------------------------------------------------------
251
 * VRB_Ignore() is a dedicated function, because we might
252
 * be able to dissuade or terminate its transmission in some protocols.
253
 *
254
 * For HTTP1, we do nothing if we are going to close the connection anyway or
255
 * just iterate it into oblivion.
256
 */
257
258
static int v_matchproto_(objiterate_f)
259 312
httpq_req_body_discard(void *priv, unsigned flush, const void *ptr, ssize_t len)
260
{
261
262 312
        (void)priv;
263 312
        (void)flush;
264 312
        (void)ptr;
265 312
        (void)len;
266 312
        return (0);
267
}
268
269
int
270 15953
VRB_Ignore(struct req *req)
271
{
272
273 15953
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
274
275 15953
        if (req->doclose != SC_NULL)
276 1036
                return (0);
277 14917
        if (req->req_body_status->avail > 0)
278 224
                (void)VRB_Iterate(req->wrk, req->vsl, req,
279
                    httpq_req_body_discard, NULL);
280 14917
        if (req->req_body_status == BS_ERROR)
281 20
                req->doclose = SC_RX_BODY;
282 14917
        return (0);
283 15953
}
284
285
/*----------------------------------------------------------------------
286
 */
287
288
void
289 15457
VRB_Free(struct req *req)
290
{
291
        int r;
292
293 15457
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
294
295 15457
        if (req->body_oc == NULL)
296 15337
                return;
297
298 120
        r = HSH_DerefObjCore(req->wrk, &req->body_oc);
299
300
        // each busyobj may have gained a reference
301 120
        assert (r >= 0);
302 120
        assert ((unsigned)r <= req->restarts + 1);
303 15457
}
304
305
/*----------------------------------------------------------------------
306
 * Cache the req.body if it is smaller than the given size
307
 *
308
 * This function must be called before any backend fetches are kicked
309
 * off to prevent parallelism.
310
 */
311
312
ssize_t
313 168
VRB_Cache(struct req *req, ssize_t maxsize)
314
{
315
        uint64_t u;
316
317 168
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
318 168
        assert (req->req_step == R_STP_RECV);
319 168
        assert(maxsize >= 0);
320
321
        /*
322
         * We only allow caching to happen the first time through vcl_recv{}
323
         * where we know we will have no competition or conflicts for the
324
         * updates to req.http.* etc.
325
         */
326 168
        if (req->restarts > 0 && req->req_body_status != BS_CACHED) {
327 0
                VSLb(req->vsl, SLT_VCL_Error,
328
                    "req.body must be cached before restarts");
329 0
                return (-1);
330
        }
331
332 168
        if (req->req_body_status == BS_CACHED) {
333 12
                AZ(ObjGetU64(req->wrk, req->body_oc, OA_LEN, &u));
334 12
                return (u);
335
        }
336
337 156
        if (req->req_body_status->avail <= 0)
338 12
                return (req->req_body_status->avail);
339
340 144
        if (req->htc->content_length > maxsize) {
341 4
                req->req_body_status = BS_ERROR;
342 4
                (void)VFP_Error(req->vfc, "Request body too big to cache");
343 4
                return (-1);
344
        }
345
346 140
        return (vrb_pull(req, maxsize, NULL, NULL));
347 168
}