Commit 39ea60c0 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Some work on H2 RST_STREAM and GOAWAY

parent 3db2f6a0
......@@ -123,8 +123,11 @@ struct h2_req {
int64_t window;
struct h2h_decode *decode;
struct worker *tx_wrk;
/* Where to wake this stream up */
struct worker *wrk;
VTAILQ_ENTRY(h2_req) tx_list;
h2_error error;
};
VTAILQ_HEAD(h2_req_s, h2_req);
......@@ -159,12 +162,12 @@ struct h2_sess {
struct h2_settings local_settings;
struct req *new_req;
int go_away;
uint32_t go_away_last_stream;
uint32_t goaway_last_stream;
VTAILQ_HEAD(,h2_req) txqueue;
struct h2_req req0[1];
h2_error error;
};
/* http2/cache_http2_panic.c */
......@@ -200,13 +203,13 @@ h2_error h2h_decode_bytes(struct h2_sess *h2, struct h2h_decode *d,
/* cache_http2_send.c */
void H2_Send_Get(struct worker *, struct h2_sess *, struct h2_req *);
void H2_Send_Rel(struct worker *, struct h2_sess *, struct h2_req *);
void H2_Send_Rel(struct h2_sess *, const struct h2_req *);
h2_error H2_Send_Frame(struct worker *, const struct h2_sess *,
h2_frame type, uint8_t flags, uint32_t len, uint32_t stream,
const void *);
h2_error H2_Send(struct worker *, struct h2_req *, int flush,
h2_error H2_Send(struct worker *, const struct h2_req *,
h2_frame type, uint8_t flags, uint32_t len, const void *);
/* cache_http2_proto.c */
......@@ -216,6 +219,5 @@ void h2_del_req(struct worker *, struct h2_req *);
int h2_rxframe(struct worker *, struct h2_sess *);
h2_error h2_set_setting(struct h2_sess *, const uint8_t *);
void h2_req_body(struct req*);
h2_error H2_StreamError(uint32_t);
h2_error H2_ConnectionError(uint32_t);
......@@ -85,11 +85,10 @@ h2_bytes(struct req *req, enum vdp_action act, void **priv,
return (0);
H2_Send_Get(req->wrk, r2->h2sess, r2);
H2_Send(req->wrk, r2,
act != VDP_NULL ? 1 : 0,
H2_F_DATA,
act == VDP_FINI ? H2FF_DATA_END_STREAM : H2FF_NONE,
len, ptr);
H2_Send_Rel(req->wrk, r2->h2sess, r2);
H2_Send_Rel(r2->h2sess, r2);
return (0);
}
......@@ -144,12 +143,12 @@ h2_minimal_response(struct req *req, uint16_t status)
/* XXX return code checking once H2_Send returns anything but 0 */
H2_Send_Get(req->wrk, r2->h2sess, r2);
H2_Send(req->wrk, r2, 1,
H2_Send(req->wrk, r2,
H2_F_HEADERS,
H2FF_HEADERS_END_HEADERS |
(status < 200 ? 0 : H2FF_HEADERS_END_STREAM),
l, buf);
H2_Send_Rel(req->wrk, r2->h2sess, r2);
H2_Send_Rel(r2->h2sess, r2);
return (0);
}
......@@ -251,10 +250,10 @@ h2_deliver(struct req *req, struct boc *boc, int sendbody)
sendbody = 0;
H2_Send_Get(req->wrk, r2->h2sess, r2);
H2_Send(req->wrk, r2, 1, H2_F_HEADERS,
H2_Send(req->wrk, r2, H2_F_HEADERS,
(sendbody ? 0 : H2FF_HEADERS_END_STREAM) | H2FF_HEADERS_END_HEADERS,
sz, req->ws->f);
H2_Send_Rel(req->wrk, r2->h2sess, r2);
H2_Send_Rel(r2->h2sess, r2);
WS_Release(req->ws, 0);
......
......@@ -42,7 +42,6 @@
#include "vtcp.h"
#include "vtim.h"
#define H2EC0(U,v,d)
#define H2EC1(U,v,d) const struct h2_error_s H2CE_##U[1] = {{#U,d,v,0,1}};
#define H2EC2(U,v,d) const struct h2_error_s H2SE_##U[1] = {{#U,d,v,1,0}};
#define H2EC3(U,v,d) H2EC1(U,v,d) H2EC2(U,v,d)
......@@ -52,6 +51,14 @@
#undef H2EC2
#undef H2EC3
static const struct h2_error_s H2NN_ERROR[1] = {{
"UNKNOWN_ERROR",
"Unknown error number",
0xffffffff,
1,
1
}};
enum h2frame {
#define H2_FRAME(l,u,t,f,...) H2F_##u = t,
#include "tbl/h2_frames.h"
......@@ -72,6 +79,56 @@ h2_framename(enum h2frame h2f)
#define H2_FRAME_FLAGS(l,u,v) const uint8_t H2FF_##u = v;
#include "tbl/h2_frames.h"
/**********************************************************************
*/
static const h2_error stream_errors[] = {
#define H2EC1(U,v,d)
#define H2EC2(U,v,d) [v] = H2SE_##U,
#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
};
#define NSTREAMERRORS (sizeof(stream_errors)/sizeof(stream_errors[0]))
h2_error
H2_StreamError(uint32_t u)
{
if (u < NSTREAMERRORS && stream_errors[u] != NULL)
return (stream_errors[u]);
else
return (H2NN_ERROR);
}
/**********************************************************************
*/
static const h2_error conn_errors[] = {
#define H2EC1(U,v,d) [v] = H2CE_##U,
#define H2EC2(U,v,d)
#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
};
#define NCONNERRORS (sizeof(conn_errors)/sizeof(conn_errors[0]))
h2_error
H2_ConnectionError(uint32_t u)
{
if (u < NCONNERRORS && conn_errors[u] != NULL)
return (conn_errors[u]);
else
return (H2NN_ERROR);
}
/**********************************************************************
*/
......@@ -189,7 +246,7 @@ h2_rx_ping(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
H2_Send_Get(wrk, h2, r2);
H2_Send_Frame(wrk, h2,
H2_F_PING, H2FF_PING_ACK, 8, 0, h2->rxf_data);
H2_Send_Rel(wrk, h2, r2);
H2_Send_Rel(h2, r2);
return (0);
}
......@@ -218,8 +275,11 @@ h2_rx_rst_stream(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
return (H2CE_FRAME_SIZE_ERROR);
if (r2 == NULL)
return (0);
INCOMPL();
NEEDLESS(return (H2CE_PROTOCOL_ERROR));
Lck_Lock(&h2->sess->mtx);
r2->error = H2_StreamError(vbe32dec(h2->rxf_data));
if (r2->wrk != NULL)
AZ(pthread_cond_signal(&r2->wrk->cond));
return (0);
}
/**********************************************************************
......@@ -228,14 +288,11 @@ h2_rx_rst_stream(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
static h2_error __match_proto__(h2_frame_f)
h2_rx_goaway(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
{
uint32_t error;
(void)wrk;
(void)r2;
h2->go_away_last_stream = vbe32dec(h2->rxf_data);
error = vbe32dec(h2->rxf_data + 4);
/*XXX*/(void)error;
h2->go_away = 1;
h2->goaway_last_stream = vbe32dec(h2->rxf_data);
h2->error = H2_ConnectionError(vbe32dec(h2->rxf_data + 4));
return (0);
}
......@@ -360,7 +417,7 @@ h2_rx_settings(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
H2_Send_Get(wrk, h2, r2);
H2_Send_Frame(wrk, h2,
H2_F_SETTINGS, H2FF_SETTINGS_ACK, 0, 0, NULL);
H2_Send_Rel(wrk, h2, r2);
H2_Send_Rel(h2, r2);
}
return (0);
}
......@@ -639,7 +696,7 @@ h2_procframe(struct worker *wrk, struct h2_sess *h2,
H2_Send_Get(wrk, h2, r2);
(void)H2_Send_Frame(wrk, h2, H2_F_RST_STREAM,
0, sizeof b, h2->rxf_stream, b);
H2_Send_Rel(wrk, h2, r2);
H2_Send_Rel(h2, r2);
h2_del_req(wrk, r2);
return (0);
......@@ -734,7 +791,7 @@ h2_rxframe(struct worker *wrk, struct h2_sess *h2)
vbe32enc(b + 4, h2e->val);
H2_Send_Get(wrk, h2, h2->req0);
(void)H2_Send_Frame(wrk, h2, H2_F_GOAWAY, 0, 8, 0, b);
H2_Send_Rel(wrk, h2, h2->req0);
H2_Send_Rel(h2, h2->req0);
}
return (h2e ? 0 : 1);
}
......@@ -43,26 +43,28 @@ H2_Send_Get(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
CHECK_OBJ_NOTNULL(h2, H2_SESS_MAGIC);
CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
r2->tx_wrk = wrk;
Lck_Lock(&h2->sess->mtx);
r2->wrk = wrk;
VTAILQ_INSERT_TAIL(&h2->txqueue, r2, tx_list);
while (VTAILQ_FIRST(&h2->txqueue) != r2)
Lck_CondWait(&wrk->cond, &h2->sess->mtx, 0);
AZ(Lck_CondWait(&wrk->cond, &h2->sess->mtx, 0));
r2->wrk = NULL;
Lck_Unlock(&h2->sess->mtx);
}
void
H2_Send_Rel(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
H2_Send_Rel(struct h2_sess *h2, const struct h2_req *r2)
{
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
CHECK_OBJ_NOTNULL(h2, H2_SESS_MAGIC);
CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
Lck_Lock(&h2->sess->mtx);
assert(VTAILQ_FIRST(&h2->txqueue) == r2);
VTAILQ_REMOVE(&h2->txqueue, r2, tx_list);
r2 = VTAILQ_FIRST(&h2->txqueue);
if (r2 != NULL)
AZ(pthread_cond_signal(&r2->tx_wrk->cond));
if (r2 != NULL) {
CHECK_OBJ_NOTNULL(r2->wrk, WORKER_MAGIC);
AZ(pthread_cond_signal(&r2->wrk->cond));
}
Lck_Unlock(&h2->sess->mtx);
}
......@@ -128,7 +130,7 @@ H2_Send_Frame(struct worker *wrk, const struct h2_sess *h2,
*/
h2_error
H2_Send(struct worker *wrk, struct h2_req *r2, int flush,
H2_Send(struct worker *wrk, const struct h2_req *r2,
h2_frame ftyp, uint8_t flags, uint32_t len, const void *ptr)
{
h2_error retval;
......@@ -137,8 +139,6 @@ H2_Send(struct worker *wrk, struct h2_req *r2, int flush,
const char *p;
uint8_t final_flags;
(void)flush;
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
h2 = r2->h2sess;
......@@ -147,6 +147,12 @@ H2_Send(struct worker *wrk, struct h2_req *r2, int flush,
assert(VTAILQ_FIRST(&h2->txqueue) == r2);
if (r2->error)
return (r2->error);
if (h2->error && r2->stream > h2->goaway_last_stream)
return (h2->error);
AN(ftyp);
AZ(flags & ~(ftyp->flags));
if (r2->stream == 0)
......
......@@ -239,7 +239,7 @@ h2_new_pu_session(struct worker *wrk, const struct h2_sess *h2)
/**********************************************************************/
static int
h2_new_ou_session(struct worker *wrk, struct h2_sess *h2,
h2_new_ou_session(const struct worker *wrk, struct h2_sess *h2,
struct req *req)
{
ssize_t sz;
......@@ -343,7 +343,7 @@ h2_new_session(struct worker *wrk, void *arg)
H2_Send_Get(wrk, h2, h2->req0);
H2_Send_Frame(wrk, h2,
H2_F_SETTINGS, H2FF_NONE, sizeof H2_settings, 0, H2_settings);
H2_Send_Rel(wrk, h2, h2->req0);
H2_Send_Rel(h2, h2->req0);
/* and off we go... */
h2->cond = &wrk->cond;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment