Merge branch 'priority'
This commit is contained in:
commit
2d4b92fc2b
|
@ -114,21 +114,21 @@ typedef struct {
|
|||
/**
|
||||
* @macro
|
||||
*
|
||||
* The default weight of priority group.
|
||||
* The default weight of stream dependency.
|
||||
*/
|
||||
#define NGHTTP2_DEFAULT_WEIGHT 16
|
||||
|
||||
/**
|
||||
* @macro
|
||||
*
|
||||
* The maximum weight of priority group.
|
||||
* The maximum weight of stream dependency.
|
||||
*/
|
||||
#define NGHTTP2_MAX_WEIGHT 256
|
||||
|
||||
/**
|
||||
* @macro
|
||||
*
|
||||
* The minimum weight of priority group.
|
||||
* The minimum weight of stream dependency.
|
||||
*/
|
||||
#define NGHTTP2_MIN_WEIGHT 1
|
||||
|
||||
|
@ -482,13 +482,9 @@ typedef enum {
|
|||
*/
|
||||
NGHTTP2_FLAG_PAD_HIGH = 0x10,
|
||||
/**
|
||||
* The PRIORITY_GROUP flag.
|
||||
* The PRIORITY flag.
|
||||
*/
|
||||
NGHTTP2_FLAG_PRIORITY_GROUP = 0x20,
|
||||
/**
|
||||
* The PRIORITY_DEPENDENCY flag.
|
||||
*/
|
||||
NGHTTP2_FLAG_PRIORITY_DEPENDENCY = 0x40
|
||||
NGHTTP2_FLAG_PRIORITY = 0x20
|
||||
} nghttp2_flag;
|
||||
|
||||
/**
|
||||
|
@ -731,93 +727,25 @@ typedef enum {
|
|||
NGHTTP2_HCAT_HEADERS = 3
|
||||
} nghttp2_headers_category;
|
||||
|
||||
/**
|
||||
* @enum
|
||||
*
|
||||
* The type of priority specified in :type:`nghttp2_priority_spec`.
|
||||
*/
|
||||
typedef enum {
|
||||
/**
|
||||
* No priority is given. The default priority will be used.
|
||||
*/
|
||||
NGHTTP2_PRIORITY_TYPE_NONE = 0,
|
||||
/**
|
||||
* Priority group ID and its weight are specified.
|
||||
*/
|
||||
NGHTTP2_PRIORITY_TYPE_GROUP = 1,
|
||||
/**
|
||||
* The stream ID of a stream to depend on and its exclusive flag is
|
||||
* specified.
|
||||
*/
|
||||
NGHTTP2_PRIORITY_TYPE_DEP = 2
|
||||
} nghttp2_priority_type;
|
||||
|
||||
/**
|
||||
* @struct
|
||||
*
|
||||
* This structure stores priority group ID and its weight.
|
||||
* The structure to specify stream dependency.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* The priority group ID
|
||||
*/
|
||||
int32_t pri_group_id;
|
||||
/**
|
||||
* The weight of the priority group
|
||||
*/
|
||||
int32_t weight;
|
||||
} nghttp2_priority_group;
|
||||
|
||||
/**
|
||||
* @struct
|
||||
*
|
||||
* This structure stores stream ID of the stream to depend on and its
|
||||
* dependency is exclusive or not.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* The stream ID of the stream to depend on.
|
||||
* The stream ID of the stream to depend on. Specifying 0 makes
|
||||
* stream not depend any other stream.
|
||||
*/
|
||||
int32_t stream_id;
|
||||
/**
|
||||
* The weight of this dependency.
|
||||
*/
|
||||
int32_t weight;
|
||||
/**
|
||||
* nonzero means exclusive dependency
|
||||
*/
|
||||
uint8_t exclusive;
|
||||
} nghttp2_priority_dep;
|
||||
|
||||
/**
|
||||
* @struct
|
||||
*
|
||||
* The structure to specify stream dependency. To specify stream
|
||||
* dependency, specify |pri_type| and fill the |group| or |dep| member
|
||||
* according to |pri_type|.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* Type of priority specification. If |pri_type| is
|
||||
* :enum:`NGHTTP2_PRIORITY_TYPE_GROUP`, fill |group|. If |pri_type|
|
||||
* is :enum:`NGHTTP2_PRIORITY_TYPE_DEP`, fill |dep|. If |pri_type|
|
||||
* is :enum:`NGHTTP2_PRIORITY_TYPE_NONE`, the other data members are
|
||||
* ignored and it means that default priority group ID (which is
|
||||
* same as the stream ID) and default weight
|
||||
* :macro:`NGHTTP2_DEFAULT_WEIGHT` are specified.
|
||||
*/
|
||||
nghttp2_priority_type pri_type;
|
||||
|
||||
union {
|
||||
/**
|
||||
* Specify priority group ID and its weight. This field is
|
||||
* interpreted only when |pri_type| member is
|
||||
* :enum:`NGHTTP2_PRIORITY_TYPE_GROUP`.
|
||||
*/
|
||||
nghttp2_priority_group group;
|
||||
/**
|
||||
* Specify stream ID of a stream to depend on and exclusive flag.
|
||||
* This field is interpreted only when |pri_type| member is
|
||||
* :enum:`NGHTTP2_PRIORITY_TYPE_DEP`.
|
||||
*/
|
||||
nghttp2_priority_dep dep;
|
||||
} spec;
|
||||
} nghttp2_priority_spec;
|
||||
|
||||
/**
|
||||
|
@ -2153,32 +2081,32 @@ const char* nghttp2_strerror(int lib_error_code);
|
|||
/**
|
||||
* @function
|
||||
*
|
||||
* Initializes |pri_spec| with priority group ID |pri_group_id| and
|
||||
* its weight |weight|.
|
||||
* Initializes |pri_spec| with the |stream_id| of the stream to depend
|
||||
* on with |weight| and its exclusive flag. If |exclusive| is
|
||||
* nonzero, exclusive flag is set.
|
||||
*
|
||||
* The |weight| must be in [:enum:`NGHTTP2_MIN_WEIGHT`,
|
||||
* :enum:`NGHTTP2_MAX_WEIGHT`], inclusive. If |weight| is strictly
|
||||
* less than :enum:`NGHTTP2_MIN_WEIGHT`, it becomes
|
||||
* :enum:`NGHTTP2_MIN_WEIGHT`. If it is strictly greater than
|
||||
* :enum:`NGHTTP2_MAX_WEIGHT`, it becomes :enum:`NGHTTP2_MAX_WEIGHT`.
|
||||
*
|
||||
* To specify weight for the default priority group (which is the same
|
||||
* as the stream ID of the stream) in `nghttp2_submit_request()` and
|
||||
* `nghttp2_submit_headers()` and its stream ID is not known in
|
||||
* advance, specify -1 to |pri_group_id|.
|
||||
* :enum:`NGHTTP2_MAX_WEIGHT`], inclusive.
|
||||
*/
|
||||
void nghttp2_priority_spec_group_init(nghttp2_priority_spec *pri_spec,
|
||||
int32_t pri_group_id, int32_t weight);
|
||||
void nghttp2_priority_spec_init(nghttp2_priority_spec *pri_spec,
|
||||
int32_t stream_id, int32_t weight,
|
||||
int exclusive);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* Initializes |pri_spec| with the |stream_id| of the stream to depend
|
||||
* on and its exclusive flag. If |exclusive| is nonzero, exclusive
|
||||
* flag is set.
|
||||
* Initializes |pri_spec| with the default values. The default values
|
||||
* are: stream_id = 0, weight = :macro:`NGHTTP2_DEFAULT_WEIGHT` and
|
||||
* exclusive = 0.
|
||||
*/
|
||||
void nghttp2_priority_spec_dep_init(nghttp2_priority_spec *pri_spec,
|
||||
int32_t stream_id, int exclusive);
|
||||
void nghttp2_priority_spec_default_init(nghttp2_priority_spec *pri_spec);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* Returns nonzero if the |pri_spec| is filled with default values.
|
||||
*/
|
||||
int nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec);
|
||||
|
||||
/**
|
||||
* @function
|
||||
|
@ -2186,12 +2114,17 @@ void nghttp2_priority_spec_dep_init(nghttp2_priority_spec *pri_spec,
|
|||
* Submits HEADERS frame and optionally one or more DATA frames.
|
||||
*
|
||||
* The |pri_spec| is priority specification of this request. ``NULL``
|
||||
* means the default priority (priority group ID becomes its stream ID
|
||||
* and weight is :macro:`NGHTTP2_DEFAULT_WEIGHT`). To specify the
|
||||
* priority, use either `nghttp2_priority_spec_group_init()` or
|
||||
* `nghttp2_priority_spec_dep_init()`. If |pri_spec| is not ``NULL``,
|
||||
* means the default priority (see
|
||||
* `nghttp2_priority_spec_default_init()`). To specify the priority,
|
||||
* use `nghttp2_priority_spec_init()`. If |pri_spec| is not ``NULL``,
|
||||
* this function will copy its data members.
|
||||
*
|
||||
* The `pri_spec->weight` must be in [:enum:`NGHTTP2_MIN_WEIGHT`,
|
||||
* :enum:`NGHTTP2_MAX_WEIGHT`], inclusive. If `pri_spec->weight` is
|
||||
* strictly less than :enum:`NGHTTP2_MIN_WEIGHT`, it becomes
|
||||
* :enum:`NGHTTP2_MIN_WEIGHT`. If it is strictly greater than
|
||||
* :enum:`NGHTTP2_MAX_WEIGHT`, it becomes :enum:`NGHTTP2_MAX_WEIGHT`.
|
||||
*
|
||||
* The |nva| is an array of name/value pair :type:`nghttp2_nv` with
|
||||
* |nvlen| elements. The value is opaque sequence of bytes and
|
||||
* therefore can contain NULL byte (0x0). If the application requires
|
||||
|
@ -2234,8 +2167,6 @@ void nghttp2_priority_spec_dep_init(nghttp2_priority_spec *pri_spec,
|
|||
*
|
||||
* :enum:`NGHTTP2_ERR_NOMEM`
|
||||
* Out of memory.
|
||||
* :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
|
||||
* The |pri_spec->pri_type| is invalid.
|
||||
*/
|
||||
int nghttp2_submit_request(nghttp2_session *session,
|
||||
const nghttp2_priority_spec *pri_spec,
|
||||
|
@ -2306,12 +2237,17 @@ int nghttp2_submit_response(nghttp2_session *session,
|
|||
* response, specify stream ID in |stream_id|.
|
||||
*
|
||||
* The |pri_spec| is priority specification of this request. ``NULL``
|
||||
* means the default priority (priority group ID becomes its stream ID
|
||||
* and weight is :macro:`NGHTTP2_DEFAULT_WEIGHT`). To specify the
|
||||
* priority, use either `nghttp2_priority_spec_group_init()` or
|
||||
* `nghttp2_priority_spec_dep_init()`. If |pri_spec| is not ``NULL``,
|
||||
* means the default priority (see
|
||||
* `nghttp2_priority_spec_default_init()`). To specify the priority,
|
||||
* use `nghttp2_priority_spec_init()`. If |pri_spec| is not ``NULL``,
|
||||
* this function will copy its data members.
|
||||
*
|
||||
* The `pri_spec->weight` must be in [:enum:`NGHTTP2_MIN_WEIGHT`,
|
||||
* :enum:`NGHTTP2_MAX_WEIGHT`], inclusive. If `pri_spec->weight` is
|
||||
* strictly less than :enum:`NGHTTP2_MIN_WEIGHT`, it becomes
|
||||
* :enum:`NGHTTP2_MIN_WEIGHT`. If it is strictly greater than
|
||||
* :enum:`NGHTTP2_MAX_WEIGHT`, it becomes :enum:`NGHTTP2_MAX_WEIGHT`.
|
||||
*
|
||||
* The |nva| is an array of name/value pair :type:`nghttp2_nv` with
|
||||
* |nvlen| elements. The value is opaque sequence of bytes and
|
||||
* therefore can contain NULL byte (0x0). If the application requires
|
||||
|
@ -2336,8 +2272,6 @@ int nghttp2_submit_response(nghttp2_session *session,
|
|||
*
|
||||
* :enum:`NGHTTP2_ERR_NOMEM`
|
||||
* Out of memory.
|
||||
* :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
|
||||
* The |pri_spec->pri_type| is invalid.
|
||||
*/
|
||||
int nghttp2_submit_headers(nghttp2_session *session, uint8_t flags,
|
||||
int32_t stream_id,
|
||||
|
@ -2379,10 +2313,15 @@ int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
|
|||
* :enum:`NGHTTP2_FLAG_NONE`.
|
||||
*
|
||||
* The |pri_spec| is priority specification of this request. ``NULL``
|
||||
* is not allowed for this function. To specify the priority, use
|
||||
* either `nghttp2_priority_spec_group_init()` or
|
||||
* `nghttp2_priority_spec_dep_init()`. This function will copy its
|
||||
* data members.
|
||||
* is not allowed for this function. To specify the priority, use
|
||||
* `nghttp2_priority_spec_init()`. This function will copy its data
|
||||
* members.
|
||||
*
|
||||
* The `pri_spec->weight` must be in [:enum:`NGHTTP2_MIN_WEIGHT`,
|
||||
* :enum:`NGHTTP2_MAX_WEIGHT`], inclusive. If `pri_spec->weight` is
|
||||
* strictly less than :enum:`NGHTTP2_MIN_WEIGHT`, it becomes
|
||||
* :enum:`NGHTTP2_MIN_WEIGHT`. If it is strictly greater than
|
||||
* :enum:`NGHTTP2_MAX_WEIGHT`, it becomes :enum:`NGHTTP2_MAX_WEIGHT`.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
|
@ -2390,8 +2329,7 @@ int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
|
|||
* :enum:`NGHTTP2_ERR_NOMEM`
|
||||
* Out of memory.
|
||||
* :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
|
||||
* The |pri_spec| is NULL; or the |pri_spec->pri_type| is invalid;
|
||||
* or trying to depend on itself.
|
||||
* The |pri_spec| is NULL; or trying to depend on itself.
|
||||
*/
|
||||
int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags,
|
||||
int32_t stream_id,
|
||||
|
|
|
@ -74,7 +74,12 @@ void nghttp2_frame_headers_init(nghttp2_headers *frame,
|
|||
frame->nva = nva;
|
||||
frame->nvlen = nvlen;
|
||||
frame->cat = NGHTTP2_HCAT_REQUEST;
|
||||
frame->pri_spec = *pri_spec;
|
||||
|
||||
if(pri_spec) {
|
||||
frame->pri_spec = *pri_spec;
|
||||
} else {
|
||||
nghttp2_priority_spec_default_init(&frame->pri_spec);
|
||||
}
|
||||
}
|
||||
|
||||
void nghttp2_frame_headers_free(nghttp2_headers *frame)
|
||||
|
@ -85,22 +90,8 @@ void nghttp2_frame_headers_free(nghttp2_headers *frame)
|
|||
void nghttp2_frame_priority_init(nghttp2_priority *frame, int32_t stream_id,
|
||||
const nghttp2_priority_spec *pri_spec)
|
||||
{
|
||||
uint8_t flags;
|
||||
|
||||
switch(pri_spec->pri_type) {
|
||||
case NGHTTP2_PRIORITY_TYPE_GROUP:
|
||||
flags = NGHTTP2_FLAG_PRIORITY_GROUP;
|
||||
|
||||
break;
|
||||
case NGHTTP2_PRIORITY_TYPE_DEP:
|
||||
flags = NGHTTP2_FLAG_PRIORITY_DEPENDENCY;
|
||||
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
nghttp2_frame_set_hd(&frame->hd, 4, NGHTTP2_PRIORITY, flags, stream_id);
|
||||
nghttp2_frame_set_hd(&frame->hd, 5, NGHTTP2_PRIORITY, NGHTTP2_FLAG_NONE,
|
||||
stream_id);
|
||||
frame->pri_spec = *pri_spec;
|
||||
}
|
||||
|
||||
|
@ -261,14 +252,10 @@ void nghttp2_frame_private_data_free(nghttp2_private_data *frame)
|
|||
|
||||
size_t nghttp2_frame_priority_len(uint8_t flags)
|
||||
{
|
||||
if(flags & NGHTTP2_FLAG_PRIORITY_GROUP) {
|
||||
if(flags & NGHTTP2_FLAG_PRIORITY) {
|
||||
return 5;
|
||||
}
|
||||
|
||||
if(flags & NGHTTP2_FLAG_PRIORITY_DEPENDENCY) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -375,7 +362,9 @@ int nghttp2_frame_pack_headers(nghttp2_bufs *bufs,
|
|||
return rv;
|
||||
}
|
||||
|
||||
nghttp2_frame_pack_priority_spec(buf->pos, &frame->pri_spec);
|
||||
if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
|
||||
nghttp2_frame_pack_priority_spec(buf->pos, &frame->pri_spec);
|
||||
}
|
||||
|
||||
frame->padlen = 0;
|
||||
frame->hd.length = nghttp2_bufs_len(bufs);
|
||||
|
@ -386,24 +375,11 @@ int nghttp2_frame_pack_headers(nghttp2_bufs *bufs,
|
|||
void nghttp2_frame_pack_priority_spec(uint8_t *buf,
|
||||
const nghttp2_priority_spec *pri_spec)
|
||||
{
|
||||
switch(pri_spec->pri_type) {
|
||||
case NGHTTP2_PRIORITY_TYPE_GROUP:
|
||||
|
||||
nghttp2_put_uint32be(buf, pri_spec->spec.group.pri_group_id);
|
||||
buf[4] = pri_spec->spec.group.weight - 1;
|
||||
|
||||
return;
|
||||
case NGHTTP2_PRIORITY_TYPE_DEP:
|
||||
|
||||
nghttp2_put_uint32be(buf, pri_spec->spec.dep.stream_id);
|
||||
if(pri_spec->spec.dep.exclusive) {
|
||||
buf[0] |= 0x80;
|
||||
}
|
||||
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
nghttp2_put_uint32be(buf, pri_spec->stream_id);
|
||||
if(pri_spec->exclusive) {
|
||||
buf[0] |= 0x80;
|
||||
}
|
||||
buf[4] = pri_spec->weight - 1;
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_priority_spec(nghttp2_priority_spec *pri_spec,
|
||||
|
@ -411,33 +387,28 @@ void nghttp2_frame_unpack_priority_spec(nghttp2_priority_spec *pri_spec,
|
|||
const uint8_t *payload,
|
||||
size_t payloadlen)
|
||||
{
|
||||
if(flags & NGHTTP2_FLAG_PRIORITY_GROUP) {
|
||||
int32_t pri_group_id;
|
||||
int32_t weight;
|
||||
int32_t dep_stream_id;
|
||||
uint8_t exclusive;
|
||||
int32_t weight;
|
||||
|
||||
pri_group_id = nghttp2_get_uint32(payload) & NGHTTP2_PRI_GROUP_ID_MASK;
|
||||
weight = payload[4] + 1;
|
||||
dep_stream_id = nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
|
||||
exclusive = (payload[0] & 0x80) > 0;
|
||||
weight = payload[4] + 1;
|
||||
|
||||
nghttp2_priority_spec_group_init(pri_spec, pri_group_id, weight);
|
||||
} else if(flags & NGHTTP2_FLAG_PRIORITY_DEPENDENCY) {
|
||||
int32_t dep_stream_id;
|
||||
uint8_t exclusive;
|
||||
|
||||
dep_stream_id = nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
|
||||
exclusive = (payload[0] & 0x80) > 0;
|
||||
|
||||
nghttp2_priority_spec_dep_init(pri_spec, dep_stream_id, exclusive);
|
||||
} else {
|
||||
pri_spec->pri_type = NGHTTP2_PRIORITY_TYPE_NONE;
|
||||
}
|
||||
nghttp2_priority_spec_init(pri_spec, dep_stream_id, weight, exclusive);
|
||||
}
|
||||
|
||||
int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen)
|
||||
{
|
||||
nghttp2_frame_unpack_priority_spec(&frame->pri_spec, frame->hd.flags,
|
||||
payload, payloadlen);
|
||||
if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
|
||||
nghttp2_frame_unpack_priority_spec(&frame->pri_spec, frame->hd.flags,
|
||||
payload, payloadlen);
|
||||
} else {
|
||||
nghttp2_priority_spec_default_init(&frame->pri_spec);
|
||||
}
|
||||
|
||||
frame->nva = NULL;
|
||||
frame->nvlen = 0;
|
||||
|
||||
|
@ -457,7 +428,7 @@ int nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame)
|
|||
|
||||
nghttp2_frame_pack_priority_spec(buf->last, &frame->pri_spec);
|
||||
|
||||
buf->last += nghttp2_frame_priority_len(frame->hd.flags);
|
||||
buf->last += 5;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -155,7 +155,8 @@ int nghttp2_frame_pack_headers(nghttp2_bufs *bufs,
|
|||
|
||||
/*
|
||||
* Unpacks HEADERS frame byte sequence into |frame|. This function
|
||||
* only unapcks bytes that come before name/value header block.
|
||||
* only unapcks bytes that come before name/value header block and
|
||||
* after PAD_HIGH and PAD_LOW.
|
||||
*
|
||||
* This function returns 0 if it succeeds or one of the following
|
||||
* negative error codes:
|
||||
|
|
|
@ -24,18 +24,25 @@
|
|||
*/
|
||||
#include "nghttp2_priority_spec.h"
|
||||
|
||||
void nghttp2_priority_spec_group_init(nghttp2_priority_spec *pri_spec,
|
||||
int32_t pri_group_id, int32_t weight)
|
||||
void nghttp2_priority_spec_init(nghttp2_priority_spec *pri_spec,
|
||||
int32_t stream_id, int32_t weight,
|
||||
int exclusive)
|
||||
{
|
||||
pri_spec->pri_type = NGHTTP2_PRIORITY_TYPE_GROUP;
|
||||
pri_spec->spec.group.pri_group_id = pri_group_id;
|
||||
pri_spec->spec.group.weight = weight;
|
||||
pri_spec->stream_id = stream_id;
|
||||
pri_spec->weight = weight;
|
||||
pri_spec->exclusive = exclusive != 0;
|
||||
}
|
||||
|
||||
void nghttp2_priority_spec_dep_init(nghttp2_priority_spec *pri_spec,
|
||||
int32_t stream_id, int exclusive)
|
||||
void nghttp2_priority_spec_default_init(nghttp2_priority_spec *pri_spec)
|
||||
{
|
||||
pri_spec->pri_type = NGHTTP2_PRIORITY_TYPE_DEP;
|
||||
pri_spec->spec.dep.stream_id = stream_id;
|
||||
pri_spec->spec.dep.exclusive = exclusive != 0;
|
||||
pri_spec->stream_id = 0;
|
||||
pri_spec->weight = NGHTTP2_DEFAULT_WEIGHT;
|
||||
pri_spec->exclusive = 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -147,13 +147,6 @@ nghttp2_stream* nghttp2_session_get_stream_raw(nghttp2_session *session,
|
|||
return (nghttp2_stream*)nghttp2_map_find(&session->streams, stream_id);
|
||||
}
|
||||
|
||||
nghttp2_stream_group* nghttp2_session_get_stream_group
|
||||
(nghttp2_session *session, int32_t pri_group_id)
|
||||
{
|
||||
return (nghttp2_stream_group*)nghttp2_map_find(&session->stream_groups,
|
||||
pri_group_id);
|
||||
}
|
||||
|
||||
static int nghttp2_outbound_item_compar(const void *lhsx, const void *rhsx)
|
||||
{
|
||||
const nghttp2_outbound_item *lhs, *rhs;
|
||||
|
@ -287,10 +280,7 @@ static int nghttp2_session_new(nghttp2_session **session_ptr,
|
|||
goto fail_map;
|
||||
}
|
||||
|
||||
rv = nghttp2_map_init(&(*session_ptr)->stream_groups);
|
||||
if(rv != 0) {
|
||||
goto fail_group_map;
|
||||
}
|
||||
nghttp2_stream_roots_init(&(*session_ptr)->roots);
|
||||
|
||||
(*session_ptr)->next_seq = 0;
|
||||
|
||||
|
@ -359,8 +349,6 @@ static int nghttp2_session_new(nghttp2_session **session_ptr,
|
|||
return 0;
|
||||
|
||||
fail_aob_framebuf:
|
||||
nghttp2_map_free(&(*session_ptr)->stream_groups);
|
||||
fail_group_map:
|
||||
nghttp2_map_free(&(*session_ptr)->streams);
|
||||
fail_map:
|
||||
nghttp2_hd_inflate_free(&(*session_ptr)->hd_inflater);
|
||||
|
@ -432,14 +420,6 @@ static int nghttp2_free_streams(nghttp2_map_entry *entry, void *ptr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int nghttp2_free_stream_groups(nghttp2_map_entry *entry, void *ptr)
|
||||
{
|
||||
nghttp2_stream_group_free((nghttp2_stream_group*)entry);
|
||||
free(entry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nghttp2_session_ob_pq_free(nghttp2_pq *pq)
|
||||
{
|
||||
while(!nghttp2_pq_empty(pq)) {
|
||||
|
@ -458,15 +438,13 @@ void nghttp2_session_del(nghttp2_session *session)
|
|||
}
|
||||
free(session->inflight_iv);
|
||||
|
||||
nghttp2_stream_roots_free(&session->roots);
|
||||
|
||||
/* Have to free streams first, so that we can check
|
||||
stream->data_item->queued */
|
||||
nghttp2_map_each_free(&session->streams, nghttp2_free_streams, NULL);
|
||||
nghttp2_map_free(&session->streams);
|
||||
|
||||
nghttp2_map_each_free(&session->stream_groups, nghttp2_free_stream_groups,
|
||||
NULL);
|
||||
nghttp2_map_free(&session->stream_groups);
|
||||
|
||||
nghttp2_session_ob_pq_free(&session->ob_pq);
|
||||
nghttp2_session_ob_pq_free(&session->ob_ss_pq);
|
||||
nghttp2_active_outbound_item_reset(&session->aob);
|
||||
|
@ -482,99 +460,71 @@ int nghttp2_session_reprioritize_stream
|
|||
const nghttp2_priority_spec *pri_spec)
|
||||
{
|
||||
int rv;
|
||||
nghttp2_stream_group *stream_group;
|
||||
nghttp2_stream_group *old_stream_group;
|
||||
nghttp2_stream *dep_stream;
|
||||
nghttp2_stream *root_stream;
|
||||
const nghttp2_priority_group *group;
|
||||
const nghttp2_priority_dep *dep;
|
||||
|
||||
switch(pri_spec->pri_type) {
|
||||
case NGHTTP2_PRIORITY_TYPE_GROUP:
|
||||
group = &pri_spec->spec.group;
|
||||
|
||||
old_stream_group = stream->stream_group;
|
||||
if(pri_spec->stream_id == stream->stream_id) {
|
||||
return nghttp2_session_terminate_session(session,
|
||||
NGHTTP2_PROTOCOL_ERROR);
|
||||
}
|
||||
|
||||
if(pri_spec->stream_id == 0) {
|
||||
nghttp2_stream_dep_remove_subtree(stream);
|
||||
|
||||
stream_group = nghttp2_session_get_stream_group(session,
|
||||
group->pri_group_id);
|
||||
/* We have to update weight after removing stream from tree */
|
||||
stream->weight = pri_spec->weight;
|
||||
|
||||
if(stream_group == NULL) {
|
||||
stream_group = nghttp2_session_open_stream_group(session,
|
||||
group->pri_group_id,
|
||||
group->weight);
|
||||
if(pri_spec->exclusive &&
|
||||
session->roots.num_streams <= NGHTTP2_MAX_DEP_TREE_LENGTH) {
|
||||
|
||||
if(stream_group == NULL) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
rv = nghttp2_stream_dep_all_your_stream_are_belong_to_us
|
||||
(stream, &session->ob_pq);
|
||||
} else {
|
||||
stream_group->weight = group->weight;
|
||||
rv = nghttp2_stream_dep_make_root(stream, &session->ob_pq);
|
||||
}
|
||||
|
||||
rv = nghttp2_stream_dep_make_root(stream_group, stream, &session->ob_pq);
|
||||
return rv;
|
||||
}
|
||||
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nghttp2_session_close_stream_group_if_empty(session, old_stream_group);
|
||||
dep_stream = nghttp2_session_get_stream_raw(session, pri_spec->stream_id);
|
||||
|
||||
if(!dep_stream || !nghttp2_stream_in_dep_tree(dep_stream)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
case NGHTTP2_PRIORITY_TYPE_DEP:
|
||||
dep = &pri_spec->spec.dep;
|
||||
if(nghttp2_stream_dep_subtree_find(stream, dep_stream)) {
|
||||
DEBUGF(fprintf(stderr,
|
||||
"stream: cycle detected, dep_stream(%p)=%d "
|
||||
"stream(%p)=%d\n",
|
||||
dep_stream, dep_stream->stream_id,
|
||||
stream, stream->stream_id));
|
||||
|
||||
if(dep->stream_id == stream->stream_id || dep->stream_id == 0) {
|
||||
return nghttp2_session_terminate_session(session,
|
||||
NGHTTP2_PROTOCOL_ERROR);
|
||||
}
|
||||
nghttp2_stream_dep_remove_subtree(dep_stream);
|
||||
nghttp2_stream_dep_make_root(dep_stream, &session->ob_pq);
|
||||
}
|
||||
|
||||
old_stream_group = stream->stream_group;
|
||||
nghttp2_stream_dep_remove_subtree(stream);
|
||||
|
||||
dep_stream = nghttp2_session_get_stream_raw(session, dep->stream_id);
|
||||
/* We have to update weight after removing stream from tree */
|
||||
stream->weight = pri_spec->weight;
|
||||
|
||||
if(dep_stream == NULL) {
|
||||
return 0;
|
||||
}
|
||||
root_stream = nghttp2_stream_get_dep_root(dep_stream);
|
||||
|
||||
/* Ignore priority request if resultant tree has cycle */
|
||||
if(nghttp2_stream_dep_subtree_find(stream, dep_stream)) {
|
||||
DEBUGF(fprintf(stderr,
|
||||
"stream: future cycle detected, dep_stream(%p)=%d "
|
||||
"stream(%p)=%d\n",
|
||||
dep_stream, dep_stream->stream_id,
|
||||
stream, stream->stream_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
nghttp2_stream_dep_remove_subtree(stream);
|
||||
|
||||
root_stream = nghttp2_stream_get_dep_root(dep_stream);
|
||||
|
||||
if(root_stream->num_substreams + stream->num_substreams >
|
||||
NGHTTP2_MAX_DEP_TREE_LENGTH) {
|
||||
rv = nghttp2_stream_dep_make_root(dep_stream->stream_group, stream,
|
||||
&session->ob_pq);
|
||||
if(root_stream->num_substreams + stream->num_substreams >
|
||||
NGHTTP2_MAX_DEP_TREE_LENGTH) {
|
||||
rv = nghttp2_stream_dep_make_root(stream, &session->ob_pq);
|
||||
} else {
|
||||
if(pri_spec->exclusive) {
|
||||
rv = nghttp2_stream_dep_insert_subtree(dep_stream, stream,
|
||||
&session->ob_pq);
|
||||
} else {
|
||||
if(dep->exclusive) {
|
||||
rv = nghttp2_stream_dep_insert_subtree(dep_stream, stream,
|
||||
&session->ob_pq);
|
||||
} else {
|
||||
rv = nghttp2_stream_dep_add_subtree(dep_stream, stream,
|
||||
&session->ob_pq);
|
||||
}
|
||||
rv = nghttp2_stream_dep_add_subtree(dep_stream, stream,
|
||||
&session->ob_pq);
|
||||
}
|
||||
}
|
||||
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nghttp2_session_close_stream_group_if_empty(session, old_stream_group);
|
||||
|
||||
return 0;
|
||||
default:
|
||||
assert(0);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -615,24 +565,30 @@ int nghttp2_session_add_frame(nghttp2_session *session,
|
|||
if(frame->hd.stream_id == -1) {
|
||||
/* Initial HEADERS, which will open stream */
|
||||
|
||||
if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY_GROUP) {
|
||||
item->weight = frame->headers.pri_spec.spec.group.weight;
|
||||
} else if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY_DEPENDENCY) {
|
||||
dep_stream = nghttp2_session_get_stream
|
||||
(session, frame->headers.pri_spec.spec.dep.stream_id);
|
||||
if(dep_stream) {
|
||||
item->weight = dep_stream->stream_group->weight;
|
||||
/* TODO If we always frame.headers.pri_spec filled in, we
|
||||
don't have to check flags */
|
||||
if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
|
||||
if(frame->headers.pri_spec.stream_id == 0) {
|
||||
item->weight = frame->headers.pri_spec.weight;
|
||||
} else {
|
||||
item->weight = NGHTTP2_DEFAULT_WEIGHT;
|
||||
dep_stream = nghttp2_session_get_stream
|
||||
(session, frame->headers.pri_spec.stream_id);
|
||||
|
||||
if(dep_stream) {
|
||||
item->weight = nghttp2_stream_dep_distributed_effective_weight
|
||||
(dep_stream, frame->headers.pri_spec.weight);
|
||||
} else {
|
||||
item->weight = frame->headers.pri_spec.weight;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
item->weight = NGHTTP2_DEFAULT_WEIGHT;
|
||||
}
|
||||
|
||||
} else if(stream) {
|
||||
/* Otherwise, the frame must have stream ID. We use its
|
||||
priority value. */
|
||||
item->weight = stream->stream_group->weight;
|
||||
/* Otherwise, the frame must have stream ID. We use its
|
||||
effective_weight. */
|
||||
item->weight = stream->effective_weight;
|
||||
}
|
||||
break;
|
||||
case NGHTTP2_PRIORITY:
|
||||
|
@ -656,7 +612,7 @@ int nghttp2_session_add_frame(nghttp2_session *session,
|
|||
case NGHTTP2_PUSH_PROMISE:
|
||||
/* Use priority of associated stream */
|
||||
if(stream) {
|
||||
item->weight = stream->stream_group->weight;
|
||||
item->weight = stream->effective_weight;
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -699,7 +655,7 @@ int nghttp2_session_add_frame(nghttp2_session *session,
|
|||
if(stream->data_item) {
|
||||
rv = NGHTTP2_ERR_DATA_EXIST;
|
||||
} else {
|
||||
item->weight = nghttp2_stream_group_shared_wait(stream->stream_group);
|
||||
item->weight = stream->effective_weight;
|
||||
|
||||
rv = nghttp2_stream_attach_data(stream, item, &session->ob_pq);
|
||||
}
|
||||
|
@ -756,57 +712,18 @@ nghttp2_stream* nghttp2_session_open_stream(nghttp2_session *session,
|
|||
nghttp2_stream *stream;
|
||||
nghttp2_stream *dep_stream;
|
||||
nghttp2_stream *root_stream;
|
||||
int32_t pri_group_id;
|
||||
int32_t weight;
|
||||
nghttp2_stream_group *stream_group;
|
||||
|
||||
dep_stream = NULL;
|
||||
|
||||
if(session->server && !nghttp2_session_is_my_stream_id(session, stream_id)) {
|
||||
nghttp2_session_adjust_closed_stream(session, 1);
|
||||
}
|
||||
|
||||
switch(pri_spec->pri_type) {
|
||||
case NGHTTP2_PRIORITY_TYPE_GROUP:
|
||||
pri_group_id = pri_spec->spec.group.pri_group_id;
|
||||
weight = pri_spec->spec.group.weight;
|
||||
|
||||
break;
|
||||
case NGHTTP2_PRIORITY_TYPE_DEP:
|
||||
dep_stream = nghttp2_session_get_stream_raw(session,
|
||||
pri_spec->spec.dep.stream_id);
|
||||
|
||||
if(dep_stream) {
|
||||
pri_group_id = dep_stream->stream_group->pri_group_id;
|
||||
weight = dep_stream->stream_group->weight;
|
||||
} else {
|
||||
pri_group_id = stream_id;
|
||||
weight = NGHTTP2_DEFAULT_WEIGHT;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
pri_group_id = stream_id;
|
||||
weight = NGHTTP2_DEFAULT_WEIGHT;
|
||||
};
|
||||
|
||||
stream_group = nghttp2_session_get_stream_group(session, pri_group_id);
|
||||
|
||||
if(stream_group == NULL) {
|
||||
stream_group = nghttp2_session_open_stream_group(session, pri_group_id,
|
||||
weight);
|
||||
|
||||
if(stream_group == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
stream = malloc(sizeof(nghttp2_stream));
|
||||
if(stream == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nghttp2_stream_init(stream, stream_id, flags, initial_state,
|
||||
pri_spec->weight, &session->roots,
|
||||
session->remote_settings
|
||||
[NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE],
|
||||
session->local_settings
|
||||
|
@ -819,8 +736,6 @@ nghttp2_stream* nghttp2_session_open_stream(nghttp2_session *session,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
nghttp2_stream_group_add_stream(stream_group, stream);
|
||||
|
||||
if(initial_state == NGHTTP2_STREAM_RESERVED) {
|
||||
if(nghttp2_session_is_my_stream_id(session, stream_id)) {
|
||||
/* half closed (remote) */
|
||||
|
@ -839,15 +754,34 @@ nghttp2_stream* nghttp2_session_open_stream(nghttp2_session *session,
|
|||
}
|
||||
}
|
||||
|
||||
/* Possibly update weight of priority group */
|
||||
stream_group->weight = weight;
|
||||
|
||||
/* We don't have to track dependency of received reserved stream */
|
||||
if(stream->shut_flags & NGHTTP2_SHUT_WR) {
|
||||
return stream;
|
||||
}
|
||||
|
||||
if(!dep_stream) {
|
||||
if(pri_spec->stream_id == 0) {
|
||||
|
||||
++session->roots.num_streams;
|
||||
|
||||
if(pri_spec->exclusive &&
|
||||
session->roots.num_streams <= NGHTTP2_MAX_DEP_TREE_LENGTH) {
|
||||
rv = nghttp2_stream_dep_all_your_stream_are_belong_to_us
|
||||
(stream, &session->ob_pq);
|
||||
|
||||
/* Since no dpri is changed in dependency tree, the above
|
||||
function call never fail. */
|
||||
assert(rv == 0);
|
||||
} else {
|
||||
nghttp2_stream_roots_add(&session->roots, stream);
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
dep_stream = nghttp2_session_get_stream_raw(session, pri_spec->stream_id);
|
||||
|
||||
/* If dep_stream is not part of dependency tree, we don't use it. */
|
||||
if(!dep_stream || !nghttp2_stream_in_dep_tree(dep_stream)) {
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
@ -858,7 +792,7 @@ nghttp2_stream* nghttp2_session_open_stream(nghttp2_session *session,
|
|||
root_stream = nghttp2_stream_get_dep_root(dep_stream);
|
||||
|
||||
if(root_stream->num_substreams < NGHTTP2_MAX_DEP_TREE_LENGTH) {
|
||||
if(pri_spec->spec.dep.exclusive) {
|
||||
if(pri_spec->exclusive) {
|
||||
nghttp2_stream_dep_insert(dep_stream, stream);
|
||||
} else {
|
||||
nghttp2_stream_dep_add(dep_stream, stream);
|
||||
|
@ -929,7 +863,9 @@ int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id,
|
|||
/* Closes both directions just in case they are not closed yet */
|
||||
stream->flags |= NGHTTP2_STREAM_FLAG_CLOSED;
|
||||
|
||||
if(session->server && !nghttp2_session_is_my_stream_id(session, stream_id)) {
|
||||
if(session->server &&
|
||||
nghttp2_stream_in_dep_tree(stream) &&
|
||||
!nghttp2_session_is_my_stream_id(session, stream_id)) {
|
||||
/* On server side, retain incoming stream object at most
|
||||
MAX_CONCURRENT_STREAMS combined with the current active streams
|
||||
to make dependency tree work better. */
|
||||
|
@ -944,18 +880,11 @@ int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id,
|
|||
void nghttp2_session_destroy_stream(nghttp2_session *session,
|
||||
nghttp2_stream *stream)
|
||||
{
|
||||
nghttp2_stream_group *stream_group;
|
||||
|
||||
DEBUGF(fprintf(stderr, "stream: destroy closed stream(%p)=%d\n",
|
||||
stream, stream->stream_id));
|
||||
|
||||
nghttp2_stream_dep_remove(stream);
|
||||
|
||||
stream_group = stream->stream_group;
|
||||
|
||||
nghttp2_stream_group_remove_stream(stream_group, stream);
|
||||
nghttp2_session_close_stream_group_if_empty(session, stream_group);
|
||||
|
||||
nghttp2_map_remove(&session->streams, stream->stream_id);
|
||||
nghttp2_stream_free(stream);
|
||||
free(stream);
|
||||
|
@ -1537,15 +1466,6 @@ static int nghttp2_session_prep_frame(nghttp2_session *session,
|
|||
frame->hd.stream_id = session->next_stream_id;
|
||||
session->next_stream_id += 2;
|
||||
|
||||
if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY_GROUP) {
|
||||
if(frame->headers.pri_spec.spec.group.pri_group_id == -1) {
|
||||
/* We now know stream_id. Assign stream_id to
|
||||
pri_group_id if it is -1. */
|
||||
frame->headers.pri_spec.spec.group.pri_group_id =
|
||||
frame->hd.stream_id;
|
||||
}
|
||||
}
|
||||
|
||||
} else if(nghttp2_session_predicate_push_response_headers_send
|
||||
(session, frame->hd.stream_id) == 0) {
|
||||
frame->headers.cat = NGHTTP2_HCAT_PUSH_RESPONSE;
|
||||
|
@ -1665,7 +1585,8 @@ static int nghttp2_session_prep_frame(nghttp2_session *session,
|
|||
|
||||
/* TODO It is unclear reserved stream dpeneds on associated
|
||||
stream with or without exclusive flag set */
|
||||
nghttp2_priority_spec_dep_init(&pri_spec, stream->stream_id, 0);
|
||||
nghttp2_priority_spec_init(&pri_spec, stream->stream_id,
|
||||
NGHTTP2_DEFAULT_WEIGHT, 0);
|
||||
|
||||
if(!nghttp2_session_open_stream
|
||||
(session, frame->push_promise.promised_stream_id,
|
||||
|
@ -2159,8 +2080,7 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session)
|
|||
assert(stream);
|
||||
next_item = nghttp2_session_get_next_ob_item(session);
|
||||
|
||||
outbound_item_cycle_weight
|
||||
(aob->item, nghttp2_stream_group_shared_wait(stream->stream_group));
|
||||
outbound_item_cycle_weight(aob->item, stream->effective_weight);
|
||||
|
||||
/* If priority of this stream is higher or equal to other stream
|
||||
waiting at the top of the queue, we continue to send this
|
||||
|
@ -2855,9 +2775,7 @@ int nghttp2_session_on_request_headers_received(nghttp2_session *session,
|
|||
(session, frame, NGHTTP2_ENHANCE_YOUR_CALM);
|
||||
}
|
||||
|
||||
if(frame->headers.pri_spec.pri_type == NGHTTP2_PRIORITY_TYPE_DEP &&
|
||||
(frame->headers.pri_spec.spec.dep.stream_id == frame->hd.stream_id ||
|
||||
frame->headers.pri_spec.spec.dep.stream_id == 0)) {
|
||||
if(frame->headers.pri_spec.stream_id == frame->hd.stream_id) {
|
||||
return nghttp2_session_inflate_handle_invalid_connection
|
||||
(session, frame, NGHTTP2_PROTOCOL_ERROR);
|
||||
}
|
||||
|
@ -3508,7 +3426,8 @@ int nghttp2_session_on_push_promise_received(nghttp2_session *session,
|
|||
|
||||
/* TODO It is unclear reserved stream dpeneds on associated
|
||||
stream with or without exclusive flag set */
|
||||
nghttp2_priority_spec_dep_init(&pri_spec, stream->stream_id, 0);
|
||||
nghttp2_priority_spec_init(&pri_spec, stream->stream_id,
|
||||
NGHTTP2_DEFAULT_WEIGHT, 0);
|
||||
|
||||
promised_stream = nghttp2_session_open_stream
|
||||
(session,
|
||||
|
@ -4229,15 +4148,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
|||
NGHTTP2_FLAG_END_HEADERS |
|
||||
NGHTTP2_FLAG_PAD_LOW |
|
||||
NGHTTP2_FLAG_PAD_HIGH |
|
||||
NGHTTP2_FLAG_PRIORITY_GROUP |
|
||||
NGHTTP2_FLAG_PRIORITY_DEPENDENCY);
|
||||
NGHTTP2_FLAG_PRIORITY);
|
||||
|
||||
rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd);
|
||||
if(rv < 0 ||
|
||||
(iframe->frame.hd.flags & (NGHTTP2_FLAG_PRIORITY_GROUP |
|
||||
NGHTTP2_FLAG_PRIORITY_DEPENDENCY)) ==
|
||||
(NGHTTP2_FLAG_PRIORITY_GROUP | NGHTTP2_FLAG_PRIORITY_DEPENDENCY)) {
|
||||
|
||||
if(rv < 0) {
|
||||
busy = 1;
|
||||
|
||||
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
|
||||
|
@ -4287,34 +4201,11 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
|||
|
||||
break;
|
||||
case NGHTTP2_PRIORITY:
|
||||
pri_fieldlen = 0;
|
||||
|
||||
DEBUGF(fprintf(stderr, "recv: PRIORITY\n"));
|
||||
|
||||
iframe->frame.hd.flags &= (NGHTTP2_FLAG_PRIORITY_GROUP |
|
||||
NGHTTP2_FLAG_PRIORITY_DEPENDENCY);
|
||||
iframe->frame.hd.flags = NGHTTP2_FLAG_NONE;
|
||||
|
||||
pri_fieldlen = nghttp2_frame_priority_len(iframe->frame.hd.flags);
|
||||
|
||||
if(iframe->frame.hd.flags == (NGHTTP2_FLAG_PRIORITY_GROUP |
|
||||
NGHTTP2_FLAG_PRIORITY_DEPENDENCY) ||
|
||||
pri_fieldlen == 0) {
|
||||
|
||||
busy = 1;
|
||||
|
||||
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
|
||||
|
||||
rv = nghttp2_session_terminate_session(session,
|
||||
NGHTTP2_PROTOCOL_ERROR);
|
||||
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(pri_fieldlen != iframe->payloadleft) {
|
||||
if(iframe->payloadleft != 5) {
|
||||
busy = 1;
|
||||
|
||||
iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
|
||||
|
@ -4324,7 +4215,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
|||
|
||||
iframe->state = NGHTTP2_IB_READ_NBYTE;
|
||||
|
||||
inbound_frame_set_mark(iframe, pri_fieldlen);
|
||||
inbound_frame_set_mark(iframe, 5);
|
||||
|
||||
break;
|
||||
case NGHTTP2_RST_STREAM:
|
||||
|
@ -4535,6 +4426,9 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
|||
iframe->state = NGHTTP2_IB_READ_NBYTE;
|
||||
inbound_frame_set_mark(iframe, pri_fieldlen);
|
||||
break;
|
||||
} else {
|
||||
/* Truncate buffers used for padding spec */
|
||||
inbound_frame_set_mark(iframe, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5653,7 +5547,7 @@ int nghttp2_session_upgrade(nghttp2_session *session,
|
|||
return rv;
|
||||
}
|
||||
|
||||
nghttp2_priority_spec_group_init(&pri_spec, 1, NGHTTP2_DEFAULT_WEIGHT);
|
||||
nghttp2_priority_spec_default_init(&pri_spec);
|
||||
|
||||
stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
|
||||
&pri_spec, NGHTTP2_STREAM_OPENING,
|
||||
|
@ -5672,41 +5566,3 @@ int nghttp2_session_upgrade(nghttp2_session *session,
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
nghttp2_stream_group* nghttp2_session_open_stream_group
|
||||
(nghttp2_session *session, int32_t pri_group_id, int32_t weight)
|
||||
{
|
||||
int rv;
|
||||
nghttp2_stream_group *stream_group;
|
||||
|
||||
stream_group = malloc(sizeof(nghttp2_stream_group));
|
||||
|
||||
if(stream_group == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nghttp2_stream_group_init(stream_group, pri_group_id, weight);
|
||||
|
||||
rv = nghttp2_map_insert(&session->stream_groups, &stream_group->map_entry);
|
||||
|
||||
if(rv != 0) {
|
||||
free(stream_group);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return stream_group;
|
||||
}
|
||||
|
||||
void nghttp2_session_close_stream_group_if_empty
|
||||
(nghttp2_session *session, nghttp2_stream_group *stream_group)
|
||||
{
|
||||
if(stream_group->num_streams == 0) {
|
||||
DEBUGF(fprintf(stderr, "stream: stream_group(%p)=%d closed\n",
|
||||
stream_group, stream_group->pri_group_id));
|
||||
|
||||
nghttp2_map_remove(&session->stream_groups, stream_group->pri_group_id);
|
||||
nghttp2_stream_group_free(stream_group);
|
||||
free(stream_group);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ typedef enum {
|
|||
|
||||
struct nghttp2_session {
|
||||
nghttp2_map /* <nghttp2_stream*> */ streams;
|
||||
nghttp2_map /* <nghttp2_stream_group*> */ stream_groups;
|
||||
nghttp2_stream_roots roots;
|
||||
/* Queue for outbound frames other than stream-creating HEADERS */
|
||||
nghttp2_pq /* <nghttp2_outbound_item*> */ ob_pq;
|
||||
/* Queue for outbound stream-creating HEADERS frame */
|
||||
|
@ -603,14 +603,6 @@ nghttp2_stream* nghttp2_session_get_stream(nghttp2_session *session,
|
|||
nghttp2_stream* nghttp2_session_get_stream_raw(nghttp2_session *session,
|
||||
int32_t stream_id);
|
||||
|
||||
/*
|
||||
* Returns nghttp2_stream_group* object whose priority group ID is
|
||||
* |pri_group_id|. It could be NULL if such priority group does not
|
||||
* exist.
|
||||
*/
|
||||
nghttp2_stream_group* nghttp2_session_get_stream_group
|
||||
(nghttp2_session *session, int32_t pri_group_id);
|
||||
|
||||
/*
|
||||
* Packs DATA frame |frame| in wire frame format and stores it in
|
||||
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
|
||||
|
@ -698,19 +690,4 @@ int nghttp2_session_reprioritize_stream
|
|||
(nghttp2_session *session, nghttp2_stream *stream,
|
||||
const nghttp2_priority_spec *pri_spec);
|
||||
|
||||
/*
|
||||
* Creates new priority group using given values.
|
||||
*
|
||||
* This function returns created priority group if it succeeds, or
|
||||
* NULL.
|
||||
*/
|
||||
nghttp2_stream_group* nghttp2_session_open_stream_group
|
||||
(nghttp2_session *session, int32_t pri_group_id, int32_t weight);
|
||||
|
||||
/*
|
||||
* Closes priority group if it does not include any streams.
|
||||
*/
|
||||
void nghttp2_session_close_stream_group_if_empty
|
||||
(nghttp2_session *session, nghttp2_stream_group *stream_group);
|
||||
|
||||
#endif /* NGHTTP2_SESSION_H */
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
|
||||
uint8_t flags,
|
||||
nghttp2_stream_state initial_state,
|
||||
int32_t weight,
|
||||
nghttp2_stream_roots *roots,
|
||||
int32_t remote_initial_window_size,
|
||||
int32_t local_initial_window_size,
|
||||
void *stream_user_data)
|
||||
|
@ -55,10 +57,16 @@ void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
|
|||
|
||||
stream->closed_next = NULL;
|
||||
|
||||
stream->stream_group = NULL;
|
||||
stream->dpri = NGHTTP2_STREAM_DPRI_NO_DATA;
|
||||
stream->num_substreams = 1;
|
||||
stream->num_subtop = 0;
|
||||
stream->weight = weight;
|
||||
stream->effective_weight = stream->weight;
|
||||
stream->sum_dep_weight = 0;
|
||||
stream->sum_norest_weight = 0;
|
||||
|
||||
stream->roots = roots;
|
||||
stream->root_prev = NULL;
|
||||
stream->root_next = NULL;
|
||||
}
|
||||
|
||||
void nghttp2_stream_free(nghttp2_stream *stream)
|
||||
|
@ -79,15 +87,12 @@ void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag)
|
|||
static int stream_push_data(nghttp2_stream *stream, nghttp2_pq *pq)
|
||||
{
|
||||
int rv;
|
||||
ssize_t weight;
|
||||
|
||||
assert(stream->data_item);
|
||||
assert(stream->data_item->queued == 0);
|
||||
|
||||
weight = nghttp2_stream_group_shared_wait(stream->stream_group);
|
||||
|
||||
if(stream->data_item->weight > weight) {
|
||||
stream->data_item->weight = weight;
|
||||
if(stream->data_item->weight > stream->effective_weight) {
|
||||
stream->data_item->weight = stream->effective_weight;
|
||||
}
|
||||
|
||||
rv = nghttp2_pq_push(pq, stream->data_item);
|
||||
|
@ -129,39 +134,49 @@ static nghttp2_stream* stream_update_dep_length(nghttp2_stream *stream,
|
|||
return stream;
|
||||
}
|
||||
|
||||
static nghttp2_stream* stream_update_dep_both_length(nghttp2_stream *stream,
|
||||
ssize_t delta_stream,
|
||||
ssize_t delta_top)
|
||||
int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream,
|
||||
int32_t weight)
|
||||
{
|
||||
stream->num_substreams += delta_stream;
|
||||
stream->num_subtop += delta_top;
|
||||
weight = stream->weight * weight / stream->sum_dep_weight;
|
||||
|
||||
stream = stream_first_sib(stream);
|
||||
|
||||
if(stream->dep_prev) {
|
||||
return stream_update_dep_both_length(stream->dep_prev, delta_stream,
|
||||
delta_top);
|
||||
}
|
||||
|
||||
return stream;
|
||||
return nghttp2_max(1, weight);
|
||||
}
|
||||
|
||||
static void stream_update_dep_set_rest_stream_group
|
||||
(nghttp2_stream *stream, nghttp2_stream_group *stream_group)
|
||||
int32_t nghttp2_stream_dep_distributed_effective_weight
|
||||
(nghttp2_stream *stream, int32_t weight)
|
||||
{
|
||||
if(stream == NULL) {
|
||||
weight = stream->effective_weight * weight / stream->sum_norest_weight;
|
||||
|
||||
return nghttp2_max(1, weight);
|
||||
}
|
||||
|
||||
/* Updates effective_weight of descendant streams in subtree of
|
||||
|stream|. We assume that stream->effective_weight is already set
|
||||
right. */
|
||||
static void stream_update_dep_effective_weight(nghttp2_stream *stream)
|
||||
{
|
||||
nghttp2_stream *si;
|
||||
|
||||
DEBUGF(fprintf(stderr, "stream: update_dep_effective_weight "
|
||||
"stream(%p)=%d, weight=%d, sum_norest_weight=%d\n",
|
||||
stream, stream->stream_id, stream->weight,
|
||||
stream->sum_norest_weight));
|
||||
|
||||
/* stream->sum_norest_weight == 0 means there is no
|
||||
NGHTTP2_STREAM_DPRI_TOP under stream */
|
||||
if(stream->dpri != NGHTTP2_STREAM_DPRI_NO_DATA ||
|
||||
stream->sum_norest_weight == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
nghttp2_stream_group_remove_stream(stream->stream_group, stream);
|
||||
nghttp2_stream_group_add_stream(stream_group, stream);
|
||||
for(si = stream->dep_next; si; si = si->sib_next) {
|
||||
if(si->dpri != NGHTTP2_STREAM_DPRI_REST) {
|
||||
si->effective_weight = nghttp2_stream_dep_distributed_effective_weight
|
||||
(stream, si->weight);
|
||||
}
|
||||
|
||||
if(stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
|
||||
stream->dpri = NGHTTP2_STREAM_DPRI_REST;
|
||||
stream_update_dep_effective_weight(si);
|
||||
}
|
||||
|
||||
stream_update_dep_set_rest_stream_group(stream->sib_next, stream_group);
|
||||
stream_update_dep_set_rest_stream_group(stream->dep_next, stream_group);
|
||||
}
|
||||
|
||||
static void stream_update_dep_set_rest(nghttp2_stream *stream)
|
||||
|
@ -174,8 +189,6 @@ static void stream_update_dep_set_rest(nghttp2_stream *stream)
|
|||
return;
|
||||
}
|
||||
|
||||
stream->num_subtop = 0;
|
||||
|
||||
if(stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
|
||||
stream->dpri = NGHTTP2_STREAM_DPRI_REST;
|
||||
|
||||
|
@ -192,37 +205,22 @@ static void stream_update_dep_set_rest(nghttp2_stream *stream)
|
|||
* Performs dfs starting |stream|, search stream which can become
|
||||
* NGHTTP2_STREAM_DPRI_TOP and queues its data_item.
|
||||
*
|
||||
* This function returns the number of stream marked as
|
||||
* NGHTTP2_STREAM_DPRI_TOP (including already marked as such) if it
|
||||
* succeeds, or one of the following negative error codes:
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
static ssize_t stream_update_dep_set_top(nghttp2_stream *stream,
|
||||
nghttp2_pq *pq)
|
||||
static int stream_update_dep_set_top(nghttp2_stream *stream, nghttp2_pq *pq)
|
||||
{
|
||||
ssize_t rv;
|
||||
ssize_t num_top;
|
||||
int rv;
|
||||
nghttp2_stream *si;
|
||||
|
||||
if(stream == NULL) {
|
||||
if(stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
|
||||
rv = stream_update_dep_set_top(stream->sib_next, pq);
|
||||
|
||||
if(rv < 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
stream->num_subtop = 1;
|
||||
|
||||
return stream->num_subtop + rv;
|
||||
}
|
||||
|
||||
if(stream->dpri == NGHTTP2_STREAM_DPRI_REST) {
|
||||
|
||||
DEBUGF(fprintf(stderr, "stream: stream=%d data is top\n",
|
||||
stream->stream_id));
|
||||
|
||||
|
@ -236,44 +234,63 @@ static ssize_t stream_update_dep_set_top(nghttp2_stream *stream,
|
|||
|
||||
stream->dpri = NGHTTP2_STREAM_DPRI_TOP;
|
||||
|
||||
rv = stream_update_dep_set_top(stream->sib_next, pq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(rv < 0) {
|
||||
for(si = stream->dep_next; si; si = si->sib_next) {
|
||||
rv = stream_update_dep_set_top(si, pq);
|
||||
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
stream->num_subtop = 1;
|
||||
|
||||
return stream->num_subtop + rv;
|
||||
}
|
||||
|
||||
assert(stream->dpri == NGHTTP2_STREAM_DPRI_NO_DATA);
|
||||
|
||||
rv = stream_update_dep_set_top(stream->sib_next, pq);
|
||||
|
||||
if(rv < 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
num_top = rv;
|
||||
|
||||
rv = stream_update_dep_set_top(stream->dep_next, pq);
|
||||
|
||||
if(rv < 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
stream->num_subtop = rv;
|
||||
|
||||
return stream->num_subtop + num_top;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t stream_update_dep_on_attach_data(nghttp2_stream *stream,
|
||||
nghttp2_pq *pq)
|
||||
/*
|
||||
* Updates stream->sum_norest_weight recursively. We have to gather
|
||||
* effective sum of weight of descendants. If stream->dpri ==
|
||||
* NGHTTP2_STREAM_DPRI_NO_DATA, we have to go deeper and check that
|
||||
* any of its descendants has dpri value of NGHTTP2_STREAM_DPRI_TOP.
|
||||
* If so, we have to add weight of its direct descendants to
|
||||
* stream->sum_norest_weight. To make this work, this function
|
||||
* returns 1 if any of its descendants has dpri value of
|
||||
* NGHTTP2_STREAM_DPRI_TOP, otherwise 0.
|
||||
*/
|
||||
static int stream_update_dep_sum_norest_weight(nghttp2_stream *stream)
|
||||
{
|
||||
ssize_t rv;
|
||||
nghttp2_stream *si;
|
||||
int rv;
|
||||
|
||||
stream->sum_norest_weight = 0;
|
||||
|
||||
if(stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(stream->dpri == NGHTTP2_STREAM_DPRI_REST) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rv = 0;
|
||||
|
||||
for(si = stream->dep_next; si; si = si->sib_next) {
|
||||
|
||||
if(stream_update_dep_sum_norest_weight(si)) {
|
||||
rv = 1;
|
||||
stream->sum_norest_weight += si->weight;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int stream_update_dep_on_attach_data(nghttp2_stream *stream,
|
||||
nghttp2_pq *pq)
|
||||
{
|
||||
int rv;
|
||||
nghttp2_stream *root_stream;
|
||||
ssize_t old_num_subtop;
|
||||
|
||||
stream->dpri = NGHTTP2_STREAM_DPRI_REST;
|
||||
|
||||
|
@ -283,16 +300,14 @@ static ssize_t stream_update_dep_on_attach_data(nghttp2_stream *stream,
|
|||
|
||||
DEBUGF(fprintf(stderr, "root=%p, stream=%p\n", root_stream, stream));
|
||||
|
||||
old_num_subtop = root_stream->num_subtop;
|
||||
|
||||
rv = stream_update_dep_set_top(root_stream, pq);
|
||||
|
||||
if(rv < 0) {
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nghttp2_stream_group_update_num_top
|
||||
(root_stream->stream_group, root_stream->num_subtop - old_num_subtop);
|
||||
stream_update_dep_sum_norest_weight(root_stream);
|
||||
stream_update_dep_effective_weight(root_stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -300,30 +315,21 @@ static ssize_t stream_update_dep_on_attach_data(nghttp2_stream *stream,
|
|||
static int stream_update_dep_on_detach_data(nghttp2_stream *stream,
|
||||
nghttp2_pq *pq)
|
||||
{
|
||||
ssize_t rv;
|
||||
int rv;
|
||||
nghttp2_stream *root_stream;
|
||||
ssize_t old_num_subtop;
|
||||
|
||||
if(stream->dpri != NGHTTP2_STREAM_DPRI_TOP) {
|
||||
stream->dpri = NGHTTP2_STREAM_DPRI_NO_DATA;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
stream->dpri = NGHTTP2_STREAM_DPRI_NO_DATA;
|
||||
|
||||
root_stream = nghttp2_stream_get_dep_root(stream);
|
||||
|
||||
old_num_subtop = root_stream->num_subtop;
|
||||
|
||||
rv = stream_update_dep_set_top(root_stream, pq);
|
||||
|
||||
if(rv < 0) {
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nghttp2_stream_group_update_num_top
|
||||
(root_stream->stream_group, root_stream->num_subtop - old_num_subtop);
|
||||
stream_update_dep_sum_norest_weight(root_stream);
|
||||
stream_update_dep_effective_weight(root_stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -475,6 +481,7 @@ void nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
|
|||
nghttp2_stream *stream)
|
||||
{
|
||||
nghttp2_stream *si;
|
||||
nghttp2_stream *root_stream;
|
||||
|
||||
assert(stream->data_item == NULL);
|
||||
|
||||
|
@ -483,6 +490,9 @@ void nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
|
|||
dep_stream, dep_stream->stream_id,
|
||||
stream, stream->stream_id));
|
||||
|
||||
stream->sum_dep_weight = dep_stream->sum_dep_weight;
|
||||
dep_stream->sum_dep_weight = stream->weight;
|
||||
|
||||
if(dep_stream->dep_next) {
|
||||
for(si = dep_stream->dep_next; si; si = si->sib_next) {
|
||||
stream->num_substreams += si->num_substreams;
|
||||
|
@ -495,13 +505,19 @@ void nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
|
|||
dep_stream->dep_next = stream;
|
||||
stream->dep_prev = dep_stream;
|
||||
|
||||
stream_update_dep_length(dep_stream, 1);
|
||||
root_stream = stream_update_dep_length(dep_stream, 1);
|
||||
|
||||
stream_update_dep_sum_norest_weight(root_stream);
|
||||
stream_update_dep_effective_weight(root_stream);
|
||||
|
||||
++stream->roots->num_streams;
|
||||
}
|
||||
|
||||
void nghttp2_stream_dep_add(nghttp2_stream *dep_stream,
|
||||
nghttp2_stream *stream)
|
||||
{
|
||||
nghttp2_stream *last_sib;
|
||||
nghttp2_stream *root_stream;
|
||||
|
||||
assert(stream->data_item == NULL);
|
||||
|
||||
|
@ -510,31 +526,52 @@ void nghttp2_stream_dep_add(nghttp2_stream *dep_stream,
|
|||
dep_stream, dep_stream->stream_id,
|
||||
stream, stream->stream_id));
|
||||
|
||||
stream_update_dep_length(dep_stream, 1);
|
||||
root_stream = stream_update_dep_length(dep_stream, 1);
|
||||
|
||||
dep_stream->sum_dep_weight += stream->weight;
|
||||
|
||||
if(dep_stream->dep_next == NULL) {
|
||||
dep_stream->dep_next = stream;
|
||||
stream->dep_prev = dep_stream;
|
||||
|
||||
return;
|
||||
} else {
|
||||
last_sib = stream_last_sib(dep_stream->dep_next);
|
||||
last_sib->sib_next = stream;
|
||||
stream->sib_prev = last_sib;
|
||||
}
|
||||
|
||||
last_sib = stream_last_sib(dep_stream->dep_next);
|
||||
last_sib->sib_next = stream;
|
||||
stream->sib_prev = last_sib;
|
||||
stream_update_dep_sum_norest_weight(root_stream);
|
||||
stream_update_dep_effective_weight(root_stream);
|
||||
|
||||
++stream->roots->num_streams;
|
||||
}
|
||||
|
||||
void nghttp2_stream_dep_remove(nghttp2_stream *stream)
|
||||
{
|
||||
nghttp2_stream *prev, *next, *dep_next;
|
||||
nghttp2_stream *prev, *next, *dep_next, *dep_prev, *si, *root_stream;
|
||||
int32_t sum_dep_weight_delta;
|
||||
|
||||
root_stream = NULL;
|
||||
|
||||
DEBUGF(fprintf(stderr, "stream: dep_remove stream(%p)=%d\n",
|
||||
stream, stream->stream_id));
|
||||
|
||||
/* Distribute weight of |stream| to direct descendants */
|
||||
sum_dep_weight_delta = -stream->weight;
|
||||
|
||||
for(si = stream->dep_next; si; si = si->sib_next) {
|
||||
si->weight = nghttp2_stream_dep_distributed_weight(stream, si->weight);
|
||||
|
||||
sum_dep_weight_delta += si->weight;
|
||||
}
|
||||
|
||||
prev = stream_first_sib(stream);
|
||||
|
||||
if(prev->dep_prev) {
|
||||
stream_update_dep_length(prev->dep_prev, -1);
|
||||
dep_prev = prev->dep_prev;
|
||||
|
||||
if(dep_prev) {
|
||||
root_stream = stream_update_dep_length(dep_prev, -1);
|
||||
|
||||
dep_prev->sum_dep_weight += sum_dep_weight_delta;
|
||||
}
|
||||
|
||||
if(stream->sib_prev) {
|
||||
|
@ -574,7 +611,7 @@ void nghttp2_stream_dep_remove(nghttp2_stream *stream)
|
|||
dep_next = NULL;
|
||||
}
|
||||
} else {
|
||||
nghttp2_stream *si;
|
||||
nghttp2_stream_roots_remove(stream->roots, stream);
|
||||
|
||||
dep_next = NULL;
|
||||
|
||||
|
@ -588,6 +625,11 @@ void nghttp2_stream_dep_remove(nghttp2_stream *stream)
|
|||
si->sib_prev = NULL;
|
||||
si->sib_next = NULL;
|
||||
|
||||
/* We already distributed weight of |stream| to this. */
|
||||
si->effective_weight = si->weight;
|
||||
|
||||
nghttp2_stream_roots_add(si->roots, si);
|
||||
|
||||
si = next;
|
||||
}
|
||||
}
|
||||
|
@ -600,11 +642,20 @@ void nghttp2_stream_dep_remove(nghttp2_stream *stream)
|
|||
next->sib_prev = prev;
|
||||
}
|
||||
|
||||
if(root_stream) {
|
||||
stream_update_dep_sum_norest_weight(root_stream);
|
||||
stream_update_dep_effective_weight(root_stream);
|
||||
}
|
||||
|
||||
stream->num_substreams = 1;
|
||||
stream->sum_dep_weight = 0;
|
||||
|
||||
stream->dep_prev = NULL;
|
||||
stream->dep_next = NULL;
|
||||
stream->sib_prev = NULL;
|
||||
stream->sib_next = NULL;
|
||||
|
||||
--stream->roots->num_streams;
|
||||
}
|
||||
|
||||
int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
|
||||
|
@ -614,10 +665,8 @@ int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
|
|||
nghttp2_stream *last_sib;
|
||||
nghttp2_stream *dep_next;
|
||||
nghttp2_stream *root_stream;
|
||||
nghttp2_stream *si;
|
||||
size_t delta_substreams;
|
||||
ssize_t old_num_subtop;
|
||||
ssize_t rv;
|
||||
int rv;
|
||||
|
||||
DEBUGF(fprintf(stderr, "stream: dep_insert_subtree dep_stream(%p)=%d "
|
||||
"stream(%p)=%d\n",
|
||||
|
@ -626,17 +675,16 @@ int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
|
|||
|
||||
delta_substreams = stream->num_substreams;
|
||||
|
||||
nghttp2_stream_group_update_num_top
|
||||
(stream->stream_group, -stream->num_subtop);
|
||||
|
||||
stream_update_dep_set_rest_stream_group(stream, dep_stream->stream_group);
|
||||
stream_update_dep_set_rest(stream);
|
||||
|
||||
if(dep_stream->dep_next) {
|
||||
dep_next = dep_stream->dep_next;
|
||||
/* dep_stream->num_substreams includes dep_stream itself */
|
||||
stream->num_substreams += dep_stream->num_substreams - 1;
|
||||
|
||||
for(si = dep_stream->dep_next; si; si = si->sib_next) {
|
||||
stream->num_substreams += si->num_substreams;
|
||||
}
|
||||
stream->sum_dep_weight += dep_stream->sum_dep_weight;
|
||||
dep_stream->sum_dep_weight = stream->weight;
|
||||
|
||||
dep_next = dep_stream->dep_next;
|
||||
|
||||
stream_update_dep_set_rest(dep_next);
|
||||
|
||||
|
@ -657,20 +705,21 @@ int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
|
|||
} else {
|
||||
dep_stream->dep_next = stream;
|
||||
stream->dep_prev = dep_stream;
|
||||
|
||||
assert(dep_stream->sum_dep_weight == 0);
|
||||
dep_stream->sum_dep_weight = stream->weight;
|
||||
}
|
||||
|
||||
root_stream = stream_update_dep_length(dep_stream, delta_substreams);
|
||||
|
||||
old_num_subtop = root_stream->num_subtop;
|
||||
|
||||
rv = stream_update_dep_set_top(root_stream, pq);
|
||||
|
||||
if(rv < 0) {
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nghttp2_stream_group_update_num_top
|
||||
(root_stream->stream_group, root_stream->num_subtop - old_num_subtop);
|
||||
stream_update_dep_sum_norest_weight(root_stream);
|
||||
stream_update_dep_effective_weight(root_stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -681,20 +730,18 @@ int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
|
|||
{
|
||||
nghttp2_stream *last_sib;
|
||||
nghttp2_stream *root_stream;
|
||||
ssize_t old_num_subtop;
|
||||
ssize_t rv;
|
||||
int rv;
|
||||
|
||||
DEBUGF(fprintf(stderr, "stream: dep_add_subtree dep_stream(%p)=%d "
|
||||
"stream(%p)=%d\n",
|
||||
dep_stream, dep_stream->stream_id,
|
||||
stream, stream->stream_id));
|
||||
|
||||
nghttp2_stream_group_update_num_top
|
||||
(stream->stream_group, -stream->num_subtop);
|
||||
|
||||
stream_update_dep_set_rest_stream_group(stream, dep_stream->stream_group);
|
||||
stream_update_dep_set_rest(stream);
|
||||
|
||||
if(dep_stream->dep_next) {
|
||||
dep_stream->sum_dep_weight += stream->weight;
|
||||
|
||||
last_sib = stream_last_sib(dep_stream->dep_next);
|
||||
|
||||
last_sib->sib_next = stream;
|
||||
|
@ -702,33 +749,32 @@ int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
|
|||
} else {
|
||||
dep_stream->dep_next = stream;
|
||||
stream->dep_prev = dep_stream;
|
||||
|
||||
assert(dep_stream->sum_dep_weight == 0);
|
||||
dep_stream->sum_dep_weight = stream->weight;
|
||||
}
|
||||
|
||||
root_stream = stream_update_dep_length(dep_stream, stream->num_substreams);
|
||||
|
||||
old_num_subtop = root_stream->num_subtop;
|
||||
|
||||
rv = stream_update_dep_set_top(root_stream, pq);
|
||||
|
||||
if(rv < 0) {
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nghttp2_stream_group_update_num_top
|
||||
(root_stream->stream_group, root_stream->num_subtop - old_num_subtop);
|
||||
stream_update_dep_sum_norest_weight(root_stream);
|
||||
stream_update_dep_effective_weight(root_stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream)
|
||||
{
|
||||
nghttp2_stream *prev, *next;
|
||||
nghttp2_stream *prev, *next, *dep_prev, *root_stream;
|
||||
|
||||
DEBUGF(fprintf(stderr, "stream: dep_remove_subtree stream(%p)=%d\n",
|
||||
stream, stream->stream_id));
|
||||
|
||||
/* Removing subtree does not change stream_group->num_top */
|
||||
|
||||
if(stream->sib_prev) {
|
||||
prev = stream->sib_prev;
|
||||
|
||||
|
@ -738,24 +784,34 @@ void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream)
|
|||
}
|
||||
|
||||
prev = stream_first_sib(prev);
|
||||
if(prev->dep_prev) {
|
||||
stream_update_dep_both_length(prev->dep_prev, -stream->num_substreams,
|
||||
-stream->num_subtop);
|
||||
}
|
||||
|
||||
dep_prev = prev->dep_prev;
|
||||
|
||||
} else if(stream->dep_prev) {
|
||||
prev = stream->dep_prev;
|
||||
dep_prev = stream->dep_prev;
|
||||
next = stream->sib_next;
|
||||
|
||||
prev->dep_next = next;
|
||||
dep_prev->dep_next = next;
|
||||
|
||||
if(next) {
|
||||
next->dep_prev = prev;
|
||||
next->dep_prev = dep_prev;
|
||||
|
||||
next->sib_prev = NULL;
|
||||
}
|
||||
|
||||
stream_update_dep_both_length(prev, -stream->num_substreams,
|
||||
-stream->num_subtop);
|
||||
} else {
|
||||
nghttp2_stream_roots_remove(stream->roots, stream);
|
||||
|
||||
dep_prev = NULL;
|
||||
}
|
||||
|
||||
if(dep_prev) {
|
||||
dep_prev->sum_dep_weight -= stream->weight;
|
||||
|
||||
root_stream = stream_update_dep_length(dep_prev, -stream->num_substreams);
|
||||
|
||||
stream_update_dep_sum_norest_weight(root_stream);
|
||||
stream_update_dep_effective_weight(root_stream);
|
||||
}
|
||||
|
||||
stream->sib_prev = NULL;
|
||||
|
@ -763,94 +819,165 @@ void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream)
|
|||
stream->dep_prev = NULL;
|
||||
}
|
||||
|
||||
int nghttp2_stream_dep_make_root(nghttp2_stream_group *stream_group,
|
||||
nghttp2_stream *stream,
|
||||
nghttp2_pq *pq)
|
||||
int nghttp2_stream_dep_make_root(nghttp2_stream *stream, nghttp2_pq *pq)
|
||||
{
|
||||
ssize_t rv;
|
||||
int rv;
|
||||
|
||||
DEBUGF(fprintf(stderr, "stream: dep_make_root new_stream_group(%p)=%d, "
|
||||
"old_stream_group(%p)=%d, stream(%p)=%d\n",
|
||||
stream_group, stream_group->pri_group_id,
|
||||
stream->stream_group, stream->stream_group->pri_group_id,
|
||||
DEBUGF(fprintf(stderr, "stream: dep_make_root stream(%p)=%d\n",
|
||||
stream, stream->stream_id));
|
||||
|
||||
/* First update num_top of old stream_group */
|
||||
nghttp2_stream_group_update_num_top
|
||||
(stream->stream_group, -stream->num_subtop);
|
||||
nghttp2_stream_roots_add(stream->roots, stream);
|
||||
|
||||
stream_update_dep_set_rest_stream_group(stream, stream_group);
|
||||
stream_update_dep_set_rest(stream);
|
||||
|
||||
stream->effective_weight = stream->weight;
|
||||
|
||||
rv = stream_update_dep_set_top(stream, pq);
|
||||
|
||||
if(rv < 0) {
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nghttp2_stream_group_update_num_top(stream_group, stream->num_subtop);
|
||||
stream_update_dep_sum_norest_weight(stream);
|
||||
stream_update_dep_effective_weight(stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_stream_group_init(nghttp2_stream_group *stream_group,
|
||||
int32_t pri_group_id,
|
||||
int32_t weight)
|
||||
int nghttp2_stream_dep_all_your_stream_are_belong_to_us
|
||||
(nghttp2_stream *stream, nghttp2_pq *pq)
|
||||
{
|
||||
nghttp2_map_entry_init(&stream_group->map_entry, pri_group_id);
|
||||
nghttp2_stream *first, *si;
|
||||
|
||||
stream_group->num_streams = 0;
|
||||
stream_group->num_top = 0;
|
||||
stream_group->pri_group_id = pri_group_id;
|
||||
stream_group->weight = weight;
|
||||
}
|
||||
|
||||
void nghttp2_stream_group_free(nghttp2_stream_group *stream_group)
|
||||
{}
|
||||
|
||||
void nghttp2_stream_group_add_stream(nghttp2_stream_group *stream_group,
|
||||
nghttp2_stream *stream)
|
||||
{
|
||||
DEBUGF(fprintf(stderr, "stream_group: stream_group(%p)=%d "
|
||||
"add stream(%p)=%d\n",
|
||||
stream_group, stream_group->pri_group_id,
|
||||
DEBUGF(fprintf(stderr, "stream: ALL YOUR STREAM ARE BELONG TO US "
|
||||
"stream(%p)=%d\n",
|
||||
stream, stream->stream_id));
|
||||
|
||||
stream->stream_group = stream_group;
|
||||
first = stream->roots->head;
|
||||
|
||||
++stream_group->num_streams;
|
||||
}
|
||||
/* stream must not be include in stream->roots->head list */
|
||||
assert(first != stream);
|
||||
|
||||
void nghttp2_stream_group_remove_stream(nghttp2_stream_group *stream_group,
|
||||
nghttp2_stream *stream)
|
||||
{
|
||||
DEBUGF(fprintf(stderr, "stream_group: stream_group(%p)=%d "
|
||||
"remove stream(%p)=%d\n",
|
||||
stream_group, stream_group->pri_group_id,
|
||||
stream, stream->stream_id));
|
||||
if(first) {
|
||||
nghttp2_stream *prev;
|
||||
|
||||
stream->stream_group = NULL;
|
||||
prev = first;
|
||||
|
||||
--stream_group->num_streams;
|
||||
}
|
||||
DEBUGF(fprintf(stderr, "stream: root stream(%p)=%d\n",
|
||||
first, first->stream_id));
|
||||
|
||||
void nghttp2_stream_group_update_num_top(nghttp2_stream_group *stream_group,
|
||||
ssize_t delta)
|
||||
{
|
||||
DEBUGF(fprintf(stderr, "stream_group: stream_group(%p)=%d "
|
||||
"update num_top current=%zd, delta=%zd, after=%zd\n",
|
||||
stream_group, stream_group->pri_group_id,
|
||||
stream_group->num_top, delta, stream_group->num_top + delta));
|
||||
stream->sum_dep_weight += first->weight;
|
||||
stream->num_substreams += first->num_substreams;
|
||||
|
||||
stream_group->num_top += delta;
|
||||
for(si = first->root_next; si; si = si->root_next) {
|
||||
|
||||
assert(stream_group->num_top >= 0);
|
||||
}
|
||||
assert(si != stream);
|
||||
|
||||
size_t nghttp2_stream_group_shared_wait(nghttp2_stream_group *stream_group)
|
||||
{
|
||||
if(stream_group->num_top == 0) {
|
||||
return 1;
|
||||
DEBUGF(fprintf(stderr, "stream: root stream(%p)=%d\n",
|
||||
si, si->stream_id));
|
||||
|
||||
fprintf(stderr, "w=%d, sum=%d\n",
|
||||
si->weight, stream->sum_dep_weight);
|
||||
stream->sum_dep_weight += si->weight;
|
||||
stream->num_substreams += si->num_substreams;
|
||||
|
||||
si->sib_prev = prev;
|
||||
prev->sib_next = si;
|
||||
|
||||
prev = si;
|
||||
}
|
||||
|
||||
if(stream->dep_next) {
|
||||
nghttp2_stream *last_sib;
|
||||
|
||||
last_sib = stream_last_sib(stream->dep_next);
|
||||
|
||||
last_sib->sib_next = first;
|
||||
first->sib_prev = last_sib;
|
||||
} else {
|
||||
stream->dep_next = first;
|
||||
first->dep_prev = stream;
|
||||
}
|
||||
}
|
||||
|
||||
return nghttp2_max(1, stream_group->weight / stream_group->num_top);
|
||||
nghttp2_stream_roots_remove_all(stream->roots);
|
||||
|
||||
return nghttp2_stream_dep_make_root(stream, pq);
|
||||
}
|
||||
|
||||
int nghttp2_stream_in_dep_tree(nghttp2_stream *stream)
|
||||
{
|
||||
return stream->dep_prev || stream->dep_next ||
|
||||
stream->sib_prev || stream->sib_next ||
|
||||
stream->root_next || stream->root_prev ||
|
||||
stream->roots->head == stream;
|
||||
}
|
||||
|
||||
void nghttp2_stream_roots_init(nghttp2_stream_roots *roots)
|
||||
{
|
||||
roots->head = NULL;
|
||||
roots->num_streams = 0;
|
||||
}
|
||||
|
||||
void nghttp2_stream_roots_free(nghttp2_stream_roots *roots)
|
||||
{}
|
||||
|
||||
void nghttp2_stream_roots_add(nghttp2_stream_roots *roots,
|
||||
nghttp2_stream *stream)
|
||||
{
|
||||
if(roots->head) {
|
||||
nghttp2_stream *si;
|
||||
for(si = roots->head; si; si = si->root_next) {
|
||||
if(si == stream) {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
stream->root_next = roots->head;
|
||||
roots->head->root_prev = stream;
|
||||
}
|
||||
|
||||
roots->head = stream;
|
||||
}
|
||||
|
||||
void nghttp2_stream_roots_remove(nghttp2_stream_roots *roots,
|
||||
nghttp2_stream *stream)
|
||||
{
|
||||
nghttp2_stream *root_prev, *root_next;
|
||||
|
||||
root_prev = stream->root_prev;
|
||||
root_next = stream->root_next;
|
||||
|
||||
if(root_prev) {
|
||||
root_prev->root_next = root_next;
|
||||
|
||||
if(root_next) {
|
||||
root_next->root_prev = root_prev;
|
||||
}
|
||||
} else {
|
||||
if(root_next) {
|
||||
root_next->root_prev = NULL;
|
||||
}
|
||||
|
||||
roots->head = root_next;
|
||||
}
|
||||
|
||||
stream->root_prev = NULL;
|
||||
stream->root_next = NULL;
|
||||
}
|
||||
|
||||
void nghttp2_stream_roots_remove_all(nghttp2_stream_roots *roots)
|
||||
{
|
||||
nghttp2_stream *si, *next;
|
||||
|
||||
for(si = roots->head; si;) {
|
||||
next = si->root_next;
|
||||
|
||||
si->root_prev = NULL;
|
||||
si->root_next = NULL;
|
||||
|
||||
si = next;
|
||||
}
|
||||
|
||||
roots->head = NULL;
|
||||
}
|
||||
|
|
|
@ -102,9 +102,9 @@ typedef enum {
|
|||
NGHTTP2_STREAM_DPRI_REST = 0x04
|
||||
} nghttp2_stream_dpri;
|
||||
|
||||
struct nghttp2_stream_group;
|
||||
struct nghttp2_stream_roots;
|
||||
|
||||
typedef struct nghttp2_stream_group nghttp2_stream_group;
|
||||
typedef struct nghttp2_stream_roots nghttp2_stream_roots;
|
||||
|
||||
struct nghttp2_stream;
|
||||
|
||||
|
@ -122,27 +122,28 @@ struct nghttp2_stream {
|
|||
dep_prev and sib_prev are NULL. */
|
||||
nghttp2_stream *dep_prev, *dep_next;
|
||||
nghttp2_stream *sib_prev, *sib_next;
|
||||
/* pointers to track dependency tree root streams. This is
|
||||
doubly-linked list and first element is pointed by
|
||||
roots->head. */
|
||||
nghttp2_stream *root_prev, *root_next;
|
||||
/* When stream is kept after closure, it may be kept in single
|
||||
linked list pointed by nghttp2_session closed_stream_head.
|
||||
closed_next points to the next stream object if it is the element
|
||||
of the list. */
|
||||
nghttp2_stream *closed_next;
|
||||
/* pointer to roots, which tracks dependency tree roots */
|
||||
nghttp2_stream_roots *roots;
|
||||
/* The arbitrary data provided by user for this stream. */
|
||||
void *stream_user_data;
|
||||
/* DATA frame item */
|
||||
nghttp2_outbound_item *data_item;
|
||||
/* stream ID */
|
||||
int32_t stream_id;
|
||||
/* priority group this stream belongs to */
|
||||
nghttp2_stream_group *stream_group;
|
||||
/* categorized priority of this stream. Only stream bearing
|
||||
NGHTTP2_STREAM_DPRI_TOP can send DATA frame. */
|
||||
nghttp2_stream_dpri dpri;
|
||||
/* the number of streams in subtree */
|
||||
size_t num_substreams;
|
||||
/* the number of streams marked as NGHTTP2_STREAM_DPRI_TOP in
|
||||
subtree */
|
||||
ssize_t num_subtop;
|
||||
/* Current remote window size. This value is computed against the
|
||||
current initial window size of remote endpoint. */
|
||||
int32_t remote_window_size;
|
||||
|
@ -157,6 +158,16 @@ struct nghttp2_stream {
|
|||
NGHTTP2_INITIAL_WINDOW_SIZE and could be increased/decreased by
|
||||
submitting WINDOW_UPDATE. See nghttp2_submit_window_update(). */
|
||||
int32_t local_window_size;
|
||||
/* weight of this stream */
|
||||
int32_t weight;
|
||||
/* effective weight of this stream in belonging dependency tree */
|
||||
int32_t effective_weight;
|
||||
/* sum of weight (not effective_weight) of direct descendants */
|
||||
int32_t sum_dep_weight;
|
||||
/* sum of weight of direct descendants which have at least one
|
||||
descendant with dpri == NGHTTP2_STREAM_DPRI_TOP. We use this
|
||||
value to calculate effective weight. */
|
||||
int32_t sum_norest_weight;
|
||||
nghttp2_stream_state state;
|
||||
/* This is bitwise-OR of 0 or more of nghttp2_stream_flag. */
|
||||
uint8_t flags;
|
||||
|
@ -167,6 +178,8 @@ struct nghttp2_stream {
|
|||
void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
|
||||
uint8_t flags,
|
||||
nghttp2_stream_state initial_state,
|
||||
int32_t weight,
|
||||
nghttp2_stream_roots *roots,
|
||||
int32_t remote_initial_window_size,
|
||||
int32_t local_initial_window_size,
|
||||
void *stream_user_data);
|
||||
|
@ -259,12 +272,30 @@ nghttp2_stream* nghttp2_stream_get_dep_root(nghttp2_stream *stream);
|
|||
int nghttp2_stream_dep_subtree_find(nghttp2_stream *stream,
|
||||
nghttp2_stream *target);
|
||||
|
||||
/*
|
||||
* Computes distributed weight of a stream of the |weight| under the
|
||||
* |stream| if |stream| is removed from a dependency tree. The result
|
||||
* is computed using stream->weight rather than
|
||||
* stream->effective_weight.
|
||||
*/
|
||||
int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream,
|
||||
int32_t weight);
|
||||
|
||||
/*
|
||||
* Computes effective weight of a stream of the |weight| under the
|
||||
* |stream|. The result is computed using stream->effective_weight
|
||||
* rather than stream->weight. This function is used to determine
|
||||
* weight in dependency tree.
|
||||
*/
|
||||
int32_t nghttp2_stream_dep_distributed_effective_weight
|
||||
(nghttp2_stream *stream, int32_t weight);
|
||||
|
||||
/*
|
||||
* Makes the |stream| depend on the |dep_stream|. This dependency is
|
||||
* exclusive. All existing direct descendants of |dep_stream| become
|
||||
* the descendants of the |stream|. This function assumes
|
||||
* |stream->data| is NULL and no dpri members are changed in this
|
||||
* dependency tree. It also does not change stream->stream_group.
|
||||
* dependency tree.
|
||||
*/
|
||||
void nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
|
||||
nghttp2_stream *stream);
|
||||
|
@ -272,8 +303,7 @@ void nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
|
|||
/*
|
||||
* Makes the |stream| depend on the |dep_stream|. This dependency is
|
||||
* not exclusive. This function assumes |stream->data| is NULL and no
|
||||
* dpri members are changed in this dependency tree. It also does not
|
||||
* change stream->stream_group.
|
||||
* dpri members are changed in this dependency tree.
|
||||
*/
|
||||
void nghttp2_stream_dep_add(nghttp2_stream *dep_stream,
|
||||
nghttp2_stream *stream);
|
||||
|
@ -342,8 +372,8 @@ int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
|
|||
|
||||
/*
|
||||
* Removes subtree whose root stream is |stream|. Removing subtree
|
||||
* does not change dpri values and removed subtree is still in the
|
||||
* same stream_group.
|
||||
* does not change dpri values. The effective_weight of streams in
|
||||
* removed subtree is not updated.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
|
@ -354,8 +384,8 @@ int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
|
|||
void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Makes the |stream| as root for |stream_group|. Updates dpri
|
||||
* members in this dependency tree.
|
||||
* Makes the |stream| as root. Updates dpri members in this
|
||||
* dependency tree.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
|
@ -363,53 +393,42 @@ void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream);
|
|||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_stream_dep_make_root(nghttp2_stream_group *stream_group,
|
||||
nghttp2_stream *stream,
|
||||
nghttp2_pq *pq);
|
||||
int nghttp2_stream_dep_make_root(nghttp2_stream *stream, nghttp2_pq *pq);
|
||||
|
||||
/*
|
||||
* Priority group of streams.
|
||||
* Makes the |stream| as root and all existing root streams become
|
||||
* direct children of |stream|.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
struct nghttp2_stream_group {
|
||||
/* Intrusive Map */
|
||||
nghttp2_map_entry map_entry;
|
||||
/* The number of streams this priority group contains */
|
||||
size_t num_streams;
|
||||
/* The number of streams marked as NGHTTP2_STREAM_DPRI_TOP */
|
||||
ssize_t num_top;
|
||||
/* The priority group ID */
|
||||
int32_t pri_group_id;
|
||||
/* The weight of this group */
|
||||
int32_t weight;
|
||||
int nghttp2_stream_dep_all_your_stream_are_belong_to_us
|
||||
(nghttp2_stream *stream, nghttp2_pq *pq);
|
||||
|
||||
/*
|
||||
* Returns nonzero if |stream| is in any dependency tree.
|
||||
*/
|
||||
int nghttp2_stream_in_dep_tree(nghttp2_stream *stream);
|
||||
|
||||
struct nghttp2_stream_roots {
|
||||
nghttp2_stream *head;
|
||||
|
||||
int32_t num_streams;
|
||||
};
|
||||
|
||||
void nghttp2_stream_group_init(nghttp2_stream_group *stream_group,
|
||||
int32_t pri_group_id,
|
||||
int32_t weight);
|
||||
void nghttp2_stream_roots_init(nghttp2_stream_roots *roots);
|
||||
|
||||
void nghttp2_stream_group_free(nghttp2_stream_group *stream_group);
|
||||
void nghttp2_stream_roots_free(nghttp2_stream_roots *roots);
|
||||
|
||||
/*
|
||||
* Adds |stream| to |stream_group|.
|
||||
*/
|
||||
void nghttp2_stream_group_add_stream(nghttp2_stream_group *stream_group,
|
||||
nghttp2_stream *stream);
|
||||
void nghttp2_stream_roots_add(nghttp2_stream_roots *roots,
|
||||
nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Removes |stream| from |stream_group|.
|
||||
*/
|
||||
void nghttp2_stream_group_remove_stream(nghttp2_stream_group *stream_group,
|
||||
nghttp2_stream *stream);
|
||||
void nghttp2_stream_roots_remove(nghttp2_stream_roots *roots,
|
||||
nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Updates |stream_group->num_top| += |delta|
|
||||
*/
|
||||
void nghttp2_stream_group_update_num_top(nghttp2_stream_group *stream_group,
|
||||
ssize_t delta);
|
||||
|
||||
/*
|
||||
* Returns shared weight among the streams belongs to |stream_group|.
|
||||
*/
|
||||
size_t nghttp2_stream_group_shared_wait(nghttp2_stream_group *stream_group);
|
||||
void nghttp2_stream_roots_remove_all(nghttp2_stream_roots *roots);
|
||||
|
||||
#endif /* NGHTTP2_STREAM */
|
||||
|
|
|
@ -77,8 +77,7 @@ static int nghttp2_submit_headers_shared
|
|||
flags_copy =
|
||||
(flags & (NGHTTP2_FLAG_END_STREAM |
|
||||
NGHTTP2_FLAG_END_SEGMENT |
|
||||
NGHTTP2_FLAG_PRIORITY_GROUP |
|
||||
NGHTTP2_FLAG_PRIORITY_DEPENDENCY)) |
|
||||
NGHTTP2_FLAG_PRIORITY)) |
|
||||
NGHTTP2_FLAG_END_HEADERS;
|
||||
|
||||
nghttp2_frame_headers_init(&frame->headers, flags_copy, stream_id, pri_spec,
|
||||
|
@ -102,14 +101,12 @@ static int nghttp2_submit_headers_shared
|
|||
return rv;
|
||||
}
|
||||
|
||||
static void adjust_priority_spec_group_weight(nghttp2_priority_spec *pri_spec)
|
||||
static void adjust_priority_spec_weight(nghttp2_priority_spec *pri_spec)
|
||||
{
|
||||
assert(pri_spec->pri_type == NGHTTP2_PRIORITY_TYPE_GROUP);
|
||||
|
||||
if(pri_spec->spec.group.weight < NGHTTP2_MIN_WEIGHT) {
|
||||
pri_spec->spec.group.weight = NGHTTP2_MIN_WEIGHT;
|
||||
} else if(pri_spec->spec.group.weight > NGHTTP2_MAX_WEIGHT) {
|
||||
pri_spec->spec.group.weight = NGHTTP2_MAX_WEIGHT;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,25 +122,13 @@ static int nghttp2_submit_headers_shared_nva
|
|||
{
|
||||
ssize_t rv;
|
||||
nghttp2_nv *nva_copy;
|
||||
nghttp2_priority_spec copy_pri_spec = {
|
||||
NGHTTP2_PRIORITY_TYPE_NONE
|
||||
};
|
||||
nghttp2_priority_spec copy_pri_spec;
|
||||
|
||||
if(pri_spec) {
|
||||
switch(pri_spec->pri_type) {
|
||||
case NGHTTP2_PRIORITY_TYPE_NONE:
|
||||
case NGHTTP2_PRIORITY_TYPE_GROUP:
|
||||
case NGHTTP2_PRIORITY_TYPE_DEP:
|
||||
break;
|
||||
default:
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
copy_pri_spec = *pri_spec;
|
||||
|
||||
if(copy_pri_spec.pri_type == NGHTTP2_PRIORITY_TYPE_GROUP) {
|
||||
adjust_priority_spec_group_weight(©_pri_spec);
|
||||
}
|
||||
adjust_priority_spec_weight(©_pri_spec);
|
||||
} else {
|
||||
nghttp2_priority_spec_default_init(©_pri_spec);
|
||||
}
|
||||
|
||||
rv = nghttp2_nv_array_copy(&nva_copy, nva, nvlen);
|
||||
|
@ -164,20 +149,10 @@ int nghttp2_submit_headers(nghttp2_session *session, uint8_t flags,
|
|||
{
|
||||
flags &= NGHTTP2_FLAG_END_STREAM;
|
||||
|
||||
if(pri_spec) {
|
||||
switch(pri_spec->pri_type) {
|
||||
case NGHTTP2_PRIORITY_TYPE_GROUP:
|
||||
flags |= NGHTTP2_FLAG_PRIORITY_GROUP;
|
||||
break;
|
||||
case NGHTTP2_PRIORITY_TYPE_DEP:
|
||||
flags |= NGHTTP2_FLAG_PRIORITY_DEPENDENCY;
|
||||
break;
|
||||
default:
|
||||
/* Default weight */
|
||||
pri_spec = NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
if(pri_spec && !nghttp2_priority_spec_check_default(pri_spec)) {
|
||||
flags |= NGHTTP2_FLAG_PRIORITY;
|
||||
} else {
|
||||
pri_spec = NULL;
|
||||
}
|
||||
|
||||
return nghttp2_submit_headers_shared_nva(session, flags, stream_id, pri_spec,
|
||||
|
@ -203,23 +178,14 @@ int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags,
|
|||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
copy_pri_spec = *pri_spec;
|
||||
|
||||
switch(copy_pri_spec.pri_type) {
|
||||
case NGHTTP2_PRIORITY_TYPE_GROUP:
|
||||
adjust_priority_spec_group_weight(©_pri_spec);
|
||||
|
||||
break;
|
||||
case NGHTTP2_PRIORITY_TYPE_DEP:
|
||||
if(stream_id == copy_pri_spec.spec.dep.stream_id) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
if(stream_id == pri_spec->stream_id) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
copy_pri_spec = *pri_spec;
|
||||
|
||||
adjust_priority_spec_weight(©_pri_spec);
|
||||
|
||||
frame = malloc(sizeof(nghttp2_frame));
|
||||
|
||||
if(frame == NULL) {
|
||||
|
@ -433,17 +399,7 @@ static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec,
|
|||
}
|
||||
|
||||
if(pri_spec) {
|
||||
switch(pri_spec->pri_type) {
|
||||
case NGHTTP2_PRIORITY_TYPE_GROUP:
|
||||
flags |= NGHTTP2_FLAG_PRIORITY_GROUP;
|
||||
break;
|
||||
case NGHTTP2_PRIORITY_TYPE_DEP:
|
||||
flags |= NGHTTP2_FLAG_PRIORITY_DEPENDENCY;
|
||||
break;
|
||||
default:
|
||||
/* Default weight */
|
||||
break;
|
||||
}
|
||||
flags |= NGHTTP2_FLAG_PRIORITY;
|
||||
}
|
||||
|
||||
return flags;
|
||||
|
@ -457,6 +413,10 @@ int nghttp2_submit_request(nghttp2_session *session,
|
|||
{
|
||||
uint8_t flags;
|
||||
|
||||
if(pri_spec && nghttp2_priority_spec_check_default(pri_spec)) {
|
||||
pri_spec = NULL;
|
||||
}
|
||||
|
||||
flags = set_request_flags(pri_spec, data_prd);
|
||||
|
||||
return nghttp2_submit_headers_shared_nva(session, flags, -1, pri_spec,
|
||||
|
|
|
@ -261,27 +261,15 @@ void print_flags(const nghttp2_frame_hd& hd)
|
|||
}
|
||||
s += "PAD_HIGH";
|
||||
}
|
||||
if(hd.flags & NGHTTP2_FLAG_PRIORITY_GROUP) {
|
||||
if(hd.flags & NGHTTP2_FLAG_PRIORITY) {
|
||||
if(!s.empty()) {
|
||||
s += " | ";
|
||||
}
|
||||
s += "PRIORITY_GROUP";
|
||||
}
|
||||
if(hd.flags & NGHTTP2_FLAG_PRIORITY_DEPENDENCY) {
|
||||
if(!s.empty()) {
|
||||
s += " | ";
|
||||
}
|
||||
s += "PRIORITY_DEPENDENCY";
|
||||
s += "PRIORITY";
|
||||
}
|
||||
|
||||
break;
|
||||
case NGHTTP2_PRIORITY:
|
||||
if(hd.flags & NGHTTP2_FLAG_PRIORITY_GROUP) {
|
||||
s += "PRIORITY_GROUP";
|
||||
} else if(hd.flags & NGHTTP2_FLAG_PRIORITY_DEPENDENCY) {
|
||||
s += "PRIORITY_DEPENDENCY";
|
||||
}
|
||||
|
||||
break;
|
||||
case NGHTTP2_SETTINGS:
|
||||
if(hd.flags & NGHTTP2_FLAG_ACK) {
|
||||
|
@ -368,14 +356,11 @@ void print_frame(print_type ptype, const nghttp2_frame *frame)
|
|||
case NGHTTP2_HEADERS:
|
||||
print_frame_attr_indent();
|
||||
fprintf(outfile, "(padlen=%zu", frame->headers.padlen);
|
||||
if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY_GROUP) {
|
||||
fprintf(outfile, ", pri_group_id=%d, weight=%u",
|
||||
frame->headers.pri_spec.spec.group.pri_group_id,
|
||||
frame->headers.pri_spec.spec.group.weight);
|
||||
} else if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY_DEPENDENCY) {
|
||||
fprintf(outfile, ", stream_id=%d, exclusive=%d",
|
||||
frame->headers.pri_spec.spec.dep.stream_id,
|
||||
frame->headers.pri_spec.spec.dep.exclusive);
|
||||
if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
|
||||
fprintf(outfile, ", stream_id=%d, weight=%u, exclusive=%d",
|
||||
frame->headers.pri_spec.stream_id,
|
||||
frame->headers.pri_spec.weight,
|
||||
frame->headers.pri_spec.exclusive);
|
||||
}
|
||||
fprintf(outfile, ")\n");
|
||||
switch(frame->headers.cat) {
|
||||
|
@ -399,19 +384,10 @@ void print_frame(print_type ptype, const nghttp2_frame *frame)
|
|||
case NGHTTP2_PRIORITY:
|
||||
print_frame_attr_indent();
|
||||
|
||||
fprintf(outfile, "(");
|
||||
|
||||
if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY_GROUP) {
|
||||
fprintf(outfile, "pri_group_id=%d, weight=%u",
|
||||
frame->priority.pri_spec.spec.group.pri_group_id,
|
||||
frame->priority.pri_spec.spec.group.weight);
|
||||
} else if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY_DEPENDENCY) {
|
||||
fprintf(outfile, "stream_id=%d, exclusive=%d",
|
||||
frame->priority.pri_spec.spec.dep.stream_id,
|
||||
frame->priority.pri_spec.spec.dep.exclusive);
|
||||
}
|
||||
|
||||
fprintf(outfile, ")\n");
|
||||
fprintf(outfile, "(stream_id=%d, weight=%u, exclusive=%d)\n",
|
||||
frame->priority.pri_spec.stream_id,
|
||||
frame->priority.pri_spec.weight,
|
||||
frame->priority.pri_spec.exclusive);
|
||||
|
||||
break;
|
||||
case NGHTTP2_RST_STREAM:
|
||||
|
|
|
@ -263,7 +263,7 @@ struct Request {
|
|||
|
||||
nghttp2_priority_spec resolve_dep(int32_t pri)
|
||||
{
|
||||
nghttp2_priority_spec pri_spec = { NGHTTP2_PRIORITY_TYPE_NONE };
|
||||
nghttp2_priority_spec pri_spec;
|
||||
int exclusive = 0;
|
||||
int32_t stream_id = -1;
|
||||
|
||||
|
@ -271,6 +271,8 @@ struct Request {
|
|||
return pri_spec;
|
||||
}
|
||||
|
||||
nghttp2_priority_spec_default_init(&pri_spec);
|
||||
|
||||
auto start = std::min(pri, (int)dep->deps.size() - 1);
|
||||
|
||||
for(auto i = start; i >= 0; --i) {
|
||||
|
@ -293,7 +295,8 @@ struct Request {
|
|||
return pri_spec;
|
||||
}
|
||||
|
||||
nghttp2_priority_spec_dep_init(&pri_spec, stream_id, exclusive);
|
||||
nghttp2_priority_spec_init(&pri_spec, stream_id, NGHTTP2_DEFAULT_WEIGHT,
|
||||
exclusive);
|
||||
|
||||
return pri_spec;
|
||||
}
|
||||
|
@ -1014,12 +1017,9 @@ void update_html_parser(HttpClient *client, Request *req,
|
|||
|
||||
nghttp2_priority_spec pri_spec;
|
||||
|
||||
// We always specify priority group of parent stream, so that
|
||||
// even if the parent stream is closed, the dependent stream is
|
||||
// in the same priority group. We adjust the priority using
|
||||
// separate PRIORITY frame after stream ID becomes known.
|
||||
nghttp2_priority_spec_group_init(&pri_spec, req->stream_id,
|
||||
config.weight);
|
||||
// We adjust the priority using separate PRIORITY frame after
|
||||
// stream ID becomes known.
|
||||
nghttp2_priority_spec_default_init(&pri_spec);
|
||||
|
||||
if ( client->add_request(uri, nullptr, 0, pri_spec, req->dep,
|
||||
req->level+1) ) {
|
||||
|
@ -1108,9 +1108,8 @@ void check_stream_id(nghttp2_session *session, int32_t stream_id,
|
|||
|
||||
auto pri_spec = req->resolve_dep(req->pri);
|
||||
|
||||
if(pri_spec.pri_type == NGHTTP2_PRIORITY_TYPE_DEP) {
|
||||
nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, stream_id,
|
||||
&pri_spec);
|
||||
if(!nghttp2_priority_spec_check_default(&pri_spec)) {
|
||||
nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, stream_id, &pri_spec);
|
||||
}
|
||||
|
||||
auto itr = std::begin(req->dep->deps);
|
||||
|
@ -1208,7 +1207,9 @@ int on_begin_headers_callback(nghttp2_session *session,
|
|||
http_parser_url u;
|
||||
memset(&u, 0, sizeof(u));
|
||||
// TODO Set pri and level
|
||||
nghttp2_priority_spec pri_spec = { NGHTTP2_PRIORITY_TYPE_NONE };
|
||||
nghttp2_priority_spec pri_spec;
|
||||
|
||||
nghttp2_priority_spec_default_init(&pri_spec);
|
||||
|
||||
auto req = util::make_unique<Request>("", u, nullptr, 0, pri_spec,
|
||||
nullptr);
|
||||
|
@ -1624,10 +1625,12 @@ int communicate(const std::string& scheme, const std::string& host,
|
|||
{
|
||||
HttpClient client{callbacks, evbase, ssl_ctx};
|
||||
|
||||
nghttp2_priority_spec pri_spec = { NGHTTP2_PRIORITY_TYPE_NONE };
|
||||
nghttp2_priority_spec pri_spec;
|
||||
|
||||
if(config.weight != NGHTTP2_DEFAULT_WEIGHT) {
|
||||
nghttp2_priority_spec_group_init(&pri_spec, -1, config.weight);
|
||||
nghttp2_priority_spec_init(&pri_spec, 0, config.weight, 0);
|
||||
} else {
|
||||
nghttp2_priority_spec_default_init(&pri_spec);
|
||||
}
|
||||
|
||||
for(auto req : requests) {
|
||||
|
|
|
@ -222,6 +222,8 @@ int main(int argc, char* argv[])
|
|||
test_nghttp2_session_stream_dep_add_subtree) ||
|
||||
!CU_add_test(pSuite, "session_stream_dep_remove_subtree",
|
||||
test_nghttp2_session_stream_dep_remove_subtree) ||
|
||||
!CU_add_test(pSuite, "session_stream_dep_all_your_stream_are_belong_to_us",
|
||||
test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us) ||
|
||||
!CU_add_test(pSuite, "session_stream_attach_data",
|
||||
test_nghttp2_session_stream_attach_data) ||
|
||||
!CU_add_test(pSuite, "session_stream_attach_data_subtree",
|
||||
|
|
|
@ -92,7 +92,7 @@ void test_nghttp2_frame_pack_headers()
|
|||
nva = headers();
|
||||
nvlen = HEADERS_LENGTH;
|
||||
|
||||
pri_spec.pri_type = NGHTTP2_PRIORITY_TYPE_NONE;
|
||||
nghttp2_priority_spec_default_init(&pri_spec);
|
||||
|
||||
nghttp2_frame_headers_init(&frame,
|
||||
NGHTTP2_FLAG_END_STREAM |
|
||||
|
@ -110,8 +110,8 @@ void test_nghttp2_frame_pack_headers()
|
|||
NGHTTP2_HEADERS,
|
||||
NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS,
|
||||
1000000007, &oframe.hd);
|
||||
/* We include NGHTTP2_PRIORITY_TYPE_NONE */
|
||||
CU_ASSERT(NGHTTP2_PRIORITY_TYPE_NONE == oframe.pri_spec.pri_type);
|
||||
/* We did not include PRIORITY flag */
|
||||
CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == oframe.pri_spec.weight);
|
||||
|
||||
hdblocklen = nghttp2_bufs_len(&bufs) - NGHTTP2_FRAME_HDLEN;
|
||||
CU_ASSERT(hdblocklen ==
|
||||
|
@ -126,9 +126,9 @@ void test_nghttp2_frame_pack_headers()
|
|||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
memset(&oframe, 0, sizeof(oframe));
|
||||
/* Next, include NGHTTP2_PRIORITY_TYPE_GROUP */
|
||||
nghttp2_priority_spec_group_init(&frame.pri_spec, 1000000009, 12);
|
||||
frame.hd.flags |= NGHTTP2_FLAG_PRIORITY_GROUP;
|
||||
/* Next, include NGHTTP2_FLAG_PRIORITY */
|
||||
nghttp2_priority_spec_init(&frame.pri_spec, 1000000009, 12, 1);
|
||||
frame.hd.flags |= NGHTTP2_FLAG_PRIORITY;
|
||||
|
||||
rv = nghttp2_frame_pack_headers(&bufs, &frame, &deflater);
|
||||
|
||||
|
@ -139,12 +139,12 @@ void test_nghttp2_frame_pack_headers()
|
|||
check_frame_header(nghttp2_bufs_len(&bufs) - NGHTTP2_FRAME_HDLEN,
|
||||
NGHTTP2_HEADERS,
|
||||
NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS |
|
||||
NGHTTP2_FLAG_PRIORITY_GROUP,
|
||||
NGHTTP2_FLAG_PRIORITY,
|
||||
1000000007, &oframe.hd);
|
||||
|
||||
CU_ASSERT(NGHTTP2_PRIORITY_TYPE_GROUP == oframe.pri_spec.pri_type);
|
||||
CU_ASSERT(1000000009 == oframe.pri_spec.spec.group.pri_group_id);
|
||||
CU_ASSERT(12 == oframe.pri_spec.spec.group.weight);
|
||||
CU_ASSERT(1000000009 == oframe.pri_spec.stream_id);
|
||||
CU_ASSERT(12 == oframe.pri_spec.weight);
|
||||
CU_ASSERT(1 == oframe.pri_spec.exclusive);
|
||||
|
||||
hdblocklen = nghttp2_bufs_len(&bufs) - NGHTTP2_FRAME_HDLEN
|
||||
- nghttp2_frame_priority_len(oframe.hd.flags);
|
||||
|
@ -159,44 +159,7 @@ void test_nghttp2_frame_pack_headers()
|
|||
nva_out_reset(&out);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
memset(&oframe, 0, sizeof(oframe));
|
||||
|
||||
/* Next, include NGHTTP2_PRIORITY_TYPE_DEP */
|
||||
nghttp2_priority_spec_dep_init(&frame.pri_spec, 123, 1);
|
||||
|
||||
frame.hd.flags =
|
||||
NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS |
|
||||
NGHTTP2_FLAG_PRIORITY_DEPENDENCY;
|
||||
|
||||
rv = nghttp2_frame_pack_headers(&bufs, &frame, &deflater);
|
||||
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &bufs));
|
||||
|
||||
check_frame_header(nghttp2_bufs_len(&bufs) - NGHTTP2_FRAME_HDLEN,
|
||||
NGHTTP2_HEADERS,
|
||||
NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS |
|
||||
NGHTTP2_FLAG_PRIORITY_DEPENDENCY,
|
||||
1000000007, &oframe.hd);
|
||||
|
||||
CU_ASSERT(NGHTTP2_PRIORITY_TYPE_DEP == oframe.pri_spec.pri_type);
|
||||
CU_ASSERT(123 == oframe.pri_spec.spec.dep.stream_id);
|
||||
CU_ASSERT(1 == oframe.pri_spec.spec.dep.exclusive);
|
||||
|
||||
hdblocklen = nghttp2_bufs_len(&bufs) - NGHTTP2_FRAME_HDLEN
|
||||
- nghttp2_frame_priority_len(oframe.hd.flags);
|
||||
CU_ASSERT(hdblocklen ==
|
||||
inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN
|
||||
+ nghttp2_frame_priority_len(oframe.hd.flags)));
|
||||
|
||||
nghttp2_nv_array_sort(out.nva, out.nvlen);
|
||||
CU_ASSERT(nvnameeq("method", &out.nva[0]));
|
||||
|
||||
nghttp2_frame_headers_free(&oframe);
|
||||
nva_out_reset(&out);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
|
||||
nghttp2_frame_headers_free(&frame);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
|
@ -208,7 +171,6 @@ void test_nghttp2_frame_pack_headers_frame_too_large(void)
|
|||
nghttp2_headers frame;
|
||||
nghttp2_bufs bufs;
|
||||
nghttp2_nv *nva;
|
||||
nghttp2_priority_spec pri_spec;
|
||||
ssize_t nvlen;
|
||||
size_t big_vallen = NGHTTP2_HD_MAX_VALUE;
|
||||
nghttp2_nv big_hds[16];
|
||||
|
@ -228,13 +190,11 @@ void test_nghttp2_frame_pack_headers_frame_too_large(void)
|
|||
big_hds[i].flags = NGHTTP2_NV_FLAG_NONE;
|
||||
}
|
||||
|
||||
pri_spec.pri_type = NGHTTP2_PRIORITY_TYPE_NONE;
|
||||
|
||||
nvlen = nghttp2_nv_array_copy(&nva, big_hds, big_hdslen);
|
||||
nghttp2_hd_deflate_init(&deflater);
|
||||
nghttp2_frame_headers_init(&frame,
|
||||
NGHTTP2_FLAG_END_STREAM|NGHTTP2_FLAG_END_HEADERS,
|
||||
1000000007, &pri_spec, nva, nvlen);
|
||||
1000000007, NULL, nva, nvlen);
|
||||
rv = nghttp2_frame_pack_headers(&bufs, &frame, &deflater);
|
||||
CU_ASSERT(NGHTTP2_ERR_HEADER_COMP == rv);
|
||||
|
||||
|
@ -256,7 +216,7 @@ void test_nghttp2_frame_pack_priority(void)
|
|||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
/* First, pack priority with priority group and weight */
|
||||
nghttp2_priority_spec_group_init(&pri_spec, 1000000009, 12);
|
||||
nghttp2_priority_spec_init(&pri_spec, 1000000009, 12, 1);
|
||||
|
||||
nghttp2_frame_priority_init(&frame, 1000000007, &pri_spec);
|
||||
rv = nghttp2_frame_pack_priority(&bufs, &frame);
|
||||
|
@ -264,34 +224,12 @@ void test_nghttp2_frame_pack_priority(void)
|
|||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(13 == nghttp2_bufs_len(&bufs));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &bufs));
|
||||
check_frame_header(4, NGHTTP2_PRIORITY, NGHTTP2_FLAG_PRIORITY_GROUP,
|
||||
check_frame_header(5, NGHTTP2_PRIORITY, NGHTTP2_FLAG_NONE,
|
||||
1000000007, &oframe.hd);
|
||||
|
||||
CU_ASSERT(NGHTTP2_PRIORITY_TYPE_GROUP == oframe.pri_spec.pri_type);
|
||||
CU_ASSERT(1000000009 == oframe.pri_spec.spec.group.pri_group_id);
|
||||
CU_ASSERT(12 == oframe.pri_spec.spec.group.weight);
|
||||
|
||||
nghttp2_frame_priority_free(&oframe);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
memset(&oframe, 0, sizeof(oframe));
|
||||
|
||||
/* Next, pack priority with stream dependency */
|
||||
nghttp2_priority_spec_dep_init(&pri_spec, 79, 1);
|
||||
|
||||
nghttp2_frame_priority_init(&frame, 1000000007, &pri_spec);
|
||||
rv = nghttp2_frame_pack_priority(&bufs, &frame);
|
||||
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(12 == nghttp2_bufs_len(&bufs));
|
||||
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &bufs));
|
||||
check_frame_header(4, NGHTTP2_PRIORITY, NGHTTP2_FLAG_PRIORITY_DEPENDENCY,
|
||||
1000000007, &oframe.hd);
|
||||
|
||||
CU_ASSERT(NGHTTP2_PRIORITY_TYPE_DEP == oframe.pri_spec.pri_type);
|
||||
CU_ASSERT(79 == oframe.pri_spec.spec.dep.stream_id);
|
||||
CU_ASSERT(1 == oframe.pri_spec.spec.dep.exclusive);
|
||||
CU_ASSERT(1000000009 == oframe.pri_spec.stream_id);
|
||||
CU_ASSERT(12 == oframe.pri_spec.weight);
|
||||
CU_ASSERT(1 == oframe.pri_spec.exclusive);
|
||||
|
||||
nghttp2_frame_priority_free(&oframe);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -103,6 +103,7 @@ void test_nghttp2_session_stream_dep_add(void);
|
|||
void test_nghttp2_session_stream_dep_remove(void);
|
||||
void test_nghttp2_session_stream_dep_add_subtree(void);
|
||||
void test_nghttp2_session_stream_dep_remove_subtree(void);
|
||||
void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void);
|
||||
void test_nghttp2_session_stream_attach_data(void);
|
||||
void test_nghttp2_session_stream_attach_data_subtree(void);
|
||||
void test_nghttp2_session_keep_closed_stream(void);
|
||||
|
|
|
@ -232,12 +232,22 @@ void bufs_large_init(nghttp2_bufs *bufs, size_t chunk_size)
|
|||
nghttp2_bufs_init2(bufs, chunk_size, 16, NGHTTP2_FRAME_HDLEN + 2);
|
||||
}
|
||||
|
||||
nghttp2_stream* open_stream(nghttp2_session *session, int32_t stream_id)
|
||||
static nghttp2_stream* open_stream_with_all(nghttp2_session *session,
|
||||
int32_t stream_id,
|
||||
int32_t weight,
|
||||
uint8_t exclusive,
|
||||
nghttp2_stream *dep_stream)
|
||||
{
|
||||
nghttp2_priority_spec pri_spec;
|
||||
int32_t dep_stream_id;
|
||||
|
||||
nghttp2_priority_spec_group_init(&pri_spec, stream_id,
|
||||
NGHTTP2_DEFAULT_WEIGHT);
|
||||
if(dep_stream) {
|
||||
dep_stream_id = dep_stream->stream_id;
|
||||
} else {
|
||||
dep_stream_id = 0;
|
||||
}
|
||||
|
||||
nghttp2_priority_spec_init(&pri_spec, dep_stream_id, weight, exclusive);
|
||||
|
||||
return nghttp2_session_open_stream(session, stream_id,
|
||||
NGHTTP2_STREAM_FLAG_NONE,
|
||||
|
@ -246,32 +256,45 @@ nghttp2_stream* open_stream(nghttp2_session *session, int32_t stream_id)
|
|||
NULL);
|
||||
}
|
||||
|
||||
|
||||
nghttp2_stream* open_stream(nghttp2_session *session, int32_t stream_id)
|
||||
{
|
||||
return open_stream_with_all(session, stream_id, NGHTTP2_DEFAULT_WEIGHT, 0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
nghttp2_stream* open_stream_with_dep(nghttp2_session *session,
|
||||
int32_t stream_id,
|
||||
nghttp2_stream *dep_stream)
|
||||
{
|
||||
nghttp2_priority_spec pri_spec;
|
||||
return open_stream_with_all(session, stream_id, NGHTTP2_DEFAULT_WEIGHT, 0,
|
||||
dep_stream);
|
||||
}
|
||||
|
||||
nghttp2_priority_spec_dep_init(&pri_spec, dep_stream->stream_id, 0);
|
||||
|
||||
return nghttp2_session_open_stream(session, stream_id,
|
||||
NGHTTP2_STREAM_FLAG_NONE,
|
||||
&pri_spec,
|
||||
NGHTTP2_STREAM_OPENED,
|
||||
NULL);
|
||||
nghttp2_stream* open_stream_with_dep_weight(nghttp2_session *session,
|
||||
int32_t stream_id,
|
||||
int32_t weight,
|
||||
nghttp2_stream *dep_stream)
|
||||
{
|
||||
return open_stream_with_all(session, stream_id, weight, 0, dep_stream);
|
||||
}
|
||||
|
||||
nghttp2_stream* open_stream_with_dep_excl(nghttp2_session *session,
|
||||
int32_t stream_id,
|
||||
nghttp2_stream *dep_stream)
|
||||
{
|
||||
nghttp2_priority_spec pri_spec;
|
||||
|
||||
nghttp2_priority_spec_dep_init(&pri_spec, dep_stream->stream_id, 1);
|
||||
|
||||
return nghttp2_session_open_stream(session, stream_id,
|
||||
NGHTTP2_STREAM_FLAG_NONE,
|
||||
&pri_spec,
|
||||
NGHTTP2_STREAM_OPENED,
|
||||
NULL);
|
||||
return open_stream_with_all(session, stream_id, NGHTTP2_DEFAULT_WEIGHT, 1,
|
||||
dep_stream);
|
||||
}
|
||||
|
||||
nghttp2_outbound_item* create_data_ob_item(void)
|
||||
{
|
||||
nghttp2_outbound_item *item;
|
||||
|
||||
item = malloc(sizeof(nghttp2_outbound_item));
|
||||
memset(item, 0, sizeof(nghttp2_outbound_item));
|
||||
item->frame_cat = NGHTTP2_CAT_DATA;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
|
|
|
@ -89,8 +89,15 @@ nghttp2_stream* open_stream_with_dep(nghttp2_session *session,
|
|||
int32_t stream_id,
|
||||
nghttp2_stream *dep_stream);
|
||||
|
||||
nghttp2_stream* open_stream_with_dep_weight(nghttp2_session *session,
|
||||
int32_t stream_id,
|
||||
int32_t weight,
|
||||
nghttp2_stream *dep_stream);
|
||||
|
||||
nghttp2_stream* open_stream_with_dep_excl(nghttp2_session *session,
|
||||
int32_t stream_id,
|
||||
nghttp2_stream *dep_stream);
|
||||
|
||||
nghttp2_outbound_item* create_data_ob_item(void);
|
||||
|
||||
#endif /* NGHTTP2_TEST_HELPER_H */
|
||||
|
|
Loading…
Reference in New Issue