varnish-cache/bin/varnishd/http1/cache_http1_fetch.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
#include "config.h"
31
32
#include "cache/cache_varnishd.h"
33
#include "cache/cache_filter.h"
34
35
#include <stdio.h>
36
#include <stdlib.h>
37
38
#include "vtcp.h"
39
#include "vtim.h"
40
41
#include "cache_http1.h"
42
43
/*--------------------------------------------------------------------
44
 * Pass the request body to the backend
45
 */
46
47
static int v_matchproto_(objiterate_f)
48 257
vbf_iter_req_body(void *priv, unsigned flush, const void *ptr, ssize_t l)
49
{
50
        struct busyobj *bo;
51
52 257
        CAST_OBJ_NOTNULL(bo, priv, BUSYOBJ_MAGIC);
53
54 257
        if (l > 0) {
55 257
                (void)V1L_Write(bo->wrk, ptr, l);
56 257
                if (flush && V1L_Flush(bo->wrk))
57 0
                        return (-1);
58 257
        }
59 257
        return (0);
60 257
}
61
62
/*--------------------------------------------------------------------
63
 * Send request to backend, including any (cached) req.body
64
 *
65
 * Return value:
66
 *       0 success
67
 *       1 failure
68
 */
69
70
int
71 13696
V1F_SendReq(struct worker *wrk, struct busyobj *bo, uint64_t *ctr_hdrbytes,
72
    uint64_t *ctr_bodybytes, int onlycached)
