varnish-cache/bin/varnishd/http1/cache_http1_vfp.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
 * HTTP1 Fetch Filters
31
 *
32
 * These filters are used for both req.body and beresp.body to handle
33
 * the HTTP/1 aspects (C-L/Chunked/EOF)
34
 *
35
 */
36
37
#include "config.h"
38
39
#include <inttypes.h>
40
41
#include "cache/cache_varnishd.h"
42
#include "cache/cache_filter.h"
43
#include "cache_http1.h"
44
45
#include "vct.h"
46
#include "vtcp.h"
47
48
/*--------------------------------------------------------------------
49
 * Read up to len bytes, returning pipelined data first.
50
 */
51
52
static ssize_t
53 2334259
v1f_read(const struct vfp_ctx *vc, struct http_conn *htc, void *d, ssize_t len)
54
{
55
        ssize_t l;
56
        unsigned char *p;
57 2334259
        ssize_t i = 0;
58
59 2334259
        CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
60 2334259
        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
61 2334259
        assert(len > 0);
62 2334259
        l = 0;
63 2334259
        p = d;
64 2334259
        if (htc->pipeline_b) {
65 116248
                l = htc->pipeline_e - htc->pipeline_b;
66 116248
                assert(l > 0);
67 116248
                l = vmin(l, len);
68 116248
                memcpy(p, htc->pipeline_b, l);
69 116248
                p += l;
70 116248
                len -= l;
71 116248
                htc->pipeline_b += l;
72 116248
                if (htc->pipeline_b == htc->pipeline_e)
73 41343
                        htc->pipeline_b = htc->pipeline_e = NULL;
74 116248
        }
75 2334259
        if (len > 0) {
76 2220879
                i = read(*htc->rfd, p, len);
77 2220879
                if (i < 0) {
78 360
                        VTCP_Assert(i);
79 720
                        VSLbs(vc->wrk->vsl, SLT_FetchError,
80 360
                            TOSTRAND(VAS_errtxt(errno)));
81 360
                        return (i);
82
                }
83 2220519
                assert(i <= len);
84 2220519
                if (i == 0)
85 2360
                        htc->doclose = SC_RESP_CLOSE;
86 2220519
        }
87 2333899
        return (i + l);
88 2334259
}
89
90
91
/*--------------------------------------------------------------------
92
 * Read a chunked HTTP object.
93
 *
94
 * XXX: Reading one byte at a time is pretty pessimal.
95
 */
96
97
static enum vfp_status v_matchproto_(vfp_pull_f)
98 2130379
v1f_chunked_pull(struct vfp_ctx *vc, struct vfp_entry *vfe, void *ptr,
99
    ssize_t *lp)
100
{
101
        struct http_conn *htc;
102
        char buf[20];           /* XXX: 20 is arbitrary */
103
        char *q;
104
        unsigned u;
105
        uintmax_t cll;
106
        ssize_t cl, l, lr;
107
108 2130379
        CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
109 2130379
        CHECK_OBJ_NOTNULL(vfe, VFP_ENTRY_MAGIC);
110 2130379
        CAST_OBJ_NOTNULL(htc, vfe->priv1, HTTP_CONN_MAGIC);
111 2130379
        AN(ptr);
112 2130379
        AN(lp);
113
114 2130379
        l = *lp;
115 2130379
        *lp = 0;
116 2130379
        if (vfe->priv2 == -1) {
117
                /* Skip leading whitespace */
118 15323
                do {
119 31965
                        lr = v1f_read(vc, htc, buf, 1);
120 31965
                        if (lr <= 0)
121 200
                                return (VFP_Error(vc, "chunked read err"));
122 31765
                } while (vct_islws(buf[0]));
123
124 15123
                if (!vct_ishex(buf[0]))
125 0
                         return (VFP_Error(vc, "chunked header non-hex"));
126
127
                /* Collect hex digits, skipping leading zeros */
128 27443
                for (u = 1; u < sizeof buf; u++) {
129 27400
                        do {
130 54203
                                lr = v1f_read(vc, htc, buf + u, 1);
131 54203
                                if (lr <= 0)
132 0
                                        return (VFP_Error(vc, "chunked read err"));
133 54203
                        } while (u == 1 && buf[0] == '0' && buf[u] == '0');
134 27400
                        if (!vct_ishex(buf[u]))
135 15080
                                break;
136 12320
                }
137
138 15123
                if (u >= sizeof buf)
139 40
                        return (VFP_Error(vc, "chunked header too long"));
140
141
                /* Skip trailing white space */
142 30163
                while (vct_islws(buf[u]) && buf[u] != '\n') {
143 15080
                        lr = v1f_read(vc, htc, buf + u, 1);
144 15080
                        if (lr <= 0)
145 0
                                return (VFP_Error(vc, "chunked read err"));
146
                }
147
148 15081
                if (buf[u] != '\n')
149 0
                        return (VFP_Error(vc, "chunked header no NL"));
150
151 15081
                buf[u] = '\0';
152
153 15081
                cll = strtoumax(buf, &q, 16);
154 15081
                if (q == NULL || *q != '\0')
155 0
                        return (VFP_Error(vc, "chunked header number syntax"));
156 15081
                cl = (ssize_t)cll;
157 15081
                if (cl < 0 || (uintmax_t)cl != cll)
158 40
                        return (VFP_Error(vc, "bogusly large chunk size"));
159
160 15041
                vfe->priv2 = cl;
161 15041
        }
162 2130097
        if (vfe->priv2 > 0) {
163 2125412
                if (vfe->priv2 < l)
164 9497
                        l = vfe->priv2;
165 2125412
                lr = v1f_read(vc, htc, ptr, l);
166 2125412
                if (lr <= 0)
167 40
                        return (VFP_Error(vc, "chunked insufficient bytes"));
168 2125372
                *lp = lr;
169 2125372
                vfe->priv2 -= lr;
170 2125372
                if (vfe->priv2 == 0)
171 10276
                        vfe->priv2 = -1;
172 2125372
                return (VFP_OK);
173
        }
174 4685
        AZ(vfe->priv2);
175 4685
        if (v1f_read(vc, htc, buf, 1) <= 0)
176 0
                return (VFP_Error(vc, "chunked read err"));
177 4685
        if (buf[0] == '\r' && v1f_read(vc, htc, buf, 1) <= 0)
178 0
                return (VFP_Error(vc, "chunked read err"));
179 4685
        if (buf[0] != '\n')
180 0
                return (VFP_Error(vc, "chunked tail no NL"));
181 4683
        return (VFP_END);
182 2130375
}
183
184
static const struct vfp v1f_chunked = {
185
        .name = "V1F_CHUNKED",
186
        .pull = v1f_chunked_pull,
187
};
188
189
190
/*--------------------------------------------------------------------*/
191
192
static enum vfp_status v_matchproto_(vfp_pull_f)
193 95485
v1f_straight_pull(struct vfp_ctx *vc, struct vfp_entry *vfe, void *p,
194
    ssize_t *lp)
