varnish-cache/bin/varnishd/http1/cache_http1_pipe.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2011 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
 * XXX: charge bytes to srcaddr
31
 */
32
33
#include "config.h"
34
35
#include "cache/cache_varnishd.h"
36
37
#include <poll.h>
38
#include <stdio.h>
39
40
#include "cache_http1.h"
41
#include "vtcp.h"
42
#include "vtim.h"
43
44
#include "VSC_vbe.h"
45
46
static struct lock pipestat_mtx;
47
48
static int
49 3046
rdf(int fd0, int fd1, uint64_t *pcnt)
50
{
51
        ssize_t i, j;
52
        char buf[BUFSIZ], *p;
53
54 3046
        i = read(fd0, buf, sizeof buf);
55 3046
        VTCP_Assert(i);
56 3046
        if (i <= 0)
57 1600
                return (1);
58 2892
        for (p = buf; i > 0; i -= j, p += j) {
59 1446
                j = write(fd1, p, i);
60 1446
                VTCP_Assert(j);
61 1446
                if (j <= 0)
62 0
                        return (1);
63 1446
                *pcnt += j;
64 1446
                if (i != j)
65 0
                        (void)usleep(100000);           /* XXX hack */
66 1446
        }
67 1446
        return (0);
68 3046
}
69
70
int
71 1040
V1P_Enter(void)
72
{
73 1040
        int retval = 0;
74
75 1040
        Lck_Lock(&pipestat_mtx);
76 1040
        if (cache_param->pipe_sess_max == 0 ||
77 40
            VSC_C_main->n_pipe < cache_param->pipe_sess_max)
78 1000
                VSC_C_main->n_pipe++;
79
        else
80 40
                retval = -1;
81 1040
        Lck_Unlock(&pipestat_mtx);
82 1040
        return (retval);
83
}
84
85
void
86 1000
V1P_Leave(void)
87
{
88
89 1000
        Lck_Lock(&pipestat_mtx);
90 1000
        assert(VSC_C_main->n_pipe > 0);
91 1000
        VSC_C_main->n_pipe--;
92 1000
        Lck_Unlock(&pipestat_mtx);
93 1000
}
94
95
void
96 1000
V1P_Charge(struct req *req, const struct v1p_acct *a, struct VSC_vbe *b)
97
{
98
99 1000
        AN(b);
100 2000
        VSLb(req->vsl, SLT_PipeAcct, "%ju %ju %ju %ju",
101 1000
            (uintmax_t)a->req,
102 1000
            (uintmax_t)a->bereq,
103 1000
            (uintmax_t)a->in,
104 1000
            (uintmax_t)a->out);
105
106 1000
        Lck_Lock(&pipestat_mtx);
107 1000
        VSC_C_main->s_pipe_hdrbytes += a->req;
108 1000
        VSC_C_main->s_pipe_in += a->in;
109 1000
        VSC_C_main->s_pipe_out += a->out;
110 1000
        b->pipe_hdrbytes += a->bereq;
111 1000
        b->pipe_out += a->in;
112 1000
        b->pipe_in += a->out;
113 1000
        Lck_Unlock(&pipestat_mtx);
114 1000
}
115
116
stream_close_t
117 960
V1P_Process(const struct req *req, int fd, struct v1p_acct *v1a,
118
    vtim_real deadline)
119
{
120
        struct pollfd fds[2];
121
        vtim_dur tmo, tmo_task;
122
        stream_close_t sc;
123
        int i, j;
124
125 960
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
126 960
        CHECK_OBJ_NOTNULL(req->sp, SESS_MAGIC);
127 960
        assert(fd > 0);
128
129 960
        if (req->htc->pipeline_b != NULL) {
130 240
                j = write(fd,  req->htc->pipeline_b,
131 120
                    req->htc->pipeline_e - req->htc->pipeline_b);
132 120
                VTCP_Assert(j);
133 120
                if (j < 0)
134 0
                        return (SC_OVERLOAD);
135 120
                req->htc->pipeline_b = NULL;
136 120
                req->htc->pipeline_e = NULL;
137 120
                v1a->in += j;
138 120
        }
139 960
        memset(fds, 0, sizeof fds);
140 960
        fds[0].fd = fd;
141 960
        fds[0].events = POLLIN;
142 960
        fds[1].fd = req->sp->fd;
143 960
        fds[1].events = POLLIN;
144
145 960
        sc = SC_TX_PIPE;
146 3206
        while (fds[0].fd > -1 || fds[1].fd > -1) {
147 3206
                fds[0].revents = 0;
148 3206
                fds[1].revents = 0;
149 3206
                tmo = cache_param->pipe_timeout;
150 3206
                if (tmo == 0.)
151 280
                        tmo = INFINITY;
152 3206
                if (deadline > 0.) {
153 646
                        tmo_task = deadline - VTIM_real();
154 646
                        tmo = vmin(tmo, tmo_task);
155 646
                }
156 3206
                i = poll(fds, 2, VTIM_poll_tmo(tmo));
157 3206
                if (i == 0)
158 160
                        sc = SC_RX_TIMEOUT;
159 3206
                if (i < 1)
160 160
                        break;
161 3046
                if (fds[0].revents &&
162 2206
                    rdf(fd, req->sp->fd, &v1a->out)) {
163 800
                        if (fds[1].fd == -1)
164 40
                                break;
165 760
                        (void)shutdown(fd, SHUT_RD);
166 760
                        (void)shutdown(req->sp->fd, SHUT_WR);
167 760
                        fds[0].events = 0;
168 760
                        fds[0].fd = -1;
169 760
                }
170 3006
                if (fds[1].revents &&
171 840
                    rdf(req->sp->fd, fd, &v1a->in)) {
172 800
                        if (fds[0].fd == -1)
173 760
                                break;
174 40
                        (void)shutdown(req->sp->fd, SHUT_RD);
175 40
                        (void)shutdown(fd, SHUT_WR);
176 40
                        fds[1].events = 0;
177 40
                        fds[1].fd = -1;
178 40
                }
179
        }
180
181 960
        return (sc);
182 960
}
183
184
/*--------------------------------------------------------------------*/
185
186
void
187 36670
V1P_Init(void)
188
{
189
190 36670
        Lck_New(&pipestat_mtx, lck_pipestat);
191 36670
}