73
{
74
        struct http *hp;
75
        int j;
76
        ssize_t i;
77
        uint64_t bytes, hdrbytes;
78
        struct http_conn *htc;
79 13696
        int do_chunked = 0;
80
81 13696
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
82 13696
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
83 13696
        CHECK_OBJ_NOTNULL(bo->htc, HTTP_CONN_MAGIC);
84 13695
        CHECK_OBJ_ORNULL(bo->req, REQ_MAGIC);
85 13696
        AN(ctr_hdrbytes);
86 13696
        AN(ctr_bodybytes);
87
88 13696
        htc = bo->htc;
89 13696
        assert(*htc->rfd > 0);
90 13696
        hp = bo->bereq;
91
92 13696
        if (bo->req != NULL &&
93 384
            bo->req->req_body_status == REQ_BODY_WITHOUT_LEN) {
94 64
                http_PrintfHeader(hp, "Transfer-Encoding: chunked");
95 64
                do_chunked = 1;
96 64
        }
97
98 13696
        VTCP_blocking(*htc->rfd);       /* XXX: we should timeout instead */
99
        /* XXX: what is the right timeout ? Isn't send_timeout client side? */
100 27392
        V1L_Open(wrk, wrk->aws, htc->rfd, bo->vsl,
101 13696
            bo->t_prev + cache_param->send_timeout, 0);
102 13696
        hdrbytes = HTTP1_Write(wrk, hp, HTTP1_Req);
103
104
        /* Deal with any message-body the request might (still) have */
105 13696
        i = 0;
106
107 14024
        if (bo->req != NULL &&
108 384
            (bo->req->req_body_status == REQ_BODY_CACHED || !onlycached)) {
109 280
                if (do_chunked)
110 56
                        V1L_Chunked(wrk);
111 280
                i = VRB_Iterate(bo->req, vbf_iter_req_body, bo);
112
113 280
                if (bo->req->req_body_status == REQ_BODY_FAIL) {
114
                        /*
115
                         * XXX: (#2332) We should test to see if the backend
116
                         * XXX: sent us some headers explaining why.
117
                         * XXX: This is hard because of the mistaken API split
118
                         * XXX: between cache_backend.c and V1F, and therefore
119
                         * XXX: Parked in this comment, pending renovation of
120
                         * XXX: the VDI/backend-protocol API to allow non-H1
121
                         * XXX: backends.
122
                         */
123 72
                        assert(i < 0);
124 144
                        VSLb(bo->vsl, SLT_FetchError,
125
                            "req.body read error: %d (%s)",
126 72
                            errno, vstrerror(errno));
127 72
                        bo->req->doclose = SC_RX_BODY;
128 72
                }
129 280
                if (do_chunked)
130 56
                        V1L_EndChunk(wrk);
131 280
        }
132
133 13696
        j = V1L_Close(wrk, &bytes);
134
135
        /* Bytes accounting */
136 13696
        if (bytes < hdrbytes)
137 0
                *ctr_hdrbytes += bytes;
138
        else {
139 13696
                *ctr_hdrbytes += hdrbytes;
140 13696
                *ctr_bodybytes += bytes - hdrbytes;
141
        }
142
143 13696
        if (j != 0 || i < 0) {
144 144
                VSLb(bo->vsl, SLT_FetchError, "backend write error: %d (%s)",
145 72
                    errno, vstrerror(errno));
146 72
                VSLb_ts_busyobj(bo, "Bereq", W_TIM_real(wrk));
147 72
                htc->doclose = SC_TX_ERROR;
148 72
                return (-1);
149
        }
150 13624
        VSLb_ts_busyobj(bo, "Bereq", W_TIM_real(wrk));
151 13624
        return (0);
152 13696
}
153
154
int
155 13504
V1F_FetchRespHdr(struct busyobj *bo)
156
{
157
158
        struct http *hp;
159
        int i;
160
        double t;
161
        struct http_conn *htc;
162
        enum htc_status_e hs;
163
164 13504
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
165 13504
        CHECK_OBJ_NOTNULL(bo->htc, HTTP_CONN_MAGIC);
166 13504
        CHECK_OBJ_ORNULL(bo->req, REQ_MAGIC);
167
168 13503
        htc = bo->htc;
169 13503
        assert(*htc->rfd > 0);
170
171 13504
        VSC_C_main->backend_req++;
172
173
        /* Receive response */
174
175 13504
        HTC_RxInit(htc, bo->ws);
176 13504
        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
177 13504
        CHECK_OBJ_NOTNULL(bo->htc, HTTP_CONN_MAGIC);
178
179 13504
        t = VTIM_real() + htc->first_byte_timeout;
180 27008
        hs = HTC_RxStuff(htc, HTTP1_Complete, NULL, NULL,
181 13504
            t, NAN, htc->between_bytes_timeout, cache_param->http_resp_size);
182 13504
        if (hs != HTC_S_COMPLETE) {
183 240
                bo->acct.beresp_hdrbytes +=
184 240
                    htc->rxbuf_e - htc->rxbuf_b;
185 240
                switch (hs) {
186
                case HTC_S_JUNK:
187 0
                        VSLb(bo->vsl, SLT_FetchError, "Received junk");
188 0
                        htc->doclose = SC_RX_JUNK;
189 0
                        break;
190
                case HTC_S_CLOSE:
191 0
                        VSLb(bo->vsl, SLT_FetchError, "backend closed");
192 0
                        htc->doclose = SC_RESP_CLOSE;
193 0
                        break;
194
                case HTC_S_TIMEOUT:
195 8
                        VSLb(bo->vsl, SLT_FetchError, "timeout");
196 8
                        htc->doclose = SC_RX_TIMEOUT;
197 8
                        break;
198
                case HTC_S_OVERFLOW:
199 112
                        VSLb(bo->vsl, SLT_FetchError, "overflow");
200 112
                        htc->doclose = SC_RX_OVERFLOW;
201 112
                        break;
202
                case HTC_S_IDLE:
203 32
                        VSLb(bo->vsl, SLT_FetchError, "first byte timeout");
204 32
                        htc->doclose = SC_RX_TIMEOUT;
205 32
                        break;
206
                default:
207 176
                        VSLb(bo->vsl, SLT_FetchError, "HTC %s (%d)",
208 88
                             HTC_Status(hs), hs);
209 88
                        htc->doclose = SC_RX_BAD;
210 88
                        break;
211
                }
212 240
                return (htc->rxbuf_e == htc->rxbuf_b ? 1 : -1);
213
        }
214 13264
        VTCP_set_read_timeout(*htc->rfd, htc->between_bytes_timeout);
215
216 13264
        hp = bo->beresp;
217
218 13264
        i = HTTP1_DissectResponse(htc, hp, bo->bereq);
219 13264
        bo->acct.beresp_hdrbytes += htc->rxbuf_e - htc->rxbuf_b;
220 13264
        if (i) {
221 128
                VSLb(bo->vsl, SLT_FetchError, "http format error");
222 128
                htc->doclose = SC_RX_JUNK;
223 128
                return (-1);
224
        }
225
226 13136
        htc->doclose = http_DoConnection(hp);
227 13136
        RFC2616_Response_Body(bo->wrk, bo);
228
229 13136
        assert(bo->vfc->resp == bo->beresp);
230 13136
        if (bo->htc->body_status != BS_NONE &&
231 8000
            bo->htc->body_status != BS_ERROR)
232 7952
                if (V1F_Setup_Fetch(bo->vfc, bo->htc)) {
233 136
                        VSLb(bo->vsl, SLT_FetchError, "overflow");
234 136
                        htc->doclose = SC_RX_OVERFLOW;
235 136
                        return (-1);
236
                }
237
238 13000
        return (0);
239 13504
}