varnish-cache/bin/varnishd/cache/cache_req_body.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
31
#include "config.h"
32
33
#include <stdlib.h>
34
35
#include "cache_varnishd.h"
36
#include "cache_filter.h"
37
#include "cache_objhead.h"
38
#include "cache_transport.h"
39
40
#include "vtim.h"
41
#include "storage/storage.h"
42
#include "hash/hash_slinger.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 44
vrb_pull(struct req *req, ssize_t maxsize, objiterate_f *func, void *priv)
53
{
54 44
        ssize_t l, r = 0, yet;
55
        struct vfp_ctx *vfc;
56
        uint8_t *ptr;
57 44
        enum vfp_status vfps = VFP_ERROR;
58
        const struct stevedore *stv;
59
60 44
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
61
62 44
        CHECK_OBJ_NOTNULL(req->htc, HTTP_CONN_MAGIC);
63 44
        CHECK_OBJ_NOTNULL(req->vfc, VFP_CTX_MAGIC);
64 44
        vfc = req->vfc;
65
66 44
        req->body_oc = HSH_Private(req->wrk);
67 44
        AN(req->body_oc);
68
69 44
        if (req->storage != NULL)
70 1
                stv = req->storage;
71
        else
72 43
                stv = stv_transient;
73
74 44
        req->storage = NULL;
75
76 44
        XXXAN(STV_NewObject(req->wrk, req->body_oc, stv, 8));
77
78 44
        vfc->oc = req->body_oc;
79
80 44
        if (VFP_Open(vfc) < 0) {
81 0
                req->req_body_status = REQ_BODY_FAIL;
82 0
                HSH_DerefBoc(req->wrk, req->body_oc);
83 0
                AZ(HSH_DerefObjCore(req->wrk, &req->body_oc, 0));
84 0
                return (-1);
85
        }
86
87 44
        AZ(req->req_bodybytes);
88 44
        AN(req->htc);
89 44
        yet = req->htc->content_length;
90 44
        if (yet != 0 && req->want100cont) {
91 3
                req->want100cont = 0;
92 3
                (void)req->transport->minimal_response(req, 100);
93
        }
94 44
        if (yet < 0)
95 4
                yet = 0;
96
        do {
97 53
                AZ(vfc->failed);
98 53
                if (maxsize >= 0 && req->req_bodybytes > maxsize) {
99 1
                        (void)VFP_Error(vfc, "Request body too big to cache");
100 1
                        break;
101
                }
102 52
                l = yet;
103 52
                if (VFP_GetStorage(vfc, &l, &ptr) != VFP_OK)
104 0
                        break;
105 52
                AZ(vfc->failed);
106 52
                AN(ptr);
107 52
                AN(l);
108 52
                vfps = VFP_Suck(vfc, ptr, &l);
109 52
                if (l > 0 && vfps != VFP_ERROR) {
110 42
                        req->req_bodybytes += l;
111 42
                        req->acct.req_bodybytes += l;
112 42
                        if (yet >= l)
113 30
                                yet -= l;
114 42
                        if (func != NULL) {
115 35
                                r = func(priv, 1, ptr, l);
116 35
                                if (r)
117 0
                                        break;
118
                        } else {
119 7
                                ObjExtend(req->wrk, req->body_oc, l);
120
                        }
121
                }
122
123 52
        } while (vfps == VFP_OK);
124 44
        VFP_Close(vfc);
125 44
        VSLb_ts_req(req, "ReqBody", VTIM_real());
126 44
        if (func != NULL) {
127 37
                HSH_DerefBoc(req->wrk, req->body_oc);
128 37
                AZ(HSH_DerefObjCore(req->wrk, &req->body_oc, 0));
129 37
                if (vfps != VFP_END) {
130 7
                        req->req_body_status = REQ_BODY_FAIL;
131 7
                        if (r == 0)
132 7
                                r = -1;
133
                }
134 37
                return (r);
135
        }
136
137 7
        ObjTrimStore(req->wrk, req->body_oc);
138 7
        AZ(ObjSetU64(req->wrk, req->body_oc, OA_LEN, req->req_bodybytes));
139 7
        HSH_DerefBoc(req->wrk, req->body_oc);
140
141 7
        if (vfps != VFP_END) {
142 2
                req->req_body_status = REQ_BODY_FAIL;
143 2
                AZ(HSH_DerefObjCore(req->wrk, &req->body_oc, 0));
144 2
                return (-1);
145
        }
146
147 5
        assert(req->req_bodybytes >= 0);
148 5
        if (req->req_bodybytes != req->htc->content_length) {
149
                /* We must update also the "pristine" req.* copy */
150 0
                http_Unset(req->http0, H_Content_Length);
151 0
                http_Unset(req->http0, H_Transfer_Encoding);
152 0
                http_PrintfHeader(req->http0, "Content-Length: %ju",
153 0
                    (uintmax_t)req->req_bodybytes);
154
155 0
                http_Unset(req->http, H_Content_Length);
156 0
                http_Unset(req->http, H_Transfer_Encoding);
157 0
                http_PrintfHeader(req->http, "Content-Length: %ju",
158 0
                    (uintmax_t)req->req_bodybytes);
159
        }
160
161 5
        req->req_body_status = REQ_BODY_CACHED;
162 5
        return (req->req_bodybytes);
163
}
164
165
/*----------------------------------------------------------------------
166
 * Iterate over the req.body.
167
 *
168
 * This can be done exactly once if uncached, and multiple times if the
169
 * req.body is cached.
170
 *
171
 * return length or -1 on error
172
 */
