Callback based padding from application
Now previous padding options are removed and instead we added select_padding_callback to select padding length for each frame by application. If this callback is not implemented by application, no padding is added. This change also fixes the broken session_detect_idle_stream() if stream_id is our side.
This commit is contained in:
parent
118ed09da5
commit
78d202ac30
|
@ -147,14 +147,6 @@ typedef struct {
|
||||||
*/
|
*/
|
||||||
#define NGHTTP2_CLIENT_CONNECTION_HEADER_LEN 24
|
#define NGHTTP2_CLIENT_CONNECTION_HEADER_LEN 24
|
||||||
|
|
||||||
/**
|
|
||||||
* @macro
|
|
||||||
*
|
|
||||||
* The default value of DATA padding alignment. See
|
|
||||||
* :member:`NGHTTP2_OPT_PADDING_BOUNDARY`.
|
|
||||||
*/
|
|
||||||
#define NGHTTP2_PADDING_BOUNDARY 64
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @enum
|
* @enum
|
||||||
*
|
*
|
||||||
|
@ -1184,6 +1176,26 @@ typedef int (*nghttp2_on_header_callback)
|
||||||
const uint8_t *value, size_t valuelen,
|
const uint8_t *value, size_t valuelen,
|
||||||
void *user_data);
|
void *user_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @functypedef
|
||||||
|
*
|
||||||
|
* Callback function invoked when the library asks application how
|
||||||
|
* much padding is required for the transmission of the |frame|. The
|
||||||
|
* application must choose the total length of payload including
|
||||||
|
* padded bytes in range [frame->hd.length, max_payloadlen],
|
||||||
|
* inclusive. Choosing number not in this range will be treated as
|
||||||
|
* :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. Returning
|
||||||
|
* ``frame->hd.length`` means no padding is added. Returning
|
||||||
|
* :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` will make
|
||||||
|
* `nghttp2_session_send()` function immediately return
|
||||||
|
* :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
|
||||||
|
*/
|
||||||
|
typedef ssize_t (*nghttp2_select_padding_callback)
|
||||||
|
(nghttp2_session *session,
|
||||||
|
const nghttp2_frame *frame,
|
||||||
|
size_t max_payloadlen,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @struct
|
* @struct
|
||||||
*
|
*
|
||||||
|
@ -1247,6 +1259,11 @@ typedef struct {
|
||||||
* received.
|
* received.
|
||||||
*/
|
*/
|
||||||
nghttp2_on_header_callback on_header_callback;
|
nghttp2_on_header_callback on_header_callback;
|
||||||
|
/**
|
||||||
|
* Callback function invoked when the library asks application how
|
||||||
|
* much padding is required for the transmission of the given frame.
|
||||||
|
*/
|
||||||
|
nghttp2_select_padding_callback select_padding_callback;
|
||||||
} nghttp2_session_callbacks;
|
} nghttp2_session_callbacks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1332,15 +1349,7 @@ typedef enum {
|
||||||
* will be overwritten if the local endpoint receives
|
* will be overwritten if the local endpoint receives
|
||||||
* SETTINGS_MAX_CONCURRENT_STREAMS from the remote endpoint.
|
* SETTINGS_MAX_CONCURRENT_STREAMS from the remote endpoint.
|
||||||
*/
|
*/
|
||||||
NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS = 1 << 2,
|
NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS = 1 << 2
|
||||||
/**
|
|
||||||
* This option specifies the alignment of padding in frame
|
|
||||||
* payload. If this option is set to N, padding is added to frame
|
|
||||||
* payload so that its payload length is divisible by N. For DATA
|
|
||||||
* frame, due to flow control, padding is not always added according
|
|
||||||
* to this alignment. Specifying 0 to this option disables padding.
|
|
||||||
*/
|
|
||||||
NGHTTP2_OPT_PADDING_BOUNDARY = 1 << 3
|
|
||||||
} nghttp2_opt;
|
} nghttp2_opt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1361,10 +1370,6 @@ typedef struct {
|
||||||
* :enum:`NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE`
|
* :enum:`NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE`
|
||||||
*/
|
*/
|
||||||
uint8_t no_auto_connection_window_update;
|
uint8_t no_auto_connection_window_update;
|
||||||
/**
|
|
||||||
* :enum:`NGHTTP2_OPT_PADDING_BOUNDARY`
|
|
||||||
*/
|
|
||||||
uint16_t padding_boundary;
|
|
||||||
} nghttp2_opt_set;
|
} nghttp2_opt_set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -227,8 +227,7 @@ ssize_t nghttp2_frame_pack_headers(uint8_t **buf_ptr,
|
||||||
size_t *buflen_ptr,
|
size_t *buflen_ptr,
|
||||||
size_t *bufoff_ptr,
|
size_t *bufoff_ptr,
|
||||||
nghttp2_headers *frame,
|
nghttp2_headers *frame,
|
||||||
nghttp2_hd_deflater *deflater,
|
nghttp2_hd_deflater *deflater)
|
||||||
size_t boundary)
|
|
||||||
{
|
{
|
||||||
size_t payloadoff = NGHTTP2_FRAME_HEAD_LENGTH + 2;
|
size_t payloadoff = NGHTTP2_FRAME_HEAD_LENGTH + 2;
|
||||||
size_t nv_offset =
|
size_t nv_offset =
|
||||||
|
@ -244,23 +243,9 @@ ssize_t nghttp2_frame_pack_headers(uint8_t **buf_ptr,
|
||||||
|
|
||||||
payloadlen = nghttp2_frame_headers_payload_nv_offset(frame) + rv;
|
payloadlen = nghttp2_frame_headers_payload_nv_offset(frame) + rv;
|
||||||
|
|
||||||
if(boundary > 0) {
|
*bufoff_ptr = 2;
|
||||||
ssize_t padlen;
|
frame->padlen = 0;
|
||||||
padlen = nghttp2_frame_add_pad(buf_ptr, buflen_ptr, bufoff_ptr,
|
frame->hd.length = payloadlen;
|
||||||
&frame->hd.flags,
|
|
||||||
payloadlen,
|
|
||||||
payloadlen + boundary,
|
|
||||||
boundary);
|
|
||||||
if(padlen < 0) {
|
|
||||||
return padlen;
|
|
||||||
}
|
|
||||||
frame->padlen = padlen;
|
|
||||||
frame->hd.length = payloadlen + padlen;
|
|
||||||
} else {
|
|
||||||
*bufoff_ptr = 2;
|
|
||||||
frame->padlen = 0;
|
|
||||||
frame->hd.length = payloadlen;
|
|
||||||
}
|
|
||||||
/* If frame->nvlen == 0, *buflen_ptr may be smaller than
|
/* If frame->nvlen == 0, *buflen_ptr may be smaller than
|
||||||
nv_offset */
|
nv_offset */
|
||||||
rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, nv_offset);
|
rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, nv_offset);
|
||||||
|
@ -269,11 +254,11 @@ ssize_t nghttp2_frame_pack_headers(uint8_t **buf_ptr,
|
||||||
}
|
}
|
||||||
memset(*buf_ptr + *bufoff_ptr, 0, NGHTTP2_FRAME_HEAD_LENGTH);
|
memset(*buf_ptr + *bufoff_ptr, 0, NGHTTP2_FRAME_HEAD_LENGTH);
|
||||||
/* pack ctrl header after length is determined */
|
/* pack ctrl header after length is determined */
|
||||||
if(NGHTTP2_FRAME_HEAD_LENGTH + NGHTTP2_MAX_FRAME_LENGTH < rv + nv_offset) {
|
if(NGHTTP2_MAX_FRAME_LENGTH < payloadlen) {
|
||||||
/* Needs CONTINUATION */
|
/* Needs CONTINUATION */
|
||||||
nghttp2_frame_hd hd = frame->hd;
|
nghttp2_frame_hd hd = frame->hd;
|
||||||
hd.flags &= ~(NGHTTP2_FLAG_END_HEADERS |
|
hd.flags &= ~NGHTTP2_FLAG_END_HEADERS;
|
||||||
NGHTTP2_FLAG_PAD_HIGH | NGHTTP2_FLAG_PAD_LOW);
|
hd.length = NGHTTP2_MAX_FRAME_LENGTH;
|
||||||
nghttp2_frame_pack_frame_hd(*buf_ptr + *bufoff_ptr, &hd);
|
nghttp2_frame_pack_frame_hd(*buf_ptr + *bufoff_ptr, &hd);
|
||||||
} else {
|
} else {
|
||||||
nghttp2_frame_pack_frame_hd(*buf_ptr + *bufoff_ptr, &frame->hd);
|
nghttp2_frame_pack_frame_hd(*buf_ptr + *bufoff_ptr, &frame->hd);
|
||||||
|
@ -660,36 +645,31 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t nghttp2_frame_add_pad(uint8_t **buf_ptr, size_t *buflen_ptr,
|
int nghttp2_frame_add_pad(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||||
size_t *bufoff_ptr,
|
size_t *bufoff_ptr,
|
||||||
uint8_t *flags_ptr,
|
uint8_t *flags_ptr,
|
||||||
size_t payloadlen,
|
size_t payloadlen,
|
||||||
size_t payloadmax,
|
size_t padlen)
|
||||||
size_t boundary)
|
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
size_t nextlen =
|
|
||||||
nghttp2_min(((payloadlen == 0 ? 1 : payloadlen) + boundary - 1)
|
|
||||||
/ boundary * boundary,
|
|
||||||
payloadmax);
|
|
||||||
size_t padlen = nextlen - payloadlen;
|
|
||||||
size_t trail_padlen = 0;
|
size_t trail_padlen = 0;
|
||||||
/* extra 2 bytes for PAD_HIGH and PAD_LOW. */
|
/* extra 2 bytes for PAD_HIGH and PAD_LOW. */
|
||||||
size_t trail_padoff = 2 + NGHTTP2_FRAME_HEAD_LENGTH + payloadlen;
|
size_t trail_padoff = *bufoff_ptr + NGHTTP2_FRAME_HEAD_LENGTH + payloadlen;
|
||||||
|
|
||||||
if(padlen > 257) {
|
if(padlen > 257) {
|
||||||
*bufoff_ptr = 0;
|
uint8_t *p;
|
||||||
|
*bufoff_ptr -= 2;
|
||||||
trail_padlen = padlen - 2;
|
trail_padlen = padlen - 2;
|
||||||
*flags_ptr |= NGHTTP2_FLAG_PAD_HIGH | NGHTTP2_FLAG_PAD_LOW;
|
*flags_ptr |= NGHTTP2_FLAG_PAD_HIGH | NGHTTP2_FLAG_PAD_LOW;
|
||||||
(*buf_ptr)[NGHTTP2_FRAME_HEAD_LENGTH] = trail_padlen >> 8;
|
p = *buf_ptr + *bufoff_ptr + NGHTTP2_FRAME_HEAD_LENGTH;
|
||||||
(*buf_ptr)[NGHTTP2_FRAME_HEAD_LENGTH + 1] = trail_padlen & 0xff;
|
*p++ = trail_padlen >> 8;
|
||||||
|
*p = trail_padlen & 0xff;
|
||||||
} else if(padlen > 0) {
|
} else if(padlen > 0) {
|
||||||
*bufoff_ptr = 1;
|
--*bufoff_ptr;
|
||||||
trail_padlen = padlen - 1;
|
trail_padlen = padlen - 1;
|
||||||
*flags_ptr |= NGHTTP2_FLAG_PAD_LOW;
|
*flags_ptr |= NGHTTP2_FLAG_PAD_LOW;
|
||||||
(*buf_ptr)[NGHTTP2_FRAME_HEAD_LENGTH + 1] = trail_padlen;
|
(*buf_ptr)[*bufoff_ptr + NGHTTP2_FRAME_HEAD_LENGTH] = trail_padlen;
|
||||||
} else {
|
} else {
|
||||||
*bufoff_ptr = 2;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -702,5 +682,5 @@ ssize_t nghttp2_frame_add_pad(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||||
possible internal data to the remote peer */
|
possible internal data to the remote peer */
|
||||||
memset((*buf_ptr) + trail_padoff, 0, trail_padlen);
|
memset((*buf_ptr) + trail_padoff, 0, trail_padlen);
|
||||||
|
|
||||||
return padlen;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,10 +105,8 @@ size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame);
|
||||||
* change. |*buf_ptr| and |*buflen_ptr| are updated accordingly.
|
* change. |*buf_ptr| and |*buflen_ptr| are updated accordingly.
|
||||||
*
|
*
|
||||||
* The first byte the frame is serialized is returned in the
|
* The first byte the frame is serialized is returned in the
|
||||||
* |*bufoff_ptr|.
|
* |*bufoff_ptr|. Currently, it is always 2 to account for possible
|
||||||
*
|
* PAD_HIGH and PAD_LOW.
|
||||||
* The |boundary| is used as padding boundary. If the |boundary| is
|
|
||||||
* zero, no padding is added.
|
|
||||||
*
|
*
|
||||||
* frame->hd.length is assigned after length is determined during
|
* frame->hd.length is assigned after length is determined during
|
||||||
* packing process. If payload length is strictly larger than
|
* packing process. If payload length is strictly larger than
|
||||||
|
@ -131,8 +129,7 @@ ssize_t nghttp2_frame_pack_headers(uint8_t **buf_ptr,
|
||||||
size_t *buflen_ptr,
|
size_t *buflen_ptr,
|
||||||
size_t *bufoff_ptr,
|
size_t *bufoff_ptr,
|
||||||
nghttp2_headers *frame,
|
nghttp2_headers *frame,
|
||||||
nghttp2_hd_deflater *deflater,
|
nghttp2_hd_deflater *deflater);
|
||||||
size_t boundary);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unpacks HEADERS frame byte sequence into |frame|. This function
|
* Unpacks HEADERS frame byte sequence into |frame|. This function
|
||||||
|
@ -505,11 +502,10 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv);
|
||||||
/*
|
/*
|
||||||
* Add padding to the payload in the |*buf_ptr| of length
|
* Add padding to the payload in the |*buf_ptr| of length
|
||||||
* |*buflen_ptr|. The payload length is given in |payloadlen|. The
|
* |*buflen_ptr|. The payload length is given in |payloadlen|. The
|
||||||
* payload must start at offset NGHTTP2_FRAME_HEAD_LENGTH + 2 from
|
* frame header starts at offset |*bufoff_ptr|. Therefore, the payload
|
||||||
* |*buf_ptr| to account for PAD_HIGH and PAD_LOW. The maximum payload
|
* must start at offset *bufoff_ptr + NGHTTP2_FRAME_HEAD_LENGTH from
|
||||||
* allowed is given in the |payloadmax|. The padding will not be made
|
* |*buf_ptr| to account for PAD_HIGH and PAD_LOW. The padding is
|
||||||
* more than |payloadmax|. The padding boundary is given in the
|
* given in the |padlen|.
|
||||||
* |boundary|.
|
|
||||||
*
|
*
|
||||||
* The |*flags_ptr| is updated to include NGHTTP2_FLAG_PAD_LOW and
|
* The |*flags_ptr| is updated to include NGHTTP2_FLAG_PAD_LOW and
|
||||||
* NGHTTP2_FLAG_PAD_HIGH based on the padding length. The
|
* NGHTTP2_FLAG_PAD_HIGH based on the padding length. The
|
||||||
|
@ -570,18 +566,14 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv);
|
||||||
* additional copy operation is required (if the |*buf_ptr| is large
|
* additional copy operation is required (if the |*buf_ptr| is large
|
||||||
* enough to account the additional padding, of course).
|
* enough to account the additional padding, of course).
|
||||||
*
|
*
|
||||||
* This function returns the number of padding added to the payload
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* including PAD_HIGH and PAD_LOW if it succeeds, or one of the
|
* negative error codes:
|
||||||
* following negative error codes:
|
|
||||||
*
|
*
|
||||||
* NGHTTP2_ERR_NOMEM
|
* NGHTTP2_ERR_NOMEM
|
||||||
* Out of memory.
|
* Out of memory.
|
||||||
*/
|
*/
|
||||||
ssize_t nghttp2_frame_add_pad(uint8_t **buf_ptr, size_t *buflen_ptr,
|
int nghttp2_frame_add_pad(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||||
size_t *bufoff_ptr,
|
size_t *bufoff_ptr, uint8_t *flags_ptr,
|
||||||
uint8_t *flags_ptr,
|
size_t payloadlen, size_t padlen);
|
||||||
size_t payloadlen,
|
|
||||||
size_t payloadmax,
|
|
||||||
size_t boundary);
|
|
||||||
|
|
||||||
#endif /* NGHTTP2_FRAME_H */
|
#endif /* NGHTTP2_FRAME_H */
|
||||||
|
|
|
@ -224,11 +224,6 @@ static int nghttp2_session_new(nghttp2_session **session_ptr,
|
||||||
(*session_ptr)->opt_flags |=
|
(*session_ptr)->opt_flags |=
|
||||||
NGHTTP2_OPTMASK_NO_AUTO_CONNECTION_WINDOW_UPDATE;
|
NGHTTP2_OPTMASK_NO_AUTO_CONNECTION_WINDOW_UPDATE;
|
||||||
}
|
}
|
||||||
if(opt_set_mask & NGHTTP2_OPT_PADDING_BOUNDARY) {
|
|
||||||
(*session_ptr)->padding_boundary = opt_set->padding_boundary;
|
|
||||||
} else {
|
|
||||||
(*session_ptr)->padding_boundary = NGHTTP2_PADDING_BOUNDARY;
|
|
||||||
}
|
|
||||||
|
|
||||||
(*session_ptr)->remote_window_size = NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
|
(*session_ptr)->remote_window_size = NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
|
||||||
(*session_ptr)->recv_window_size = 0;
|
(*session_ptr)->recv_window_size = 0;
|
||||||
|
@ -1080,6 +1075,23 @@ static int nghttp2_session_predicate_data_send(nghttp2_session *session,
|
||||||
return NGHTTP2_ERR_INVALID_STREAM_STATE;
|
return NGHTTP2_ERR_INVALID_STREAM_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t session_call_select_padding(nghttp2_session *session,
|
||||||
|
const nghttp2_frame *frame,
|
||||||
|
size_t max_payloadlen)
|
||||||
|
{
|
||||||
|
ssize_t rv;
|
||||||
|
if(session->callbacks.select_padding_callback) {
|
||||||
|
rv = session->callbacks.select_padding_callback(session, frame,
|
||||||
|
max_payloadlen,
|
||||||
|
session->user_data);
|
||||||
|
if(rv < frame->hd.length || rv > max_payloadlen) {
|
||||||
|
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
return frame->hd.length;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t nghttp2_session_prep_frame(nghttp2_session *session,
|
static ssize_t nghttp2_session_prep_frame(nghttp2_session *session,
|
||||||
nghttp2_outbound_item *item)
|
nghttp2_outbound_item *item)
|
||||||
{
|
{
|
||||||
|
@ -1089,11 +1101,12 @@ static ssize_t nghttp2_session_prep_frame(nghttp2_session *session,
|
||||||
frame = nghttp2_outbound_item_get_ctrl_frame(item);
|
frame = nghttp2_outbound_item_get_ctrl_frame(item);
|
||||||
switch(frame->hd.type) {
|
switch(frame->hd.type) {
|
||||||
case NGHTTP2_HEADERS: {
|
case NGHTTP2_HEADERS: {
|
||||||
|
int r;
|
||||||
nghttp2_headers_aux_data *aux_data;
|
nghttp2_headers_aux_data *aux_data;
|
||||||
|
ssize_t padded_payloadlen;
|
||||||
aux_data = (nghttp2_headers_aux_data*)item->aux_data;
|
aux_data = (nghttp2_headers_aux_data*)item->aux_data;
|
||||||
if(frame->hd.stream_id == -1) {
|
if(frame->hd.stream_id == -1) {
|
||||||
/* initial HEADERS, which opens stream */
|
/* initial HEADERS, which opens stream */
|
||||||
int r;
|
|
||||||
frame->headers.cat = NGHTTP2_HCAT_REQUEST;
|
frame->headers.cat = NGHTTP2_HCAT_REQUEST;
|
||||||
r = nghttp2_session_predicate_request_headers_send(session,
|
r = nghttp2_session_predicate_request_headers_send(session,
|
||||||
&frame->headers);
|
&frame->headers);
|
||||||
|
@ -1109,7 +1122,6 @@ static ssize_t nghttp2_session_prep_frame(nghttp2_session *session,
|
||||||
(session, frame->hd.stream_id) == 0) {
|
(session, frame->hd.stream_id) == 0) {
|
||||||
frame->headers.cat = NGHTTP2_HCAT_RESPONSE;
|
frame->headers.cat = NGHTTP2_HCAT_RESPONSE;
|
||||||
} else {
|
} else {
|
||||||
int r;
|
|
||||||
frame->headers.cat = NGHTTP2_HCAT_HEADERS;
|
frame->headers.cat = NGHTTP2_HCAT_HEADERS;
|
||||||
r = nghttp2_session_predicate_headers_send(session,
|
r = nghttp2_session_predicate_headers_send(session,
|
||||||
frame->hd.stream_id);
|
frame->hd.stream_id);
|
||||||
|
@ -1121,11 +1133,47 @@ static ssize_t nghttp2_session_prep_frame(nghttp2_session *session,
|
||||||
&session->aob.framebufmax,
|
&session->aob.framebufmax,
|
||||||
&session->aob.framebufoff,
|
&session->aob.framebufoff,
|
||||||
&frame->headers,
|
&frame->headers,
|
||||||
&session->hd_deflater,
|
&session->hd_deflater);
|
||||||
session->padding_boundary);
|
|
||||||
if(framebuflen < 0) {
|
if(framebuflen < 0) {
|
||||||
return framebuflen;
|
return framebuflen;
|
||||||
}
|
}
|
||||||
|
padded_payloadlen = session_call_select_padding
|
||||||
|
(session, frame,
|
||||||
|
(frame->hd.length == 0 ? NGHTTP2_MAX_FRAME_LENGTH :
|
||||||
|
(frame->hd.length + NGHTTP2_MAX_FRAME_LENGTH - 1)
|
||||||
|
/ NGHTTP2_MAX_FRAME_LENGTH * NGHTTP2_MAX_FRAME_LENGTH));
|
||||||
|
if(nghttp2_is_fatal(padded_payloadlen)) {
|
||||||
|
return padded_payloadlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame->headers.padlen = padded_payloadlen - frame->hd.length;
|
||||||
|
frame->hd.length = padded_payloadlen;
|
||||||
|
|
||||||
|
if(frame->hd.length > NGHTTP2_MAX_FRAME_LENGTH) {
|
||||||
|
/* PAD_HIGH and PAD_LOW will be added in
|
||||||
|
nghttp2_session_after_frame_sent(). */
|
||||||
|
/* This may make framebuflen > session->aob.framebufmax. But
|
||||||
|
before we access the missing part, we will allocate it in
|
||||||
|
nghttp2_session_after_frame_sent(). */
|
||||||
|
framebuflen += frame->headers.padlen;
|
||||||
|
} else if(frame->hd.length <= NGHTTP2_MAX_FRAME_LENGTH &&
|
||||||
|
padded_payloadlen > frame->hd.length) {
|
||||||
|
r = nghttp2_frame_add_pad(&session->aob.framebuf,
|
||||||
|
&session->aob.framebufmax,
|
||||||
|
&session->aob.framebufoff,
|
||||||
|
&frame->hd.flags,
|
||||||
|
frame->hd.length,
|
||||||
|
padded_payloadlen - frame->hd.length);
|
||||||
|
if(nghttp2_is_fatal(r)) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
framebuflen = session->aob.framebufoff + frame->hd.length
|
||||||
|
+ NGHTTP2_FRAME_HEAD_LENGTH;
|
||||||
|
|
||||||
|
nghttp2_frame_pack_frame_hd
|
||||||
|
(session->aob.framebuf + session->aob.framebufoff, &frame->hd);
|
||||||
|
}
|
||||||
|
|
||||||
switch(frame->headers.cat) {
|
switch(frame->headers.cat) {
|
||||||
case NGHTTP2_HCAT_REQUEST: {
|
case NGHTTP2_HCAT_REQUEST: {
|
||||||
if(nghttp2_session_open_stream
|
if(nghttp2_session_open_stream
|
||||||
|
@ -1444,21 +1492,38 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session)
|
||||||
session->aob.framebufmark,
|
session->aob.framebufmark,
|
||||||
NGHTTP2_MAX_FRAME_LENGTH);
|
NGHTTP2_MAX_FRAME_LENGTH);
|
||||||
cont_hd.type = NGHTTP2_CONTINUATION;
|
cont_hd.type = NGHTTP2_CONTINUATION;
|
||||||
|
cont_hd.stream_id = frame->hd.stream_id;
|
||||||
|
/* Reuse previous buffers for frame header */
|
||||||
|
session->aob.framebufoff -= NGHTTP2_FRAME_HEAD_LENGTH;
|
||||||
if(cont_hd.length + session->aob.framebufmark ==
|
if(cont_hd.length + session->aob.framebufmark ==
|
||||||
session->aob.framebuflen) {
|
session->aob.framebuflen) {
|
||||||
|
DEBUGF(fprintf(stderr,
|
||||||
|
"last CONTINUATION payloadlen=%zu, padlen=%zu\n",
|
||||||
|
cont_hd.length, frame->headers.padlen));
|
||||||
|
|
||||||
cont_hd.flags = NGHTTP2_FLAG_END_HEADERS;
|
cont_hd.flags = NGHTTP2_FLAG_END_HEADERS;
|
||||||
cont_hd.flags |=
|
rv = nghttp2_frame_add_pad(&session->aob.framebuf,
|
||||||
(NGHTTP2_FLAG_PAD_HIGH | NGHTTP2_FLAG_PAD_LOW) & frame->hd.flags;
|
&session->aob.framebufmax,
|
||||||
|
&session->aob.framebufoff,
|
||||||
|
&cont_hd.flags,
|
||||||
|
cont_hd.length - frame->headers.padlen,
|
||||||
|
frame->headers.padlen);
|
||||||
|
if(nghttp2_is_fatal(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
/* we reuses previous up to 2 bytes for PAD_HIGH and
|
||||||
|
PAD_LOW. Because of this, session->aob.framebuflen is 1
|
||||||
|
or 2 bytes longer. Re-compute the value here. */
|
||||||
|
session->aob.framebuflen = session->aob.framebufmark =
|
||||||
|
session->aob.framebufoff + NGHTTP2_FRAME_HEAD_LENGTH +
|
||||||
|
cont_hd.length;
|
||||||
} else {
|
} else {
|
||||||
cont_hd.flags = NGHTTP2_FLAG_NONE;
|
cont_hd.flags = NGHTTP2_FLAG_NONE;
|
||||||
|
session->aob.framebufmark += cont_hd.length;
|
||||||
}
|
}
|
||||||
cont_hd.stream_id = frame->hd.stream_id;
|
|
||||||
nghttp2_frame_pack_frame_hd(session->aob.framebuf +
|
nghttp2_frame_pack_frame_hd(session->aob.framebuf +
|
||||||
session->aob.framebufmark -
|
session->aob.framebufoff,
|
||||||
NGHTTP2_FRAME_HEAD_LENGTH,
|
|
||||||
&cont_hd);
|
&cont_hd);
|
||||||
session->aob.framebufmark += cont_hd.length;
|
|
||||||
session->aob.framebufoff -= NGHTTP2_FRAME_HEAD_LENGTH;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1754,9 +1819,13 @@ int nghttp2_session_send(nghttp2_session *session)
|
||||||
|
|
||||||
if(item->frame_cat == NGHTTP2_CAT_CTRL) {
|
if(item->frame_cat == NGHTTP2_CAT_CTRL) {
|
||||||
nghttp2_frame *frame = nghttp2_outbound_item_get_ctrl_frame(item);
|
nghttp2_frame *frame = nghttp2_outbound_item_get_ctrl_frame(item);
|
||||||
|
/* We have to get frame size from headers, because
|
||||||
|
frame->hd.length does not always shows the actual frame
|
||||||
|
size, especially for HEADERS size >
|
||||||
|
NGHTTP2_MAX_FRAME_LENGTH */
|
||||||
session->aob.framebufmark =
|
session->aob.framebufmark =
|
||||||
session->aob.framebufoff +
|
session->aob.framebufoff + NGHTTP2_FRAME_HEAD_LENGTH +
|
||||||
frame->hd.length + NGHTTP2_FRAME_HEAD_LENGTH;
|
nghttp2_get_uint16(session->aob.framebuf + session->aob.framebufoff);
|
||||||
r = session_call_before_frame_send(session, frame);
|
r = session_call_before_frame_send(session, frame);
|
||||||
if(nghttp2_is_fatal(r)) {
|
if(nghttp2_is_fatal(r)) {
|
||||||
return r;
|
return r;
|
||||||
|
@ -1766,8 +1835,8 @@ int nghttp2_session_send(nghttp2_session *session)
|
||||||
frame = nghttp2_outbound_item_get_data_frame(session->aob.item);
|
frame = nghttp2_outbound_item_get_data_frame(session->aob.item);
|
||||||
/* session->aob.framebufmark = session->aob.framebuflen; */
|
/* session->aob.framebufmark = session->aob.framebuflen; */
|
||||||
session->aob.framebufmark =
|
session->aob.framebufmark =
|
||||||
session->aob.framebufoff +
|
session->aob.framebufoff + NGHTTP2_FRAME_HEAD_LENGTH +
|
||||||
frame->hd.length + NGHTTP2_FRAME_HEAD_LENGTH;
|
frame->hd.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1887,7 +1956,7 @@ static int session_detect_idle_stream(nghttp2_session *session,
|
||||||
{
|
{
|
||||||
/* Assume that stream object with stream_id does not exist */
|
/* Assume that stream object with stream_id does not exist */
|
||||||
if(nghttp2_session_is_my_stream_id(session, stream_id)) {
|
if(nghttp2_session_is_my_stream_id(session, stream_id)) {
|
||||||
if(session->next_stream_id >= (uint32_t)stream_id) {
|
if(session->next_stream_id <= (uint32_t)stream_id) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2812,7 +2881,7 @@ int nghttp2_session_on_push_promise_received(nghttp2_session *session,
|
||||||
if(!stream || stream->state == NGHTTP2_STREAM_CLOSING) {
|
if(!stream || stream->state == NGHTTP2_STREAM_CLOSING) {
|
||||||
if(!stream) {
|
if(!stream) {
|
||||||
if(session_detect_idle_stream(session, frame->hd.stream_id)) {
|
if(session_detect_idle_stream(session, frame->hd.stream_id)) {
|
||||||
return nghttp2_session_handle_invalid_connection
|
return nghttp2_session_inflate_handle_invalid_connection
|
||||||
(session, frame, NGHTTP2_PROTOCOL_ERROR);
|
(session, frame, NGHTTP2_PROTOCOL_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3327,11 +3396,13 @@ static int inbound_frame_handle_pad(nghttp2_inbound_frame *iframe,
|
||||||
}
|
}
|
||||||
iframe->state = NGHTTP2_IB_READ_NBYTE;
|
iframe->state = NGHTTP2_IB_READ_NBYTE;
|
||||||
iframe->left = 2;
|
iframe->left = 2;
|
||||||
|
iframe->buflen = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if(hd->flags & NGHTTP2_FLAG_PAD_LOW) {
|
if(hd->flags & NGHTTP2_FLAG_PAD_LOW) {
|
||||||
iframe->state = NGHTTP2_IB_READ_NBYTE;
|
iframe->state = NGHTTP2_IB_READ_NBYTE;
|
||||||
iframe->left = 1;
|
iframe->left = 1;
|
||||||
|
iframe->buflen = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
DEBUGF(fprintf(stderr, "no padding\n"));
|
DEBUGF(fprintf(stderr, "no padding\n"));
|
||||||
|
@ -3353,7 +3424,8 @@ static ssize_t inbound_frame_compute_pad(nghttp2_inbound_frame *iframe)
|
||||||
}
|
}
|
||||||
++padlen;
|
++padlen;
|
||||||
DEBUGF(fprintf(stderr, "padlen=%zu\n", padlen));
|
DEBUGF(fprintf(stderr, "padlen=%zu\n", padlen));
|
||||||
if(padlen > iframe->frame.hd.length) {
|
/* We cannot use iframe->frame.hd.length because of CONTINUATION */
|
||||||
|
if(padlen - (padlen > 255) - 1 > iframe->payloadleft) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
iframe->padlen = padlen;
|
iframe->padlen = padlen;
|
||||||
|
@ -3837,7 +3909,8 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
||||||
nghttp2_inbound_frame_reset(session);
|
nghttp2_inbound_frame_reset(session);
|
||||||
break;
|
break;
|
||||||
case NGHTTP2_IB_EXPECT_CONTINUATION:
|
case NGHTTP2_IB_EXPECT_CONTINUATION:
|
||||||
case NGHTTP2_IB_IGN_CONTINUATION:
|
case NGHTTP2_IB_IGN_CONTINUATION: {
|
||||||
|
nghttp2_inbound_state state_back;
|
||||||
#ifdef DEBUGBUILD
|
#ifdef DEBUGBUILD
|
||||||
if(iframe->state == NGHTTP2_IB_EXPECT_CONTINUATION) {
|
if(iframe->state == NGHTTP2_IB_EXPECT_CONTINUATION) {
|
||||||
fprintf(stderr, "[IB_EXPECT_CONTINUATION]\n");
|
fprintf(stderr, "[IB_EXPECT_CONTINUATION]\n");
|
||||||
|
@ -3872,7 +3945,9 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
||||||
iframe->frame.hd.flags |= cont_hd.flags &
|
iframe->frame.hd.flags |= cont_hd.flags &
|
||||||
(NGHTTP2_FLAG_END_HEADERS |
|
(NGHTTP2_FLAG_END_HEADERS |
|
||||||
NGHTTP2_FLAG_PAD_HIGH | NGHTTP2_FLAG_PAD_LOW);
|
NGHTTP2_FLAG_PAD_HIGH | NGHTTP2_FLAG_PAD_LOW);
|
||||||
|
iframe->frame.hd.length += cont_hd.length;
|
||||||
|
|
||||||
|
state_back = iframe->state;
|
||||||
rv = inbound_frame_handle_pad(iframe, &cont_hd);
|
rv = inbound_frame_handle_pad(iframe, &cont_hd);
|
||||||
if(rv < 0) {
|
if(rv < 0) {
|
||||||
busy = 1;
|
busy = 1;
|
||||||
|
@ -3885,7 +3960,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(rv == 1) {
|
if(rv == 1) {
|
||||||
if(iframe->state == NGHTTP2_IB_EXPECT_CONTINUATION) {
|
if(state_back == NGHTTP2_IB_EXPECT_CONTINUATION) {
|
||||||
iframe->state = NGHTTP2_IB_READ_PAD_CONTINUATION;
|
iframe->state = NGHTTP2_IB_READ_PAD_CONTINUATION;
|
||||||
} else {
|
} else {
|
||||||
iframe->state = NGHTTP2_IB_IGN_PAD_CONTINUATION;
|
iframe->state = NGHTTP2_IB_IGN_PAD_CONTINUATION;
|
||||||
|
@ -3900,6 +3975,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
||||||
iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
|
iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case NGHTTP2_IB_READ_PAD_CONTINUATION:
|
case NGHTTP2_IB_READ_PAD_CONTINUATION:
|
||||||
case NGHTTP2_IB_IGN_PAD_CONTINUATION:
|
case NGHTTP2_IB_IGN_PAD_CONTINUATION:
|
||||||
#ifdef DEBUGBUILD
|
#ifdef DEBUGBUILD
|
||||||
|
@ -4192,16 +4268,22 @@ ssize_t nghttp2_session_pack_data(nghttp2_session *session,
|
||||||
size_t datamax,
|
size_t datamax,
|
||||||
nghttp2_private_data *frame)
|
nghttp2_private_data *frame)
|
||||||
{
|
{
|
||||||
/* extra 2 bytes for PAD_HIGH and PAD_LOW. We allocate extra 2 bytes
|
size_t payloadoff;
|
||||||
for padding. Based on the padding length, we adjust the starting
|
ssize_t framelen;
|
||||||
offset of frame data. The starting offset is assigned into
|
|
||||||
|*bufoff_ptr|. */
|
|
||||||
size_t payloadoff = NGHTTP2_FRAME_HEAD_LENGTH + 2;
|
|
||||||
ssize_t framelen = payloadoff + datamax;
|
|
||||||
ssize_t rv;
|
ssize_t rv;
|
||||||
int eof_flags;
|
int eof_flags;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
ssize_t payloadlen;
|
ssize_t payloadlen;
|
||||||
|
ssize_t padded_payloadlen;
|
||||||
|
nghttp2_frame data_frame;
|
||||||
|
|
||||||
|
/* extra 2 bytes for PAD_HIGH and PAD_LOW. We allocate extra 2 bytes
|
||||||
|
for padding. Based on the padding length, we adjust the starting
|
||||||
|
offset of frame data. The starting offset is assigned into
|
||||||
|
|*bufoff_ptr|. */
|
||||||
|
*bufoff_ptr = 2;
|
||||||
|
payloadoff = *bufoff_ptr + NGHTTP2_FRAME_HEAD_LENGTH;
|
||||||
|
framelen = payloadoff + datamax;
|
||||||
|
|
||||||
rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, framelen);
|
rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, framelen);
|
||||||
if(rv != 0) {
|
if(rv != 0) {
|
||||||
|
@ -4226,21 +4308,32 @@ ssize_t nghttp2_session_pack_data(nghttp2_session *session,
|
||||||
frame->hd.flags &= ~(NGHTTP2_FLAG_PAD_HIGH | NGHTTP2_FLAG_PAD_LOW);
|
frame->hd.flags &= ~(NGHTTP2_FLAG_PAD_HIGH | NGHTTP2_FLAG_PAD_LOW);
|
||||||
flags = 0;
|
flags = 0;
|
||||||
|
|
||||||
if(session->padding_boundary && (size_t)payloadlen < datamax) {
|
if(eof_flags) {
|
||||||
rv = nghttp2_frame_add_pad(buf_ptr, buflen_ptr, bufoff_ptr,
|
frame->eof = 1;
|
||||||
&flags, payloadlen, datamax,
|
if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
|
||||||
session->padding_boundary);
|
flags |= NGHTTP2_FLAG_END_STREAM;
|
||||||
if(rv < 0) {
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
frame->padlen = rv;
|
|
||||||
frame->hd.length = payloadlen + rv;
|
|
||||||
} else {
|
|
||||||
*bufoff_ptr = 2;
|
|
||||||
frame->padlen = 0;
|
|
||||||
frame->hd.length = payloadlen;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(&data_frame, 0, sizeof(data_frame));
|
||||||
|
data_frame.hd.length = payloadlen;
|
||||||
|
data_frame.hd.stream_id = frame->hd.stream_id;
|
||||||
|
data_frame.hd.type = NGHTTP2_DATA;
|
||||||
|
data_frame.hd.flags = flags;
|
||||||
|
|
||||||
|
padded_payloadlen = session_call_select_padding(session, &data_frame,
|
||||||
|
datamax);
|
||||||
|
if(nghttp2_is_fatal(padded_payloadlen)) {
|
||||||
|
return padded_payloadlen;
|
||||||
|
}
|
||||||
|
rv = nghttp2_frame_add_pad(buf_ptr, buflen_ptr, bufoff_ptr, &flags,
|
||||||
|
payloadlen, padded_payloadlen - payloadlen);
|
||||||
|
if(nghttp2_is_fatal(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
frame->padlen = padded_payloadlen - payloadlen;
|
||||||
|
frame->hd.length = padded_payloadlen;
|
||||||
|
|
||||||
/* Set PAD flags so that we can supply frame to the callback with
|
/* Set PAD flags so that we can supply frame to the callback with
|
||||||
the correct flags */
|
the correct flags */
|
||||||
frame->hd.flags |= flags;
|
frame->hd.flags |= flags;
|
||||||
|
@ -4248,12 +4341,6 @@ ssize_t nghttp2_session_pack_data(nghttp2_session *session,
|
||||||
memset(*buf_ptr + *bufoff_ptr, 0, NGHTTP2_FRAME_HEAD_LENGTH);
|
memset(*buf_ptr + *bufoff_ptr, 0, NGHTTP2_FRAME_HEAD_LENGTH);
|
||||||
nghttp2_put_uint16be(&(*buf_ptr)[*bufoff_ptr], frame->hd.length);
|
nghttp2_put_uint16be(&(*buf_ptr)[*bufoff_ptr], frame->hd.length);
|
||||||
|
|
||||||
if(eof_flags) {
|
|
||||||
frame->eof = 1;
|
|
||||||
if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
|
|
||||||
flags |= NGHTTP2_FLAG_END_STREAM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(*buf_ptr)[*bufoff_ptr + 3] = flags;
|
(*buf_ptr)[*bufoff_ptr + 3] = flags;
|
||||||
nghttp2_put_uint32be(&(*buf_ptr)[*bufoff_ptr + 4], frame->hd.stream_id);
|
nghttp2_put_uint32be(&(*buf_ptr)[*bufoff_ptr + 4], frame->hd.stream_id);
|
||||||
|
|
||||||
|
|
|
@ -153,8 +153,6 @@ struct nghttp2_session {
|
||||||
size_t num_incoming_streams;
|
size_t num_incoming_streams;
|
||||||
/* The number of bytes allocated for nvbuf */
|
/* The number of bytes allocated for nvbuf */
|
||||||
size_t nvbuflen;
|
size_t nvbuflen;
|
||||||
/* padding alignemnt. See NGHTTP2_OPT_PADDING_BOUNDARY. */
|
|
||||||
size_t padding_boundary;
|
|
||||||
/* Next Stream ID. Made unsigned int to detect >= (1 << 31). */
|
/* Next Stream ID. Made unsigned int to detect >= (1 << 31). */
|
||||||
uint32_t next_stream_id;
|
uint32_t next_stream_id;
|
||||||
/* The largest stream ID received so far */
|
/* The largest stream ID received so far */
|
||||||
|
|
|
@ -66,7 +66,7 @@ const std::string NGHTTPD_SERVER = "nghttpd nghttp2/" NGHTTP2_VERSION;
|
||||||
Config::Config()
|
Config::Config()
|
||||||
: data_ptr(nullptr),
|
: data_ptr(nullptr),
|
||||||
output_upper_thres(1024*1024),
|
output_upper_thres(1024*1024),
|
||||||
padding_boundary(NGHTTP2_PADDING_BOUNDARY),
|
padding_boundary(0),
|
||||||
header_table_size(-1),
|
header_table_size(-1),
|
||||||
port(0),
|
port(0),
|
||||||
verbose(false),
|
verbose(false),
|
||||||
|
@ -362,14 +362,8 @@ int Http2Handler::on_connect()
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
nghttp2_session_callbacks callbacks;
|
nghttp2_session_callbacks callbacks;
|
||||||
nghttp2_opt_set opt_set;
|
|
||||||
|
|
||||||
memset(&opt_set, 0, sizeof(opt_set));
|
|
||||||
opt_set.padding_boundary = sessions_->get_config()->padding_boundary;
|
|
||||||
|
|
||||||
fill_callback(callbacks, sessions_->get_config());
|
fill_callback(callbacks, sessions_->get_config());
|
||||||
r = nghttp2_session_server_new2(&session_, &callbacks, this,
|
r = nghttp2_session_server_new(&session_, &callbacks, this);
|
||||||
NGHTTP2_OPT_PADDING_BOUNDARY, &opt_set);
|
|
||||||
if(r != 0) {
|
if(r != 0) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -931,6 +925,23 @@ int hd_on_frame_send_callback
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
ssize_t select_padding_callback
|
||||||
|
(nghttp2_session *session, const nghttp2_frame *frame, size_t max_payload,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
auto hd = static_cast<Http2Handler*>(user_data);
|
||||||
|
auto bd = hd->get_config()->padding_boundary;
|
||||||
|
if(bd == 0) {
|
||||||
|
return frame->hd.length;
|
||||||
|
}
|
||||||
|
if(frame->hd.length == 0) {
|
||||||
|
return bd;
|
||||||
|
}
|
||||||
|
return std::min(max_payload, (frame->hd.length + bd - 1) / bd * bd);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
int on_data_chunk_recv_callback
|
int on_data_chunk_recv_callback
|
||||||
(nghttp2_session *session, uint8_t flags, int32_t stream_id,
|
(nghttp2_session *session, uint8_t flags, int32_t stream_id,
|
||||||
|
@ -977,6 +988,7 @@ void fill_callback(nghttp2_session_callbacks& callbacks, const Config *config)
|
||||||
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
|
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
|
||||||
callbacks.on_header_callback = on_header_callback;
|
callbacks.on_header_callback = on_header_callback;
|
||||||
callbacks.on_begin_headers_callback = on_begin_headers_callback;
|
callbacks.on_begin_headers_callback = on_begin_headers_callback;
|
||||||
|
callbacks.select_padding_callback = select_padding_callback;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ struct Config {
|
||||||
bool continuation;
|
bool continuation;
|
||||||
Config()
|
Config()
|
||||||
: output_upper_thres(1024*1024),
|
: output_upper_thres(1024*1024),
|
||||||
padding_boundary(NGHTTP2_PADDING_BOUNDARY),
|
padding_boundary(0),
|
||||||
peer_max_concurrent_streams(NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS),
|
peer_max_concurrent_streams(NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS),
|
||||||
header_table_size(-1),
|
header_table_size(-1),
|
||||||
pri(NGHTTP2_PRI_DEFAULT),
|
pri(NGHTTP2_PRI_DEFAULT),
|
||||||
|
@ -716,10 +716,8 @@ struct HttpClient {
|
||||||
}
|
}
|
||||||
nghttp2_opt_set opt_set;
|
nghttp2_opt_set opt_set;
|
||||||
opt_set.peer_max_concurrent_streams = config.peer_max_concurrent_streams;
|
opt_set.peer_max_concurrent_streams = config.peer_max_concurrent_streams;
|
||||||
opt_set.padding_boundary = config.padding_boundary;
|
|
||||||
rv = nghttp2_session_client_new2(&session, callbacks, this,
|
rv = nghttp2_session_client_new2(&session, callbacks, this,
|
||||||
NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS |
|
NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS,
|
||||||
NGHTTP2_OPT_PADDING_BOUNDARY,
|
|
||||||
&opt_set);
|
&opt_set);
|
||||||
if(rv != 0) {
|
if(rv != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -964,14 +962,10 @@ int submit_request
|
||||||
{"accept-encoding", "gzip, deflate"},
|
{"accept-encoding", "gzip, deflate"},
|
||||||
{"user-agent", "nghttp2/" NGHTTP2_VERSION}};
|
{"user-agent", "nghttp2/" NGHTTP2_VERSION}};
|
||||||
if(config.continuation) {
|
if(config.continuation) {
|
||||||
build_headers.emplace_back("continuation-test-1",
|
for(size_t i = 0; i < 8; ++i) {
|
||||||
std::string(4096, '-'));
|
build_headers.emplace_back("continuation-test-" + util::utos(i+1),
|
||||||
build_headers.emplace_back("continuation-test-2",
|
std::string(4096, '-'));
|
||||||
std::string(4096, '-'));
|
}
|
||||||
build_headers.emplace_back("continuation-test-3",
|
|
||||||
std::string(4096, '-'));
|
|
||||||
build_headers.emplace_back("continuation-test-4",
|
|
||||||
std::string(4096, '-'));
|
|
||||||
}
|
}
|
||||||
auto num_initial_headers = build_headers.size();
|
auto num_initial_headers = build_headers.size();
|
||||||
if(req->data_prd) {
|
if(req->data_prd) {
|
||||||
|
@ -1132,6 +1126,22 @@ int before_frame_send_callback
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
ssize_t select_padding_callback
|
||||||
|
(nghttp2_session *session, const nghttp2_frame *frame, size_t max_payload,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
auto bd = config.padding_boundary;
|
||||||
|
if(bd == 0) {
|
||||||
|
return frame->hd.length;
|
||||||
|
}
|
||||||
|
if(frame->hd.length == 0) {
|
||||||
|
return bd;
|
||||||
|
}
|
||||||
|
return std::min(max_payload, (frame->hd.length + bd - 1) / bd * bd);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void check_response_header(nghttp2_session *session, Request* req)
|
void check_response_header(nghttp2_session *session, Request* req)
|
||||||
{
|
{
|
||||||
|
@ -1588,6 +1598,7 @@ int run(char **uris, int n)
|
||||||
}
|
}
|
||||||
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
|
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
|
||||||
callbacks.on_header_callback = on_header_callback;
|
callbacks.on_header_callback = on_header_callback;
|
||||||
|
callbacks.select_padding_callback = select_padding_callback;
|
||||||
|
|
||||||
std::string prev_scheme;
|
std::string prev_scheme;
|
||||||
std::string prev_host;
|
std::string prev_host;
|
||||||
|
|
|
@ -201,8 +201,6 @@ int main(int argc, char* argv[])
|
||||||
test_nghttp2_frame_pack_headers) ||
|
test_nghttp2_frame_pack_headers) ||
|
||||||
!CU_add_test(pSuite, "frame_pack_headers_frame_too_large",
|
!CU_add_test(pSuite, "frame_pack_headers_frame_too_large",
|
||||||
test_nghttp2_frame_pack_headers_frame_too_large) ||
|
test_nghttp2_frame_pack_headers_frame_too_large) ||
|
||||||
!CU_add_test(pSuite, "frame_pack_headers_with_padding",
|
|
||||||
test_nghttp2_frame_pack_headers_with_padding) ||
|
|
||||||
!CU_add_test(pSuite, "frame_pack_priority",
|
!CU_add_test(pSuite, "frame_pack_priority",
|
||||||
test_nghttp2_frame_pack_priority) ||
|
test_nghttp2_frame_pack_priority) ||
|
||||||
!CU_add_test(pSuite, "frame_pack_rst_stream",
|
!CU_add_test(pSuite, "frame_pack_rst_stream",
|
||||||
|
|
|
@ -91,7 +91,7 @@ void test_nghttp2_frame_pack_headers()
|
||||||
1000000007,
|
1000000007,
|
||||||
1 << 20, nva, nvlen);
|
1 << 20, nva, nvlen);
|
||||||
framelen = nghttp2_frame_pack_headers(&buf, &buflen, &bufoff, &frame,
|
framelen = nghttp2_frame_pack_headers(&buf, &buflen, &bufoff, &frame,
|
||||||
&deflater, 0);
|
&deflater);
|
||||||
|
|
||||||
CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf + bufoff,
|
CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf + bufoff,
|
||||||
framelen - bufoff));
|
framelen - bufoff));
|
||||||
|
@ -117,7 +117,7 @@ void test_nghttp2_frame_pack_headers()
|
||||||
/* Next, include PRIORITY flag */
|
/* Next, include PRIORITY flag */
|
||||||
frame.hd.flags |= NGHTTP2_FLAG_PRIORITY;
|
frame.hd.flags |= NGHTTP2_FLAG_PRIORITY;
|
||||||
framelen = nghttp2_frame_pack_headers(&buf, &buflen, &bufoff, &frame,
|
framelen = nghttp2_frame_pack_headers(&buf, &buflen, &bufoff, &frame,
|
||||||
&deflater, 0);
|
&deflater);
|
||||||
|
|
||||||
CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf + bufoff,
|
CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf + bufoff,
|
||||||
framelen - bufoff));
|
framelen - bufoff));
|
||||||
|
@ -173,7 +173,7 @@ void test_nghttp2_frame_pack_headers_frame_too_large(void)
|
||||||
1000000007,
|
1000000007,
|
||||||
0, nva, nvlen);
|
0, nva, nvlen);
|
||||||
framelen = nghttp2_frame_pack_headers(&buf, &buflen, &bufoff, &frame,
|
framelen = nghttp2_frame_pack_headers(&buf, &buflen, &bufoff, &frame,
|
||||||
&deflater, 0);
|
&deflater);
|
||||||
CU_ASSERT_EQUAL(NGHTTP2_ERR_HEADER_COMP, framelen);
|
CU_ASSERT_EQUAL(NGHTTP2_ERR_HEADER_COMP, framelen);
|
||||||
|
|
||||||
nghttp2_frame_headers_free(&frame);
|
nghttp2_frame_headers_free(&frame);
|
||||||
|
@ -184,134 +184,6 @@ void test_nghttp2_frame_pack_headers_frame_too_large(void)
|
||||||
nghttp2_hd_deflate_free(&deflater);
|
nghttp2_hd_deflate_free(&deflater);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void test_nghttp2_frame_pack_headers_with_padding(void)
|
|
||||||
{
|
|
||||||
nghttp2_hd_deflater deflater;
|
|
||||||
nghttp2_hd_inflater inflater;
|
|
||||||
nghttp2_headers frame, oframe;
|
|
||||||
uint8_t *buf = NULL;
|
|
||||||
size_t buflen = 0;
|
|
||||||
size_t bufoff;
|
|
||||||
ssize_t framelen;
|
|
||||||
nghttp2_nv *nva;
|
|
||||||
ssize_t nvlen;
|
|
||||||
nva_out out;
|
|
||||||
size_t trail_padlen;
|
|
||||||
size_t header_blocklen;
|
|
||||||
|
|
||||||
nva_out_init(&out);
|
|
||||||
nghttp2_hd_deflate_init(&deflater, NGHTTP2_HD_SIDE_REQUEST);
|
|
||||||
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
|
|
||||||
|
|
||||||
/* Payload length is 0, so no padding */
|
|
||||||
nghttp2_frame_headers_init(&frame,
|
|
||||||
NGHTTP2_FLAG_END_STREAM|NGHTTP2_FLAG_END_HEADERS,
|
|
||||||
1000000007, NGHTTP2_PRI_DEFAULT, NULL, 0);
|
|
||||||
framelen = nghttp2_frame_pack_headers(&buf, &buflen, &bufoff, &frame,
|
|
||||||
&deflater, 128);
|
|
||||||
|
|
||||||
CU_ASSERT(2 == bufoff);
|
|
||||||
CU_ASSERT((ssize_t)bufoff + NGHTTP2_FRAME_HEAD_LENGTH == framelen);
|
|
||||||
|
|
||||||
CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf + bufoff,
|
|
||||||
framelen - bufoff));
|
|
||||||
check_frame_header(framelen - bufoff - NGHTTP2_FRAME_HEAD_LENGTH,
|
|
||||||
NGHTTP2_HEADERS,
|
|
||||||
NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS,
|
|
||||||
1000000007, &oframe.hd);
|
|
||||||
|
|
||||||
CU_ASSERT(NGHTTP2_PRI_DEFAULT == oframe.pri);
|
|
||||||
nghttp2_frame_headers_free(&oframe);
|
|
||||||
|
|
||||||
/* Include priroty */
|
|
||||||
frame.hd.flags |= NGHTTP2_FLAG_PRIORITY;
|
|
||||||
frame.pri = 1000000009;
|
|
||||||
bufoff = 0;
|
|
||||||
|
|
||||||
framelen = nghttp2_frame_pack_headers(&buf, &buflen, &bufoff, &frame,
|
|
||||||
&deflater, 128);
|
|
||||||
|
|
||||||
CU_ASSERT(1 == bufoff);
|
|
||||||
CU_ASSERT((ssize_t)bufoff + NGHTTP2_FRAME_HEAD_LENGTH + 128 == framelen);
|
|
||||||
|
|
||||||
CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf + bufoff,
|
|
||||||
framelen - bufoff));
|
|
||||||
check_frame_header(framelen - bufoff - NGHTTP2_FRAME_HEAD_LENGTH,
|
|
||||||
NGHTTP2_HEADERS,
|
|
||||||
NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS |
|
|
||||||
NGHTTP2_FLAG_PRIORITY | NGHTTP2_FLAG_PAD_LOW,
|
|
||||||
1000000007, &oframe.hd);
|
|
||||||
|
|
||||||
CU_ASSERT(1000000009 == oframe.pri);
|
|
||||||
nghttp2_frame_headers_free(&oframe);
|
|
||||||
|
|
||||||
/* padding more than 256 */
|
|
||||||
bufoff = 0;
|
|
||||||
|
|
||||||
framelen = nghttp2_frame_pack_headers(&buf, &buflen, &bufoff, &frame,
|
|
||||||
&deflater, 512);
|
|
||||||
|
|
||||||
CU_ASSERT(0 == bufoff);
|
|
||||||
CU_ASSERT(NGHTTP2_FRAME_HEAD_LENGTH + 512 == framelen);
|
|
||||||
|
|
||||||
CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf + bufoff,
|
|
||||||
framelen - bufoff));
|
|
||||||
check_frame_header(framelen - bufoff - NGHTTP2_FRAME_HEAD_LENGTH,
|
|
||||||
NGHTTP2_HEADERS,
|
|
||||||
NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS |
|
|
||||||
NGHTTP2_FLAG_PRIORITY |
|
|
||||||
NGHTTP2_FLAG_PAD_HIGH | NGHTTP2_FLAG_PAD_LOW,
|
|
||||||
1000000007, &oframe.hd);
|
|
||||||
|
|
||||||
CU_ASSERT(1000000009 == oframe.pri);
|
|
||||||
nghttp2_frame_headers_free(&oframe);
|
|
||||||
|
|
||||||
/* Include priority + headers */
|
|
||||||
nva = headers();
|
|
||||||
nvlen = HEADERS_LENGTH;
|
|
||||||
frame.nva = nva;
|
|
||||||
frame.nvlen = nvlen;
|
|
||||||
bufoff = 0;
|
|
||||||
|
|
||||||
framelen = nghttp2_frame_pack_headers(&buf, &buflen, &bufoff, &frame,
|
|
||||||
&deflater, 512);
|
|
||||||
|
|
||||||
CU_ASSERT(0 == bufoff);
|
|
||||||
CU_ASSERT(NGHTTP2_FRAME_HEAD_LENGTH + 512 == framelen);
|
|
||||||
|
|
||||||
CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf + bufoff,
|
|
||||||
framelen - bufoff));
|
|
||||||
check_frame_header(framelen - bufoff - NGHTTP2_FRAME_HEAD_LENGTH,
|
|
||||||
NGHTTP2_HEADERS,
|
|
||||||
NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS |
|
|
||||||
NGHTTP2_FLAG_PRIORITY |
|
|
||||||
NGHTTP2_FLAG_PAD_HIGH | NGHTTP2_FLAG_PAD_LOW,
|
|
||||||
1000000007, &oframe.hd);
|
|
||||||
|
|
||||||
CU_ASSERT(1000000009 == oframe.pri);
|
|
||||||
trail_padlen = (buf[NGHTTP2_FRAME_HEAD_LENGTH] << 8) |
|
|
||||||
buf[NGHTTP2_FRAME_HEAD_LENGTH + 1];
|
|
||||||
|
|
||||||
header_blocklen = framelen - NGHTTP2_FRAME_HEAD_LENGTH - 2 - 4
|
|
||||||
- trail_padlen;
|
|
||||||
CU_ASSERT((ssize_t)header_blocklen ==
|
|
||||||
inflate_hd(&inflater, &out,
|
|
||||||
buf + NGHTTP2_FRAME_HEAD_LENGTH + 2 + 4,
|
|
||||||
header_blocklen));
|
|
||||||
|
|
||||||
CU_ASSERT(nvlen == (ssize_t)out.nvlen);
|
|
||||||
assert_nv_equal(nva, out.nva, nvlen);
|
|
||||||
|
|
||||||
nghttp2_frame_headers_free(&oframe);
|
|
||||||
nva_out_reset(&out);
|
|
||||||
|
|
||||||
free(buf);
|
|
||||||
nghttp2_frame_headers_free(&frame);
|
|
||||||
nghttp2_hd_inflate_free(&inflater);
|
|
||||||
nghttp2_hd_deflate_free(&deflater);
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_nghttp2_frame_pack_priority(void)
|
void test_nghttp2_frame_pack_priority(void)
|
||||||
{
|
{
|
||||||
nghttp2_priority frame, oframe;
|
nghttp2_priority frame, oframe;
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
|
|
||||||
void test_nghttp2_frame_pack_headers(void);
|
void test_nghttp2_frame_pack_headers(void);
|
||||||
void test_nghttp2_frame_pack_headers_frame_too_large(void);
|
void test_nghttp2_frame_pack_headers_frame_too_large(void);
|
||||||
void test_nghttp2_frame_pack_headers_with_padding(void);
|
|
||||||
void test_nghttp2_frame_pack_priority(void);
|
void test_nghttp2_frame_pack_priority(void);
|
||||||
void test_nghttp2_frame_pack_rst_stream(void);
|
void test_nghttp2_frame_pack_rst_stream(void);
|
||||||
void test_nghttp2_frame_pack_settings(void);
|
void test_nghttp2_frame_pack_settings(void);
|
||||||
|
|
|
@ -72,6 +72,7 @@ typedef struct {
|
||||||
int begin_headers_cb_called;
|
int begin_headers_cb_called;
|
||||||
nghttp2_nv nv;
|
nghttp2_nv nv;
|
||||||
size_t data_chunk_len;
|
size_t data_chunk_len;
|
||||||
|
size_t padding_boundary;
|
||||||
} my_user_data;
|
} my_user_data;
|
||||||
|
|
||||||
static void scripted_data_feed_init(scripted_data_feed *df,
|
static void scripted_data_feed_init(scripted_data_feed *df,
|
||||||
|
@ -202,6 +203,17 @@ static int pause_on_data_chunk_recv_callback(nghttp2_session *session,
|
||||||
return NGHTTP2_ERR_PAUSE;
|
return NGHTTP2_ERR_PAUSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t select_padding_callback(nghttp2_session *session,
|
||||||
|
const nghttp2_frame *frame,
|
||||||
|
size_t max_payloadlen,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
my_user_data *ud = (my_user_data*)user_data;
|
||||||
|
return nghttp2_min(max_payloadlen,
|
||||||
|
(frame->hd.length + ud->padding_boundary - 1)
|
||||||
|
/ ud->padding_boundary * ud->padding_boundary);
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t fixed_length_data_source_read_callback
|
static ssize_t fixed_length_data_source_read_callback
|
||||||
(nghttp2_session *session, int32_t stream_id,
|
(nghttp2_session *session, int32_t stream_id,
|
||||||
uint8_t *buf, size_t len, int *eof,
|
uint8_t *buf, size_t len, int *eof,
|
||||||
|
@ -358,7 +370,7 @@ void test_nghttp2_session_recv(void)
|
||||||
1, NGHTTP2_PRI_DEFAULT, nva, nvlen);
|
1, NGHTTP2_PRI_DEFAULT, nva, nvlen);
|
||||||
framelen = nghttp2_frame_pack_headers(&framedata, &framedatalen, &bufoff,
|
framelen = nghttp2_frame_pack_headers(&framedata, &framedatalen, &bufoff,
|
||||||
&frame.headers,
|
&frame.headers,
|
||||||
&deflater, 0);
|
&deflater);
|
||||||
|
|
||||||
scripted_data_feed_init(&df, framedata + bufoff, framelen - bufoff);
|
scripted_data_feed_init(&df, framedata + bufoff, framelen - bufoff);
|
||||||
/* Send 1 byte per each read */
|
/* Send 1 byte per each read */
|
||||||
|
@ -378,7 +390,7 @@ void test_nghttp2_session_recv(void)
|
||||||
5, NGHTTP2_PRI_DEFAULT, NULL, 0);
|
5, NGHTTP2_PRI_DEFAULT, NULL, 0);
|
||||||
framelen = nghttp2_frame_pack_headers(&framedata, &framedatalen, &bufoff,
|
framelen = nghttp2_frame_pack_headers(&framedata, &framedatalen, &bufoff,
|
||||||
&frame.headers,
|
&frame.headers,
|
||||||
&deflater, 0);
|
&deflater);
|
||||||
|
|
||||||
nghttp2_frame_headers_free(&frame.headers);
|
nghttp2_frame_headers_free(&frame.headers);
|
||||||
|
|
||||||
|
@ -440,7 +452,7 @@ void test_nghttp2_session_recv_invalid_stream_id(void)
|
||||||
NGHTTP2_PRI_DEFAULT, NULL, 0);
|
NGHTTP2_PRI_DEFAULT, NULL, 0);
|
||||||
framelen = nghttp2_frame_pack_headers(&framedata, &framedatalen, &bufoff,
|
framelen = nghttp2_frame_pack_headers(&framedata, &framedatalen, &bufoff,
|
||||||
&frame.headers,
|
&frame.headers,
|
||||||
&deflater, 0);
|
&deflater);
|
||||||
|
|
||||||
scripted_data_feed_init(&df, framedata + bufoff, framelen - bufoff);
|
scripted_data_feed_init(&df, framedata + bufoff, framelen - bufoff);
|
||||||
nghttp2_frame_headers_free(&frame.headers);
|
nghttp2_frame_headers_free(&frame.headers);
|
||||||
|
@ -485,7 +497,7 @@ void test_nghttp2_session_recv_invalid_frame(void)
|
||||||
NGHTTP2_PRI_DEFAULT, nva, nvlen);
|
NGHTTP2_PRI_DEFAULT, nva, nvlen);
|
||||||
framelen = nghttp2_frame_pack_headers(&framedata, &framedatalen, &bufoff,
|
framelen = nghttp2_frame_pack_headers(&framedata, &framedatalen, &bufoff,
|
||||||
&frame.headers,
|
&frame.headers,
|
||||||
&deflater, 0);
|
&deflater);
|
||||||
|
|
||||||
scripted_data_feed_init(&df, framedata + bufoff, framelen - bufoff);
|
scripted_data_feed_init(&df, framedata + bufoff, framelen - bufoff);
|
||||||
|
|
||||||
|
@ -687,7 +699,7 @@ void test_nghttp2_session_recv_continuation(void)
|
||||||
framedatalen = nghttp2_frame_pack_headers(&framedata, &framedatacap,
|
framedatalen = nghttp2_frame_pack_headers(&framedata, &framedatacap,
|
||||||
&bufoff,
|
&bufoff,
|
||||||
&frame.headers,
|
&frame.headers,
|
||||||
&deflater, 0);
|
&deflater);
|
||||||
nghttp2_frame_headers_free(&frame.headers);
|
nghttp2_frame_headers_free(&frame.headers);
|
||||||
|
|
||||||
memcpy(data, framedata + bufoff, 9);
|
memcpy(data, framedata + bufoff, 9);
|
||||||
|
@ -742,7 +754,7 @@ void test_nghttp2_session_recv_continuation(void)
|
||||||
1, NGHTTP2_PRI_DEFAULT, nva, nvlen);
|
1, NGHTTP2_PRI_DEFAULT, nva, nvlen);
|
||||||
framedatalen = nghttp2_frame_pack_headers(&framedata, &framedatacap, &bufoff,
|
framedatalen = nghttp2_frame_pack_headers(&framedata, &framedatacap, &bufoff,
|
||||||
&frame.headers,
|
&frame.headers,
|
||||||
&deflater, 0);
|
&deflater);
|
||||||
nghttp2_frame_headers_free(&frame.headers);
|
nghttp2_frame_headers_free(&frame.headers);
|
||||||
memcpy(data, framedata + bufoff, framedatalen - bufoff);
|
memcpy(data, framedata + bufoff, framedatalen - bufoff);
|
||||||
datalen = framedatalen - bufoff;
|
datalen = framedatalen - bufoff;
|
||||||
|
@ -812,7 +824,7 @@ void test_nghttp2_session_continue(void)
|
||||||
1, NGHTTP2_PRI_DEFAULT, nva, nvlen);
|
1, NGHTTP2_PRI_DEFAULT, nva, nvlen);
|
||||||
framelen1 = nghttp2_frame_pack_headers(&framedata, &framedatalen, &bufoff,
|
framelen1 = nghttp2_frame_pack_headers(&framedata, &framedatalen, &bufoff,
|
||||||
&frame.headers,
|
&frame.headers,
|
||||||
&deflater, 0);
|
&deflater);
|
||||||
nghttp2_frame_headers_free(&frame.headers);
|
nghttp2_frame_headers_free(&frame.headers);
|
||||||
|
|
||||||
memcpy(buffer, framedata + bufoff, framelen1 - bufoff);
|
memcpy(buffer, framedata + bufoff, framelen1 - bufoff);
|
||||||
|
@ -823,7 +835,7 @@ void test_nghttp2_session_continue(void)
|
||||||
3, NGHTTP2_PRI_DEFAULT, nva, nvlen);
|
3, NGHTTP2_PRI_DEFAULT, nva, nvlen);
|
||||||
framelen2 = nghttp2_frame_pack_headers(&framedata, &framedatalen, &bufoff,
|
framelen2 = nghttp2_frame_pack_headers(&framedata, &framedatalen, &bufoff,
|
||||||
&frame.headers,
|
&frame.headers,
|
||||||
&deflater, 0);
|
&deflater);
|
||||||
nghttp2_frame_headers_free(&frame.headers);
|
nghttp2_frame_headers_free(&frame.headers);
|
||||||
|
|
||||||
memcpy(buffer + framelen1, framedata + bufoff, framelen2 - bufoff);
|
memcpy(buffer + framelen1, framedata + bufoff, framelen2 - bufoff);
|
||||||
|
@ -963,7 +975,6 @@ void test_nghttp2_session_add_frame(void)
|
||||||
acc.length = 0;
|
acc.length = 0;
|
||||||
user_data.acc = &acc;
|
user_data.acc = &acc;
|
||||||
CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &user_data));
|
CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &user_data));
|
||||||
session_disable_pad(session);
|
|
||||||
|
|
||||||
frame = malloc(sizeof(nghttp2_frame));
|
frame = malloc(sizeof(nghttp2_frame));
|
||||||
nvlen = nghttp2_nv_array_copy(&nva, nv, ARRLEN(nv));
|
nvlen = nghttp2_nv_array_copy(&nva, nv, ARRLEN(nv));
|
||||||
|
@ -1488,11 +1499,17 @@ void test_nghttp2_session_on_push_promise_received(void)
|
||||||
CU_ASSERT(0 == user_data.begin_headers_cb_called);
|
CU_ASSERT(0 == user_data.begin_headers_cb_called);
|
||||||
CU_ASSERT(NULL == nghttp2_session_get_stream(session, 8));
|
CU_ASSERT(NULL == nghttp2_session_get_stream(session, 8));
|
||||||
item = nghttp2_session_get_next_ob_item(session);
|
item = nghttp2_session_get_next_ob_item(session);
|
||||||
CU_ASSERT(NGHTTP2_RST_STREAM == OB_CTRL_TYPE(item));
|
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
|
||||||
CU_ASSERT(8 == OB_CTRL(item)->hd.stream_id);
|
CU_ASSERT(0 == OB_CTRL(item)->hd.stream_id);
|
||||||
CU_ASSERT(NGHTTP2_REFUSED_STREAM == OB_CTRL(item)->rst_stream.error_code);
|
CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == OB_CTRL(item)->goaway.error_code);
|
||||||
CU_ASSERT(0 == nghttp2_session_send(session));
|
CU_ASSERT(0 == nghttp2_session_send(session));
|
||||||
|
|
||||||
|
nghttp2_session_del(session);
|
||||||
|
|
||||||
|
nghttp2_session_client_new(&session, &callbacks, &user_data);
|
||||||
|
memset(session->iframe.buf, 0, 4);
|
||||||
|
session->iframe.buflen = 4;
|
||||||
|
|
||||||
/* Same ID twice */
|
/* Same ID twice */
|
||||||
stream->state = NGHTTP2_STREAM_OPENING;
|
stream->state = NGHTTP2_STREAM_OPENING;
|
||||||
|
|
||||||
|
@ -2182,7 +2199,7 @@ void test_nghttp2_submit_request_without_data(void)
|
||||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||||
callbacks.send_callback = accumulator_send_callback;
|
callbacks.send_callback = accumulator_send_callback;
|
||||||
CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
|
CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
|
||||||
session_disable_pad(session);
|
|
||||||
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
|
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
|
||||||
CU_ASSERT(0 == nghttp2_submit_request(session, NGHTTP2_PRI_DEFAULT,
|
CU_ASSERT(0 == nghttp2_submit_request(session, NGHTTP2_PRI_DEFAULT,
|
||||||
nva, ARRLEN(nva), &data_prd, NULL));
|
nva, ARRLEN(nva), &data_prd, NULL));
|
||||||
|
@ -2254,7 +2271,7 @@ void test_nghttp2_submit_response_without_data(void)
|
||||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||||
callbacks.send_callback = accumulator_send_callback;
|
callbacks.send_callback = accumulator_send_callback;
|
||||||
CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
|
CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
|
||||||
session_disable_pad(session);
|
|
||||||
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_RESPONSE);
|
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_RESPONSE);
|
||||||
nghttp2_session_open_stream(session, 1, NGHTTP2_FLAG_END_STREAM,
|
nghttp2_session_open_stream(session, 1, NGHTTP2_FLAG_END_STREAM,
|
||||||
NGHTTP2_PRI_DEFAULT,
|
NGHTTP2_PRI_DEFAULT,
|
||||||
|
@ -2426,7 +2443,7 @@ void test_nghttp2_submit_headers(void)
|
||||||
callbacks.on_frame_send_callback = on_frame_send_callback;
|
callbacks.on_frame_send_callback = on_frame_send_callback;
|
||||||
|
|
||||||
CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
|
CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
|
||||||
session_disable_pad(session);
|
|
||||||
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
|
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
|
||||||
CU_ASSERT(0 == nghttp2_submit_headers(session,
|
CU_ASSERT(0 == nghttp2_submit_headers(session,
|
||||||
NGHTTP2_FLAG_END_STREAM,
|
NGHTTP2_FLAG_END_STREAM,
|
||||||
|
@ -3867,10 +3884,13 @@ void test_nghttp2_session_pack_data_with_padding(void)
|
||||||
memset(&callbacks, 0, sizeof(callbacks));
|
memset(&callbacks, 0, sizeof(callbacks));
|
||||||
callbacks.send_callback = block_count_send_callback;
|
callbacks.send_callback = block_count_send_callback;
|
||||||
callbacks.on_frame_send_callback = on_frame_send_callback;
|
callbacks.on_frame_send_callback = on_frame_send_callback;
|
||||||
|
callbacks.select_padding_callback = select_padding_callback;
|
||||||
|
|
||||||
data_prd.read_callback = fixed_length_data_source_read_callback;
|
data_prd.read_callback = fixed_length_data_source_read_callback;
|
||||||
|
|
||||||
nghttp2_session_client_new(&session, &callbacks, &ud);
|
nghttp2_session_client_new(&session, &callbacks, &ud);
|
||||||
session->padding_boundary = 512;
|
|
||||||
|
ud.padding_boundary = 512;
|
||||||
|
|
||||||
nghttp2_submit_request(session, NGHTTP2_PRI_DEFAULT, NULL, 0, &data_prd,
|
nghttp2_submit_request(session, NGHTTP2_PRI_DEFAULT, NULL, 0, &data_prd,
|
||||||
NULL);
|
NULL);
|
||||||
|
@ -3881,7 +3901,8 @@ void test_nghttp2_session_pack_data_with_padding(void)
|
||||||
CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
|
CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
|
||||||
|
|
||||||
frame = OB_DATA(session->aob.item);
|
frame = OB_DATA(session->aob.item);
|
||||||
CU_ASSERT(session->padding_boundary - datalen == frame->padlen);
|
|
||||||
|
CU_ASSERT(ud.padding_boundary - datalen == frame->padlen);
|
||||||
CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PAD_LOW);
|
CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PAD_LOW);
|
||||||
CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PAD_HIGH);
|
CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PAD_HIGH);
|
||||||
|
|
||||||
|
@ -3896,6 +3917,8 @@ void test_nghttp2_session_pack_data_with_padding(void)
|
||||||
/* Check without PAD_HIGH */
|
/* Check without PAD_HIGH */
|
||||||
nghttp2_session_client_new(&session, &callbacks, &ud);
|
nghttp2_session_client_new(&session, &callbacks, &ud);
|
||||||
|
|
||||||
|
ud.padding_boundary = 64;
|
||||||
|
|
||||||
nghttp2_submit_request(session, NGHTTP2_PRI_DEFAULT, NULL, 0, &data_prd,
|
nghttp2_submit_request(session, NGHTTP2_PRI_DEFAULT, NULL, 0, &data_prd,
|
||||||
NULL);
|
NULL);
|
||||||
ud.block_count = 1;
|
ud.block_count = 1;
|
||||||
|
@ -3905,7 +3928,7 @@ void test_nghttp2_session_pack_data_with_padding(void)
|
||||||
CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
|
CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
|
||||||
|
|
||||||
frame = OB_DATA(session->aob.item);
|
frame = OB_DATA(session->aob.item);
|
||||||
CU_ASSERT((frame->padlen + datalen) % session->padding_boundary == 0);
|
CU_ASSERT((frame->padlen + datalen) % ud.padding_boundary == 0);
|
||||||
CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PAD_LOW);
|
CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PAD_LOW);
|
||||||
CU_ASSERT(0 == (frame->hd.flags & NGHTTP2_FLAG_PAD_HIGH));
|
CU_ASSERT(0 == (frame->hd.flags & NGHTTP2_FLAG_PAD_HIGH));
|
||||||
|
|
||||||
|
|
|
@ -163,8 +163,3 @@ ssize_t inflate_hd(nghttp2_hd_inflater *inflater, nva_out *out,
|
||||||
nghttp2_hd_inflate_end_headers(inflater);
|
nghttp2_hd_inflate_end_headers(inflater);
|
||||||
return initial - buflen;
|
return initial - buflen;
|
||||||
}
|
}
|
||||||
|
|
||||||
void session_disable_pad(nghttp2_session *session)
|
|
||||||
{
|
|
||||||
session->pad_alignment = 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
# include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include "nghttp2_session.h"
|
|
||||||
#include "nghttp2_frame.h"
|
#include "nghttp2_frame.h"
|
||||||
#include "nghttp2_hd.h"
|
#include "nghttp2_hd.h"
|
||||||
|
|
||||||
|
@ -76,6 +75,4 @@ void add_out(nva_out *out, nghttp2_nv *nv);
|
||||||
ssize_t inflate_hd(nghttp2_hd_inflater *inflater, nva_out *out,
|
ssize_t inflate_hd(nghttp2_hd_inflater *inflater, nva_out *out,
|
||||||
uint8_t *buf, size_t buflen);
|
uint8_t *buf, size_t buflen);
|
||||||
|
|
||||||
void session_disable_pad(nghttp2_session *session);
|
|
||||||
|
|
||||||
#endif /* NGHTTP2_TEST_HELPER_H */
|
#endif /* NGHTTP2_TEST_HELPER_H */
|
||||||
|
|
Loading…
Reference in New Issue