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";
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));
}
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:
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;
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));
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) {