173
174
ssize_t
175 47
VRB_Iterate(struct req *req, objiterate_f *func, void *priv)
176
{
177
        int i;
178
179 47
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
180 47
        AN(func);
181
182 47
        switch (req->req_body_status) {
183
        case REQ_BODY_CACHED:
184 12
                if (req->req_bodybytes > 0 &&
185 6
                    ObjIterate(req->wrk, req->body_oc, priv, func, 0))
186 0
                        return (-1);
187 6
                return (0);
188
        case REQ_BODY_NONE:
189 0
                return (0);
190
        case REQ_BODY_WITH_LEN:
191
        case REQ_BODY_WITHOUT_LEN:
192 37
                break;
193
        case REQ_BODY_TAKEN:
194 0
                VSLb(req->vsl, SLT_VCL_Error,
195
                    "Uncached req.body can only be consumed once.");
196 0
                return (-1);
197
        case REQ_BODY_FAIL:
198 4
                VSLb(req->vsl, SLT_FetchError,
199
                    "Had failed reading req.body before.");
200 4
                return (-1);
201
        default:
202 0
                WRONG("Wrong req_body_status in VRB_Iterate()");
203
        }
204 37
        Lck_Lock(&req->sp->mtx);
205 46
        if (req->req_body_status == REQ_BODY_WITH_LEN ||
206 9
            req->req_body_status == REQ_BODY_WITHOUT_LEN) {
207 37
                req->req_body_status = REQ_BODY_TAKEN;
208 37
                i = 0;
209
        } else
210 0
                i = -1;
211 37
        Lck_Unlock(&req->sp->mtx);
212 37
        if (i) {
213 0
                VSLb(req->vsl, SLT_VCL_Error,
214
                    "Multiple attempts to access non-cached req.body");
215 0
                return (i);
216
        }
217 37
        return (vrb_pull(req, -1, func, priv));
218
}
219
220
/*----------------------------------------------------------------------
221
 * VRB_Ignore() is a dedicated function, because we might
222
 * be able to disuade or terminate its transmission in some protocols.
223
 *
224
 * For HTTP1, we do nothing if we are going to close the connection anyway or
225
 * just iterate it into oblivion.
226
 */
227
228
static int v_matchproto_(objiterate_f)
229 12
httpq_req_body_discard(void *priv, int flush, const void *ptr, ssize_t len)
230
{
231
232
        (void)priv;
233
        (void)flush;
234
        (void)ptr;
235
        (void)len;
236 12
        return (0);
237
}
238
239
int
240 1991
VRB_Ignore(struct req *req)
241
{
242
243 1991
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
244
245 1991
        if (req->doclose)
246 101
                return (0);
247 3769
        if (req->req_body_status == REQ_BODY_WITH_LEN ||
248 1879
            req->req_body_status == REQ_BODY_WITHOUT_LEN)
249 14
                (void)VRB_Iterate(req, httpq_req_body_discard, NULL);
250 1890
        return(0);
251
}
252
253
/*----------------------------------------------------------------------
254
 */
255
256
void
257 1915
VRB_Free(struct req *req)
258
{
259
260 1915
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
261
262 1915
        if (req->body_oc != NULL)
263 5
                AZ(HSH_DerefObjCore(req->wrk, &req->body_oc, 0));
264 1915
}
265
266
/*----------------------------------------------------------------------
267
 * Cache the req.body if it is smaller than the given size
268
 *
269
 * This function must be called before any backend fetches are kicked
270
 * off to prevent parallelism.
271
 */
272
273
ssize_t
274 10
VRB_Cache(struct req *req, ssize_t maxsize)
275
{
276
277 10
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
278 10
        assert(maxsize >= 0);
279
280
        /*
281
         * We only allow caching to happen the first time through vcl_recv{}
282
         * where we know we will have no competition or conflicts for the
283
         * updates to req.http.* etc.
284
         */
285 10
        if (req->restarts > 0 && req->req_body_status != REQ_BODY_CACHED)
286 0
                return (-1);
287
288 10
        assert (req->req_step == R_STP_RECV);
289 10
        switch (req->req_body_status) {
290
        case REQ_BODY_CACHED:
291 1
                return (req->req_bodybytes);
292
        case REQ_BODY_FAIL:
293 0
                return (-1);
294
        case REQ_BODY_NONE:
295 1
                return (0);
296
        case REQ_BODY_WITHOUT_LEN:
297
        case REQ_BODY_WITH_LEN:
298 8
                break;
299
        default:
300 0
                WRONG("Wrong req_body_status in VRB_Cache()");
301
        }
302
303 8
        if (req->htc->content_length > maxsize) {
304 1
                req->req_body_status = REQ_BODY_FAIL;
305 1
                (void)VFP_Error(req->vfc, "Request body too big to cache");
306 1
                return (-1);
307
        }
308
309 7
        return (vrb_pull(req, maxsize, NULL, NULL));
310
}