[master] 0c35ac8 Use the HTTP/1 VFP's for fetching the req.body
Poul-Henning Kamp
phk at FreeBSD.org
Mon Sep 8 15:18:30 CEST 2014
commit 0c35ac8a7df799b53c31d8429206b928a9b9ca2b
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Mon Sep 8 13:17:56 2014 +0000
Use the HTTP/1 VFP's for fetching the req.body
diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index 89d019f..1f0e512 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -605,12 +605,6 @@ struct req {
volatile enum req_body_state_e req_body_status;
struct body body[1];
- struct {
- ssize_t bytes_done;
- ssize_t bytes_yet;
- intptr_t chunk_ctr;
- } h1; /* HTTP1 specific */
-
/* The busy objhead we sleep on */
struct objhead *hash_objhead;
@@ -810,7 +804,7 @@ void VBO_waitstate(struct busyobj *bo, enum busyobj_state_e want);
/* cache_http1_fetch.c [V1F] */
int V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, struct req *req);
-void V1F_Setup_Fetch(struct vfp_ctx *vfc, ssize_t cl, struct http_conn *htc);
+void V1F_Setup_Fetch(struct vfp_ctx *vfc, struct http_conn *htc);
/* cache_http1_fsm.c [HTTP1] */
typedef int (req_body_iter_f)(struct req *, void *priv, void *ptr, size_t);
diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c
index ab71e87..ba547ca 100644
--- a/bin/varnishd/cache/cache_fetch.c
+++ b/bin/varnishd/cache/cache_fetch.c
@@ -556,7 +556,7 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo)
ObjSetFlag(bo->vfc, OF_IMSCAND, 1);
if (bo->htc->body_status != BS_NONE)
- V1F_Setup_Fetch(bo->vfc, bo->content_length, bo->htc);
+ V1F_Setup_Fetch(bo->vfc, bo->htc);
/*
* Ready to fetch the body
diff --git a/bin/varnishd/cache/cache_http1_fetch.c b/bin/varnishd/cache/cache_http1_fetch.c
index 4ab5d47..4b76f46 100644
--- a/bin/varnishd/cache/cache_http1_fetch.c
+++ b/bin/varnishd/cache/cache_http1_fetch.c
@@ -153,7 +153,7 @@ static const struct vfp v1f_eof = {
*/
void
-V1F_Setup_Fetch(struct vfp_ctx *vfc, ssize_t cl, struct http_conn *htc)
+V1F_Setup_Fetch(struct vfp_ctx *vfc, struct http_conn *htc)
{
struct vfp_entry *vfe;
@@ -162,17 +162,17 @@ V1F_Setup_Fetch(struct vfp_ctx *vfc, ssize_t cl, struct http_conn *htc)
switch(htc->body_status) {
case BS_EOF:
- assert(cl == -1);
+ assert(htc->content_length == -1);
vfe = VFP_Push(vfc, &v1f_eof, 0);
vfe->priv2 = 0;
break;
case BS_LENGTH:
- assert(cl > 0);
+ assert(htc->content_length > 0);
vfe = VFP_Push(vfc, &v1f_straight, 0);
- vfe->priv2 = cl;
+ vfe->priv2 = htc->content_length;
break;
case BS_CHUNKED:
- assert(cl == -1);
+ assert(htc->content_length == -1);
vfe = VFP_Push(vfc, &v1f_chunked, 0);
vfe->priv2 = -1;
break;
@@ -181,7 +181,6 @@ V1F_Setup_Fetch(struct vfp_ctx *vfc, ssize_t cl, struct http_conn *htc)
break;
}
vfe->priv1 = htc;
- return;
}
/*--------------------------------------------------------------------
diff --git a/bin/varnishd/cache/cache_http1_fsm.c b/bin/varnishd/cache/cache_http1_fsm.c
index b707e55..3a1a7cc 100644
--- a/bin/varnishd/cache/cache_http1_fsm.c
+++ b/bin/varnishd/cache/cache_http1_fsm.c
@@ -270,8 +270,6 @@ http1_dissect(struct worker *wrk, struct req *req)
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
- memset(&req->h1, 0, sizeof req->h1);
-
/*
* Cache_req_fsm zeros the vxid once a requests is processed.
* Allocate a new one only now that we know will need it.
@@ -305,11 +303,8 @@ http1_dissect(struct worker *wrk, struct req *req)
if (req->req_body_status != REQ_BODY_INIT) {
assert(req->req_body_status == REQ_BODY_NONE); // ESI
} else if (req->htc->body_status == BS_CHUNKED) {
- req->h1.chunk_ctr = -1;
req->req_body_status = REQ_BODY_CHUNKED;
} else if (req->htc->body_status == BS_LENGTH) {
- req->req_bodybytes = req->htc->content_length;
- req->h1.bytes_yet = req->req_bodybytes - req->h1.bytes_done;
req->req_body_status = REQ_BODY_PRESENT;
} else if (req->htc->body_status == BS_NONE) {
req->req_body_status = REQ_BODY_NONE;
@@ -446,50 +441,6 @@ HTTP1_Session(struct worker *wrk, struct req *req)
}
}
-static ssize_t
-http1_iter_req_body(struct req *req, enum req_body_state_e bs,
- void *buf, ssize_t len)
-{
- const char *err;
-
- CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
-
- AN(len);
- AN(buf);
- if (bs == REQ_BODY_PRESENT) {
- AN(req->req_bodybytes);
- if (len > req->req_bodybytes - req->h1.bytes_done)
- len = req->req_bodybytes - req->h1.bytes_done;
- if (len == 0) {
- req->req_body_status = REQ_BODY_DONE;
- return (0);
- }
- len = HTTP1_Read(req->htc, buf, len);
- if (len <= 0) {
- req->req_body_status = REQ_BODY_FAIL;
- return (-1);
- }
- req->h1.bytes_done += len;
- req->h1.bytes_yet = req->req_bodybytes - req->h1.bytes_done;
- req->acct.req_bodybytes += len;
- return (len);
- } else if (bs == REQ_BODY_CHUNKED) {
- switch (HTTP1_Chunked(req->htc, &req->h1.chunk_ctr, &err,
- &req->acct.req_bodybytes, buf, &len)) {
- case H1CR_ERROR:
- VSLb(req->vsl, SLT_Debug, "CHUNKERR: %s", err);
- return (-1);
- case H1CR_MORE:
- return (len);
- case H1CR_END:
- return (0);
- default:
- WRONG("invalid HTTP1_Chunked return");
- }
- } else
- WRONG("Illegal req_bodystatus");
-}
-
/*----------------------------------------------------------------------
* Iterate over the req.body.
*
@@ -502,9 +453,10 @@ HTTP1_IterateReqBody(struct req *req, req_body_iter_f *func, void *priv)
{
char buf[8192];
struct storage *st;
- enum req_body_state_e bs;
ssize_t l;
int i;
+ struct vfp_ctx vfc;
+ enum vfp_status vfps = VFP_ERROR;
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
AN(func);
@@ -535,7 +487,6 @@ HTTP1_IterateReqBody(struct req *req, req_body_iter_f *func, void *priv)
WRONG("Wrong req_body_status in HTTP1_IterateReqBody()");
}
Lck_Lock(&req->sp->mtx);
- bs = req->req_body_status;
if (req->req_body_status == REQ_BODY_PRESENT ||
req->req_body_status == REQ_BODY_CHUNKED) {
req->req_body_status = REQ_BODY_TAKEN;
@@ -549,20 +500,33 @@ HTTP1_IterateReqBody(struct req *req, req_body_iter_f *func, void *priv)
return (i);
}
+ VFP_Setup(&vfc);
+ vfc.http = req->http;
+ vfc.vsl = req->vsl;
+ V1F_Setup_Fetch(&vfc, req->htc);
+ if (VFP_Open(&vfc) < 0) {
+ VSLb(req->vsl, SLT_FetchError, "Could not open Fetch Pipeline");
+ return (-1);
+ }
+
do {
- l = http1_iter_req_body(req, bs, buf, sizeof buf);
- if (l < 0) {
- req->doclose = SC_RX_BODY;
+ l = sizeof buf;
+ vfps = VFP_Suck(&vfc, buf, &l);
+ if (vfps == VFP_ERROR) {
+ req->req_body_status = REQ_BODY_FAIL;
+ l = -1;
break;
- }
- if (l > 0) {
- i = func(req, priv, buf, l);
- if (i) {
- l = i;
+ } else if (l > 0) {
+ req->req_bodybytes += l;
+ req->acct.req_bodybytes += l;
+ l = func(req, priv, buf, l);
+ if (l) {
+ req->req_body_status = REQ_BODY_FAIL;
break;
}
}
- } while (l > 0);
+ } while (vfps == VFP_OK);
+ VFP_Close(&vfc);
VSLb_ts_req(req, "ReqBody", VTIM_real());
return (l);
@@ -609,7 +573,9 @@ int
HTTP1_CacheReqBody(struct req *req, ssize_t maxsize)
{
struct storage *st;
- ssize_t l, l2;
+ ssize_t l, yet;
+ struct vfp_ctx vfc;
+ enum vfp_status vfps = VFP_ERROR;
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
@@ -627,18 +593,30 @@ HTTP1_CacheReqBody(struct req *req, ssize_t maxsize)
WRONG("Wrong req_body_status in HTTP1_CacheReqBody()");
}
- if (req->req_bodybytes > maxsize) {
+ if (req->htc->content_length > maxsize) {
req->req_body_status = REQ_BODY_FAIL;
return (-1);
}
- l2 = 0;
+ VFP_Setup(&vfc);
+ vfc.http = req->http;
+ vfc.vsl = req->vsl;
+ V1F_Setup_Fetch(&vfc, req->htc);
+
+ if (VFP_Open(&vfc) < 0) {
+ req->req_body_status = REQ_BODY_FAIL;
+ return (-1);
+ }
+
+
+ yet = req->htc->content_length;
+ if (yet < 0)
+ yet = 0;
st = NULL;
do {
if (st == NULL) {
st = STV_alloc_transient(
- req->h1.bytes_yet ?
- req->h1.bytes_yet : cache_param->fetch_chunksize);
+ yet ? yet : cache_param->fetch_chunksize);
if (st == NULL) {
req->req_body_status = REQ_BODY_FAIL;
l = -1;
@@ -647,39 +625,46 @@ HTTP1_CacheReqBody(struct req *req, ssize_t maxsize)
VTAILQ_INSERT_TAIL(&req->body->list, st, list);
}
}
-
l = st->space - st->len;
- l = http1_iter_req_body(req, req->req_body_status,
- st->ptr + st->len, l);
- if (l < 0) {
- req->doclose = SC_RX_BODY;
- break;
- }
- if (req->req_bodybytes > maxsize) {
+ vfps = VFP_Suck(&vfc, st->ptr + st->len, &l);
+ if (vfps == VFP_ERROR) {
req->req_body_status = REQ_BODY_FAIL;
l = -1;
break;
}
if (l > 0) {
- l2 += l;
+ req->req_bodybytes += l;
+ req->acct.req_bodybytes += l;
+ if (yet > 0)
+ yet -= l;
st->len += l;
if (st->space == st->len)
st = NULL;
+ l = 0;
}
- } while (l > 0);
+ if (req->req_bodybytes > maxsize) {
+ req->req_body_status = REQ_BODY_FAIL;
+ l = -1;
+ break;
+ }
+ } while (vfps == VFP_OK);
+ VFP_Close(&vfc);
+
+
if (l == 0) {
- req->req_bodybytes = l2;
- /* We must update also the "pristine" req.* copy */
-
- http_Unset(req->http0, H_Content_Length);
- http_Unset(req->http0, H_Transfer_Encoding);
- http_PrintfHeader(req->http0, "Content-Length: %ju",
- (uintmax_t)req->req_bodybytes);
-
- http_Unset(req->http, H_Content_Length);
- http_Unset(req->http, H_Transfer_Encoding);
- http_PrintfHeader(req->http, "Content-Length: %ju",
- (uintmax_t)req->req_bodybytes);
+
+ if (req->req_bodybytes != req->htc->content_length) {
+ /* We must update also the "pristine" req.* copy */
+ http_Unset(req->http0, H_Content_Length);
+ http_Unset(req->http0, H_Transfer_Encoding);
+ http_PrintfHeader(req->http0, "Content-Length: %ju",
+ (uintmax_t)req->req_bodybytes);
+
+ http_Unset(req->http, H_Content_Length);
+ http_Unset(req->http, H_Transfer_Encoding);
+ http_PrintfHeader(req->http, "Content-Length: %ju",
+ (uintmax_t)req->req_bodybytes);
+ }
req->req_body_status = REQ_BODY_CACHED;
}
More information about the varnish-commit
mailing list