From 001823c3047676130d4e9d8825f3669359741479 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 12 Sep 2018 17:25:32 +0200 Subject: [PATCH] MEDIUM: h1: remove the useless H1_MSG_BODY state This state was only a delimiter between headers and body but it now causes more harm than good because it requires someone to change it. Since the H1 parser knows if we're in DATA or CHUNK_SIZE, simply let it set the right next state so that h1m->state constantly matches what is expected afterwards. --- include/proto/h1.h | 1 - include/types/h1.h | 22 +++++++++------------- src/h1.c | 25 +++++++++++++++++-------- src/mux_h2.c | 6 +++--- 4 files changed, 29 insertions(+), 25 deletions(-) diff --git a/include/proto/h1.h b/include/proto/h1.h index e6a4204ff..fb040d138 100644 --- a/include/proto/h1.h +++ b/include/proto/h1.h @@ -150,7 +150,6 @@ static inline const char *h1m_state_str(enum h1_state msg_state) case H1_MSG_HDR_L2_LF: return "MSG_HDR_L2_LF"; case H1_MSG_HDR_L2_LWS: return "MSG_HDR_L2_LWS"; case H1_MSG_LAST_LF: return "MSG_LAST_LF"; - case H1_MSG_BODY: return "MSG_BODY"; case H1_MSG_CHUNK_SIZE: return "MSG_CHUNK_SIZE"; case H1_MSG_DATA: return "MSG_DATA"; case H1_MSG_CHUNK_CRLF: return "MSG_CHUNK_CRLF"; diff --git a/include/types/h1.h b/include/types/h1.h index c6c97dcbd..26eafd339 100644 --- a/include/types/h1.h +++ b/include/types/h1.h @@ -120,21 +120,17 @@ enum h1m_state { H1_MSG_HDR_L2_LF = 23, // parsing header LWS (LF) inside/after value H1_MSG_HDR_L2_LWS = 24, // checking whether it's a new header or an LWS - H1_MSG_LAST_LF = 25, // parsing last LF + H1_MSG_LAST_LF = 25, // parsing last LF, last state for headers - /* Body processing. - * The state H1_MSG_BODY is a delimiter to know if we're waiting for headers - * or body. All the sub-states below also indicate we're processing the body, - * with some additional information. - */ - H1_MSG_BODY = 26, // parsing body at end of headers - H1_MSG_CHUNK_SIZE = 27, // parsing the chunk size (RFC7230 #4.1) - H1_MSG_DATA = 28, // skipping data chunk / content-length data - H1_MSG_CHUNK_CRLF = 29, // skipping CRLF after data chunk - H1_MSG_TRAILERS = 30, // trailers (post-data entity headers) + /* Body processing. */ + + H1_MSG_CHUNK_SIZE = 26, // parsing the chunk size (RFC7230 #4.1) + H1_MSG_DATA = 27, // skipping data chunk / content-length data + H1_MSG_CHUNK_CRLF = 28, // skipping CRLF after data chunk + H1_MSG_TRAILERS = 29, // trailers (post-data entity headers) /* we enter this state when we've received the end of the current message */ - H1_MSG_DONE = 31, // message end received, waiting for resync or close - H1_MSG_TUNNEL = 32, // tunneled data after DONE + H1_MSG_DONE = 30, // message end received, waiting for resync or close + H1_MSG_TUNNEL = 31, // tunneled data after DONE } __attribute__((packed)); diff --git a/src/h1.c b/src/h1.c index d88408efe..fc0b8da58 100644 --- a/src/h1.c +++ b/src/h1.c @@ -1073,7 +1073,21 @@ int h1_headers_to_hdr_list(char *start, const char *stop, } http_set_hdr(&hdr[hdr_count++], ist(""), ist("")); } - state = H1_MSG_BODY; + + /* reaching here we've parsed the whole message. We may detect + * that we were already continuing an interrupted parsing pass + * so we were silently looking for the end of message not + * updating anything before deciding to parse it fully at once. + * It's guaranteed that we won't match this test twice in a row + * since restarting will turn zero. + */ + if (restarting) + goto restart; + + if (h1m->flags & H1_MF_CHNK) + state = H1_MSG_CHUNK_SIZE; + else + state = H1_MSG_DATA; break; default: @@ -1081,14 +1095,9 @@ int h1_headers_to_hdr_list(char *start, const char *stop, goto http_msg_invalid; } - /* reaching here, we've parsed the whole message and the state is - * H1_MSG_BODY. We may discover that we were already continuing an - * interrupted parsing session, thus we were silently looking for - * the end of message before deciding to parse it fully at once. - * We won't come there again since restarting will turn zero. + /* Now we've left the headers state and are either in H1_MSG_DATA or + * H1_MSG_CHUNK_SIZE. */ - if (restarting) - goto restart; if (slp && !skip_update) *slp = sl; diff --git a/src/mux_h2.c b/src/mux_h2.c index d842cd8d2..922cabefe 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -3237,8 +3237,8 @@ static size_t h2s_frt_make_resp_headers(struct h2s *h2s, const struct buffer *bu h1m->err_pos = -1; // don't care about errors on the response path goto end; } - else - h1m->state = (h1m->flags & H1_MF_CHNK) ? H1_MSG_CHUNK_SIZE : H1_MSG_BODY; + + /* now the h1m state is either H1_MSG_CHUNK_SIZE or H1_MSG_DATA */ end: //fprintf(stderr, "[%d] sent simple H2 response (sid=%d) = %d bytes (%d in, ep=%u, es=%s)\n", h2c->st0, h2s->id, outbuf.len, ret, h1m->err_pos, h1_msg_state_str(h1m->err_state)); @@ -3568,7 +3568,7 @@ static size_t h2_snd_buf(struct conn_stream *cs, struct buffer *buf, size_t coun h2s->flags |= H2_SF_OUTGOING_DATA; while (h2s->h1m.state < H1_MSG_DONE && count) { - if (h2s->h1m.state < H1_MSG_BODY) { + if (h2s->h1m.state <= H1_MSG_LAST_LF) { ret = h2s_frt_make_resp_headers(h2s, buf, total, count); } else if (h2s->h1m.state < H1_MSG_TRAILERS) {