Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ws: Prep work for trailers support #4130

Merged
merged 2 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions bin/varnishd/cache/cache_session.c
Original file line number Diff line number Diff line change
Expand Up @@ -258,12 +258,20 @@ HTC_Status(enum htc_status_e e, const char **name, const char **desc)
void
HTC_RxInit(struct http_conn *htc, struct ws *ws)
{
unsigned l;
unsigned rollback;
int l;

CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
htc->ws = ws;

l = WS_ReqPipeline(htc->ws, htc->pipeline_b, htc->pipeline_e);
/* NB: HTTP/1 keep-alive triggers a rollback, so does the first
* request of a session or an h2 request where the rollback is a
* no-op in terms of workspace usage.
*/
rollback = !strcasecmp(ws->id, "req") && htc->body_status == NULL;
l = WS_Pipeline(htc->ws, htc->pipeline_b, htc->pipeline_e, rollback);
xxxassert(l >= 0);

htc->rxbuf_b = WS_Reservation(ws);
htc->rxbuf_e = htc->rxbuf_b + l;
htc->pipeline_b = NULL;
Expand Down
2 changes: 1 addition & 1 deletion bin/varnishd/cache/cache_varnishd.h
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ WS_IsReserved(const struct ws *ws)

void *WS_AtOffset(const struct ws *ws, unsigned off, unsigned len);
unsigned WS_ReservationOffset(const struct ws *ws);
unsigned WS_ReqPipeline(struct ws *, const void *b, const void *e);
int WS_Pipeline(struct ws *, const void *b, const void *e, unsigned rollback);

/* cache_ws_common.c */
void WS_Id(const struct ws *ws, char *id);
Expand Down
11 changes: 5 additions & 6 deletions bin/varnishd/cache/cache_ws.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,17 +135,15 @@ WS_Reset(struct ws *ws, uintptr_t pp)
* may not originate from the same workspace.
*/

unsigned
WS_ReqPipeline(struct ws *ws, const void *b, const void *e)
int
WS_Pipeline(struct ws *ws, const void *b, const void *e, unsigned rollback)
{
unsigned r, l;

WS_Assert(ws);

if (!strcasecmp(ws->id, "req"))
if (rollback)
WS_Rollback(ws, 0);
else
AZ(b);

r = WS_ReserveAll(ws);

Expand All @@ -156,7 +154,8 @@ WS_ReqPipeline(struct ws *ws, const void *b, const void *e)

AN(e);
l = pdiff(b, e);
assert(l <= r);
if (l > r)
return (-1);
memmove(ws->f, b, l);
return (l);
}
Expand Down
57 changes: 29 additions & 28 deletions bin/varnishd/cache/cache_ws_emu.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,45 +221,46 @@ WS_Reset(struct ws *ws, uintptr_t pp)
WS_Assert(ws);
}

