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 5355
vrb_pull(struct req *req, ssize_t maxsize, objiterate_f *func, void *priv)
53
{
54 5355
        ssize_t l, r = 0, yet;
55
        struct vrt_ctx ctx[1];
56
        struct vfp_ctx *vfc;
57
        uint8_t *ptr;
58 5355
        enum vfp_status vfps = VFP_ERROR;
59
        const struct stevedore *stv;
60 5355
        ssize_t req_bodybytes = 0;
61 5355
        unsigned flush = OBJ_ITER_FLUSH;
62
63 5355
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
64
65 5355
        CHECK_OBJ_NOTNULL(req->htc, HTTP_CONN_MAGIC);
66 5355
        CHECK_OBJ_NOTNULL(req->vfc, VFP_CTX_MAGIC);
67 5355
        vfc = req->vfc;
68
69 5355
        req->body_oc = HSH_Private(req->wrk);
70 5355
        AN(req->body_oc);
71
72 5355
        if (req->storage != NULL)
73 126
                stv = req->storage;
74
        else
75 5229
                stv = stv_transient;
76
77 5355
        req->storage = NULL;
78
79 5355
        if (STV_NewObject(req->wrk, req->body_oc, stv, 0) == 0) {
80 42
                req->req_body_status = BS_ERROR;
81 42
                HSH_DerefBoc(req->wrk, req->body_oc);
82 42
                AZ(HSH_DerefObjCore(req->wrk, &req->body_oc));
83 84
                (void)VFP_Error(vfc, "Object allocation failed:"
84 42
                    " Ran out of space in %s", stv->vclname);
85 42
                return (-1);
86
        }
87
88 5313
        vfc->oc = req->body_oc;
89
90 5313
        INIT_OBJ(ctx, VRT_CTX_MAGIC);
91 5313
        VCL_Req2Ctx(ctx, req);
92
93 5313
        if (req->vfp_filter_list != NULL &&
94 168
            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 5313
        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 5313
        AN(req->htc);
111 5313
        yet = req->htc->content_length;
112 5313
        if (yet != 0 && req->want100cont) {
113 63
                req->want100cont = 0;
114 63
                (void)req->transport->minimal_response(req, 100);
115 63
        }
116 5313
        yet = vmax_t(ssize_t, yet, 0);
117 5313
        do {
118 9049
                AZ(vfc->failed);
119 9049
                if (maxsize >= 0 && req_bodybytes > maxsize) {
120 21
                        (void)VFP_Error(vfc, "Request body too big to cache");
121 21
                        break;
122
                }
123
                /* NB: only attempt a full allocation when caching. */
124 9028
                l = maxsize > 0 ? yet : 0;
125 9028
                if (VFP_GetStorage(vfc, &l, &ptr) != VFP_OK)
126 0
                        break;
127 9028
                AZ(vfc->failed);
128 9028
                AN(ptr);
129 9028
                AN(l);
130 9028
                vfps = VFP_Suck(vfc, ptr, &l);
131 9028
                if (l > 0 && vfps != VFP_ERROR) {
132 8257
                        req_bodybytes += l;
133 8257
                        if (yet >= l)
134 3530
                                yet -= l;
135 4727
                        else if (yet > 0)
136 0
                                yet = 0;
137 8257
                        if (func != NULL) {
138 6973
                                if (vfps == VFP_END)
139 3994
                                        flush |= OBJ_ITER_END;
140 6973
                                r = func(priv, flush, ptr, l);
141
                                // ending delivery early is not an error,
142
                                // continue sucking
143 6973
                                if (r > 0)
144 63
                                        func = NULL;
145 6910
                                else if (r)
146 0
                                        break;
147 6973
                        } else {
148 2568
                                ObjExtend(req->wrk, req->body_oc, l,
149 1284
                                    vfps == VFP_END ? 1 : 0);
150
                        }
151 8257
                }
152
153 9028
        } while (vfps == VFP_OK);
154 5313
        req->acct.req_bodybytes += VFP_Close(vfc);
155 5313
        VSLb_ts_req(req, "ReqBody", VTIM_real());
156 5313
        if (func != NULL || r > 0) {
157 4620
                HSH_DerefBoc(req->wrk, req->body_oc);
158 4620
                AZ(HSH_DerefObjCore(req->wrk, &req->body_oc));
159 4620
                if (r > 0)
160 63
                        return (r);
161 4557
                AN(func);
162 4557
                if (vfps == VFP_END && r == 0 && (flush & OBJ_ITER_END) == 0)
163 139
                        r = func(priv, flush | OBJ_ITER_END, NULL, 0);
164 4557
                if (vfps != VFP_END) {
165 430
                        req->req_body_status = BS_ERROR;
166 430
                        if (r == 0)
167 430
                                r = -1;
168 430
                }
169 4557
                return (r);
170
        }
171
172 693
        AZ(ObjSetU64(req->wrk, req->body_oc, OA_LEN, req_bodybytes));
173 693
        HSH_DerefBoc(req->wrk, req->body_oc);
174
175 693
        if (vfps != VFP_END) {
176 63
                req->req_body_status = BS_ERROR;
177 63
                AZ(HSH_DerefObjCore(req->wrk, &req->body_oc));
178 63
                return (-1);
179
        }
180
181 630
        assert(req_bodybytes >= 0);
182 630
        if (req_bodybytes != req->htc->content_length) {
183
                // XXX wrong for rollback
184
                /* We must update also the "pristine" req.* copy */
185 168
                http_Unset(req->http0, H_Content_Length);
186 168
                http_Unset(req->http0, H_Transfer_Encoding);
187 336
                http_PrintfHeader(req->http0, "Content-Length: %ju",
188 168
                    (uintmax_t)req_bodybytes);
189
190 168
                http_Unset(req->http, H_Content_Length);
191 168
                http_Unset(req->http, H_Transfer_Encoding);
192 336
                http_PrintfHeader(req->http, "Content-Length: %ju",
193 168
                    (uintmax_t)req_bodybytes);
194 168
        }
195
196 630
        req->req_body_status = BS_CACHED;
197 630
        return (req_bodybytes);
198 5355
}
199
200
/*----------------------------------------------------------------------
201
 * Iterate over the req.body.
202
 *
203
 * This can be done exactly once if uncached, and multiple times if the
204
 * req.body is cached.
205
 *
206
 * return length or -1 on error
207
 */
208
209
ssize_t
210 5271
VRB_Iterate(struct worker *wrk, struct vsl_log *vsl,
211
    struct req *req, objiterate_f *func, void *priv)
212
{
213
        int i;
214
215 5271
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
216 5271
        AN(func);
217
218 5271
        if (req->req_body_status == BS_CACHED) {
219 651
                AN(req->body_oc);
220 651
                if (ObjIterate(wrk, req->body_oc, priv, func, 0))
221 0
                        return (-1);
222 651
                return (0);
223
        }
224 4620
        if (req->req_body_status == BS_NONE)
225 0
                return (0);
226 4620
        if (req->req_body_status == BS_TAKEN) {
227 0
                VSLb(vsl, SLT_VCL_Error,
228
                    "Uncached req.body can only be consumed once.");
229 0
                return (-1);
230
        }
231 4620
        if (req->req_body_status == BS_ERROR) {
232 0
                VSLb(vsl, SLT_FetchError,
233
                    "Had failed reading req.body before.");
234 0
                return (-1);
235
        }
236 4620
        Lck_Lock(&req->sp->mtx);
237 4620
        if (req->req_body_status->avail > 0) {
238 4620
                req->req_body_status = BS_TAKEN;
239 4620
                i = 0;
240 4620
        } else
241 0
                i = -1;
242 4620
        Lck_Unlock(&req->sp->mtx);
243 4620
        if (i) {
244 0
                VSLb(vsl, SLT_VCL_Error,
245
                    "Multiple attempts to access non-cached req.body");
246 0
                return (i);
247
        }
248 4620
        return (vrb_pull(req, -1, func, priv));
249 5271
}
250
251
/*----------------------------------------------------------------------
252
 * VRB_Ignore() is a dedicated function, because we might
253
 * be able to dissuade or terminate its transmission in some protocols.
254
 *
255
 * For HTTP1, we do nothing if we are going to close the connection anyway or
256
 * just iterate it into oblivion.
257
 */
258
259
static int v_matchproto_(objiterate_f)
260 1692
httpq_req_body_discard(void *priv, unsigned flush, const void *ptr, ssize_t len)
261
{
262
263 1692
        (void)priv;
264 1692
        (void)flush;
265 1692
        (void)ptr;
266 1692
        (void)len;
267 1692
        return (0);
268
}
269
270
int
271 87490
VRB_Ignore(struct req *req)
272
{
273
274 87490
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
275
276 87490
        if (req->doclose != SC_NULL)
277 4524
                return (0);
278 82966
        if (req->req_body_status->avail > 0)
279 1239
                (void)VRB_Iterate(req->wrk, req->vsl, req,
280
                    httpq_req_body_discard, NULL);
281 82966
        if (req->req_body_status == BS_ERROR)
282 115
                req->doclose = SC_RX_BODY;
283 82966
        return (0);
284 87490
}
285
286
/*----------------------------------------------------------------------
287
 */
288
289
void
290 85955
VRB_Free(struct req *req)
291
{
292
        int r;
293
294 85955
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
295
296 85955
        if (req->body_oc == NULL)
297 85325
                return;
298
299 630
        r = HSH_DerefObjCore(req->wrk, &req->body_oc);
300
301
        // each busyobj may have gained a reference
302 630
        assert (r >= 0);
303 630
        assert ((unsigned)r <= req->restarts + 1);
304 85955
}
305
306
/*----------------------------------------------------------------------
307
 * Cache the req.body if it is smaller than the given size
308
 *
309
 * This function must be called before any backend fetches are kicked
310
 * off to prevent parallelism.
311
 */
312
313
ssize_t
314 882
VRB_Cache(struct req *req, ssize_t maxsize)
315
{
316
        uint64_t u;
317
318 882
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
319 882
        assert (req->req_step == R_STP_RECV);
320 882
        assert(maxsize >= 0);
321
322
        /*
323
         * We only allow caching to happen the first time through vcl_recv{}
324
         * where we know we will have no competition or conflicts for the
325
         * updates to req.http.* etc.
326
         */
327 882
        if (req->restarts > 0 && req->req_body_status != BS_CACHED) {
328 0
                VSLb(req->vsl, SLT_VCL_Error,
329
                    "req.body must be cached before restarts");
330 0
                return (-1);
331
        }
332
333 882
        if (req->req_body_status == BS_CACHED) {
334 63
                AZ(ObjGetU64(req->wrk, req->body_oc, OA_LEN, &u));
335 63
                return (u);
336
        }
337
338 819
        if (req->req_body_status->avail <= 0)
339 63
                return (req->req_body_status->avail);
340
341 756
        if (req->htc->content_length > maxsize) {
342 21
                req->req_body_status = BS_ERROR;
343 21
                (void)VFP_Error(req->vfc, "Request body too big to cache");
344 21
                return (-1);
345
        }
346
347 735
        return (vrb_pull(req, maxsize, NULL, NULL));
348 882
}