|  |  | 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 | 882 | rdf(int fd0, int fd1, uint64_t *pcnt) | 
| 50 |  | { | 
| 51 |  |         ssize_t i, j; | 
| 52 |  |         char buf[BUFSIZ], *p; | 
| 53 |  |  | 
| 54 | 882 |         i = read(fd0, buf, sizeof buf); | 
| 55 | 882 |         VTCP_Assert(i); | 
| 56 | 882 |         if (i <= 0) | 
| 57 | 456 |                 return (1); | 
| 58 | 852 |         for (p = buf; i > 0; i -= j, p += j) { | 
| 59 | 426 |                 j = write(fd1, p, i); | 
| 60 | 426 |                 VTCP_Assert(j); | 
| 61 | 426 |                 if (j <= 0) | 
| 62 | 0 |                         return (1); | 
| 63 | 426 |                 assert(j <= i); | 
| 64 | 426 |                 *pcnt += j; | 
| 65 | 426 |                 if (i != j) | 
| 66 | 0 |                         VTIM_sleep(0.1);                /* XXX hack */ | 
| 67 | 426 |         } | 
| 68 | 426 |         return (0); | 
| 69 | 882 | } | 
| 70 |  |  | 
| 71 |  | int | 
| 72 | 300 | V1P_Enter(void) | 
| 73 |  | { | 
| 74 | 300 |         int retval = 0; | 
| 75 |  |  | 
| 76 | 300 |         Lck_Lock(&pipestat_mtx); | 
| 77 | 300 |         if (cache_param->pipe_sess_max == 0 || | 
| 78 | 12 |             VSC_C_main->n_pipe < cache_param->pipe_sess_max) | 
| 79 | 288 |                 VSC_C_main->n_pipe++; | 
| 80 |  |         else | 
| 81 | 12 |                 retval = -1; | 
| 82 | 300 |         Lck_Unlock(&pipestat_mtx); | 
| 83 | 300 |         return (retval); | 
| 84 |  | } | 
| 85 |  |  | 
| 86 |  | void | 
| 87 | 288 | V1P_Leave(void) | 
| 88 |  | { | 
| 89 |  |  | 
| 90 | 288 |         Lck_Lock(&pipestat_mtx); | 
| 91 | 288 |         assert(VSC_C_main->n_pipe > 0); | 
| 92 | 288 |         VSC_C_main->n_pipe--; | 
| 93 | 288 |         Lck_Unlock(&pipestat_mtx); | 
| 94 | 288 | } | 
| 95 |  |  | 
| 96 |  | void | 
| 97 | 288 | V1P_Charge(struct req *req, const struct v1p_acct *a, struct VSC_vbe *b) | 
| 98 |  | { | 
| 99 |  |  | 
| 100 | 288 |         AN(b); | 
| 101 | 576 |         VSLb(req->vsl, SLT_PipeAcct, "%ju %ju %ju %ju", | 
| 102 | 288 |             (uintmax_t)a->req, | 
| 103 | 288 |             (uintmax_t)a->bereq, | 
| 104 | 288 |             (uintmax_t)a->in, | 
| 105 | 288 |             (uintmax_t)a->out); | 
| 106 |  |  | 
| 107 | 288 |         Lck_Lock(&pipestat_mtx); | 
| 108 | 288 |         VSC_C_main->s_pipe_hdrbytes += a->req; | 
| 109 | 288 |         VSC_C_main->s_pipe_in += a->in; | 
| 110 | 288 |         VSC_C_main->s_pipe_out += a->out; | 
| 111 | 288 |         b->pipe_hdrbytes += a->bereq; | 
| 112 | 288 |         b->pipe_out += a->in; | 
| 113 | 288 |         b->pipe_in += a->out; | 
| 114 | 288 |         Lck_Unlock(&pipestat_mtx); | 
| 115 | 288 | } | 
| 116 |  |  | 
| 117 |  | stream_close_t | 
| 118 | 276 | V1P_Process(const struct req *req, int fd, struct v1p_acct *v1a, | 
| 119 |  |     vtim_real deadline) | 
| 120 |  | { | 
| 121 |  |         struct pollfd fds[2]; | 
| 122 |  |         vtim_dur tmo, tmo_task; | 
| 123 |  |         stream_close_t sc; | 
| 124 |  |         int i, j; | 
| 125 |  |  | 
| 126 | 276 |         CHECK_OBJ_NOTNULL(req, REQ_MAGIC); | 
| 127 | 276 |         CHECK_OBJ_NOTNULL(req->sp, SESS_MAGIC); | 
| 128 | 276 |         assert(fd > 0); | 
| 129 |  |  | 
| 130 | 276 |         if (req->htc->pipeline_b != NULL) { | 
| 131 | 72 |                 j = write(fd,  req->htc->pipeline_b, | 
| 132 | 36 |                     req->htc->pipeline_e - req->htc->pipeline_b); | 
| 133 | 36 |                 VTCP_Assert(j); | 
| 134 | 36 |                 if (j < 0) | 
| 135 | 0 |                         return (SC_OVERLOAD); | 
| 136 | 36 |                 req->htc->pipeline_b = NULL; | 
| 137 | 36 |                 req->htc->pipeline_e = NULL; | 
| 138 | 36 |                 v1a->in += j; | 
| 139 | 36 |         } | 
| 140 | 276 |         memset(fds, 0, sizeof fds); | 
| 141 | 276 |         fds[0].fd = fd; | 
| 142 | 276 |         fds[0].events = POLLIN; | 
| 143 | 276 |         fds[1].fd = req->sp->fd; | 
| 144 | 276 |         fds[1].events = POLLIN; | 
| 145 |  |  | 
| 146 | 276 |         sc = SC_TX_PIPE; | 
| 147 | 930 |         while (fds[0].fd > -1 || fds[1].fd > -1) { | 
| 148 | 930 |                 fds[0].revents = 0; | 
| 149 | 930 |                 fds[1].revents = 0; | 
| 150 | 930 |                 tmo = cache_param->pipe_timeout; | 
| 151 | 930 |                 if (tmo == 0.) | 
| 152 | 84 |                         tmo = INFINITY; | 
| 153 | 930 |                 if (deadline > 0.) { | 
| 154 | 198 |                         tmo_task = deadline - VTIM_real(); | 
| 155 | 198 |                         tmo = vmin(tmo, tmo_task); | 
| 156 | 198 |                 } | 
| 157 | 930 |                 i = poll(fds, 2, VTIM_poll_tmo(tmo)); | 
| 158 | 930 |                 if (i == 0) | 
| 159 | 48 |                         sc = SC_RX_TIMEOUT; | 
| 160 | 930 |                 if (i < 1) | 
| 161 | 48 |                         break; | 
| 162 | 882 |                 if (fds[0].revents && | 
| 163 | 642 |                     rdf(fd, req->sp->fd, &v1a->out)) { | 
| 164 | 228 |                         if (fds[1].fd == -1) | 
| 165 | 12 |                                 break; | 
| 166 | 216 |                         (void)shutdown(fd, SHUT_RD); | 
| 167 | 216 |                         (void)shutdown(req->sp->fd, SHUT_WR); | 
| 168 | 216 |                         fds[0].events = 0; | 
| 169 | 216 |                         fds[0].fd = -1; | 
| 170 | 216 |                 } | 
| 171 | 870 |                 if (fds[1].revents && | 
| 172 | 240 |                     rdf(req->sp->fd, fd, &v1a->in)) { | 
| 173 | 228 |                         if (fds[0].fd == -1) | 
| 174 | 216 |                                 break; | 
| 175 | 12 |                         (void)shutdown(req->sp->fd, SHUT_RD); | 
| 176 | 12 |                         (void)shutdown(fd, SHUT_WR); | 
| 177 | 12 |                         fds[1].events = 0; | 
| 178 | 12 |                         fds[1].fd = -1; | 
| 179 | 12 |                 } | 
| 180 |  |         } | 
| 181 |  |  | 
| 182 | 276 |         return (sc); | 
| 183 | 276 | } | 
| 184 |  |  | 
| 185 |  | /*--------------------------------------------------------------------*/ | 
| 186 |  |  | 
| 187 |  | void | 
| 188 | 11411 | V1P_Init(void) | 
| 189 |  | { | 
| 190 |  |  | 
| 191 | 11411 |         Lck_New(&pipestat_mtx, lck_pipestat); | 
| 192 | 11411 | } |