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 291485
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 291485
        ssize_t i = 0;
58
59 291485
        CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
60 291485
        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
61 291485
        assert(len > 0);
62 291485
        l = 0;
63 291485
        p = d;
64 291485
        if (htc->pipeline_b) {
65 14568
                l = htc->pipeline_e - htc->pipeline_b;
66 14568
                assert(l > 0);
67 14568
                l = vmin(l, len);
68 14568
                memcpy(p, htc->pipeline_b, l);
69 14568
                p += l;
70 14568
                len -= l;
71 14568
                htc->pipeline_b += l;
72 14568
                if (htc->pipeline_b == htc->pipeline_e)
73 5205
                        htc->pipeline_b = htc->pipeline_e = NULL;
74 14568
        }
75 291485
        if (len > 0) {
76 277284
                i = read(*htc->rfd, p, len);
77 277284
                if (i < 0) {
78 45
                        VTCP_Assert(i);
79 90
                        VSLbs(vc->wrk->vsl, SLT_FetchError,
80 45
                            TOSTRAND(VAS_errtxt(errno)));
81 45
                        return (i);
82
                }
83 277239
                assert(i <= len);
84 277239
                if (i == 0)
85 295
                        htc->doclose = SC_RESP_CLOSE;
86 277239
        }
87 291440
        return (i + l);
88 291485
}
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 266132
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 266132
        CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
109 266132
        CHECK_OBJ_NOTNULL(vfe, VFP_ENTRY_MAGIC);
110 266132
        CAST_OBJ_NOTNULL(htc, vfe->priv1, HTTP_CONN_MAGIC);
111 266132
        AN(ptr);
112 266132
        AN(lp);
113
114 266132
        l = *lp;
115 266132
        *lp = 0;
116 266132
        if (vfe->priv2 == -1) {
117
                /* Skip leading whitespace */
118 1917
                do {
119 3992
                        lr = v1f_read(vc, htc, buf, 1);
120 3992
                        if (lr <= 0)
121 25
                                return (VFP_Error(vc, "chunked read err"));
122 3967
                } while (vct_islws(buf[0]));
123
124 1892
                if (!vct_ishex(buf[0]))
125 0
                         return (VFP_Error(vc, "chunked header non-hex"));
126
127
                /* Collect hex digits, skipping leading zeros */
128 3432
                for (u = 1; u < sizeof buf; u++) {
129 3425
                        do {
130 6775
                                lr = v1f_read(vc, htc, buf + u, 1);
131 6775
                                if (lr <= 0)
132 0
                                        return (VFP_Error(vc, "chunked read err"));
133 6775
                        } while (u == 1 && buf[0] == '0' && buf[u] == '0');
134 3425
                        if (!vct_ishex(buf[u]))
135 1885
                                break;
136 1540
                }
137
138 1892
                if (u >= sizeof buf)
139 5
                        return (VFP_Error(vc, "chunked header too long"));
140
141
                /* Skip trailing white space */
142 3772
                while (vct_islws(buf[u]) && buf[u] != '\n') {
143 1885
                        lr = v1f_read(vc, htc, buf + u, 1);
144 1885
                        if (lr <= 0)
145 0
                                return (VFP_Error(vc, "chunked read err"));
146
                }
147
148 1887
                if (buf[u] != '\n')
149 0
                        return (VFP_Error(vc, "chunked header no NL"));
150
151 1887
                buf[u] = '\0';
152
153 1887
                cll = strtoumax(buf, &q, 16);
154 1887
                if (q == NULL || *q != '\0')
155 4
                        return (VFP_Error(vc, "chunked header number syntax"));
156 1883
                cl = (ssize_t)cll;
157 1883
                if (cl < 0 || (uintmax_t)cl != cll)
158 5
                        return (VFP_Error(vc, "bogusly large chunk size"));
159
160 1878
                vfe->priv2 = cl;
161 1878
        }
