Fix DATA is not consumed if nghttp2_http_on_data_chunk failed
This commit fixes the bug that DATA is not consumed if nghttp2_http_on_data_chunk is failed. It also simplify the handling of missing stream in NGHTTP2_IB_READ_DATA state.
This commit is contained in:
parent
693fba3b64
commit
c70cfe64c4
|
@ -5739,6 +5739,14 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case NGHTTP2_IB_READ_DATA:
|
case NGHTTP2_IB_READ_DATA:
|
||||||
|
stream = nghttp2_session_get_stream(session, iframe->frame.hd.stream_id);
|
||||||
|
|
||||||
|
if (!stream) {
|
||||||
|
busy = 1;
|
||||||
|
iframe->state = NGHTTP2_IB_IGN_DATA;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
DEBUGF(fprintf(stderr, "recv: [IB_READ_DATA]\n"));
|
DEBUGF(fprintf(stderr, "recv: [IB_READ_DATA]\n"));
|
||||||
|
|
||||||
readlen = inbound_frame_payload_readlen(iframe, in, last);
|
readlen = inbound_frame_payload_readlen(iframe, in, last);
|
||||||
|
@ -5756,68 +5764,65 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream =
|
rv = session_update_recv_stream_window_size(
|
||||||
nghttp2_session_get_stream(session, iframe->frame.hd.stream_id);
|
session, stream, readlen,
|
||||||
if (stream) {
|
iframe->payloadleft ||
|
||||||
rv = session_update_recv_stream_window_size(
|
(iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0);
|
||||||
session, stream, readlen,
|
if (nghttp2_is_fatal(rv)) {
|
||||||
iframe->payloadleft ||
|
return rv;
|
||||||
(iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0);
|
}
|
||||||
|
|
||||||
|
data_readlen = inbound_frame_effective_readlen(
|
||||||
|
iframe, iframe->payloadleft, readlen);
|
||||||
|
|
||||||
|
padlen = readlen - data_readlen;
|
||||||
|
|
||||||
|
if (padlen > 0) {
|
||||||
|
/* Padding is considered as "consumed" immediately */
|
||||||
|
rv = nghttp2_session_consume(session, iframe->frame.hd.stream_id,
|
||||||
|
padlen);
|
||||||
|
|
||||||
if (nghttp2_is_fatal(rv)) {
|
if (nghttp2_is_fatal(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data_readlen = inbound_frame_effective_readlen(
|
DEBUGF(fprintf(stderr, "recv: data_readlen=%zd\n", data_readlen));
|
||||||
iframe, iframe->payloadleft, readlen);
|
|
||||||
|
|
||||||
padlen = readlen - data_readlen;
|
if (data_readlen > 0) {
|
||||||
|
if (session_enforce_http_messaging(session)) {
|
||||||
|
if (nghttp2_http_on_data_chunk(stream, data_readlen) != 0) {
|
||||||
|
if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) {
|
||||||
|
/* Consume all data for connection immediately here */
|
||||||
|
rv = session_update_connection_consumed_size(session,
|
||||||
|
data_readlen);
|
||||||
|
|
||||||
if (padlen > 0) {
|
|
||||||
/* Padding is considered as "consumed" immediately */
|
|
||||||
rv = nghttp2_session_consume(session, iframe->frame.hd.stream_id,
|
|
||||||
padlen);
|
|
||||||
|
|
||||||
if (nghttp2_is_fatal(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUGF(fprintf(stderr, "recv: data_readlen=%zd\n", data_readlen));
|
|
||||||
|
|
||||||
if (data_readlen > 0) {
|
|
||||||
if (session_enforce_http_messaging(session)) {
|
|
||||||
if (nghttp2_http_on_data_chunk(stream, data_readlen) != 0) {
|
|
||||||
rv = nghttp2_session_add_rst_stream(session,
|
|
||||||
iframe->frame.hd.stream_id,
|
|
||||||
NGHTTP2_PROTOCOL_ERROR);
|
|
||||||
if (nghttp2_is_fatal(rv)) {
|
if (nghttp2_is_fatal(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
busy = 1;
|
|
||||||
iframe->state = NGHTTP2_IB_IGN_DATA;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (session->callbacks.on_data_chunk_recv_callback) {
|
|
||||||
rv = session->callbacks.on_data_chunk_recv_callback(
|
|
||||||
session, iframe->frame.hd.flags, iframe->frame.hd.stream_id,
|
|
||||||
in - readlen, data_readlen, session->user_data);
|
|
||||||
if (rv == NGHTTP2_ERR_PAUSE) {
|
|
||||||
return in - first;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rv = nghttp2_session_add_rst_stream(
|
||||||
|
session, iframe->frame.hd.stream_id, NGHTTP2_PROTOCOL_ERROR);
|
||||||
if (nghttp2_is_fatal(rv)) {
|
if (nghttp2_is_fatal(rv)) {
|
||||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
return rv;
|
||||||
}
|
}
|
||||||
|
busy = 1;
|
||||||
|
iframe->state = NGHTTP2_IB_IGN_DATA;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) {
|
if (session->callbacks.on_data_chunk_recv_callback) {
|
||||||
/* stream was closed or does not exist. Consume all data
|
rv = session->callbacks.on_data_chunk_recv_callback(
|
||||||
for connection immediately here */
|
session, iframe->frame.hd.flags, iframe->frame.hd.stream_id,
|
||||||
rv = session_update_connection_consumed_size(session, readlen);
|
in - readlen, data_readlen, session->user_data);
|
||||||
|
if (rv == NGHTTP2_ERR_PAUSE) {
|
||||||
|
return in - first;
|
||||||
|
}
|
||||||
|
|
||||||
if (nghttp2_is_fatal(rv)) {
|
if (nghttp2_is_fatal(rv)) {
|
||||||
return rv;
|
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue