Hi PHK, Attached is a set of patches to fix up the connection handling in Varnish, making it more general for both client and backend connections. This is a fairly benign cleanup set, that makes the code paths clearer. I propose this for inclusion in 4.1 (and with very small font, almost unreadable, I mention that it also sneaks in the necessary hooks for my Backend SSL stuff).
Martin -- <http://varnish-software.com>*Martin Blix Grydeland* Senior Developer | Varnish Software AS Mobile: +47 992 74 756 We Make Websites Fly!
From 928e015bde951b21a7ed06b888f30c14c7c71595 Mon Sep 17 00:00:00 2001 From: Martin Blix Grydeland <[email protected]> Date: Thu, 9 Jul 2015 11:07:21 +0200 Subject: [PATCH 01/10] Move the HTTP request receive code away from cache_sess.c Move the HTTP request receive code away from cache_sess.c to cache_htc.c. This code can then be shared with the backend response code. --- bin/varnishd/Makefile.am | 1 + bin/varnishd/cache/cache.h | 15 +-- bin/varnishd/cache/cache_htc.c | 190 +++++++++++++++++++++++++++++++++ bin/varnishd/cache/cache_session.c | 150 +------------------------- bin/varnishd/http1/cache_http1_fetch.c | 4 +- bin/varnishd/http1/cache_http1_fsm.c | 4 +- bin/varnishd/proxy/cache_proxy_proto.c | 4 +- 7 files changed, 206 insertions(+), 162 deletions(-) create mode 100644 bin/varnishd/cache/cache_htc.c diff --git a/bin/varnishd/Makefile.am b/bin/varnishd/Makefile.am index dd2bae2..f98a480 100644 --- a/bin/varnishd/Makefile.am +++ b/bin/varnishd/Makefile.am @@ -27,6 +27,7 @@ varnishd_SOURCES = \ cache/cache_fetch_proc.c \ cache/cache_gzip.c \ cache/cache_hash.c \ + cache/cache_htc.c \ cache/cache_http.c \ cache/cache_lck.c \ cache/cache_main.c \ diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index 522fad2..5a311f6 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -975,13 +975,6 @@ enum htc_status_e { HTC_S_IDLE = 3, }; -void SES_RxInit(struct http_conn *htc, struct ws *ws, - unsigned maxbytes, unsigned maxhdr); -void SES_RxReInit(struct http_conn *htc); -enum htc_status_e SES_Rx(struct http_conn *htc, double tmo); -enum htc_status_e SES_RxReq(const struct worker *, struct req *, - htc_complete_f *func); - #define SESS_ATTR(UP, low, typ, len) \ int SES_Get_##low(const struct sess *sp, typ *dst); \ void SES_Reserve_##low(struct sess *sp, typ *dst); @@ -990,6 +983,14 @@ enum htc_status_e SES_RxReq(const struct worker *, struct req *, void SES_Set_String_Attr(struct sess *sp, enum sess_attr a, const char *src); const char *SES_Get_String_Attr(const struct sess *sp, enum sess_attr a); +/* cache_htc.c */ +void HTC_RxInit(struct http_conn *htc, struct ws *ws, + unsigned maxbytes, unsigned maxhdr); +void HTC_RxReInit(struct http_conn *htc); +enum htc_status_e HTC_Rx(struct http_conn *htc, double tmo); +enum htc_status_e HTC_RxReq(const struct worker *, struct req *, + htc_complete_f *func); + /* cache_shmlog.c */ extern struct VSC_C_main *VSC_C_main; void VSM_Init(void); diff --git a/bin/varnishd/cache/cache_htc.c b/bin/varnishd/cache/cache_htc.c new file mode 100644 index 0000000..f42ecf0 --- /dev/null +++ b/bin/varnishd/cache/cache_htc.c @@ -0,0 +1,190 @@ +/*- + * Copyright (c) 2006 Verdens Gang AS + * Copyright (c) 2006-2011 Varnish Software AS + * All rights reserved. + * + * Author: Poul-Henning Kamp <[email protected]> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * HTTP connection handling + * + */ + +#include "config.h" + +#include <errno.h> +#include <poll.h> +#include <stdlib.h> + +#include "vtim.h" + +#include "cache.h" + +/*--------------------------------------------------------------------*/ + +void +HTC_RxInit(struct http_conn *htc, struct ws *ws, unsigned maxbytes, + unsigned maxhdr) +{ + + htc->magic = HTTP_CONN_MAGIC; + htc->ws = ws; + htc->maxbytes = maxbytes; + htc->maxhdr = maxhdr; + + (void)WS_Reserve(htc->ws, htc->maxbytes); + htc->rxbuf_b = ws->f; + htc->rxbuf_e = ws->f; + *htc->rxbuf_e = '\0'; + htc->pipeline_b = NULL; + htc->pipeline_e = NULL; +} + +/*-------------------------------------------------------------------- + * Start over, and recycle any pipelined input. + * The WS_Reset is safe, even though the pipelined input is stored in + * the ws somewhere, because WS_Reset only fiddles pointers. + */ + +void +HTC_RxReInit(struct http_conn *htc) +{ + ssize_t l; + + CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC); + (void)WS_Reserve(htc->ws, htc->maxbytes); + htc->rxbuf_b = htc->ws->f; + htc->rxbuf_e = htc->ws->f; + if (htc->pipeline_b != NULL) { + l = htc->pipeline_e - htc->pipeline_b; + assert(l > 0); + memmove(htc->rxbuf_b, htc->pipeline_b, l); + htc->rxbuf_e += l; + htc->pipeline_b = NULL; + htc->pipeline_e = NULL; + } + *htc->rxbuf_e = '\0'; +} + +/*-------------------------------------------------------------------- + * Receive more HTTP protocol bytes + */ + +enum htc_status_e +HTC_Rx(struct http_conn *htc, double tmo) +{ + int i, j; + struct pollfd pfd[1]; + + CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC); + AN(htc->ws->r); + AZ(htc->pipeline_b); + AZ(htc->pipeline_e); + i = (htc->ws->r - htc->rxbuf_e) - 1; /* space for NUL */ + if (i <= 0) + return (HTC_S_OVERFLOW); + if (tmo > 0.0) { + pfd[0].fd = htc->fd; + pfd[0].events = POLLIN; + pfd[0].revents = 0; + j = (int)floor(tmo * 1e3); + if (j == 0) + j++; + j = poll(pfd, 1, j); + if (j == 0) + return (HTC_S_TIMEOUT); + } + i = read(htc->fd, htc->rxbuf_e, i); + if (i <= 0) + return (HTC_S_EOF); + htc->rxbuf_e += i; + *htc->rxbuf_e = '\0'; + return (HTC_S_MORE); +} + +/*---------------------------------------------------------------------- + * Receive a request/packet/whatever, with timeouts + */ + +enum htc_status_e +HTC_RxReq(const struct worker *wrk, struct req *req, htc_complete_f *func) +{ + double tmo; + double now, when; + struct sess *sp; + enum htc_status_e hs; + + CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); + CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + sp = req->sp; + CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); + CHECK_OBJ_NOTNULL(req->htc, HTTP_CONN_MAGIC); + + AZ(isnan(sp->t_idle)); + assert(isnan(req->t_first)); + + when = sp->t_idle + cache_param->timeout_idle; + tmo = cache_param->timeout_linger; + while (1) { + hs = HTC_Rx(req->htc, tmo); + now = VTIM_real(); + if (hs == HTC_S_EOF) { + WS_ReleaseP(req->htc->ws, req->htc->rxbuf_b); + return (HTC_S_CLOSE); + } + if (hs == HTC_S_OVERFLOW) { + WS_ReleaseP(req->htc->ws, req->htc->rxbuf_b); + return (HTC_S_OVERFLOW); + } + hs = func(req->htc); + if (hs == HTC_S_OVERFLOW) { + WS_ReleaseP(req->htc->ws, req->htc->rxbuf_b); + return (HTC_S_OVERFLOW); + } + if (hs == HTC_S_JUNK) { + WS_ReleaseP(req->htc->ws, req->htc->rxbuf_b); + return (HTC_S_JUNK); + } + if (hs == HTC_S_COMPLETE) { + /* Got it, run with it */ + if (isnan(req->t_first)) + req->t_first = now; + req->t_req = now; + return (HTC_S_COMPLETE); + } + if (when < now) + return (HTC_S_TIMEOUT); + if (hs == HTC_S_MORE) { + /* Working on it */ + if (isnan(req->t_first)) + req->t_first = now; + tmo = when - now; + continue; + } + assert(hs == HTC_S_EMPTY); + /* Nothing but whitespace */ + tmo = sp->t_idle + cache_param->timeout_linger - now; + if (tmo < 0) + return (HTC_S_IDLE); + } +} diff --git a/bin/varnishd/cache/cache_session.c b/bin/varnishd/cache/cache_session.c index f3ab04a..6dcf6f6 100644 --- a/bin/varnishd/cache/cache_session.c +++ b/bin/varnishd/cache/cache_session.c @@ -144,154 +144,6 @@ SES_Get_String_Attr(const struct sess *sp, enum sess_attr a) return (q); } -/*--------------------------------------------------------------------*/ - -void -SES_RxInit(struct http_conn *htc, struct ws *ws, unsigned maxbytes, - unsigned maxhdr) -{ - - htc->magic = HTTP_CONN_MAGIC; - htc->ws = ws; - htc->maxbytes = maxbytes; - htc->maxhdr = maxhdr; - - (void)WS_Reserve(htc->ws, htc->maxbytes); - htc->rxbuf_b = ws->f; - htc->rxbuf_e = ws->f; - *htc->rxbuf_e = '\0'; - htc->pipeline_b = NULL; - htc->pipeline_e = NULL; -} - -/*-------------------------------------------------------------------- - * Start over, and recycle any pipelined input. - * The WS_Reset is safe, even though the pipelined input is stored in - * the ws somewhere, because WS_Reset only fiddles pointers. - */ - -void -SES_RxReInit(struct http_conn *htc) -{ - ssize_t l; - - CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC); - (void)WS_Reserve(htc->ws, htc->maxbytes); - htc->rxbuf_b = htc->ws->f; - htc->rxbuf_e = htc->ws->f; - if (htc->pipeline_b != NULL) { - l = htc->pipeline_e - htc->pipeline_b; - assert(l > 0); - memmove(htc->rxbuf_b, htc->pipeline_b, l); - htc->rxbuf_e += l; - htc->pipeline_b = NULL; - htc->pipeline_e = NULL; - } - *htc->rxbuf_e = '\0'; -} - -/*-------------------------------------------------------------------- - * Receive more HTTP protocol bytes - */ - -enum htc_status_e -SES_Rx(struct http_conn *htc, double tmo) -{ - int i, j; - struct pollfd pfd[1]; - - CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC); - AN(htc->ws->r); - AZ(htc->pipeline_b); - AZ(htc->pipeline_e); - i = (htc->ws->r - htc->rxbuf_e) - 1; /* space for NUL */ - if (i <= 0) - return (HTC_S_OVERFLOW); - if (tmo > 0.0) { - pfd[0].fd = htc->fd; - pfd[0].events = POLLIN; - pfd[0].revents = 0; - j = (int)floor(tmo * 1e3); - if (j == 0) - j++; - j = poll(pfd, 1, j); - if (j == 0) - return (HTC_S_TIMEOUT); - } - i = read(htc->fd, htc->rxbuf_e, i); - if (i <= 0) - return (HTC_S_EOF); - htc->rxbuf_e += i; - *htc->rxbuf_e = '\0'; - return (HTC_S_MORE); -} - -/*---------------------------------------------------------------------- - * Receive a request/packet/whatever, with timeouts - */ - -enum htc_status_e -SES_RxReq(const struct worker *wrk, struct req *req, htc_complete_f *func) -{ - double tmo; - double now, when; - struct sess *sp; - enum htc_status_e hs; - - CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); - CHECK_OBJ_NOTNULL(req, REQ_MAGIC); - sp = req->sp; - CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); - - AZ(isnan(sp->t_idle)); - assert(isnan(req->t_first)); - - when = sp->t_idle + cache_param->timeout_idle; - tmo = cache_param->timeout_linger; - while (1) { - hs = SES_Rx(req->htc, tmo); - now = VTIM_real(); - if (hs == HTC_S_EOF) { - WS_ReleaseP(req->htc->ws, req->htc->rxbuf_b); - return (HTC_S_CLOSE); - } - if (hs == HTC_S_OVERFLOW) { - WS_ReleaseP(req->htc->ws, req->htc->rxbuf_b); - return (HTC_S_OVERFLOW); - } - hs = func(req->htc); - if (hs == HTC_S_OVERFLOW) { - WS_ReleaseP(req->htc->ws, req->htc->rxbuf_b); - return (HTC_S_OVERFLOW); - } - if (hs == HTC_S_JUNK) { - WS_ReleaseP(req->htc->ws, req->htc->rxbuf_b); - return (HTC_S_JUNK); - } - if (hs == HTC_S_COMPLETE) { - /* Got it, run with it */ - if (isnan(req->t_first)) - req->t_first = now; - req->t_req = now; - return (HTC_S_COMPLETE); - } - if (when < now) - return (HTC_S_TIMEOUT); - if (hs == HTC_S_MORE) { - /* Working on it */ - if (isnan(req->t_first)) - req->t_first = now; - tmo = when - now; - continue; - } - assert(hs == HTC_S_EMPTY); - /* Nothing but whitespace */ - tmo = sp->t_idle + cache_param->timeout_linger - now; - if (tmo < 0) - return (HTC_S_IDLE); - } -} - /*-------------------------------------------------------------------- * Get a new session, preferably by recycling an already ready one * @@ -381,7 +233,7 @@ SES_Proto_Sess(struct worker *wrk, void *arg) req = Req_New(wrk, sp); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); req->htc->fd = sp->fd; - SES_RxInit(req->htc, req->ws, + HTC_RxInit(req->htc, req->ws, cache_param->http_req_size, cache_param->http_req_hdr_len); if (sp->sess_step < S_STP_H1_LAST) { diff --git a/bin/varnishd/http1/cache_http1_fetch.c b/bin/varnishd/http1/cache_http1_fetch.c index 2a2099b..d935c7a 100644 --- a/bin/varnishd/http1/cache_http1_fetch.c +++ b/bin/varnishd/http1/cache_http1_fetch.c @@ -151,7 +151,7 @@ V1F_FetchRespHdr(struct busyobj *bo) /* Receive response */ - SES_RxInit(htc, bo->ws, cache_param->http_resp_size, + HTC_RxInit(htc, bo->ws, cache_param->http_resp_size, cache_param->http_resp_hdr_len); CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC); CHECK_OBJ_NOTNULL(bo->htc, HTTP_CONN_MAGIC); @@ -160,7 +160,7 @@ V1F_FetchRespHdr(struct busyobj *bo) first = 1; do { - hs = SES_Rx(htc, 0); + hs = HTC_Rx(htc, 0); if (hs == HTC_S_MORE) hs = HTTP1_Complete(htc); if (hs == HTC_S_OVERFLOW) { diff --git a/bin/varnishd/http1/cache_http1_fsm.c b/bin/varnishd/http1/cache_http1_fsm.c index 103ba3b..7fc177b 100644 --- a/bin/varnishd/http1/cache_http1_fsm.c +++ b/bin/varnishd/http1/cache_http1_fsm.c @@ -199,7 +199,7 @@ HTTP1_Session(struct worker *wrk, struct req *req) AZ(req->vcl); AZ(req->esi_level); - hs = SES_RxReq(wrk, req, HTTP1_Complete); + hs = HTC_RxReq(wrk, req, HTTP1_Complete); if (hs < HTC_S_EMPTY) { req->acct.req_hdrbytes += req->htc->rxbuf_e - req->htc->rxbuf_b; @@ -272,7 +272,7 @@ HTTP1_Session(struct worker *wrk, struct req *req) case S_STP_H1CLEANUP: if (Req_Cleanup(sp, wrk, req)) return; - SES_RxReInit(req->htc); + HTC_RxReInit(req->htc); if (HTTP1_Complete(req->htc) == HTC_S_COMPLETE) { AZ(req->vsl->wid); req->t_first = req->t_req = sp->t_idle; diff --git a/bin/varnishd/proxy/cache_proxy_proto.c b/bin/varnishd/proxy/cache_proxy_proto.c index e359cb0..3ca1c8a 100644 --- a/bin/varnishd/proxy/cache_proxy_proto.c +++ b/bin/varnishd/proxy/cache_proxy_proto.c @@ -351,7 +351,7 @@ VPX_Proto_Sess(struct worker *wrk, void *priv) assert(sizeof vpx1_sig == 5); assert(sizeof vpx2_sig == 12); - hs = SES_RxReq(wrk, req, vpx_complete); + hs = HTC_RxReq(wrk, req, vpx_complete); if (hs != HTC_S_COMPLETE) { Req_Release(req); SES_Delete(sp, SC_RX_JUNK, NAN); @@ -376,7 +376,7 @@ VPX_Proto_Sess(struct worker *wrk, void *priv) else req->htc->pipeline_e = req->htc->rxbuf_e; WS_Release(req->htc->ws, 0); - SES_RxReInit(req->htc); + HTC_RxReInit(req->htc); req->t_req = NAN; req->t_first = NAN; req->sp->sess_step = S_STP_H1NEWREQ; -- 2.1.4
From ccc36eff64f59695c7e0771c4da55ec13ced4945 Mon Sep 17 00:00:00 2001 From: Martin Blix Grydeland <[email protected]> Date: Thu, 9 Jul 2015 11:51:59 +0200 Subject: [PATCH 02/10] Remove unused wrk argument from HTC_RxReq --- bin/varnishd/cache/cache.h | 3 +-- bin/varnishd/cache/cache_htc.c | 3 +-- bin/varnishd/http1/cache_http1_fsm.c | 2 +- bin/varnishd/proxy/cache_proxy_proto.c | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index 5a311f6..b45e45b 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -988,8 +988,7 @@ void HTC_RxInit(struct http_conn *htc, struct ws *ws, unsigned maxbytes, unsigned maxhdr); void HTC_RxReInit(struct http_conn *htc); enum htc_status_e HTC_Rx(struct http_conn *htc, double tmo); -enum htc_status_e HTC_RxReq(const struct worker *, struct req *, - htc_complete_f *func); +enum htc_status_e HTC_RxReq(struct req *req, htc_complete_f *func); /* cache_shmlog.c */ extern struct VSC_C_main *VSC_C_main; diff --git a/bin/varnishd/cache/cache_htc.c b/bin/varnishd/cache/cache_htc.c index f42ecf0..4f9cfb8 100644 --- a/bin/varnishd/cache/cache_htc.c +++ b/bin/varnishd/cache/cache_htc.c @@ -127,14 +127,13 @@ HTC_Rx(struct http_conn *htc, double tmo) */ enum htc_status_e -HTC_RxReq(const struct worker *wrk, struct req *req, htc_complete_f *func) +HTC_RxReq(struct req *req, htc_complete_f *func) { double tmo; double now, when; struct sess *sp; enum htc_status_e hs; - CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); sp = req->sp; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); diff --git a/bin/varnishd/http1/cache_http1_fsm.c b/bin/varnishd/http1/cache_http1_fsm.c index 7fc177b..16fda8b 100644 --- a/bin/varnishd/http1/cache_http1_fsm.c +++ b/bin/varnishd/http1/cache_http1_fsm.c @@ -199,7 +199,7 @@ HTTP1_Session(struct worker *wrk, struct req *req) AZ(req->vcl); AZ(req->esi_level); - hs = HTC_RxReq(wrk, req, HTTP1_Complete); + hs = HTC_RxReq(req, HTTP1_Complete); if (hs < HTC_S_EMPTY) { req->acct.req_hdrbytes += req->htc->rxbuf_e - req->htc->rxbuf_b; diff --git a/bin/varnishd/proxy/cache_proxy_proto.c b/bin/varnishd/proxy/cache_proxy_proto.c index 3ca1c8a..679ebf1 100644 --- a/bin/varnishd/proxy/cache_proxy_proto.c +++ b/bin/varnishd/proxy/cache_proxy_proto.c @@ -351,7 +351,7 @@ VPX_Proto_Sess(struct worker *wrk, void *priv) assert(sizeof vpx1_sig == 5); assert(sizeof vpx2_sig == 12); - hs = HTC_RxReq(wrk, req, vpx_complete); + hs = HTC_RxReq(req, vpx_complete); if (hs != HTC_S_COMPLETE) { Req_Release(req); SES_Delete(sp, SC_RX_JUNK, NAN); -- 2.1.4
From b0d511d2aa892672ee15375d7eaa346ff9c68789 Mon Sep 17 00:00:00 2001 From: Martin Blix Grydeland <[email protected]> Date: Thu, 9 Jul 2015 11:52:19 +0200 Subject: [PATCH 03/10] Create a HTC_RxResp function to receive backend response. HTC_RxResp reads a backend response from a struct http_conn. --- bin/varnishd/cache/cache.h | 1 + bin/varnishd/cache/cache_htc.c | 48 ++++++++++++++++++++++++++++++++ bin/varnishd/http1/cache_http1_fetch.c | 51 ++++++---------------------------- 3 files changed, 58 insertions(+), 42 deletions(-) diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index b45e45b..6e85407 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -989,6 +989,7 @@ void HTC_RxInit(struct http_conn *htc, struct ws *ws, void HTC_RxReInit(struct http_conn *htc); enum htc_status_e HTC_Rx(struct http_conn *htc, double tmo); enum htc_status_e HTC_RxReq(struct req *req, htc_complete_f *func); +enum htc_status_e HTC_RxResp(struct busyobj *bo, htc_complete_f *func); /* cache_shmlog.c */ extern struct VSC_C_main *VSC_C_main; diff --git a/bin/varnishd/cache/cache_htc.c b/bin/varnishd/cache/cache_htc.c index 4f9cfb8..b11c3ba 100644 --- a/bin/varnishd/cache/cache_htc.c +++ b/bin/varnishd/cache/cache_htc.c @@ -37,6 +37,7 @@ #include <stdlib.h> #include "vtim.h" +#include "vtcp.h" #include "cache.h" @@ -187,3 +188,50 @@ HTC_RxReq(struct req *req, htc_complete_f *func) return (HTC_S_IDLE); } } + +/*---------------------------------------------------------------------- + * Receive a response/packet/whatever, with timeouts + */ + +enum htc_status_e +HTC_RxResp(struct busyobj *bo, htc_complete_f *func) +{ + struct http_conn *htc; + int first; + enum htc_status_e hs; + + CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); + CHECK_OBJ_NOTNULL(bo->htc, HTTP_CONN_MAGIC); + AN(func); + + htc = bo->htc; + VTCP_set_read_timeout(htc->fd, htc->first_byte_timeout); + + first = 1; + do { + hs = HTC_Rx(htc, 0); + if (hs == HTC_S_MORE) + hs = func(htc); + if (hs == HTC_S_OVERFLOW) { + WS_ReleaseP(htc->ws, htc->rxbuf_b); + VSLb(bo->vsl, SLT_FetchError, + "http %sread error: overflow", + first ? "first " : ""); + htc->doclose = SC_RX_OVERFLOW; + return (hs); + } + if (hs == HTC_S_EOF) { + WS_ReleaseP(htc->ws, htc->rxbuf_b); + VSLb(bo->vsl, SLT_FetchError, "http %sread error: EOF", + first ? "first " : ""); + htc->doclose = SC_RX_TIMEOUT; + return (HTC_S_TIMEOUT); + } + if (first) { + first = 0; + VTCP_set_read_timeout(htc->fd, + htc->between_bytes_timeout); + } + } while (hs != HTC_S_COMPLETE); + return (hs); +} diff --git a/bin/varnishd/http1/cache_http1_fetch.c b/bin/varnishd/http1/cache_http1_fetch.c index d935c7a..5084a9e 100644 --- a/bin/varnishd/http1/cache_http1_fetch.c +++ b/bin/varnishd/http1/cache_http1_fetch.c @@ -135,11 +135,8 @@ V1F_SendReq(struct worker *wrk, struct busyobj *bo, uint64_t *ctr, int V1F_FetchRespHdr(struct busyobj *bo) { - - struct http *hp; - enum htc_status_e hs; - int first; struct http_conn *htc; + enum htc_status_e hs; CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); CHECK_OBJ_NOTNULL(bo->htc, HTTP_CONN_MAGIC); @@ -153,52 +150,22 @@ V1F_FetchRespHdr(struct busyobj *bo) HTC_RxInit(htc, bo->ws, cache_param->http_resp_size, cache_param->http_resp_hdr_len); - CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC); - CHECK_OBJ_NOTNULL(bo->htc, HTTP_CONN_MAGIC); - VTCP_set_read_timeout(htc->fd, htc->first_byte_timeout); - - first = 1; - do { - hs = HTC_Rx(htc, 0); - if (hs == HTC_S_MORE) - hs = HTTP1_Complete(htc); - if (hs == HTC_S_OVERFLOW) { - WS_ReleaseP(htc->ws, htc->rxbuf_b); - bo->acct.beresp_hdrbytes += - htc->rxbuf_e - htc->rxbuf_b; - VSLb(bo->vsl, SLT_FetchError, - "http %sread error: overflow", - first ? "first " : ""); - htc->doclose = SC_RX_OVERFLOW; - return (-1); - } - if (hs == HTC_S_EOF) { - WS_ReleaseP(htc->ws, htc->rxbuf_b); - bo->acct.beresp_hdrbytes += - htc->rxbuf_e - htc->rxbuf_b; - VSLb(bo->vsl, SLT_FetchError, "http %sread error: EOF", - first ? "first " : ""); - htc->doclose = SC_RX_TIMEOUT; - return (first ? 1 : -1); - } - if (first) { - first = 0; - VTCP_set_read_timeout(htc->fd, - htc->between_bytes_timeout); - } - } while (hs != HTC_S_COMPLETE); + hs = HTC_RxResp(bo, HTTP1_Complete); bo->acct.beresp_hdrbytes += htc->rxbuf_e - htc->rxbuf_b; + if (hs == HTC_S_TIMEOUT && htc->rxbuf_e == htc->rxbuf_b) + /* Timeout and not received anything - allow retry */ + return (1); + else if (hs != HTC_S_COMPLETE) + return (-1); - hp = bo->beresp; - - if (HTTP1_DissectResponse(hp, htc)) { + if (HTTP1_DissectResponse(bo->beresp, htc)) { VSLb(bo->vsl, SLT_FetchError, "http format error"); htc->doclose = SC_RX_JUNK; return (-1); } - htc->doclose = http_DoConnection(hp); + htc->doclose = http_DoConnection(bo->beresp); return (0); } -- 2.1.4
From 58eb168f871639e2c0d5fc436403f4b342ebfd74 Mon Sep 17 00:00:00 2001 From: Martin Blix Grydeland <[email protected]> Date: Thu, 9 Jul 2015 11:57:50 +0200 Subject: [PATCH 04/10] Make HTC_Rx static HTC_Rx is now only used from cache_htc.c. Make it a local static function. --- bin/varnishd/cache/cache.h | 1 - bin/varnishd/cache/cache_htc.c | 77 +++++++++++++++++++++--------------------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index 6e85407..50f7609 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -987,7 +987,6 @@ const char *SES_Get_String_Attr(const struct sess *sp, enum sess_attr a); void HTC_RxInit(struct http_conn *htc, struct ws *ws, unsigned maxbytes, unsigned maxhdr); void HTC_RxReInit(struct http_conn *htc); -enum htc_status_e HTC_Rx(struct http_conn *htc, double tmo); enum htc_status_e HTC_RxReq(struct req *req, htc_complete_f *func); enum htc_status_e HTC_RxResp(struct busyobj *bo, htc_complete_f *func); diff --git a/bin/varnishd/cache/cache_htc.c b/bin/varnishd/cache/cache_htc.c index b11c3ba..58cc798 100644 --- a/bin/varnishd/cache/cache_htc.c +++ b/bin/varnishd/cache/cache_htc.c @@ -41,6 +41,43 @@ #include "cache.h" +/*-------------------------------------------------------------------- + * Receive more HTTP protocol bytes + */ + +static enum htc_status_e +htc_rx(struct http_conn *htc, double tmo) +{ + int i, j; + struct pollfd pfd[1]; + + CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC); + CHECK_OBJ_NOTNULL(htc->ws, WS_MAGIC); + AN(htc->ws->r); + AZ(htc->pipeline_b); + AZ(htc->pipeline_e); + i = (htc->ws->r - htc->rxbuf_e) - 1; /* space for NUL */ + if (i <= 0) + return (HTC_S_OVERFLOW); + if (tmo > 0.0) { + pfd[0].fd = htc->fd; + pfd[0].events = POLLIN; + pfd[0].revents = 0; + j = (int)floor(tmo * 1e3); + if (j == 0) + j++; + j = poll(pfd, 1, j); + if (j == 0) + return (HTC_S_TIMEOUT); + } + i = read(htc->fd, htc->rxbuf_e, i); + if (i <= 0) + return (HTC_S_EOF); + htc->rxbuf_e += i; + *htc->rxbuf_e = '\0'; + return (HTC_S_MORE); +} + /*--------------------------------------------------------------------*/ void @@ -87,42 +124,6 @@ HTC_RxReInit(struct http_conn *htc) *htc->rxbuf_e = '\0'; } -/*-------------------------------------------------------------------- - * Receive more HTTP protocol bytes - */ - -enum htc_status_e -HTC_Rx(struct http_conn *htc, double tmo) -{ - int i, j; - struct pollfd pfd[1]; - - CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC); - AN(htc->ws->r); - AZ(htc->pipeline_b); - AZ(htc->pipeline_e); - i = (htc->ws->r - htc->rxbuf_e) - 1; /* space for NUL */ - if (i <= 0) - return (HTC_S_OVERFLOW); - if (tmo > 0.0) { - pfd[0].fd = htc->fd; - pfd[0].events = POLLIN; - pfd[0].revents = 0; - j = (int)floor(tmo * 1e3); - if (j == 0) - j++; - j = poll(pfd, 1, j); - if (j == 0) - return (HTC_S_TIMEOUT); - } - i = read(htc->fd, htc->rxbuf_e, i); - if (i <= 0) - return (HTC_S_EOF); - htc->rxbuf_e += i; - *htc->rxbuf_e = '\0'; - return (HTC_S_MORE); -} - /*---------------------------------------------------------------------- * Receive a request/packet/whatever, with timeouts */ @@ -146,7 +147,7 @@ HTC_RxReq(struct req *req, htc_complete_f *func) when = sp->t_idle + cache_param->timeout_idle; tmo = cache_param->timeout_linger; while (1) { - hs = HTC_Rx(req->htc, tmo); + hs = htc_rx(req->htc, tmo); now = VTIM_real(); if (hs == HTC_S_EOF) { WS_ReleaseP(req->htc->ws, req->htc->rxbuf_b); @@ -209,7 +210,7 @@ HTC_RxResp(struct busyobj *bo, htc_complete_f *func) first = 1; do { - hs = HTC_Rx(htc, 0); + hs = htc_rx(htc, 0); if (hs == HTC_S_MORE) hs = func(htc); if (hs == HTC_S_OVERFLOW) { -- 2.1.4
From 500e0377c08b7528f35bfe38acd2bc67fdc43bd7 Mon Sep 17 00:00:00 2001 From: Martin Blix Grydeland <[email protected]> Date: Thu, 9 Jul 2015 11:17:24 +0200 Subject: [PATCH 05/10] Make struct http_conn have an int pointer to the fd Make struct http_conn have an int pointer to the fd in the owning struct. This ensures changes (e.g. setting to -1 on close) are visible throughout. Add a HTC_InitObj helper function to help set up a struct http_conn --- bin/varnishd/cache/cache.h | 3 ++- bin/varnishd/cache/cache_backend.c | 3 +-- bin/varnishd/cache/cache_htc.c | 27 +++++++++++++++++++++------ bin/varnishd/cache/cache_panic.c | 6 +++++- bin/varnishd/cache/cache_session.c | 2 +- bin/varnishd/http1/cache_http1_fetch.c | 4 ++-- bin/varnishd/http1/cache_http1_vfp.c | 2 +- 7 files changed, 33 insertions(+), 14 deletions(-) diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index 50f7609..31bcf2b 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -223,7 +223,7 @@ struct http_conn { unsigned magic; #define HTTP_CONN_MAGIC 0x3e19edd1 - int fd; + int *pfd; enum sess_close doclose; unsigned maxbytes; unsigned maxhdr; @@ -984,6 +984,7 @@ void SES_Set_String_Attr(struct sess *sp, enum sess_attr a, const char *src); const char *SES_Get_String_Attr(const struct sess *sp, enum sess_attr a); /* cache_htc.c */ +void HTC_InitObj(struct http_conn *htc, int *fd); void HTC_RxInit(struct http_conn *htc, struct ws *ws, unsigned maxbytes, unsigned maxhdr); void HTC_RxReInit(struct http_conn *htc); diff --git a/bin/varnishd/cache/cache_backend.c b/bin/varnishd/cache/cache_backend.c index bb5da81..d38b0fc 100644 --- a/bin/varnishd/cache/cache_backend.c +++ b/bin/varnishd/cache/cache_backend.c @@ -135,9 +135,8 @@ vbe_dir_getfd(struct worker *wrk, struct backend *bp, struct busyobj *bo) vc->fd, bp->display_name, abuf2, pbuf2, abuf1, pbuf1); bp->vsc->req++; - INIT_OBJ(bo->htc, HTTP_CONN_MAGIC); + HTC_InitObj(bo->htc, &vc->fd); bo->htc->priv = vc; - bo->htc->fd = vc->fd; FIND_TMO(first_byte_timeout, bo->htc->first_byte_timeout, bo, bp); FIND_TMO(between_bytes_timeout, diff --git a/bin/varnishd/cache/cache_htc.c b/bin/varnishd/cache/cache_htc.c index 58cc798..d822fa7 100644 --- a/bin/varnishd/cache/cache_htc.c +++ b/bin/varnishd/cache/cache_htc.c @@ -60,7 +60,7 @@ htc_rx(struct http_conn *htc, double tmo) if (i <= 0) return (HTC_S_OVERFLOW); if (tmo > 0.0) { - pfd[0].fd = htc->fd; + pfd[0].fd = *htc->pfd; pfd[0].events = POLLIN; pfd[0].revents = 0; j = (int)floor(tmo * 1e3); @@ -70,7 +70,7 @@ htc_rx(struct http_conn *htc, double tmo) if (j == 0) return (HTC_S_TIMEOUT); } - i = read(htc->fd, htc->rxbuf_e, i); + i = read(*htc->pfd, htc->rxbuf_e, i); if (i <= 0) return (HTC_S_EOF); htc->rxbuf_e += i; @@ -78,14 +78,29 @@ htc_rx(struct http_conn *htc, double tmo) return (HTC_S_MORE); } -/*--------------------------------------------------------------------*/ +/*-------------------------------------------------------------------- + * Initialize a struct http_conn pointer + */ +void +HTC_InitObj(struct http_conn *htc, int *pfd) +{ + + AN(htc); + AN(pfd); + INIT_OBJ(htc, HTTP_CONN_MAGIC); + htc->pfd = pfd; +} + +/*-------------------------------------------------------------------- + * Set up a struct http_conn to read from the given workspace. + */ void HTC_RxInit(struct http_conn *htc, struct ws *ws, unsigned maxbytes, unsigned maxhdr) { - htc->magic = HTTP_CONN_MAGIC; + CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC); htc->ws = ws; htc->maxbytes = maxbytes; htc->maxhdr = maxhdr; @@ -206,7 +221,7 @@ HTC_RxResp(struct busyobj *bo, htc_complete_f *func) AN(func); htc = bo->htc; - VTCP_set_read_timeout(htc->fd, htc->first_byte_timeout); + VTCP_set_read_timeout(*htc->pfd, htc->first_byte_timeout); first = 1; do { @@ -230,7 +245,7 @@ HTC_RxResp(struct busyobj *bo, htc_complete_f *func) } if (first) { first = 0; - VTCP_set_read_timeout(htc->fd, + VTCP_set_read_timeout(*htc->pfd, htc->between_bytes_timeout); } } while (hs != HTC_S_COMPLETE); diff --git a/bin/varnishd/cache/cache_panic.c b/bin/varnishd/cache/cache_panic.c index c35ddaa..aaeb7a3 100644 --- a/bin/varnishd/cache/cache_panic.c +++ b/bin/varnishd/cache/cache_panic.c @@ -148,7 +148,11 @@ pan_htc(struct vsb *vsb, const struct http_conn *htc) { VSB_printf(vsb, "http_conn = %p {\n", htc); - VSB_printf(vsb, " fd = %d,\n", htc->fd); + VSB_printf(vsb, " pfd = %p(", htc->pfd); + if (htc->pfd) + VSB_printf(vsb, "<nil>),\n"); + else + VSB_printf(vsb, "%d),\n", *htc->pfd); VSB_printf(vsb, "},\n"); } diff --git a/bin/varnishd/cache/cache_session.c b/bin/varnishd/cache/cache_session.c index 6dcf6f6..aebc433 100644 --- a/bin/varnishd/cache/cache_session.c +++ b/bin/varnishd/cache/cache_session.c @@ -232,7 +232,7 @@ SES_Proto_Sess(struct worker *wrk, void *arg) (void)VTCP_blocking(sp->fd); req = Req_New(wrk, sp); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); - req->htc->fd = sp->fd; + HTC_InitObj(req->htc, &sp->fd); HTC_RxInit(req->htc, req->ws, cache_param->http_req_size, cache_param->http_req_hdr_len); diff --git a/bin/varnishd/http1/cache_http1_fetch.c b/bin/varnishd/http1/cache_http1_fetch.c index 5084a9e..7f32b32 100644 --- a/bin/varnishd/http1/cache_http1_fetch.c +++ b/bin/varnishd/http1/cache_http1_fetch.c @@ -96,8 +96,8 @@ V1F_SendReq(struct worker *wrk, struct busyobj *bo, uint64_t *ctr, do_chunked = 1; } - (void)VTCP_blocking(htc->fd); /* XXX: we should timeout instead */ - V1L_Reserve(wrk, wrk->aws, &htc->fd, bo->vsl, bo->t_prev); + (void)VTCP_blocking(*htc->pfd); /* XXX: we should timeout instead */ + V1L_Reserve(wrk, wrk->aws, htc->pfd, bo->vsl, bo->t_prev); *ctr += HTTP1_Write(wrk, hp, HTTP1_Req); /* Deal with any message-body the request might (still) have */ diff --git a/bin/varnishd/http1/cache_http1_vfp.c b/bin/varnishd/http1/cache_http1_vfp.c index c63716d..83d483e 100644 --- a/bin/varnishd/http1/cache_http1_vfp.c +++ b/bin/varnishd/http1/cache_http1_vfp.c @@ -73,7 +73,7 @@ v1f_read(const struct vfp_ctx *vc, struct http_conn *htc, void *d, ssize_t len) htc->pipeline_b = htc->pipeline_e = NULL; } if (len > 0) { - i = read(htc->fd, p, len); + i = read(*htc->pfd, p, len); if (i < 0) { // XXX: VTCP_Assert(i); // but also: EAGAIN VSLb(vc->wrk->vsl, SLT_FetchError, -- 2.1.4
From 6e014de5a89813b6a0ba60f75a7ca54e69ecd11d Mon Sep 17 00:00:00 2001 From: Martin Blix Grydeland <[email protected]> Date: Thu, 9 Jul 2015 13:19:07 +0200 Subject: [PATCH 06/10] Make V1L_Reserve take a pointer to a struct http_conn Instead of being handed an fd pointer, take the pointer to a struct http_conn instead. --- bin/varnishd/http1/cache_http1.h | 4 ++-- bin/varnishd/http1/cache_http1_deliver.c | 2 +- bin/varnishd/http1/cache_http1_fetch.c | 2 +- bin/varnishd/http1/cache_http1_line.c | 21 +++++++++++---------- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/bin/varnishd/http1/cache_http1.h b/bin/varnishd/http1/cache_http1.h index f717b78..050fb77 100644 --- a/bin/varnishd/http1/cache_http1.h +++ b/bin/varnishd/http1/cache_http1.h @@ -56,8 +56,8 @@ void V1P_Charge(struct req *, const struct v1p_acct *, struct VSC_C_vbe *); /* cache_http1_line.c */ void V1L_Chunked(const struct worker *w); void V1L_EndChunk(const struct worker *w); -void V1L_Reserve(struct worker *, struct ws *, int *fd, struct vsl_log *, - double t0); +void V1L_Reserve(struct worker *, struct ws *, struct http_conn *, + struct vsl_log *, double t0); unsigned V1L_Flush(const struct worker *w); unsigned V1L_FlushRelease(struct worker *w); size_t V1L_Write(const struct worker *w, const void *ptr, ssize_t len); diff --git a/bin/varnishd/http1/cache_http1_deliver.c b/bin/varnishd/http1/cache_http1_deliver.c index f0762df..6b0ffb0 100644 --- a/bin/varnishd/http1/cache_http1_deliver.c +++ b/bin/varnishd/http1/cache_http1_deliver.c @@ -105,7 +105,7 @@ V1D_Deliver(struct req *req, struct busyobj *bo) VDP_push(req, v1d_bytes, NULL, 1); - V1L_Reserve(req->wrk, req->ws, &req->sp->fd, req->vsl, req->t_prev); + V1L_Reserve(req->wrk, req->ws, req->htc, req->vsl, req->t_prev); req->acct.resp_hdrbytes += HTTP1_Write(req->wrk, req->resp, HTTP1_Resp); if (DO_DEBUG(DBG_FLUSH_HEAD)) diff --git a/bin/varnishd/http1/cache_http1_fetch.c b/bin/varnishd/http1/cache_http1_fetch.c index 7f32b32..dfa0d3a 100644 --- a/bin/varnishd/http1/cache_http1_fetch.c +++ b/bin/varnishd/http1/cache_http1_fetch.c @@ -97,7 +97,7 @@ V1F_SendReq(struct worker *wrk, struct busyobj *bo, uint64_t *ctr, } (void)VTCP_blocking(*htc->pfd); /* XXX: we should timeout instead */ - V1L_Reserve(wrk, wrk->aws, htc->pfd, bo->vsl, bo->t_prev); + V1L_Reserve(wrk, wrk->aws, htc, bo->vsl, bo->t_prev); *ctr += HTTP1_Write(wrk, hp, HTTP1_Req); /* Deal with any message-body the request might (still) have */ diff --git a/bin/varnishd/http1/cache_http1_line.c b/bin/varnishd/http1/cache_http1_line.c index 2bcaf6e..448f208 100644 --- a/bin/varnishd/http1/cache_http1_line.c +++ b/bin/varnishd/http1/cache_http1_line.c @@ -49,7 +49,7 @@ struct v1l { unsigned magic; #define V1L_MAGIC 0x2f2142e5 - int *wfd; + struct http_conn *htc; unsigned werr; /* valid after V1L_Flush() */ struct iovec *iov; unsigned siov; @@ -68,14 +68,15 @@ struct v1l { */ void -V1L_Reserve(struct worker *wrk, struct ws *ws, int *fd, struct vsl_log *vsl, - double t0) +V1L_Reserve(struct worker *wrk, struct ws *ws, struct http_conn *htc, + struct vsl_log *vsl, double t0) { struct v1l *v1l; unsigned u; void *res; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); + CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC); AZ(wrk->v1l); res = WS_Snapshot(ws); @@ -98,7 +99,7 @@ V1L_Reserve(struct worker *wrk, struct ws *ws, int *fd, struct vsl_log *vsl, v1l->werr = 0; v1l->liov = 0; v1l->niov = 0; - v1l->wfd = fd; + v1l->htc = htc; v1l->t0 = t0; v1l->vsl = vsl; wrk->v1l = v1l; @@ -154,13 +155,13 @@ V1L_Flush(const struct worker *wrk) CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); v1l = wrk->v1l; CHECK_OBJ_NOTNULL(v1l, V1L_MAGIC); - AN(v1l->wfd); + CHECK_OBJ_NOTNULL(v1l->htc, HTTP_CONN_MAGIC); /* For chunked, there must be one slot reserved for the chunked tail */ if (v1l->ciov < v1l->siov) assert(v1l->niov < v1l->siov); - if (*v1l->wfd >= 0 && v1l->liov > 0 && v1l->werr == 0) { + if (*v1l->htc->pfd >= 0 && v1l->liov > 0 && v1l->werr == 0) { if (v1l->ciov < v1l->siov && v1l->cliov > 0) { /* Add chunk head & tail */ bprintf(cbuf, "00%zx\r\n", v1l->cliov); @@ -177,7 +178,7 @@ V1L_Flush(const struct worker *wrk) v1l->iov[v1l->ciov].iov_len = 0; } - i = writev(*v1l->wfd, v1l->iov, v1l->niov); + i = writev(*v1l->htc->pfd, v1l->iov, v1l->niov); if (i > 0) v1l->cnt += i; while (i != v1l->liov && i > 0) { @@ -203,7 +204,7 @@ V1L_Flush(const struct worker *wrk) i, v1l->liov); v1l_prune(v1l, i); - i = writev(*v1l->wfd, v1l->iov, v1l->niov); + i = writev(*v1l->htc->pfd, v1l->iov, v1l->niov); if (i > 0) v1l->cnt += i; } @@ -230,8 +231,8 @@ V1L_Write(const struct worker *wrk, const void *ptr, ssize_t len) CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); v1l = wrk->v1l; CHECK_OBJ_NOTNULL(v1l, V1L_MAGIC); - AN(v1l->wfd); - if (len == 0 || *v1l->wfd < 0) + CHECK_OBJ_NOTNULL(v1l->htc, HTTP_CONN_MAGIC); + if (len == 0 || *v1l->htc->pfd < 0) return (0); if (len == -1) len = strlen(ptr); -- 2.1.4
From a5690e2b83d5ae469f6ecd12b1aad1e2235c37fb Mon Sep 17 00:00:00 2001 From: Martin Blix Grydeland <[email protected]> Date: Thu, 9 Jul 2015 13:52:04 +0200 Subject: [PATCH 07/10] Add pluggable read/write function pointers to struct http_conn Make the socket read and write calls go through function pointers. This allows changing the way bits are written (e.g. adding crypto) while still using the protocol read/write functionality in Varnish. --- bin/varnishd/cache/cache.h | 42 ++++++++++++++++++++++++++++++++++- bin/varnishd/cache/cache_backend.c | 2 +- bin/varnishd/cache/cache_htc.c | 9 +++++--- bin/varnishd/cache/cache_session.c | 2 +- bin/varnishd/http1/cache_http1_line.c | 4 ++-- bin/varnishd/http1/cache_http1_vfp.c | 2 +- 6 files changed, 52 insertions(+), 9 deletions(-) diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index 31bcf2b..4eb46df 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -219,6 +219,8 @@ struct vfp_ctx { * */ +struct htc_oper; + struct http_conn { unsigned magic; #define HTTP_CONN_MAGIC 0x3e19edd1 @@ -236,12 +238,50 @@ struct http_conn { enum body_status body_status; struct vfp_ctx vfc[1]; void *priv; + const struct htc_oper *oper; /* Timeouts */ double first_byte_timeout; double between_bytes_timeout; }; +typedef ssize_t htc_read_f(struct http_conn *, void *, size_t); +typedef ssize_t htc_write_f(struct http_conn *, void *, size_t); +typedef ssize_t htc_writev_f(struct http_conn *, const struct iovec *, int); + +struct htc_oper { + htc_read_f *read; + htc_write_f *write; + htc_writev_f *writev; +}; + +static inline ssize_t +HTC_read(struct http_conn *htc, void *buf, size_t count) +{ + if (htc->oper && htc->oper->read) + return (htc->oper->read(htc, buf, count)); + else + return (read(*htc->pfd, buf, count)); +} + +static inline ssize_t +HTC_write(struct http_conn *htc, void *buf, size_t count) +{ + if (htc->oper && htc->oper->write) + return (htc->oper->write(htc, buf, count)); + else + return (write(*htc->pfd, buf, count)); +} + +static inline ssize_t +HTC_writev(struct http_conn *htc, const struct iovec *iov, int iovcnt) +{ + if (htc->oper && htc->oper->writev) + return (htc->oper->writev(htc, iov, iovcnt)); + else + return (writev(*htc->pfd, iov, iovcnt)); +} + /*--------------------------------------------------------------------*/ struct acct_req { @@ -984,7 +1024,7 @@ void SES_Set_String_Attr(struct sess *sp, enum sess_attr a, const char *src); const char *SES_Get_String_Attr(const struct sess *sp, enum sess_attr a); /* cache_htc.c */ -void HTC_InitObj(struct http_conn *htc, int *fd); +void HTC_InitObj(struct http_conn *htc, int *fd, const struct htc_oper *); void HTC_RxInit(struct http_conn *htc, struct ws *ws, unsigned maxbytes, unsigned maxhdr); void HTC_RxReInit(struct http_conn *htc); diff --git a/bin/varnishd/cache/cache_backend.c b/bin/varnishd/cache/cache_backend.c index d38b0fc..3f08eab 100644 --- a/bin/varnishd/cache/cache_backend.c +++ b/bin/varnishd/cache/cache_backend.c @@ -135,7 +135,7 @@ vbe_dir_getfd(struct worker *wrk, struct backend *bp, struct busyobj *bo) vc->fd, bp->display_name, abuf2, pbuf2, abuf1, pbuf1); bp->vsc->req++; - HTC_InitObj(bo->htc, &vc->fd); + HTC_InitObj(bo->htc, &vc->fd, NULL); bo->htc->priv = vc; FIND_TMO(first_byte_timeout, bo->htc->first_byte_timeout, bo, bp); diff --git a/bin/varnishd/cache/cache_htc.c b/bin/varnishd/cache/cache_htc.c index d822fa7..a877245 100644 --- a/bin/varnishd/cache/cache_htc.c +++ b/bin/varnishd/cache/cache_htc.c @@ -70,7 +70,7 @@ htc_rx(struct http_conn *htc, double tmo) if (j == 0) return (HTC_S_TIMEOUT); } - i = read(*htc->pfd, htc->rxbuf_e, i); + i = HTC_read(htc, htc->rxbuf_e, i); if (i <= 0) return (HTC_S_EOF); htc->rxbuf_e += i; @@ -79,16 +79,19 @@ htc_rx(struct http_conn *htc, double tmo) } /*-------------------------------------------------------------------- - * Initialize a struct http_conn pointer + * Initialize a struct http_conn pointer. + * oper is an optional pointer to a struct with function pointers + * for read/write operations */ void -HTC_InitObj(struct http_conn *htc, int *pfd) +HTC_InitObj(struct http_conn *htc, int *pfd, const struct htc_oper *oper) { AN(htc); AN(pfd); INIT_OBJ(htc, HTTP_CONN_MAGIC); htc->pfd = pfd; + htc->oper = oper; } /*-------------------------------------------------------------------- diff --git a/bin/varnishd/cache/cache_session.c b/bin/varnishd/cache/cache_session.c index aebc433..4f62e25 100644 --- a/bin/varnishd/cache/cache_session.c +++ b/bin/varnishd/cache/cache_session.c @@ -232,7 +232,7 @@ SES_Proto_Sess(struct worker *wrk, void *arg) (void)VTCP_blocking(sp->fd); req = Req_New(wrk, sp); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); - HTC_InitObj(req->htc, &sp->fd); + HTC_InitObj(req->htc, &sp->fd, NULL); HTC_RxInit(req->htc, req->ws, cache_param->http_req_size, cache_param->http_req_hdr_len); diff --git a/bin/varnishd/http1/cache_http1_line.c b/bin/varnishd/http1/cache_http1_line.c index 448f208..ef40184 100644 --- a/bin/varnishd/http1/cache_http1_line.c +++ b/bin/varnishd/http1/cache_http1_line.c @@ -178,7 +178,7 @@ V1L_Flush(const struct worker *wrk) v1l->iov[v1l->ciov].iov_len = 0; } - i = writev(*v1l->htc->pfd, v1l->iov, v1l->niov); + i = HTC_writev(v1l->htc, v1l->iov, v1l->niov); if (i > 0) v1l->cnt += i; while (i != v1l->liov && i > 0) { @@ -204,7 +204,7 @@ V1L_Flush(const struct worker *wrk) i, v1l->liov); v1l_prune(v1l, i); - i = writev(*v1l->htc->pfd, v1l->iov, v1l->niov); + i = HTC_writev(v1l->htc, v1l->iov, v1l->niov); if (i > 0) v1l->cnt += i; } diff --git a/bin/varnishd/http1/cache_http1_vfp.c b/bin/varnishd/http1/cache_http1_vfp.c index 83d483e..41a2ef1 100644 --- a/bin/varnishd/http1/cache_http1_vfp.c +++ b/bin/varnishd/http1/cache_http1_vfp.c @@ -73,7 +73,7 @@ v1f_read(const struct vfp_ctx *vc, struct http_conn *htc, void *d, ssize_t len) htc->pipeline_b = htc->pipeline_e = NULL; } if (len > 0) { - i = read(*htc->pfd, p, len); + i = HTC_read(htc, p, len); if (i < 0) { // XXX: VTCP_Assert(i); // but also: EAGAIN VSLb(vc->wrk->vsl, SLT_FetchError, -- 2.1.4
From ac7ccf5ec4fe926b91c0c22586463a8621b6a021 Mon Sep 17 00:00:00 2001 From: Martin Blix Grydeland <[email protected]> Date: Thu, 9 Jul 2015 15:19:32 +0200 Subject: [PATCH 08/10] Update pipe to use struct http_conn --- bin/varnishd/cache/cache_backend.c | 4 ++- bin/varnishd/http1/cache_http1.h | 2 +- bin/varnishd/http1/cache_http1_pipe.c | 47 ++++++++++++++++------------------- 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/bin/varnishd/cache/cache_backend.c b/bin/varnishd/cache/cache_backend.c index 3f08eab..40053a5 100644 --- a/bin/varnishd/cache/cache_backend.c +++ b/bin/varnishd/cache/cache_backend.c @@ -297,6 +297,7 @@ vbe_dir_http1pipe(const struct director *d, struct req *req, struct busyobj *bo) CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); + CHECK_OBJ_NOTNULL(req->htc, HTTP_CONN_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); CAST_OBJ_NOTNULL(bp, d->priv, BACKEND_MAGIC); @@ -314,12 +315,13 @@ vbe_dir_http1pipe(const struct director *d, struct req *req, struct busyobj *bo) VSLb(bo->vsl, SLT_FetchError, "no backend connection"); SES_Close(req->sp, SC_RX_TIMEOUT); } else { + CHECK_OBJ_NOTNULL(bo->htc, HTTP_CONN_MAGIC); i = V1F_SendReq(req->wrk, bo, &v1a.bereq, 1); VSLb_ts_req(req, "Pipe", W_TIM_real(req->wrk)); if (vbc->state == VBC_STATE_STOLEN) VBT_Wait(req->wrk, vbc); if (i == 0) - V1P_Process(req, vbc->fd, &v1a); + V1P_Process(req->htc, bo->htc, &v1a); VSLb_ts_req(req, "PipeSess", W_TIM_real(req->wrk)); SES_Close(req->sp, SC_TX_PIPE); bo->htc->doclose = SC_TX_PIPE; diff --git a/bin/varnishd/http1/cache_http1.h b/bin/varnishd/http1/cache_http1.h index 050fb77..6041828 100644 --- a/bin/varnishd/http1/cache_http1.h +++ b/bin/varnishd/http1/cache_http1.h @@ -50,7 +50,7 @@ struct v1p_acct { }; void V1P_Init(void); -void V1P_Process(struct req *, int fd, struct v1p_acct *); +void V1P_Process(struct http_conn *, struct http_conn *, struct v1p_acct *); void V1P_Charge(struct req *, const struct v1p_acct *, struct VSC_C_vbe *); /* cache_http1_line.c */ diff --git a/bin/varnishd/http1/cache_http1_pipe.c b/bin/varnishd/http1/cache_http1_pipe.c index 85df545..e177b2a 100644 --- a/bin/varnishd/http1/cache_http1_pipe.c +++ b/bin/varnishd/http1/cache_http1_pipe.c @@ -43,16 +43,16 @@ static struct lock pipestat_mtx; static int -rdf(int fd0, int fd1, uint64_t *pcnt) +rdf(struct http_conn *htc_r, struct http_conn *htc_w, uint64_t *pcnt) { int i, j; char buf[BUFSIZ], *p; - i = read(fd0, buf, sizeof buf); + i = HTC_read(htc_r, buf, sizeof buf); if (i <= 0) return (1); - for (p = buf; i > 0; i -= j, p += j) { - j = write(fd1, p, i); + for (p = buf; i > 0; i-= j, p += j) { + j = HTC_write(htc_w, p, i); if (j <= 0) return (1); *pcnt += j; @@ -84,52 +84,49 @@ V1P_Charge(struct req *req, const struct v1p_acct *a, struct VSC_C_vbe *b) } void -V1P_Process(struct req *req, int fd, struct v1p_acct *v1a) +V1P_Process(struct http_conn *htc_c, struct http_conn *htc_b, + struct v1p_acct *v1a) { struct pollfd fds[2]; int i, j; - CHECK_OBJ_NOTNULL(req, REQ_MAGIC); - CHECK_OBJ_NOTNULL(req->sp, SESS_MAGIC); - assert(fd > 0); + CHECK_OBJ_NOTNULL(htc_c, HTTP_CONN_MAGIC); + CHECK_OBJ_NOTNULL(htc_b, HTTP_CONN_MAGIC); - if (req->htc->pipeline_b != NULL) { - j = write(fd, req->htc->pipeline_b, - req->htc->pipeline_e - req->htc->pipeline_b); + if (htc_c->pipeline_b != NULL) { + j = HTC_write(htc_b, htc_c->pipeline_b, + htc_c->pipeline_e - htc_c->pipeline_b); if (j < 0) return; - req->htc->pipeline_b = NULL; - req->htc->pipeline_e = NULL; + htc_c->pipeline_b = NULL; + htc_c->pipeline_e = NULL; v1a->in += j; } memset(fds, 0, sizeof fds); - fds[0].fd = fd; + fds[0].fd = *htc_b->pfd; fds[0].events = POLLIN | POLLERR; - fds[1].fd = req->sp->fd; + fds[1].fd = *htc_c->pfd; fds[1].events = POLLIN | POLLERR; while (fds[0].fd > -1 || fds[1].fd > -1) { fds[0].revents = 0; fds[1].revents = 0; - i = poll(fds, 2, - (int)(cache_param->pipe_timeout * 1e3)); + i = poll(fds, 2, (int)(cache_param->pipe_timeout * 1e3)); if (i < 1) break; - if (fds[0].revents && - rdf(fd, req->sp->fd, &v1a->out)) { + if (fds[0].revents && rdf(htc_b, htc_c, &v1a->out)) { if (fds[1].fd == -1) break; - (void)shutdown(fd, SHUT_RD); - (void)shutdown(req->sp->fd, SHUT_WR); + (void)shutdown(*htc_b->pfd, SHUT_RD); + (void)shutdown(*htc_c->pfd, SHUT_WR); fds[0].events = 0; fds[0].fd = -1; } - if (fds[1].revents && - rdf(req->sp->fd, fd, &v1a->in)) { + if (fds[1].revents && rdf(htc_c, htc_b, &v1a->in)) { if (fds[0].fd == -1) break; - (void)shutdown(req->sp->fd, SHUT_RD); - (void)shutdown(fd, SHUT_WR); + (void)shutdown(*htc_c->pfd, SHUT_RD); + (void)shutdown(*htc_b->pfd, SHUT_WR); fds[1].events = 0; fds[1].fd = -1; } -- 2.1.4
From 95cffb69f43ca6e088dc633c65bc07f84475caf2 Mon Sep 17 00:00:00 2001 From: Martin Blix Grydeland <[email protected]> Date: Thu, 9 Jul 2015 15:52:17 +0200 Subject: [PATCH 09/10] Make pan_htc more useful --- bin/varnishd/cache/cache_panic.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/bin/varnishd/cache/cache_panic.c b/bin/varnishd/cache/cache_panic.c index aaeb7a3..482e11f 100644 --- a/bin/varnishd/cache/cache_panic.c +++ b/bin/varnishd/cache/cache_panic.c @@ -148,11 +148,27 @@ pan_htc(struct vsb *vsb, const struct http_conn *htc) { VSB_printf(vsb, "http_conn = %p {\n", htc); - VSB_printf(vsb, " pfd = %p(", htc->pfd); + VSB_indent(vsb, 2); + VSB_printf(vsb, "pfd = %p(", htc->pfd); if (htc->pfd) VSB_printf(vsb, "<nil>),\n"); else VSB_printf(vsb, "%d),\n", *htc->pfd); + VSB_printf(vsb, "doclose = %s,\n", sess_close_2str(htc->doclose, 0)); + VSB_printf(vsb, "ws = %p,\n", htc->ws); + VSB_printf(vsb, "{rxbuf_b, rxbuf_e} = {%p, %p},\n", + htc->rxbuf_b, htc->rxbuf_e); + VSB_printf(vsb, "{pipeline_b, pipeline_e} = {%p, %p},\n", + htc->pipeline_b, htc->pipeline_e); + VSB_printf(vsb, "content_length = %jd,\n", htc->content_length); + VSB_printf(vsb, "body_status = %s,\n", + body_status_2str(htc->body_status)); + VSB_printf(vsb, "oper = %p,\n", htc->oper); + VSB_printf(vsb, "first_byte_timeout = %f,\n", + htc->first_byte_timeout); + VSB_printf(vsb, "between_bytes_timeout = %f,\n", + htc->between_bytes_timeout); + VSB_indent(vsb, -2); VSB_printf(vsb, "},\n"); } @@ -327,11 +343,9 @@ pan_busyobj(struct vsb *vsb, const struct busyobj *bo) VSB_indent(vsb, -2); VSB_printf(vsb, "},\n"); - if (bo->htc != NULL) { - VSB_printf(vsb, "bodystatus = %d (%s),\n", - bo->htc->body_status, - body_status_2str(bo->htc->body_status)); - } + if (VALID_OBJ(bo->htc, HTTP_CONN_MAGIC)) + pan_htc(vsb, bo->htc); + if (!VTAILQ_EMPTY(&bo->vfc->vfp)) { VSB_printf(vsb, "filters ="); VTAILQ_FOREACH(vfe, &bo->vfc->vfp, list) @@ -340,8 +354,6 @@ pan_busyobj(struct vsb *vsb, const struct busyobj *bo) VSB_printf(vsb, "\n"); } - if (VALID_OBJ(bo->htc, HTTP_CONN_MAGIC)) - pan_htc(vsb, bo->htc); VDI_Panic(bo->director_req, vsb, "director_req"); if (bo->director_resp == bo->director_req) VSB_printf(vsb, "director_resp = director_req,\n"); @@ -402,6 +414,8 @@ pan_req(struct vsb *vsb, const struct req *req) pan_wrk(vsb, req->wrk); pan_ws(vsb, req->ws); + if (VALID_OBJ(req->htc, HTTP_CONN_MAGIC)) + pan_htc(vsb, req->htc); pan_http(vsb, "req", req->http); if (req->resp->ws != NULL) pan_http(vsb, "resp", req->resp); -- 2.1.4
From f5e7a72bb4c8818363a643c0ee09c7e54d296833 Mon Sep 17 00:00:00 2001 From: Martin Blix Grydeland <[email protected]> Date: Thu, 9 Jul 2015 17:19:35 +0200 Subject: [PATCH 10/10] Add a panic operation to htc for custom panic message --- bin/varnishd/cache/cache.h | 2 ++ bin/varnishd/cache/cache_panic.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h index 4eb46df..71c144d 100644 --- a/bin/varnishd/cache/cache.h +++ b/bin/varnishd/cache/cache.h @@ -248,11 +248,13 @@ struct http_conn { typedef ssize_t htc_read_f(struct http_conn *, void *, size_t); typedef ssize_t htc_write_f(struct http_conn *, void *, size_t); typedef ssize_t htc_writev_f(struct http_conn *, const struct iovec *, int); +typedef ssize_t htc_panic_f(struct vsb *, const struct http_conn *); struct htc_oper { htc_read_f *read; htc_write_f *write; htc_writev_f *writev; + htc_panic_f *panic; }; static inline ssize_t diff --git a/bin/varnishd/cache/cache_panic.c b/bin/varnishd/cache/cache_panic.c index 482e11f..4b334db 100644 --- a/bin/varnishd/cache/cache_panic.c +++ b/bin/varnishd/cache/cache_panic.c @@ -168,6 +168,8 @@ pan_htc(struct vsb *vsb, const struct http_conn *htc) htc->first_byte_timeout); VSB_printf(vsb, "between_bytes_timeout = %f,\n", htc->between_bytes_timeout); + if (htc->oper && htc->oper->panic) + htc->oper->panic(vsb, htc); VSB_indent(vsb, -2); VSB_printf(vsb, "},\n"); } -- 2.1.4
_______________________________________________ varnish-dev mailing list [email protected] https://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev
