From: Tomas Krizek Date: Thu, 1 Apr 2021 15:04:10 +0000 (+0200) Subject: daemon/http: improve handling of stream errors X-Git-Tag: v5.3.2~9^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2cdec753ca46248cea97eb65d33e812ea68f919c;p=thirdparty%2Fknot-resolver.git daemon/http: improve handling of stream errors The on_frame_recv() callback ins't guaranteed to be called by nghttp2. This can happen e.g. in a case when nghttp2 issues a PROTOCOL_ERROR RST_STREAM frame. Previously, it would leave the connection in a stream-processing state, making it completely useless. While this guarantees a cleanup will be called eventually, some streams may still get ignored due to the order of various callbacks and data processing procedures. Still, it's better than the previous implementation. --- diff --git a/daemon/http.c b/daemon/http.c index f72465f65..5782941e6 100644 --- a/daemon/http.c +++ b/daemon/http.c @@ -243,6 +243,15 @@ static void refuse_stream(nghttp2_session *h2, int32_t stream_id) h2, NGHTTP2_FLAG_NONE, stream_id, NGHTTP2_REFUSED_STREAM); } +/* Return the http ctx into a pristine state in which no stream is being processed. */ +static void http_cleanup_stream(struct http_ctx *ctx) +{ + ctx->incomplete_stream = -1; + ctx->current_method = HTTP_METHOD_NONE; + free(ctx->uri_path); + ctx->uri_path = NULL; +} + /* * Save stream id from first header's frame. * @@ -388,10 +397,7 @@ static int on_frame_recv_callback(nghttp2_session *h2, const nghttp2_frame *fram refuse_stream(h2, stream_id); } } - ctx->incomplete_stream = -1; - ctx->current_method = HTTP_METHOD_NONE; - free(ctx->uri_path); - ctx->uri_path = NULL; + http_cleanup_stream(ctx); len = ctx->buf_pos - sizeof(uint16_t); if (len <= 0 || len > KNOT_WIRE_MAX_PKTSIZE) { @@ -431,6 +437,12 @@ static int on_stream_close_callback(nghttp2_session *h2, int32_t stream_id, uint32_t error_code, void *user_data) { struct http_data *data; + struct http_ctx *ctx = (struct http_ctx *)user_data; + + /* Ensure connection state is cleaned up in case the stream gets + * unexpectedly closed, e.g. by PROTOCOL_ERROR issued from nghttp2. */ + if (ctx->incomplete_stream == stream_id) + http_cleanup_stream(ctx); data = nghttp2_session_get_stream_user_data(h2, stream_id); if (data)