195
{
196
        ssize_t l, lr;
197
        struct http_conn *htc;
198
199 95485
        CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
200 95485
        CHECK_OBJ_NOTNULL(vfe, VFP_ENTRY_MAGIC);
201 95485
        CAST_OBJ_NOTNULL(htc, vfe->priv1, HTTP_CONN_MAGIC);
202 95485
        AN(p);
203 95485
        AN(lp);
204
205 95485
        l = *lp;
206 95485
        *lp = 0;
207
208 95485
        if (vfe->priv2 == 0) // XXX: Optimize Content-Len: 0 out earlier
209 0
                return (VFP_END);
210 95485
        l = vmin(l, vfe->priv2);
211 95485
        lr = v1f_read(vc, htc, p, l);
212 95485
        if (lr <= 0)
213 920
                return (VFP_Error(vc, "straight insufficient bytes"));
214 94565
        *lp = lr;
215 94565
        vfe->priv2 -= lr;
216 94565
        if (vfe->priv2 == 0)
217 38759
                return (VFP_END);
218 55806
        return (VFP_OK);
219 95485
}
220
221
static const struct vfp v1f_straight = {
222
        .name = "V1F_STRAIGHT",
223
        .pull = v1f_straight_pull,
224
};
225
226
/*--------------------------------------------------------------------*/
227
228
static enum vfp_status v_matchproto_(vfp_pull_f)
229 2760
v1f_eof_pull(struct vfp_ctx *vc, struct vfp_entry *vfe, void *p, ssize_t *lp)
230
{
231
        ssize_t l, lr;
232
        struct http_conn *htc;
233
234 2760
        CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
235 2760
        CHECK_OBJ_NOTNULL(vfe, VFP_ENTRY_MAGIC);
236 2760
        CAST_OBJ_NOTNULL(htc, vfe->priv1, HTTP_CONN_MAGIC);
237 2760
        AN(p);
238
239 2760
        AN(lp);
240
241 2760
        l = *lp;
242 2760
        *lp = 0;
243 2760
        lr = v1f_read(vc, htc, p, l);
244 2760
        if (lr < 0)
245 120
                return (VFP_Error(vc, "eof socket fail"));
246 2640
        if (lr == 0)
247 800
                return (VFP_END);
248 1840
        *lp = lr;
249 1840
        return (VFP_OK);
250 2760
}
251
252
static const struct vfp v1f_eof = {
253
        .name = "V1F_EOF",
254
        .pull = v1f_eof_pull,
255
};
256
257
/*--------------------------------------------------------------------
258
 */
259
260
int
261 50996
V1F_Setup_Fetch(struct vfp_ctx *vfc, struct http_conn *htc)
262
{
263
        struct vfp_entry *vfe;
264
265 50996
        CHECK_OBJ_NOTNULL(vfc, VFP_CTX_MAGIC);
266 50996
        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
267
268 50996
        if (htc->body_status == BS_EOF) {
269 920
                assert(htc->content_length == -1);
270 920
                vfe = VFP_Push(vfc, &v1f_eof);
271 920
                if (vfe == NULL)
272 0
                        return (ENOSPC);
273 920
                vfe->priv2 = 0;
274 50996
        } else if (htc->body_status == BS_LENGTH) {
275 43996
                assert(htc->content_length > 0);
276 43996
                vfe = VFP_Push(vfc, &v1f_straight);
277 43996
                if (vfe == NULL)
278 0
                        return (ENOSPC);
279 43996
                vfe->priv2 = htc->content_length;
280 50076
        } else if (htc->body_status == BS_CHUNKED) {
281 6080
                assert(htc->content_length == -1);
282 6080
                vfe = VFP_Push(vfc, &v1f_chunked);
283 6080
                if (vfe == NULL)
284 640
                        return (ENOSPC);
285 5440
                vfe->priv2 = -1;
286 5440
        } else {
287 0
                WRONG("Wrong body_status");
288
        }
289 50356
        vfe->priv1 = htc;
290 50356
        return (0);
291 50996
}