diff --git a/doc/Makefile.am b/doc/Makefile.am index 4a4c37ca..0bc4f66c 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -105,6 +105,7 @@ APIDOCS= \ nghttp2_session_mem_recv.rst \ nghttp2_session_mem_send.rst \ nghttp2_session_recv.rst \ + nghttp2_session_change_stream_priority.rst \ nghttp2_session_check_request_allowed.rst \ nghttp2_session_check_server_session.rst \ nghttp2_session_resume_data.rst \ diff --git a/lib/includes/nghttp2/nghttp2.h b/lib/includes/nghttp2/nghttp2.h index d4ba7e3d..94b07753 100644 --- a/lib/includes/nghttp2/nghttp2.h +++ b/lib/includes/nghttp2/nghttp2.h @@ -2853,6 +2853,40 @@ NGHTTP2_EXTERN int nghttp2_session_consume_stream(nghttp2_session *session, int32_t stream_id, size_t size); +/** + * @function + * + * Changes priority of existing stream denoted by |stream_id|. The + * new priority specification is |pri_spec|. + * + * The priority is changed silently and instantly, and no PRIORITY + * frame will be sent to notify the peer of this change. This + * function may be useful for server to change the priority of pushed + * stream. + * + * If |session| is initialized as server, and ``pri_spec->stream_id`` + * points to the idle stream, the idle stream is created if it does + * not exist. The created idle stream will depend on root stream + * (stream 0) with weight 16. + * + * If stream denoted by ``pri_spec->stream_id`` is not found, we use + * default priority instead of given |pri_spec|. That is make stream + * depend on root stream with weight 16. + * + * 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` + * Attempted to depend on itself; no stream exist for the given + * |stream_id|. + */ +NGHTTP2_EXTERN int +nghttp2_session_change_stream_priority(nghttp2_session *session, + int32_t stream_id, + const nghttp2_priority_spec *pri_spec); + /** * @function * diff --git a/lib/nghttp2_priority_spec.c b/lib/nghttp2_priority_spec.c index cd254b1f..c2196e30 100644 --- a/lib/nghttp2_priority_spec.c +++ b/lib/nghttp2_priority_spec.c @@ -42,3 +42,11 @@ int nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec) { return pri_spec->stream_id == 0 && pri_spec->weight == NGHTTP2_DEFAULT_WEIGHT && pri_spec->exclusive == 0; } + +void nghttp2_priority_spec_normalize_weight(nghttp2_priority_spec *pri_spec) { + if (pri_spec->weight < NGHTTP2_MIN_WEIGHT) { + pri_spec->weight = NGHTTP2_MIN_WEIGHT; + } else if (pri_spec->weight > NGHTTP2_MAX_WEIGHT) { + pri_spec->weight = NGHTTP2_MAX_WEIGHT; + } +} diff --git a/lib/nghttp2_priority_spec.h b/lib/nghttp2_priority_spec.h index a325a581..98fac210 100644 --- a/lib/nghttp2_priority_spec.h +++ b/lib/nghttp2_priority_spec.h @@ -31,4 +31,12 @@ #include +/* + * This function normalizes pri_spec->weight if it is out of range. + * If pri_spec->weight is less than NGHTTP2_MIN_WEIGHT, it is set to + * NGHTTP2_MIN_WEIGHT. If pri_spec->weight is larger than + * NGHTTP2_MAX_WEIGHT, it is set to NGHTTP2_MAX_WEIGHT. + */ +void nghttp2_priority_spec_normalize_weight(nghttp2_priority_spec *pri_spec); + #endif /* NGHTTP2_PRIORITY_SPEC_H */ diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c index 64e39da5..6e815ca2 100644 --- a/lib/nghttp2_session.c +++ b/lib/nghttp2_session.c @@ -6771,3 +6771,24 @@ nghttp2_stream *nghttp2_session_get_root_stream(nghttp2_session *session) { int nghttp2_session_check_server_session(nghttp2_session *session) { return session->server; } + +int nghttp2_session_change_stream_priority( + nghttp2_session *session, int32_t stream_id, + const nghttp2_priority_spec *pri_spec) { + nghttp2_stream *stream; + nghttp2_priority_spec pri_spec_copy; + + if (stream_id == pri_spec->stream_id) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + stream = nghttp2_session_get_stream_raw(session, stream_id); + if (!stream) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + pri_spec_copy = *pri_spec; + nghttp2_priority_spec_normalize_weight(&pri_spec_copy); + + return nghttp2_session_reprioritize_stream(session, stream, &pri_spec_copy); +} diff --git a/lib/nghttp2_submit.c b/lib/nghttp2_submit.c index 763b4038..65226363 100644 --- a/lib/nghttp2_submit.c +++ b/lib/nghttp2_submit.c @@ -117,14 +117,6 @@ fail2: return rv; } -static void adjust_priority_spec_weight(nghttp2_priority_spec *pri_spec) { - if (pri_spec->weight < NGHTTP2_MIN_WEIGHT) { - pri_spec->weight = NGHTTP2_MIN_WEIGHT; - } else if (pri_spec->weight > NGHTTP2_MAX_WEIGHT) { - pri_spec->weight = NGHTTP2_MAX_WEIGHT; - } -} - static int32_t submit_headers_shared_nva(nghttp2_session *session, uint8_t flags, int32_t stream_id, const nghttp2_priority_spec *pri_spec, @@ -141,7 +133,7 @@ static int32_t submit_headers_shared_nva(nghttp2_session *session, if (pri_spec) { copy_pri_spec = *pri_spec; - adjust_priority_spec_weight(©_pri_spec); + nghttp2_priority_spec_normalize_weight(©_pri_spec); } else { nghttp2_priority_spec_default_init(©_pri_spec); } @@ -206,7 +198,7 @@ int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags _U_, copy_pri_spec = *pri_spec; - adjust_priority_spec_weight(©_pri_spec); + nghttp2_priority_spec_normalize_weight(©_pri_spec); item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));