[master] e5f8204 Make Continuation frames non-panicky.
Poul-Henning Kamp
phk at FreeBSD.org
Fri Mar 3 16:15:06 CET 2017
commit e5f8204e7161de46f15347c506112078159e95c4
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Fri Mar 3 15:14:32 2017 +0000
Make Continuation frames non-panicky.
diff --git a/bin/varnishd/http2/cache_http2.h b/bin/varnishd/http2/cache_http2.h
index 58acdeb..b950dad 100644
--- a/bin/varnishd/http2/cache_http2.h
+++ b/bin/varnishd/http2/cache_http2.h
@@ -28,6 +28,7 @@
*/
struct h2_sess;
+struct h2h_decode;
#include "hpack/vhp.h"
@@ -83,6 +84,7 @@ struct h2_req {
struct req *req;
VTAILQ_ENTRY(h2_req) list;
int64_t window;
+ struct h2h_decode *decode;
};
VTAILQ_HEAD(h2_req_s, h2_req);
diff --git a/bin/varnishd/http2/cache_http2_proto.c b/bin/varnishd/http2/cache_http2_proto.c
index 63eeb4e..602608f 100644
--- a/bin/varnishd/http2/cache_http2_proto.c
+++ b/bin/varnishd/http2/cache_http2_proto.c
@@ -32,6 +32,7 @@
#include "cache/cache.h"
#include <stdio.h>
+#include <stdlib.h>
#include "cache/cache_transport.h"
#include "cache/cache_filter.h"
@@ -206,19 +207,6 @@ h2_rx_ping(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
*/
static h2_error __match_proto__(h2_frame_f)
-h2_rx_continuation(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
-{
- (void)wrk;
- (void)h2;
- (void)r2;
- INCOMPL();
- NEEDLESS(return (H2CE_PROTOCOL_ERROR));
-}
-
-/**********************************************************************
- */
-
-static h2_error __match_proto__(h2_frame_f)
h2_rx_push_promise(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
{
(void)wrk;
@@ -363,20 +351,41 @@ h2_do_req(struct worker *wrk, void *priv)
h2_del_req(wrk, r2);
}
+static h2_error
+h2_end_headers(struct worker *wrk, struct h2_sess *h2, struct req *req,
+ struct h2_req *r2)
+{
+ h2_error h2e;
+
+ h2e = h2h_decode_fini(h2, r2->decode);
+ FREE_OBJ(r2->decode);
+ if (h2e != NULL) {
+ VSL(SLT_Debug, 0, "H2H_DECODE_FINI %s", h2e->name);
+ return (h2e);
+ }
+ VSLb_ts_req(req, "Req", req->t_req);
+
+ if (h2->rxf_flags & H2FF_HEADERS_END_STREAM)
+ req->req_body_status = REQ_BODY_NONE;
+ else
+ req->req_body_status = REQ_BODY_WITHOUT_LEN;
+
+ req->task.func = h2_do_req;
+ req->task.priv = req;
+ XXXAZ(Pool_Task(wrk->pool, &req->task, TASK_QUEUE_REQ));
+ return (0);
+}
+
static h2_error __match_proto__(h2_frame_f)
h2_rx_headers(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
{
struct req *req;
- struct h2h_decode d[1];
h2_error h2e;
const uint8_t *p;
size_t l;
- /* XXX: This still lacks support for CONTINUATION frames, half
- * read frames and proper error handling.
- */
-
- xxxassert(r2->state == H2_S_IDLE);
+ if (r2->state != H2_S_IDLE)
+ return (H2CE_PROTOCOL_ERROR); // XXX spec ?
r2->state = H2_S_OPEN;
req = r2->req;
@@ -400,7 +409,12 @@ h2_rx_headers(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
wrk->vcl = NULL;
HTTP_Setup(req->http, req->ws, req->vsl, SLT_ReqMethod);
- h2h_decode_init(h2, d);
+ http_SetH(req->http, HTTP_HDR_PROTO, "HTTP/2.0");
+
+ ALLOC_OBJ(r2->decode, H2H_DECODE_MAGIC);
+ AN(r2->decode);
+ h2h_decode_init(h2, r2->decode);
+
/* XXX: Error handling */
p = h2->rxf_data;
l = h2->rxf_len;
@@ -412,27 +426,36 @@ h2_rx_headers(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
p += 5;
l -= 5;
}
- h2e = h2h_decode_bytes(h2, d, p, l);
+ h2e = h2h_decode_bytes(h2, r2->decode, p, l);
if (h2e != NULL) {
VSL(SLT_Debug, 0, "H2H_DECODE_BYTES %s", h2e->name);
return (h2e);
}
- h2e = h2h_decode_fini(h2, d);
+ if (h2->rxf_flags & H2FF_HEADERS_END_HEADERS)
+ return (h2_end_headers(wrk, h2, req, r2));
+ return (0);
+}
+
+/**********************************************************************
+ * XXX: Check hard sequence req. for Cont.
+ */
+
+static h2_error __match_proto__(h2_frame_f)
+h2_rx_continuation(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
+{
+ struct req *req;
+ h2_error h2e;
+
+ if (r2->state != H2_S_OPEN)
+ return (H2CE_PROTOCOL_ERROR); // XXX spec ?
+ req = r2->req;
+ h2e = h2h_decode_bytes(h2, r2->decode, h2->rxf_data, h2->rxf_len);
if (h2e != NULL) {
- VSL(SLT_Debug, 0, "H2H_DECODE_FINI %s", h2e->name);
+ VSL(SLT_Debug, 0, "H2H_DECODE_BYTES %s", h2e->name);
return (h2e);
}
- VSLb_ts_req(req, "Req", req->t_req);
- http_SetH(req->http, HTTP_HDR_PROTO, "HTTP/2.0");
-
- if (h2->rxf_flags & H2FF_HEADERS_END_STREAM)
- req->req_body_status = REQ_BODY_NONE;
- else
- req->req_body_status = REQ_BODY_WITHOUT_LEN;
-
- req->task.func = h2_do_req;
- req->task.priv = req;
- XXXAZ(Pool_Task(wrk->pool, &req->task, TASK_QUEUE_REQ));
+ if (h2->rxf_flags & H2FF_HEADERS_END_HEADERS)
+ return (h2_end_headers(wrk, h2, req, r2));
return (0);
}
diff --git a/bin/varnishtest/tests/t02006.vtc b/bin/varnishtest/tests/t02006.vtc
index 1fd54e1..0160090 100644
--- a/bin/varnishtest/tests/t02006.vtc
+++ b/bin/varnishtest/tests/t02006.vtc
@@ -11,7 +11,18 @@ varnish v1 -cliok "param.set debug +syncvsl"
client c1 {
stream 1 {
- txreq -req POST -hdr expect 100-continue -hdr content-type text/plain -hdr content-length 7 -body request
+ txreq \
+ -req POST \
+ -hdr content-type text/plain \
+ -nostrend \
+ -nohdrend
+ txcont \
+ -hdr expect 100-continue \
+ -hdr content-length 7 \
+ -nostrend
+
+ txdata \
+ -data request
rxhdrs
expect resp.status == 100
More information about the varnish-commit
mailing list