unsigned
WS_ReqPipeline(struct ws *ws, const void *b, const void *e)
int
WS_Pipeline(struct ws *ws, const void *b, const void *e, unsigned rollback)
{
struct ws_emu *we;
struct ws_alloc *wa;
unsigned l;
void *tmp;
unsigned r, l;

WS_Assert(ws);
AZ(ws->f);
AZ(ws->r);

if (strcasecmp(ws->id, "req"))
AZ(b);

if (b == NULL) {
/* NB: the pipeline cannot be moved if it comes from the same
* workspace because a rollback would free the memory. This is
* emulated with two copies instead.
*/

if (b != NULL) {
AN(e);
l = pdiff(b, e);
tmp = malloc(l);
AN(tmp);
memcpy(tmp, b, l);
} else {
AZ(e);
if (!strcasecmp(ws->id, "req"))
WS_Rollback(ws, 0);
(void)WS_ReserveAll(ws);
return (0);
l = 0;
tmp = NULL;
}

we = ws_emu(ws);
ALLOC_OBJ(wa, WS_ALLOC_MAGIC);
AN(wa);
wa->len = we->len;
wa->ptr = malloc(wa->len);
AN(wa->ptr);
if (rollback)
WS_Rollback(ws, 0);

AN(e);
l = pdiff(b, e);
assert(l <= wa->len);
memcpy(wa->ptr, b, l);
r = WS_ReserveAll(ws);

WS_Rollback(ws, 0);
ws->f = wa->ptr;
ws->r = ws->f + wa->len;
VTAILQ_INSERT_TAIL(&we->head, wa, list);
WS_Assert(ws);
if (l > r) {
free(tmp);
return (-1);
}

if (l > 0)
memcpy(ws->f, tmp, l);
free(tmp);
return (l);
}

Expand Down
6 changes: 3 additions & 3 deletions bin/varnishd/http2/cache_http2.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,17 +234,17 @@ struct h2h_decode {
unsigned has_scheme:1;
h2_error error;
enum vhd_ret_e vhd_ret;
struct ws *ws;
char *out;
char *reset;
int64_t limit;
size_t out_l;
size_t out_u;
size_t namelen;
struct vhd_decode vhd[1];
};

void h2h_decode_init(const struct h2_sess *h2);
h2_error h2h_decode_fini(const struct h2_sess *h2);
void h2h_decode_hdr_init(const struct h2_sess *h2);
h2_error h2h_decode_hdr_fini(const struct h2_sess *h2);
h2_error h2h_decode_bytes(struct h2_sess *h2, const uint8_t *ptr,
size_t len);

Expand Down
42 changes: 26 additions & 16 deletions bin/varnishd/http2/cache_http2_hpack.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,27 +257,25 @@ h2h_addhdr(struct http *hp, struct h2h_decode *d)
return (0);
}

void
h2h_decode_init(const struct h2_sess *h2)
static void
h2h_decode_init(const struct h2_sess *h2, struct ws *ws)
{
struct h2h_decode *d;

CHECK_OBJ_NOTNULL(h2, H2_SESS_MAGIC);
CHECK_OBJ_NOTNULL(h2->new_req, REQ_MAGIC);
CHECK_OBJ_NOTNULL(h2->new_req->http, HTTP_MAGIC);
CHECK_OBJ_NOTNULL(ws, WS_MAGIC);

AN(h2->decode);
d = h2->decode;
INIT_OBJ(d, H2H_DECODE_MAGIC);
VHD_Init(d->vhd);
d->out_l = WS_ReserveSize(h2->new_req->http->ws,
cache_param->http_req_size);
d->out_l = WS_ReserveSize(ws, cache_param->http_req_size);
/*
* Can't do any work without any buffer
* space. Require non-zero size.
*/
XXXAN(d->out_l);
d->out = WS_Reservation(h2->new_req->http->ws);
d->reset = d->out;
d->out = WS_Reservation(ws);

if (cache_param->h2_max_header_list_size == 0)
d->limit =
Expand All @@ -287,6 +285,18 @@ h2h_decode_init(const struct h2_sess *h2)

if (d->limit < h2->local_settings.max_header_list_size)
d->limit = INT64_MAX;

d->ws = ws;
}

void
h2h_decode_hdr_init(const struct h2_sess *h2)
{

CHECK_OBJ_NOTNULL(h2, H2_SESS_MAGIC);
CHECK_OBJ_NOTNULL(h2->new_req, REQ_MAGIC);
CHECK_OBJ_NOTNULL(h2->new_req->http, HTTP_MAGIC);
h2h_decode_init(h2, h2->new_req->ws);
}

