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 <errno.h>
36
#include <stdio.h>
37
#include <stdlib.h>
38
39
#include "vtcp.h"
40
#include "vtim.h"
41
42
#include "cache_http1.h"
43
44
/*--------------------------------------------------------------------
45
 * Pass the request body to the backend
46
 */
47
48
static int v_matchproto_(objiterate_f)
49 29
vbf_iter_req_body(void *priv, int flush, const void *ptr, ssize_t l)
50
{
51
        struct busyobj *bo;
52
53 29
        CAST_OBJ_NOTNULL(bo, priv, BUSYOBJ_MAGIC);
54
55 29
        if (l > 0) {
56 29
                bo->acct.bereq_bodybytes += V1L_Write(bo->wrk, ptr, l);
57 29
                if (flush && V1L_Flush(bo->wrk))
58 0
                        return (-1);
59
        }
60 29
        return (0);
61
}
62
63
/*--------------------------------------------------------------------
64
 * Send request to backend, including any (cached) req.body
65
 *
66
 * Return value:
67
 *       0 success
68
 *       1 failure
69
 */
70
71
int
72 1325
V1F_SendReq(struct worker *wrk, struct busyobj *bo, uint64_t *ctr,
73
    int onlycached)
74
{
75
        struct http *hp;
76
        int j;
77
        ssize_t i;
78
        struct http_conn *htc;
79 1325
        int do_chunked = 0;
80
        char abuf[VTCP_ADDRBUFSIZE];
81
        char pbuf[VTCP_PORTBUFSIZE];
82
83 1325
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
84 1325
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
85 1325
        CHECK_OBJ_NOTNULL(bo->htc, HTTP_CONN_MAGIC);
86 1325
        CHECK_OBJ_ORNULL(bo->req, REQ_MAGIC);
87
88 1325
        htc = bo->htc;
89 1325
        assert(*htc->rfd > 0);
90 1325
        hp = bo->bereq;
91
92 1366
        if (bo->req != NULL &&
93 41
            bo->req->req_body_status == REQ_BODY_WITHOUT_LEN) {
94 7
                http_PrintfHeader(hp, "Transfer-Encoding: chunked");
95 7
                do_chunked = 1;
96
        }
97
98 1325
        VTCP_hisname(*htc->rfd, abuf, sizeof abuf, pbuf, sizeof pbuf);
99 1325
        VSLb(bo->vsl, SLT_BackendStart, "%s %s", abuf, pbuf);
100
101 1325
        (void)VTCP_blocking(*htc->rfd); /* XXX: we should timeout instead */
102 1325
        V1L_Open(wrk, wrk->aws, htc->rfd, bo->vsl, bo->t_prev, 0);
103 1325
        *ctr += HTTP1_Write(wrk, hp, HTTP1_Req);
104
105
        /* Deal with any message-body the request might (still) have */
106 1325
        i = 0;
107
108 1366
        if (bo->req != NULL &&
109 76
            (bo->req->req_body_status == REQ_BODY_CACHED || !onlycached)) {
110 33
                if (do_chunked)
111 6
                        V1L_Chunked(wrk);
112 33
                i = VRB_Iterate(bo->req, vbf_iter_req_body, bo);
113
114 33
                if (bo->req->req_body_status == REQ_BODY_FAIL) {
115 9
                        assert(i < 0);
116 18
                        VSLb(bo->vsl, SLT_FetchError,
117
                            "req.body read error: %d (%s)",
118 18
                            errno, strerror(errno));
119 9
                        bo->req->doclose = SC_RX_BODY;
120
                }
121 33
                if (do_chunked)
122 6
                        V1L_EndChunk(wrk);
123
        }
124
125 1325
        j = V1L_Close(wrk);
126 1325
        if (j != 0 || i < 0) {
127 18
                VSLb(bo->vsl, SLT_FetchError, "backend write error: %d (%s)",
128 18
                    errno, strerror(errno));
129 9
                VSLb_ts_busyobj(bo, "Bereq", W_TIM_real(wrk));
130 9
                htc->doclose = SC_TX_ERROR;
131 9
                return (-1);
132
        }
133 1316
        VSLb_ts_busyobj(bo, "Bereq", W_TIM_real(wrk));
134 1316
        return (0);
135
}
136
137
int
138 1306
V1F_FetchRespHdr(struct busyobj *bo)
139
{
140
141
        struct http *hp;
142
        int i;
143
        double t;
144
        struct http_conn *htc;
145
        enum htc_status_e hs;
146
147 1306
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
148 1306
        CHECK_OBJ_NOTNULL(bo->htc, HTTP_CONN_MAGIC);
149 1306
        CHECK_OBJ_ORNULL(bo->req, REQ_MAGIC);
150
151 1306
        htc = bo->htc;
152 1306
        assert(*htc->rfd > 0);
153
154 1306
        VSC_C_main->backend_req++;
155
156
        /* Receive response */
157
158 1306
        HTC_RxInit(htc, bo->ws);
159 1306
        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
160 1306
        CHECK_OBJ_NOTNULL(bo->htc, HTTP_CONN_MAGIC);
161
162 1306
        t = VTIM_real() + htc->first_byte_timeout;
163 2612
        hs = HTC_RxStuff(htc, HTTP1_Complete, NULL, NULL,
164 2612
            t, t + htc->between_bytes_timeout, cache_param->http_resp_size);
165 1306
        if (hs != HTC_S_COMPLETE) {
166 38
                bo->acct.beresp_hdrbytes +=
167 19
                    htc->rxbuf_e - htc->rxbuf_b;
168 19
                switch (hs) {
169
                case HTC_S_JUNK:
170 0
                        VSLb(bo->vsl, SLT_FetchError, "Received junk");
171 0
                        htc->doclose = SC_RX_JUNK;
172 0
                        break;
173
                case HTC_S_CLOSE:
174 0
                        VSLb(bo->vsl, SLT_FetchError, "backend closed");
175 0
                        htc->doclose = SC_RESP_CLOSE;
176 0
                        break;
177
                case HTC_S_TIMEOUT:
178 0
                        VSLb(bo->vsl, SLT_FetchError, "timeout");
179 0
                        htc->doclose = SC_RX_TIMEOUT;
180 0
                        break;
181
                case HTC_S_OVERFLOW:
182 6
                        VSLb(bo->vsl, SLT_FetchError, "overflow");
183 6
                        htc->doclose = SC_RX_OVERFLOW;
184 6
                        break;
185
                default:
186 13
                        VSLb(bo->vsl, SLT_FetchError, "HTC status %d", hs);
187 13
                        htc->doclose = SC_RX_BAD;
188 13
                        break;
189
                }
190 19
                return (htc->rxbuf_e == htc->rxbuf_b ? 1 : -1);
191
        }
192 1287
        VTCP_set_read_timeout(*htc->rfd, htc->between_bytes_timeout);
193
194 1287
        hp = bo->beresp;
195
196 1287
        i = HTTP1_DissectResponse(htc, hp, bo->bereq);
197 1287
        bo->acct.beresp_hdrbytes += htc->rxbuf_e - htc->rxbuf_b;
198 1287
        if (i) {
199 16
                VSLb(bo->vsl, SLT_FetchError, "http format error");
200 16
                htc->doclose = SC_RX_JUNK;
201 16
                return (-1);
202
        }
203
204 1271
        htc->doclose = http_DoConnection(hp);
205 1271
        RFC2616_Response_Body(bo->wrk, bo);
206
207 1271
        assert(bo->vfc->resp == bo->beresp);
208 2034
        if (bo->htc->body_status != BS_NONE &&
209 763
            bo->htc->body_status != BS_ERROR)
210 757
                (void)V1F_Setup_Fetch(bo->vfc, bo->htc);
211
212 1271
        return (0);
213
}