162 266093
        if (vfe->priv2 > 0) {
163 265508
                if (vfe->priv2 < l)
164 1188
                        l = vfe->priv2;
165 265508
                lr = v1f_read(vc, htc, ptr, l);
166 265508
                if (lr <= 0)
167 5
                        return (VFP_Error(vc, "chunked insufficient bytes"));
168 265503
                *lp = lr;
169 265503
                vfe->priv2 -= lr;
170 265503
                if (vfe->priv2 == 0)
171 1285
                        vfe->priv2 = -1;
172 265503
                return (VFP_OK);
173
        }
174 585
        AZ(vfe->priv2);
175 585
        if (v1f_read(vc, htc, buf, 1) <= 0)
176 0
                return (VFP_Error(vc, "chunked read err"));
177 585
        if (buf[0] == '\r' && v1f_read(vc, htc, buf, 1) <= 0)
178 0
                return (VFP_Error(vc, "chunked read err"));
179 585
        if (buf[0] != '\n')
180 0
                return (VFP_Error(vc, "chunked tail no NL"));
181 585
        return (VFP_END);
182 266128
}
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 11816
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 11816
        CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
200 11816
        CHECK_OBJ_NOTNULL(vfe, VFP_ENTRY_MAGIC);
201 11816
        CAST_OBJ_NOTNULL(htc, vfe->priv1, HTTP_CONN_MAGIC);
202 11816
        AN(p);
203 11816
        AN(lp);
204
205 11816
        l = *lp;
206 11816
        *lp = 0;
207
208 11816
        if (vfe->priv2 == 0) // XXX: Optimize Content-Len: 0 out earlier
209 0
                return (VFP_END);
210 11816
        l = vmin(l, vfe->priv2);
211 11816
        lr = v1f_read(vc, htc, p, l);
212 11816
        if (lr <= 0)
213 115
                return (VFP_Error(vc, "straight insufficient bytes"));
214 11701
        *lp = lr;
215 11701
        vfe->priv2 -= lr;
216 11701
        if (vfe->priv2 == 0)
217 4884
                return (VFP_END);
218 6817
        return (VFP_OK);
219 11816
}
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 345
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 345
        CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
235 345
        CHECK_OBJ_NOTNULL(vfe, VFP_ENTRY_MAGIC);
236 345
        CAST_OBJ_NOTNULL(htc, vfe->priv1, HTTP_CONN_MAGIC);
237 345
        AN(p);
238
239 345
        AN(lp);
240
241 345
        l = *lp;
242 345
        *lp = 0;
243 345
        lr = v1f_read(vc, htc, p, l);
244 345
        if (lr < 0)
245 15
                return (VFP_Error(vc, "eof socket fail"));
246 330
        if (lr == 0)
247 100
                return (VFP_END);
248 230
        *lp = lr;
249 230
        return (VFP_OK);
250 345
}
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 6414
V1F_Setup_Fetch(struct vfp_ctx *vfc, struct http_conn *htc)
262
{
263
        struct vfp_entry *vfe;
264
265 6414
        CHECK_OBJ_NOTNULL(vfc, VFP_CTX_MAGIC);
266 6414
        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
267
268 6414
        if (htc->body_status == BS_EOF) {
269 115
                assert(htc->content_length == -1);
270 115
                vfe = VFP_Push(vfc, &v1f_eof);
271 115
                if (vfe == NULL)
272 0
                        return (ENOSPC);
273 115
                vfe->priv2 = 0;
274 6414
        } else if (htc->body_status == BS_LENGTH) {
275 5539
                assert(htc->content_length > 0);
276 5539
                vfe = VFP_Push(vfc, &v1f_straight);
277 5539
                if (vfe == NULL)
278 0
                        return (ENOSPC);
279 5539
                vfe->priv2 = htc->content_length;
280 6299
        } else if (htc->body_status == BS_CHUNKED) {
281 760
                assert(htc->content_length == -1);
282 760
                vfe = VFP_Push(vfc, &v1f_chunked);
283 760
                if (vfe == NULL)
284 80
                        return (ENOSPC);
285 680
                vfe->priv2 = -1;
286 680
        } else {
287 0
                WRONG("Wrong body_status");
288
        }
289 6334
        vfe->priv1 = htc;
290 6334
        return (0);
291 6414
}