/* Possible error returns:
Expand All @@ -298,7 +308,7 @@ h2h_decode_init(const struct h2_sess *h2)
* is a stream level error.
*/
h2_error
h2h_decode_fini(const struct h2_sess *h2)
h2h_decode_hdr_fini(const struct h2_sess *h2)
{
h2_error ret;
struct h2h_decode *d;
Expand All @@ -307,7 +317,7 @@ h2h_decode_fini(const struct h2_sess *h2)
d = h2->decode;
CHECK_OBJ_NOTNULL(h2->new_req, REQ_MAGIC);
CHECK_OBJ_NOTNULL(d, H2H_DECODE_MAGIC);
WS_ReleaseP(h2->new_req->http->ws, d->out);
WS_ReleaseP(d->ws, d->out);
if (d->vhd_ret != VHD_OK) {
/* HPACK header block didn't finish at an instruction
boundary */
Expand Down Expand Up @@ -347,12 +357,12 @@ h2h_decode_bytes(struct h2_sess *h2, const uint8_t *in, size_t in_l)
CHECK_OBJ_NOTNULL(h2->new_req, REQ_MAGIC);
hp = h2->new_req->http;
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
CHECK_OBJ_NOTNULL(hp->ws, WS_MAGIC);
r = WS_Reservation(hp->ws);
AN(r);
e = r + WS_ReservationSize(hp->ws);
d = h2->decode;
CHECK_OBJ_NOTNULL(d, H2H_DECODE_MAGIC);
CHECK_OBJ_NOTNULL(d->ws, WS_MAGIC);
r = WS_Reservation(d->ws);
AN(r);
e = r + WS_ReservationSize(d->ws);

/* Only H2E_ENHANCE_YOUR_CALM indicates that we should continue
processing. Other errors should have been returned and handled
Expand Down Expand Up @@ -427,7 +437,7 @@ h2h_decode_bytes(struct h2_sess *h2, const uint8_t *in, size_t in_l)
}

if (H2_ERROR_MATCH(d->error, H2SE_ENHANCE_YOUR_CALM)) {
d->out = d->reset;
d->out = WS_Reservation(d->ws);
d->out_l = e - d->out;
d->limit -= d->out_u;
d->out_u = 0;
Expand All @@ -444,7 +454,7 @@ h2h_decode_bytes(struct h2_sess *h2, const uint8_t *in, size_t in_l)
}

if (H2_ERROR_MATCH(d->error, H2SE_ENHANCE_YOUR_CALM)) {
/* Stream error, delay reporting until h2h_decode_fini so
/* Stream error, delay reporting until h2h_decode_hdr_fini so
* that we can process the complete header block. */
return (NULL);
}
Expand Down
10 changes: 5 additions & 5 deletions bin/varnishd/http2/cache_http2_proto.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ h2_kill_req(struct worker *wrk, struct h2_sess *h2,
r2 = NULL;
} else {
if (r2->state == H2_S_OPEN && h2->new_req == r2->req)
(void)h2h_decode_fini(h2);
(void)h2h_decode_hdr_fini(h2);
}
Lck_Unlock(&h2->sess->mtx);
if (r2 != NULL)
Expand Down Expand Up @@ -634,7 +634,7 @@ h2_end_headers(struct worker *wrk, struct h2_sess *h2,

ASSERT_RXTHR(h2);
assert(r2->state == H2_S_OPEN);
h2e = h2h_decode_fini(h2);
h2e = h2h_decode_hdr_fini(h2);
h2->new_req = NULL;
if (h2e != NULL) {
Lck_Lock(&h2->sess->mtx);
Expand Down Expand Up @@ -767,7 +767,7 @@ h2_rx_headers(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
HTTP_Setup(req->http, req->ws, req->vsl, SLT_ReqMethod);
http_SetH(req->http, HTTP_HDR_PROTO, "HTTP/2.0");

h2h_decode_init(h2);
h2h_decode_hdr_init(h2);

p = h2->rxf_data;
l = h2->rxf_len;
Expand All @@ -788,7 +788,7 @@ h2_rx_headers(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
Lck_Lock(&h2->sess->mtx);
VSLb(h2->vsl, SLT_Debug, "HPACK(hdr) %s", h2e->name);
Lck_Unlock(&h2->sess->mtx);
(void)h2h_decode_fini(h2);
(void)h2h_decode_hdr_fini(h2);
assert(!WS_IsReserved(r2->req->ws));
h2_del_req(wrk, r2);
return (h2e);
Expand Down Expand Up @@ -823,7 +823,7 @@ h2_rx_continuation(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
Lck_Lock(&h2->sess->mtx);
VSLb(h2->vsl, SLT_Debug, "HPACK(cont) %s", h2e->name);
Lck_Unlock(&h2->sess->mtx);
(void)h2h_decode_fini(h2);
(void)h2h_decode_hdr_fini(h2);
assert(!WS_IsReserved(r2->req->ws));
h2_del_req(wrk, r2);
return (h2e);
Expand Down