Permalink
Browse files

Introduce a selfdescribing h2_error struct

  • Loading branch information...
1 parent 3f46e4f commit a62435b33d1f445fdda131e3e41c0b4a6d7da2a9 @bsdphk bsdphk committed Feb 16, 2017
@@ -31,13 +31,26 @@ struct h2_sess;
#include "hpack/vhp.h"
-enum h2_error_e {
- H2E__DUMMY = -1,
-#define H2_ERROR(NAME, val, sc, desc) \
- H2E_##NAME = val,
-#include "tbl/h2_error.h"
+struct h2_error_s {
+ const char *name;
+ const char *txt;
+ uint32_t val;
+ int stream;
+ int connection;
};
+typedef const struct h2_error_s *h2_error;
+
+#define H2EC0(U,v,d)
+#define H2EC1(U,v,d) extern const struct h2_error_s H2E_C_##U[1];
+#define H2EC2(U,v,d) extern const struct h2_error_s H2E_S_##U[1];
+#define H2EC3(U,v,d) H2EC1(U,v,d) H2EC2(U,v,d)
+#define H2_ERROR(NAME, val, sc, desc) H2EC##sc(NAME, val, desc)
+#include "tbl/h2_error.h"
+#undef H2EC1
+#undef H2EC2
+#undef H2EC3
+
enum h2_frame_e {
H2_FRAME__DUMMY = -1,
#define H2_FRAME(l,u,t,f) H2_FRAME_##u = t,
@@ -118,7 +131,7 @@ struct h2h_decode {
unsigned magic;
#define H2H_DECODE_MAGIC 0xd092bde4
- int error;
+ h2_error error;
enum vhd_ret_e vhd_ret;
char *out;
char *reset;
@@ -129,8 +142,8 @@ struct h2h_decode {
};
void h2h_decode_init(const struct h2_sess *h2, struct h2h_decode *d);
-int h2h_decode_fini(const struct h2_sess *h2, struct h2h_decode *d);
-int h2h_decode_bytes(struct h2_sess *h2, struct h2h_decode *d,
+h2_error h2h_decode_fini(const struct h2_sess *h2, struct h2h_decode *d);
+h2_error h2h_decode_bytes(struct h2_sess *h2, struct h2h_decode *d,
const uint8_t *ptr, size_t len);
int H2_Send_Frame(struct worker *, const struct h2_sess *,
@@ -37,7 +37,7 @@
#include "http2/cache_http2.h"
#include "vct.h"
-static int
+static h2_error
h2h_checkhdr(const struct http *hp, const char *b, size_t namelen, size_t len)
{
const char *p;
@@ -49,7 +49,7 @@ h2h_checkhdr(const struct http *hp, const char *b, size_t namelen, size_t len)
if (namelen == 2) {
VSLb(hp->vsl, SLT_BogoHeader, "Empty name");
- return (H2E_PROTOCOL_ERROR);
+ return (H2E_C_PROTOCOL_ERROR);
}
for (p = b; p < b + len; p++) {
@@ -64,7 +64,7 @@ h2h_checkhdr(const struct http *hp, const char *b, size_t namelen, size_t len)
VSLb(hp->vsl, SLT_BogoHeader,
"Illegal header name: %.*s",
(int)(len > 20 ? 20 : len), b);
- return (H2E_PROTOCOL_ERROR);
+ return (H2E_C_PROTOCOL_ERROR);
} else if (p < b + namelen) {
/* ': ' added by us */
assert(*p == ':' || *p == ' ');
@@ -75,14 +75,14 @@ h2h_checkhdr(const struct http *hp, const char *b, size_t namelen, size_t len)
VSLb(hp->vsl, SLT_BogoHeader,
"Illegal header value: %.*s",
(int)(len > 20 ? 20 : len), b);
- return (H2E_PROTOCOL_ERROR);
+ return (H2E_C_PROTOCOL_ERROR);
}
}
return (0);
}
-static int
+static h2_error
h2h_addhdr(struct http *hp, char *b, size_t namelen, size_t len)
{
/* XXX: This might belong in cache/cache_http.c */
@@ -95,7 +95,7 @@ h2h_addhdr(struct http *hp, char *b, size_t namelen, size_t len)
if (len > UINT_MAX) { /* XXX: cache_param max header size */
VSLb(hp->vsl, SLT_BogoHeader, "Header too large: %.20s", b);
- return (H2E_ENHANCE_YOUR_CALM);
+ return (H2E_S_ENHANCE_YOUR_CALM);
}
if (b[0] == ':') {
@@ -127,7 +127,7 @@ h2h_addhdr(struct http *hp, char *b, size_t namelen, size_t len)
VSLb(hp->vsl, SLT_BogoHeader,
"Unknown pseudo-header: %.*s",
(int)(len > 20 ? 20 : len), b);
- return (H2E_PROTOCOL_ERROR);
+ return (H2E_S_PROTOCOL_ERROR);
}
} else
n = hp->nhd;
@@ -138,14 +138,14 @@ h2h_addhdr(struct http *hp, char *b, size_t namelen, size_t len)
VSLb(hp->vsl, SLT_BogoHeader,
"Duplicate pseudo-header: %.*s",
(int)(len > 20 ? 20 : len), b);
- return (H2E_PROTOCOL_ERROR);
+ return (H2E_S_PROTOCOL_ERROR);
}
} else {
/* Check for space in struct http */
if (n >= hp->shd) {
VSLb(hp->vsl, SLT_LostHeader, "Too many headers: %.*s",
(int)(len > 20 ? 20 : len), b);
- return (H2E_ENHANCE_YOUR_CALM);
+ return (H2E_S_ENHANCE_YOUR_CALM);
}
hp->nhd++;
}
@@ -181,10 +181,10 @@ h2h_decode_init(const struct h2_sess *h2, struct h2h_decode *d)
* H2E_ENHANCE_YOUR_CALM: Ran out of workspace or http header space. This
* is a stream level error.
*/
-int
+h2_error
h2h_decode_fini(const struct h2_sess *h2, struct h2h_decode *d)
{
- int ret;
+ h2_error ret;
CHECK_OBJ_NOTNULL(h2, H2_SESS_MAGIC);
CHECK_OBJ_NOTNULL(h2->new_req, REQ_MAGIC);
@@ -195,7 +195,7 @@ h2h_decode_fini(const struct h2_sess *h2, struct h2h_decode *d)
boundary */
VSLb(h2->new_req->http->vsl, SLT_BogoHeader,
"HPACK compression error (%s)", VHD_Error(d->vhd_ret));
- ret = H2E_COMPRESSION_ERROR;
+ ret = H2E_C_COMPRESSION_ERROR;
} else
ret = d->error;
d->magic = 0;
@@ -209,7 +209,7 @@ h2h_decode_fini(const struct h2_sess *h2, struct h2h_decode *d)
*
* H2E_PROTOCOL_ERROR: Malformed header or duplicate pseudo-header.
*/
-int
+h2_error
h2h_decode_bytes(struct h2_sess *h2, struct h2h_decode *d,
const uint8_t *in, size_t in_l)
{
@@ -227,7 +227,7 @@ h2h_decode_bytes(struct h2_sess *h2, struct h2h_decode *d,
/* Only H2E_ENHANCE_YOUR_CALM indicates that we should continue
processing. Other errors should have been returned and handled
by the caller. */
- assert(d->error == 0 || d->error == H2E_ENHANCE_YOUR_CALM);
+ assert(d->error == 0 || d->error == H2E_S_ENHANCE_YOUR_CALM);
while (1) {
AN(d->out);
@@ -239,14 +239,14 @@ h2h_decode_bytes(struct h2_sess *h2, struct h2h_decode *d,
VSLb(hp->vsl, SLT_BogoHeader,
"HPACK compression error (%s)",
VHD_Error(d->vhd_ret));
- d->error = H2E_COMPRESSION_ERROR;
+ d->error = H2E_C_COMPRESSION_ERROR;
break;
} else if (d->vhd_ret == VHD_OK || d->vhd_ret == VHD_MORE) {
assert(in_u == in_l);
break;
}
- if (d->error == H2E_ENHANCE_YOUR_CALM) {
+ if (d->error == H2E_S_ENHANCE_YOUR_CALM) {
d->out_u = 0;
assert(d->out_u < d->out_l);
continue;
@@ -258,7 +258,7 @@ h2h_decode_bytes(struct h2_sess *h2, struct h2h_decode *d,
case VHD_NAME:
assert(d->namelen == 0);
if (d->out_l - d->out_u < 2) {
- d->error = H2E_ENHANCE_YOUR_CALM;
+ d->error = H2E_S_ENHANCE_YOUR_CALM;
break;
}
d->out[d->out_u++] = ':';
@@ -271,7 +271,7 @@ h2h_decode_bytes(struct h2_sess *h2, struct h2h_decode *d,
case VHD_VALUE:
assert(d->namelen > 0);
if (d->out_l - d->out_u < 1) {
- d->error = H2E_ENHANCE_YOUR_CALM;
+ d->error = H2E_S_ENHANCE_YOUR_CALM;
break;
}
d->error = h2h_checkhdr(hp, d->out, d->namelen,
@@ -289,15 +289,15 @@ h2h_decode_bytes(struct h2_sess *h2, struct h2h_decode *d,
break;
case VHD_BUF:
- d->error = H2E_ENHANCE_YOUR_CALM;
+ d->error = H2E_S_ENHANCE_YOUR_CALM;
break;
default:
WRONG("Unhandled return value");
break;
}
- if (d->error == H2E_ENHANCE_YOUR_CALM) {
+ if (d->error == H2E_S_ENHANCE_YOUR_CALM) {
http_Teardown(hp);
d->out = d->reset;
d->out_l = hp->ws->r - d->out;
@@ -307,7 +307,7 @@ h2h_decode_bytes(struct h2_sess *h2, struct h2h_decode *d,
break;
}
- if (d->error == H2E_ENHANCE_YOUR_CALM)
+ if (d->error == H2E_S_ENHANCE_YOUR_CALM)
return (0); /* Stream error, delay reporting until
h2h_decode_fini so that we can process the
complete header block */
@@ -40,6 +40,16 @@
#include "vtcp.h"
#include "vtim.h"
+#define H2EC0(U,v,d)
+#define H2EC1(U,v,d) const struct h2_error_s H2E_C_##U[1] = {{#U,d,v,0,1}};
+#define H2EC2(U,v,d) const struct h2_error_s H2E_S_##U[1] = {{#U,d,v,1,0}};
+#define H2EC3(U,v,d) H2EC1(U,v,d) H2EC2(U,v,d)
+#define H2_ERROR(NAME, val, sc, desc) H2EC##sc(NAME, val, desc)
+#include "tbl/h2_error.h"
+#undef H2EC1
+#undef H2EC2
+#undef H2EC3
+
enum h2frame {
#define H2_FRAME(l,u,t,f) H2F_##u = t,
#include "tbl/h2_frames.h"
@@ -189,7 +199,7 @@ h2_new_req(const struct worker *wrk, struct h2_sess *h2,
}
static void
-h2_del_req(struct worker *wrk, struct h2_req *r2, enum h2_error_e err)
+h2_del_req(struct worker *wrk, struct h2_req *r2, h2_error err)
{
struct h2_sess *h2;
struct sess *sp;
@@ -384,7 +394,7 @@ h2_do_req(struct worker *wrk, void *priv)
VSL(SLT_Debug, 0, "H2REQ CNT done");
/* XXX clean up req */
r2->state = H2_S_CLOSED;
- h2_del_req(wrk, r2, H2E_NO_ERROR);
+ h2_del_req(wrk, r2, H2E_S_NO_ERROR);
}
void __match_proto__(h2_frame_f)
@@ -394,7 +404,6 @@ h2_rx_headers(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
struct h2h_decode d[1];
const uint8_t *p;
size_t l;
- int i;
/* XXX: This still lacks support for CONTINUATION frames, half
* read frames and proper error handling.
@@ -436,14 +445,8 @@ h2_rx_headers(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
p += 5;
l -= 5;
}
- i = h2h_decode_bytes(h2, d, p, l);
- if (i)
- VSLb(h2->vsl, SLT_Debug, "H2H_decode_bytes = %d", i);
- XXXAZ(i);
- i = h2h_decode_fini(h2, d);
- if (i)
- VSLb(h2->vsl, SLT_Debug, "H2H_decode_fini = %d", i);
- XXXAZ(i);
+ XXXAZ(h2h_decode_bytes(h2, d, p, l));
+ XXXAZ(h2h_decode_fini(h2, d));
VSLb_ts_req(req, "Req", req->t_req);
http_SetH(req->http, HTTP_HDR_PROTO, "HTTP/2.0");
@@ -762,7 +765,7 @@ h2_new_session(struct worker *wrk, void *arg)
/* Delete all idle streams */
VTAILQ_FOREACH_SAFE(r2, &h2->streams, list, r22) {
if (r2->state == H2_S_IDLE)
- h2_del_req(wrk, r2, H2E_NO_ERROR);
+ h2_del_req(wrk, r2, H2E_S_NO_ERROR);
}
}
@@ -32,7 +32,7 @@
/*lint -save -e525 -e539 */
-H2_ERROR(NO_ERROR, 0x0,0, "Graceful shutdown")
+H2_ERROR(NO_ERROR, 0x0,3, "Graceful shutdown")
H2_ERROR(PROTOCOL_ERROR, 0x1,3, "Protocol error detected")
H2_ERROR(INTERNAL_ERROR, 0x2,3, "Implementation fault")
H2_ERROR(FLOW_CONTROL_ERROR, 0x3,3, "Flow-control limits exceeded")

0 comments on commit a62435b

Please sign in to comment.