Add nghttp2_session_consume_{connection,stream} to consume bytes independently

The existing nghttp2_session_consume() affects both connection and
stream level flow control windows.  The new functions only affects
either connection or stream.  There is some interesting use cases.
For example, we may want to pause a stream by not sending
WINDOW_UPDATE, meanwhile we want to continue to process other streams.
In this case, we use nghttp2_session_consume_connection() to tell
library that only connection level window is recovered.  The relevant
discussion: https://code.google.com/p/chromium/issues/detail?id=473259
This commit is contained in:
Tatsuhiro Tsujikawa 2015-04-07 00:14:18 +09:00
parent ef4e39be55
commit d56ecd7414
3 changed files with 99 additions and 7 deletions

View File

@ -76,6 +76,8 @@ APIDOCS= \
nghttp2_session_client_new2.rst \ nghttp2_session_client_new2.rst \
nghttp2_session_client_new3.rst \ nghttp2_session_client_new3.rst \
nghttp2_session_consume.rst \ nghttp2_session_consume.rst \
nghttp2_session_consume_connection.rst \
nghttp2_session_consume_stream.rst \
nghttp2_session_del.rst \ nghttp2_session_del.rst \
nghttp2_session_get_effective_local_window_size.rst \ nghttp2_session_get_effective_local_window_size.rst \
nghttp2_session_get_effective_recv_data_length.rst \ nghttp2_session_get_effective_recv_data_length.rst \

View File

@ -2728,8 +2728,11 @@ NGHTTP2_EXTERN uint32_t
* Tells the |session| that |size| bytes for a stream denoted by * Tells the |session| that |size| bytes for a stream denoted by
* |stream_id| were consumed by application and are ready to * |stream_id| were consumed by application and are ready to
* WINDOW_UPDATE. The consumed bytes are counted towards both * WINDOW_UPDATE. The consumed bytes are counted towards both
* connection and stream level WINDOW_UPDATE. This function is * connection and stream level WINDOW_UPDATE (see
* intended to be used without automatic window update (see * `nghttp2_session_consume_connection()` and
* `nghttp2_session_consume_stream()` to update consumption
* independently). This function is intended to be used without
* automatic window update (see
* `nghttp2_option_set_no_auto_window_update()`). * `nghttp2_option_set_no_auto_window_update()`).
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
@ -2745,6 +2748,47 @@ NGHTTP2_EXTERN uint32_t
NGHTTP2_EXTERN int nghttp2_session_consume(nghttp2_session *session, NGHTTP2_EXTERN int nghttp2_session_consume(nghttp2_session *session,
int32_t stream_id, size_t size); int32_t stream_id, size_t size);
/**
* @function
*
* Like `nghttp2_session_consume()`, but this only tells library that
* |size| bytes were consumed only for connection level. Note that
* HTTP/2 maintains connection and stream level flow control windows
* independently.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* :enum:`NGHTTP2_ERR_NOMEM`
* Out of memory.
* :enum:`NGHTTP2_ERR_INVALID_STATE`
* Automatic WINDOW_UPDATE is not disabled.
*/
NGHTTP2_EXTERN int nghttp2_session_consume_connection(nghttp2_session *session,
size_t size);
/**
* @function
*
* Like `nghttp2_session_consume()`, but this only tells library that
* |size| bytes were consumed only for stream denoted by |stream_id|.
* Note that HTTP/2 maintains connection and stream level flow control
* windows independently.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* :enum:`NGHTTP2_ERR_NOMEM`
* Out of memory.
* :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
* The |stream_id| is 0.
* :enum:`NGHTTP2_ERR_INVALID_STATE`
* Automatic WINDOW_UPDATE is not disabled.
*/
NGHTTP2_EXTERN int nghttp2_session_consume_stream(nghttp2_session *session,
int32_t stream_id,
size_t size);
/** /**
* @function * @function
* *

View File

@ -6587,12 +6587,58 @@ int nghttp2_session_consume(nghttp2_session *session, int32_t stream_id,
stream = nghttp2_session_get_stream(session, stream_id); stream = nghttp2_session_get_stream(session, stream_id);
if (stream) { if (!stream) {
rv = session_update_stream_consumed_size(session, stream, size); return 0;
}
if (nghttp2_is_fatal(rv)) { rv = session_update_stream_consumed_size(session, stream, size);
return rv;
} if (nghttp2_is_fatal(rv)) {
return rv;
}
return 0;
}
int nghttp2_session_consume_connection(nghttp2_session *session, size_t size) {
int rv;
if (!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE)) {
return NGHTTP2_ERR_INVALID_STATE;
}
rv = session_update_connection_consumed_size(session, size);
if (nghttp2_is_fatal(rv)) {
return rv;
}
return 0;
}
int nghttp2_session_consume_stream(nghttp2_session *session, int32_t stream_id,
size_t size) {
int rv;
nghttp2_stream *stream;
if (stream_id == 0) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
if (!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE)) {
return NGHTTP2_ERR_INVALID_STATE;
}
stream = nghttp2_session_get_stream(session, stream_id);
if (!stream) {
return 0;
}
rv = session_update_stream_consumed_size(session, stream, size);
if (nghttp2_is_fatal(rv)) {
return rv;
} }
return 0; return 0;