Contribute flow control window for each byte PAD_HIGH and _LOW in DATA

This may help the pathological situation where window is too small.
This commit is contained in:
Tatsuhiro Tsujikawa 2014-02-12 21:35:40 +09:00
parent c7a17093cb
commit 082876d92d
2 changed files with 46 additions and 33 deletions

View File

@ -3534,7 +3534,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
break; break;
} }
if(rv == 1) { if(rv == 1) {
iframe->state = NGHTTP2_IB_READ_NBYTE; iframe->state = NGHTTP2_IB_READ_PAD_DATA;
break; break;
} }
iframe->state = NGHTTP2_IB_READ_DATA; iframe->state = NGHTTP2_IB_READ_DATA;
@ -3675,38 +3675,6 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
return in - first; return in - first;
} }
switch(iframe->frame.hd.type) { switch(iframe->frame.hd.type) {
case NGHTTP2_DATA:
busy = 1;
rv = inbound_frame_compute_pad(iframe);
if(rv < 0) {
rv = nghttp2_session_terminate_session(session,
NGHTTP2_PROTOCOL_ERROR);
if(nghttp2_is_fatal(rv)) {
return rv;
}
iframe->state = NGHTTP2_IB_IGN_DATA;
break;
}
iframe->frame.data.padlen = rv;
iframe->state = NGHTTP2_IB_READ_DATA;
/* PAD_HIGH and PAD_LOW are subject to flow control */
rv = nghttp2_session_update_recv_connection_window_size
(session, iframe->buflen);
if(nghttp2_is_fatal(rv)) {
return rv;
}
stream = nghttp2_session_get_stream(session,
iframe->frame.hd.stream_id);
if(stream) {
rv = nghttp2_session_update_recv_stream_window_size
(session, stream, iframe->buflen,
iframe->payloadleft ||
(iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0);
if(nghttp2_is_fatal(rv)) {
return rv;
}
}
break;
case NGHTTP2_HEADERS: case NGHTTP2_HEADERS:
if(iframe->padlen == 0 && if(iframe->padlen == 0 &&
iframe->frame.hd.flags & NGHTTP2_FLAG_PAD_LOW) { iframe->frame.hd.flags & NGHTTP2_FLAG_PAD_LOW) {
@ -4072,6 +4040,50 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK; iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
} }
break; break;
case NGHTTP2_IB_READ_PAD_DATA:
DEBUGF(fprintf(stderr, "[IB_READ_PAD_DATA]\n"));
readlen = inbound_frame_buf_read(iframe, in, last);
in += readlen;
iframe->payloadleft -= readlen;
DEBUGF(fprintf(stderr, "readlen=%zu, payloadleft=%zu, left=%zu\n",
readlen, iframe->payloadleft, iframe->left));
/* PAD_HIGH and PAD_LOW are subject to flow control */
rv = nghttp2_session_update_recv_connection_window_size
(session, readlen);
if(nghttp2_is_fatal(rv)) {
return rv;
}
stream = nghttp2_session_get_stream(session,
iframe->frame.hd.stream_id);
if(stream) {
rv = nghttp2_session_update_recv_stream_window_size
(session, stream, readlen,
iframe->payloadleft ||
(iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0);
if(nghttp2_is_fatal(rv)) {
return rv;
}
}
if(iframe->left) {
return in - first;
}
busy = 1;
rv = inbound_frame_compute_pad(iframe);
if(rv < 0) {
rv = nghttp2_session_terminate_session(session,
NGHTTP2_PROTOCOL_ERROR);
if(nghttp2_is_fatal(rv)) {
return rv;
}
iframe->state = NGHTTP2_IB_IGN_DATA;
break;
}
iframe->frame.data.padlen = rv;
iframe->state = NGHTTP2_IB_READ_DATA;
break;
case NGHTTP2_IB_READ_DATA: case NGHTTP2_IB_READ_DATA:
DEBUGF(fprintf(stderr, "[IB_READ_DATA]\n")); DEBUGF(fprintf(stderr, "[IB_READ_DATA]\n"));
readlen = inbound_frame_payload_readlen(iframe, in, last); readlen = inbound_frame_payload_readlen(iframe, in, last);

View File

@ -88,6 +88,7 @@ typedef enum {
NGHTTP2_IB_IGN_CONTINUATION, NGHTTP2_IB_IGN_CONTINUATION,
NGHTTP2_IB_READ_PAD_CONTINUATION, NGHTTP2_IB_READ_PAD_CONTINUATION,
NGHTTP2_IB_IGN_PAD_CONTINUATION, NGHTTP2_IB_IGN_PAD_CONTINUATION,
NGHTTP2_IB_READ_PAD_DATA,
NGHTTP2_IB_READ_DATA, NGHTTP2_IB_READ_DATA,
NGHTTP2_IB_IGN_DATA NGHTTP2_IB_IGN_DATA
} nghttp2_inbound_state; } nghttp2_inbound_state;