Merge branch 'change-stream-priority'

This commit is contained in:
Tatsuhiro Tsujikawa 2015-11-23 20:13:02 +09:00
commit 2fee05242e
9 changed files with 112 additions and 10 deletions

View File

@ -105,6 +105,7 @@ APIDOCS= \
nghttp2_session_mem_recv.rst \ nghttp2_session_mem_recv.rst \
nghttp2_session_mem_send.rst \ nghttp2_session_mem_send.rst \
nghttp2_session_recv.rst \ nghttp2_session_recv.rst \
nghttp2_session_change_stream_priority.rst \
nghttp2_session_check_request_allowed.rst \ nghttp2_session_check_request_allowed.rst \
nghttp2_session_check_server_session.rst \ nghttp2_session_check_server_session.rst \
nghttp2_session_resume_data.rst \ nghttp2_session_resume_data.rst \

View File

@ -2853,6 +2853,40 @@ NGHTTP2_EXTERN int nghttp2_session_consume_stream(nghttp2_session *session,
int32_t stream_id, int32_t stream_id,
size_t size); 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 * @function
* *

View File

@ -42,3 +42,11 @@ int nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec) {
return pri_spec->stream_id == 0 && return pri_spec->stream_id == 0 &&
pri_spec->weight == NGHTTP2_DEFAULT_WEIGHT && pri_spec->exclusive == 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;
}
}

View File

@ -31,4 +31,12 @@
#include <nghttp2/nghttp2.h> #include <nghttp2/nghttp2.h>
/*
* 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 */ #endif /* NGHTTP2_PRIORITY_SPEC_H */

View File

@ -6771,3 +6771,24 @@ nghttp2_stream *nghttp2_session_get_root_stream(nghttp2_session *session) {
int nghttp2_session_check_server_session(nghttp2_session *session) { int nghttp2_session_check_server_session(nghttp2_session *session) {
return session->server; 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);
}

View File

@ -117,14 +117,6 @@ fail2:
return rv; 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, static int32_t submit_headers_shared_nva(nghttp2_session *session,
uint8_t flags, int32_t stream_id, uint8_t flags, int32_t stream_id,
const nghttp2_priority_spec *pri_spec, const nghttp2_priority_spec *pri_spec,
@ -141,7 +133,7 @@ static int32_t submit_headers_shared_nva(nghttp2_session *session,
if (pri_spec) { if (pri_spec) {
copy_pri_spec = *pri_spec; copy_pri_spec = *pri_spec;
adjust_priority_spec_weight(&copy_pri_spec); nghttp2_priority_spec_normalize_weight(&copy_pri_spec);
} else { } else {
nghttp2_priority_spec_default_init(&copy_pri_spec); nghttp2_priority_spec_default_init(&copy_pri_spec);
} }
@ -206,7 +198,7 @@ int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags _U_,
copy_pri_spec = *pri_spec; copy_pri_spec = *pri_spec;
adjust_priority_spec_weight(&copy_pri_spec); nghttp2_priority_spec_normalize_weight(&copy_pri_spec);
item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));

View File

@ -282,6 +282,8 @@ int main(int argc _U_, char *argv[] _U_) {
!CU_add_test(pSuite, "session_detach_item_from_closed_stream", !CU_add_test(pSuite, "session_detach_item_from_closed_stream",
test_nghttp2_session_detach_item_from_closed_stream) || test_nghttp2_session_detach_item_from_closed_stream) ||
!CU_add_test(pSuite, "session_flooding", test_nghttp2_session_flooding) || !CU_add_test(pSuite, "session_flooding", test_nghttp2_session_flooding) ||
!CU_add_test(pSuite, "session_change_stream_priority",
test_nghttp2_session_change_stream_priority) ||
!CU_add_test(pSuite, "http_mandatory_headers", !CU_add_test(pSuite, "http_mandatory_headers",
test_nghttp2_http_mandatory_headers) || test_nghttp2_http_mandatory_headers) ||
!CU_add_test(pSuite, "http_content_length", !CU_add_test(pSuite, "http_content_length",

View File

@ -8319,6 +8319,41 @@ void test_nghttp2_session_flooding(void) {
nghttp2_bufs_free(&bufs); nghttp2_bufs_free(&bufs);
} }
void test_nghttp2_session_change_stream_priority(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
nghttp2_stream *stream1, *stream2, *stream3;
nghttp2_priority_spec pri_spec;
int rv;
memset(&callbacks, 0, sizeof(callbacks));
nghttp2_session_server_new(&session, &callbacks, NULL);
stream1 = open_stream(session, 1);
stream3 = open_stream_with_dep_weight(session, 3, 199, stream1);
stream2 = open_stream_with_dep_weight(session, 2, 101, stream3);
nghttp2_priority_spec_init(&pri_spec, 1, 256, 0);
rv = nghttp2_session_change_stream_priority(session, 2, &pri_spec);
CU_ASSERT(0 == rv);
CU_ASSERT(stream1 == stream2->dep_prev);
CU_ASSERT(256 == stream2->weight);
/* Cannot change stream which does not exist */
rv = nghttp2_session_change_stream_priority(session, 5, &pri_spec);
CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
/* It is an error to depend on itself */
rv = nghttp2_session_change_stream_priority(session, 1, &pri_spec);
CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
nghttp2_session_del(session);
}
static void check_nghttp2_http_recv_headers_fail( static void check_nghttp2_http_recv_headers_fail(
nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id, nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
int stream_state, const nghttp2_nv *nva, size_t nvlen) { int stream_state, const nghttp2_nv *nva, size_t nvlen) {

View File

@ -133,6 +133,7 @@ void test_nghttp2_session_on_begin_headers_temporal_failure(void);
void test_nghttp2_session_defer_then_close(void); void test_nghttp2_session_defer_then_close(void);
void test_nghttp2_session_detach_item_from_closed_stream(void); void test_nghttp2_session_detach_item_from_closed_stream(void);
void test_nghttp2_session_flooding(void); void test_nghttp2_session_flooding(void);
void test_nghttp2_session_change_stream_priority(void);
void test_nghttp2_http_mandatory_headers(void); void test_nghttp2_http_mandatory_headers(void);
void test_nghttp2_http_content_length(void); void test_nghttp2_http_content_length(void);
void test_nghttp2_http_content_length_mismatch(void); void test_nghttp2_http_content_length_mismatch(void);