Implement padding for HEADERS and CONTINUATION

This commit is contained in:
Tatsuhiro Tsujikawa 2014-02-09 00:35:21 +09:00
parent 10feab02e8
commit 1db2195389
14 changed files with 453 additions and 199 deletions

View File

@ -151,9 +151,9 @@ typedef struct {
* @macro * @macro
* *
* The default value of DATA padding alignment. See * The default value of DATA padding alignment. See
* :member:`NGHTTP2_OPT_DATA_PAD_ALIGNMENT`. * :member:`NGHTTP2_OPT_PAD_ALIGNMENT`.
*/ */
#define NGHTTP2_DATA_PAD_ALIGNMENT 256 #define NGHTTP2_PAD_ALIGNMENT 256
/** /**
* @enum * @enum
@ -655,6 +655,11 @@ typedef struct {
* The frame header. * The frame header.
*/ */
nghttp2_frame_hd hd; nghttp2_frame_hd hd;
/**
* The length of the padding in this frame. This includes PAD_HIGH
* and PAD_LOW.
*/
size_t padlen;
/** /**
* The name/value pairs. * The name/value pairs.
*/ */
@ -746,6 +751,11 @@ typedef struct {
* The frame header. * The frame header.
*/ */
nghttp2_frame_hd hd; nghttp2_frame_hd hd;
/**
* The length of the padding in this frame. This includes PAD_HIGH
* and PAD_LOW.
*/
size_t padlen;
/** /**
* The name/value pairs. * The name/value pairs.
*/ */
@ -1324,13 +1334,14 @@ typedef enum {
*/ */
NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS = 1 << 2, NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS = 1 << 2,
/** /**
* This option specifies the alignment of padding in DATA frame. If * This option specifies the alignment of padding in frame
* this option is set to N, padding is added to DATA payload so that * payload. If this option is set to N, padding is added to frame
* its payload length is divisible by N. Due to flow control, * payload so that its payload length is divisible by N. For DATA
* padding is not always added according to this alignment. The * frame, due to flow control, padding is not always added according
* option value must be greater than or equal to 8. * to this alignment. The option value must be greater than or equal
* to 8.
*/ */
NGHTTP2_OPT_DATA_PAD_ALIGNMENT = 1 << 3 NGHTTP2_OPT_PAD_ALIGNMENT = 1 << 3
} nghttp2_opt; } nghttp2_opt;
/** /**
@ -1352,9 +1363,9 @@ typedef struct {
*/ */
uint8_t no_auto_connection_window_update; uint8_t no_auto_connection_window_update;
/** /**
* :enum:`NGHTTP2_OPT_DATA_PAD_ALIGNMENT` * :enum:`NGHTTP2_OPT_PAD_ALIGNMENT`
*/ */
uint16_t data_pad_alignment; uint16_t pad_alignment;
} nghttp2_opt_set; } nghttp2_opt_set;
/** /**

View File

@ -193,9 +193,9 @@ void nghttp2_frame_data_init(nghttp2_data *frame, nghttp2_private_data *pdata)
} }
} }
size_t nghttp2_frame_data_trail_padlen(nghttp2_data *frame) size_t nghttp2_frame_trail_padlen(nghttp2_frame *frame, size_t padlen)
{ {
return frame->padlen return padlen
- ((frame->hd.flags & NGHTTP2_FLAG_PAD_HIGH) > 0) - ((frame->hd.flags & NGHTTP2_FLAG_PAD_HIGH) > 0)
- ((frame->hd.flags & NGHTTP2_FLAG_PAD_LOW) > 0); - ((frame->hd.flags & NGHTTP2_FLAG_PAD_LOW) > 0);
} }
@ -214,19 +214,6 @@ void nghttp2_frame_private_data_init(nghttp2_private_data *frame,
void nghttp2_frame_private_data_free(nghttp2_private_data *frame) void nghttp2_frame_private_data_free(nghttp2_private_data *frame)
{} {}
/*
* Returns the offset of the name/header block in the HEADERS frame,
* including frame header length.
*/
static size_t headers_nv_offset(nghttp2_headers *frame)
{
if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
return NGHTTP2_FRAME_HEAD_LENGTH + 4;
} else {
return NGHTTP2_FRAME_HEAD_LENGTH;
}
}
size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame) size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame)
{ {
if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) { if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
@ -238,23 +225,41 @@ size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame)
ssize_t nghttp2_frame_pack_headers(uint8_t **buf_ptr, ssize_t nghttp2_frame_pack_headers(uint8_t **buf_ptr,
size_t *buflen_ptr, size_t *buflen_ptr,
size_t *bufoff_ptr,
nghttp2_headers *frame, nghttp2_headers *frame,
nghttp2_hd_deflater *deflater) nghttp2_hd_deflater *deflater,
size_t align)
{ {
ssize_t framelen; size_t payloadoff = NGHTTP2_FRAME_HEAD_LENGTH + 2;
size_t nv_offset = headers_nv_offset(frame); size_t nv_offset =
payloadoff + nghttp2_frame_headers_payload_nv_offset(frame);
ssize_t rv; ssize_t rv;
size_t payloadlen;
rv = nghttp2_hd_deflate_hd(deflater, buf_ptr, buflen_ptr, nv_offset, rv = nghttp2_hd_deflate_hd(deflater, buf_ptr, buflen_ptr, nv_offset,
frame->nva, frame->nvlen); frame->nva, frame->nvlen);
if(rv < 0) { if(rv < 0) {
return rv; return rv;
} }
framelen = rv + nv_offset;
if(NGHTTP2_FRAME_HEAD_LENGTH + NGHTTP2_MAX_FRAME_LENGTH < rv + nv_offset) { payloadlen = nghttp2_frame_headers_payload_nv_offset(frame) + rv;
frame->hd.length = NGHTTP2_MAX_FRAME_LENGTH;
frame->hd.flags &= ~NGHTTP2_FLAG_END_HEADERS; if(align > 0) {
ssize_t padlen;
padlen = nghttp2_frame_add_pad(buf_ptr, buflen_ptr, bufoff_ptr,
&frame->hd.flags,
payloadlen,
payloadlen + align,
align);
if(padlen < 0) {
return padlen;
}
frame->padlen = padlen;
frame->hd.length = payloadlen + padlen;
} else { } else {
frame->hd.length = framelen - NGHTTP2_FRAME_HEAD_LENGTH; *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 */
@ -262,13 +267,21 @@ ssize_t nghttp2_frame_pack_headers(uint8_t **buf_ptr,
if(rv < 0) { if(rv < 0) {
return rv; return rv;
} }
memset(*buf_ptr, 0, nv_offset); memset(*buf_ptr + *bufoff_ptr, 0, NGHTTP2_FRAME_HEAD_LENGTH);
/* pack ctrl header after length is determined */ /* pack ctrl header after length is determined */
nghttp2_frame_pack_frame_hd(*buf_ptr, &frame->hd); if(NGHTTP2_FRAME_HEAD_LENGTH + NGHTTP2_MAX_FRAME_LENGTH < rv + nv_offset) {
if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) { /* Needs CONTINUATION */
nghttp2_put_uint32be(&(*buf_ptr)[8], frame->pri); nghttp2_frame_hd hd = frame->hd;
hd.flags &= ~(NGHTTP2_FLAG_END_HEADERS |
NGHTTP2_FLAG_PAD_HIGH | NGHTTP2_FLAG_PAD_LOW);
nghttp2_frame_pack_frame_hd(*buf_ptr + *bufoff_ptr, &hd);
} else {
nghttp2_frame_pack_frame_hd(*buf_ptr + *bufoff_ptr, &frame->hd);
} }
return framelen; if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
nghttp2_put_uint32be(&(*buf_ptr)[payloadoff], frame->pri);
}
return frame->hd.length + NGHTTP2_FRAME_HEAD_LENGTH + *bufoff_ptr;
} }
int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame, int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
@ -276,7 +289,6 @@ int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
size_t payloadlen) size_t payloadlen)
{ {
if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) { if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
assert(payloadlen == 4);
frame->pri = nghttp2_get_uint32(payload) & NGHTTP2_PRIORITY_MASK; frame->pri = nghttp2_get_uint32(payload) & NGHTTP2_PRIORITY_MASK;
} else { } else {
frame->pri = NGHTTP2_PRI_DEFAULT; frame->pri = NGHTTP2_PRI_DEFAULT;
@ -660,19 +672,23 @@ ssize_t nghttp2_frame_add_pad(uint8_t **buf_ptr, size_t *buflen_ptr,
payloadmax); payloadmax);
size_t padlen = nextlen - payloadlen; size_t padlen = nextlen - payloadlen;
size_t trail_padlen = 0; size_t trail_padlen = 0;
size_t headoff = 2; /* extra 2 bytes for PAD_HIGH and PAD_LOW. */
size_t trail_padoff = headoff + NGHTTP2_FRAME_HEAD_LENGTH + payloadlen; size_t trail_padoff = 2 + NGHTTP2_FRAME_HEAD_LENGTH + payloadlen;
if(padlen > 257) { if(padlen > 257) {
headoff = 0; *bufoff_ptr = 0;
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; (*buf_ptr)[NGHTTP2_FRAME_HEAD_LENGTH] = trail_padlen >> 8;
(*buf_ptr)[NGHTTP2_FRAME_HEAD_LENGTH + 1] = trail_padlen & 0xff; (*buf_ptr)[NGHTTP2_FRAME_HEAD_LENGTH + 1] = trail_padlen & 0xff;
} else if(padlen > 0) { } else if(padlen > 0) {
headoff = 1; *bufoff_ptr = 1;
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)[NGHTTP2_FRAME_HEAD_LENGTH + 1] = trail_padlen;
} else {
*bufoff_ptr = 2;
return 0;
} }
rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr,
@ -682,7 +698,6 @@ ssize_t nghttp2_frame_add_pad(uint8_t **buf_ptr, size_t *buflen_ptr,
} }
memset((*buf_ptr) + trail_padoff, 0, trail_padlen); memset((*buf_ptr) + trail_padoff, 0, trail_padlen);
*bufoff_ptr = headoff;
return padlen; return padlen;
} }

View File

@ -104,14 +104,21 @@ size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame);
* expansion occurred, memory previously pointed by |*buf_ptr| may * expansion occurred, memory previously pointed by |*buf_ptr| may
* 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
* |*bufoff_ptr|.
*
* The |align| is used as padding alignment. If the |align| 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
* NGHTTP2_MAX_FRAME_LENGTH, payload data is still serialized as is, * NGHTTP2_MAX_FRAME_LENGTH, payload data is still serialized as is,
* but frame->hd.length is set to NGHTTP2_MAX_FRAME_LENGTH and * but frame->hd.length is set to NGHTTP2_MAX_FRAME_LENGTH and
* NGHTTP2_FLAG_END_HEADERS flag is cleared from frame->hd.flags. * NGHTTP2_FLAG_END_HEADERS flag is cleared from frame->hd.flags.
* *
* This function returns the size of packed frame if it succeeds, or * This function returns the size of packed frame (which includes
* returns one of the following negative error codes: * |*bufoff_ptr| bytes) if it succeeds, or returns one of the
* following negative error codes:
* *
* NGHTTP2_ERR_HEADER_COMP * NGHTTP2_ERR_HEADER_COMP
* The deflate operation failed. * The deflate operation failed.
@ -122,8 +129,10 @@ size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame);
*/ */
ssize_t nghttp2_frame_pack_headers(uint8_t **buf_ptr, ssize_t nghttp2_frame_pack_headers(uint8_t **buf_ptr,
size_t *buflen_ptr, size_t *buflen_ptr,
size_t *bufoff_ptr,
nghttp2_headers *frame, nghttp2_headers *frame,
nghttp2_hd_deflater *deflater); nghttp2_hd_deflater *deflater,
size_t align);
/* /*
* Unpacks HEADERS frame byte sequence into |frame|. This function * Unpacks HEADERS frame byte sequence into |frame|. This function
@ -427,10 +436,11 @@ void nghttp2_frame_window_update_free(nghttp2_window_update *frame);
void nghttp2_frame_data_init(nghttp2_data *frame, nghttp2_private_data *pdata); void nghttp2_frame_data_init(nghttp2_data *frame, nghttp2_private_data *pdata);
/* /*
* Returns the number of padding data after application data * Returns the number of padding bytes after payload. The total
* payload. Thus this does not include the PAD_HIGH and PAD_LOW. * padding length is given in the |padlen|. The returned value does
* not include the PAD_HIGH and PAD_LOW.
*/ */
size_t nghttp2_frame_data_trail_padlen(nghttp2_data *frame); size_t nghttp2_frame_trail_padlen(nghttp2_frame *frame, size_t padlen);
void nghttp2_frame_private_data_init(nghttp2_private_data *frame, void nghttp2_frame_private_data_init(nghttp2_private_data *frame,
uint8_t flags, uint8_t flags,

View File

@ -173,6 +173,7 @@ static void nghttp2_inbound_frame_reset(nghttp2_session *session)
iframe->left = NGHTTP2_FRAME_HEAD_LENGTH; iframe->left = NGHTTP2_FRAME_HEAD_LENGTH;
iframe->niv = 0; iframe->niv = 0;
iframe->payloadleft = 0; iframe->payloadleft = 0;
iframe->padlen = 0;
iframe->error_code = 0; iframe->error_code = 0;
iframe->buflen = 0; iframe->buflen = 0;
} }
@ -223,11 +224,11 @@ 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_DATA_PAD_ALIGNMENT) && if((opt_set_mask & NGHTTP2_OPT_PAD_ALIGNMENT) &&
opt_set->data_pad_alignment >= 8) { opt_set->pad_alignment >= 8) {
(*session_ptr)->data_pad_alignment = opt_set->data_pad_alignment; (*session_ptr)->pad_alignment = opt_set->pad_alignment;
} else { } else {
(*session_ptr)->data_pad_alignment = NGHTTP2_DATA_PAD_ALIGNMENT; (*session_ptr)->pad_alignment = NGHTTP2_PAD_ALIGNMENT;
} }
(*session_ptr)->remote_window_size = NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE; (*session_ptr)->remote_window_size = NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
@ -1119,8 +1120,10 @@ static ssize_t nghttp2_session_prep_frame(nghttp2_session *session,
} }
framebuflen = nghttp2_frame_pack_headers(&session->aob.framebuf, framebuflen = nghttp2_frame_pack_headers(&session->aob.framebuf,
&session->aob.framebufmax, &session->aob.framebufmax,
&session->aob.framebufoff,
&frame->headers, &frame->headers,
&session->hd_deflater); &session->hd_deflater,
session->pad_alignment);
if(framebuflen < 0) { if(framebuflen < 0) {
return framebuflen; return framebuflen;
} }
@ -1442,8 +1445,11 @@ 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;
if(cont_hd.length < NGHTTP2_MAX_FRAME_LENGTH) { if(cont_hd.length + session->aob.framebufmark ==
session->aob.framebuflen) {
cont_hd.flags = NGHTTP2_FLAG_END_HEADERS; cont_hd.flags = NGHTTP2_FLAG_END_HEADERS;
cont_hd.flags |=
(NGHTTP2_FLAG_PAD_HIGH | NGHTTP2_FLAG_PAD_LOW) & frame->hd.flags;
} else { } else {
cont_hd.flags = NGHTTP2_FLAG_NONE; cont_hd.flags = NGHTTP2_FLAG_NONE;
} }
@ -1456,9 +1462,6 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session)
session->aob.framebufoff -= NGHTTP2_FRAME_HEAD_LENGTH; session->aob.framebufoff -= NGHTTP2_FRAME_HEAD_LENGTH;
return 0; return 0;
} }
/* Update frame payload length to include data sent in
CONTINUATION frame. */
frame->hd.length = session->aob.framebuflen - NGHTTP2_FRAME_HEAD_LENGTH;
} }
rv = session_call_on_frame_send(session, frame); rv = session_call_on_frame_send(session, frame);
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
@ -3318,24 +3321,73 @@ static int inbound_frame_set_settings_entry(nghttp2_inbound_frame *iframe)
* accordingly. If padding is set, this function returns 1. If no * accordingly. If padding is set, this function returns 1. If no
* padding is set, this function returns 0. On error, returns -1. * padding is set, this function returns 0. On error, returns -1.
*/ */
static int inbound_frame_handle_pad(nghttp2_inbound_frame *iframe) static int inbound_frame_handle_pad(nghttp2_inbound_frame *iframe,
nghttp2_frame_hd *hd)
{ {
if(iframe->frame.hd.flags & NGHTTP2_FLAG_PAD_HIGH) { if(hd->flags & NGHTTP2_FLAG_PAD_HIGH) {
if((iframe->frame.hd.flags & NGHTTP2_FLAG_PAD_LOW) == 0) { if((hd->flags & NGHTTP2_FLAG_PAD_LOW) == 0) {
return -1; return -1;
} }
iframe->state = NGHTTP2_IB_READ_NBYTE; iframe->state = NGHTTP2_IB_READ_NBYTE;
iframe->left = 2; iframe->left = 2;
return 1; return 1;
} }
if(iframe->frame.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;
return 1; return 1;
} }
DEBUGF(fprintf(stderr, "no padding\n"));
return 0; return 0;
} }
/*
* Computes number of padding based on flags. This function returns
* the calculated length if it succeeds, or -1.
*/
static ssize_t inbound_frame_compute_pad(nghttp2_inbound_frame *iframe)
{
size_t padlen;
padlen = iframe->buf[0];
if(iframe->frame.hd.flags & NGHTTP2_FLAG_PAD_HIGH) {
padlen <<= 8;
padlen |= iframe->buf[1];
++padlen;
}
++padlen;
DEBUGF(fprintf(stderr, "padlen=%zu\n", padlen));
if(padlen > iframe->frame.hd.length) {
return -1;
}
iframe->padlen = padlen;
return padlen;
}
/*
* This function returns the effective payload length in the data of
* length |readlen| when the remaning payload is |payloadleft|. The
* |payloadleft| does not include |readlen|. If padding was started
* strictly before this data chunk, this function returns -1.
*/
static ssize_t inbound_frame_effective_readlen(nghttp2_inbound_frame *iframe,
size_t payloadleft,
size_t readlen)
{
size_t trail_padlen = nghttp2_frame_trail_padlen(&iframe->frame,
iframe->padlen);
if(trail_padlen > payloadleft) {
size_t padlen;
padlen = trail_padlen - payloadleft;
if(readlen < padlen) {
return -1;
} else {
return readlen - padlen;
}
}
return readlen;
}
ssize_t nghttp2_session_mem_recv(nghttp2_session *session, ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
const uint8_t *in, size_t inlen) const uint8_t *in, size_t inlen)
{ {
@ -3363,7 +3415,6 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
switch(iframe->frame.hd.type) { switch(iframe->frame.hd.type) {
case NGHTTP2_DATA: { case NGHTTP2_DATA: {
DEBUGF(fprintf(stderr, "DATA\n")); DEBUGF(fprintf(stderr, "DATA\n"));
iframe->frame.data.padlen = 0;
/* Check stream is open. If it is not open or closing, /* Check stream is open. If it is not open or closing,
ignore payload. */ ignore payload. */
busy = 1; busy = 1;
@ -3377,7 +3428,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
return rv; return rv;
} }
rv = inbound_frame_handle_pad(iframe); rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd);
if(rv < 0) { if(rv < 0) {
iframe->state = NGHTTP2_IB_IGN_DATA; iframe->state = NGHTTP2_IB_IGN_DATA;
rv = nghttp2_session_terminate_session(session, rv = nghttp2_session_terminate_session(session,
@ -3395,6 +3446,20 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
} }
case NGHTTP2_HEADERS: case NGHTTP2_HEADERS:
DEBUGF(fprintf(stderr, "HEADERS\n")); DEBUGF(fprintf(stderr, "HEADERS\n"));
rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd);
if(rv < 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(rv == 1) {
break;
}
if(iframe->frame.hd.flags & NGHTTP2_FLAG_PRIORITY) { if(iframe->frame.hd.flags & NGHTTP2_FLAG_PRIORITY) {
if(iframe->payloadleft < 4) { if(iframe->payloadleft < 4) {
busy = 1; busy = 1;
@ -3497,16 +3562,8 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
switch(iframe->frame.hd.type) { switch(iframe->frame.hd.type) {
case NGHTTP2_DATA: case NGHTTP2_DATA:
busy = 1; busy = 1;
iframe->frame.data.padlen = iframe->buf[0]; rv = inbound_frame_compute_pad(iframe);
if(iframe->frame.hd.flags & NGHTTP2_FLAG_PAD_HIGH) { if(rv < 0) {
iframe->frame.data.padlen <<= 8;
iframe->frame.data.padlen |= iframe->buf[1];
++iframe->frame.data.padlen;
}
++iframe->frame.data.padlen;
DEBUGF(fprintf(stderr, "padlen=%zu\n", iframe->frame.data.padlen));
if(iframe->frame.data.padlen > iframe->frame.hd.length) {
rv = nghttp2_session_terminate_session(session, rv = nghttp2_session_terminate_session(session,
NGHTTP2_PROTOCOL_ERROR); NGHTTP2_PROTOCOL_ERROR);
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
@ -3515,9 +3572,36 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
iframe->state = NGHTTP2_IB_IGN_DATA; iframe->state = NGHTTP2_IB_IGN_DATA;
break; break;
} }
iframe->frame.data.padlen = rv;
iframe->state = NGHTTP2_IB_READ_DATA; iframe->state = NGHTTP2_IB_READ_DATA;
break; break;
case NGHTTP2_HEADERS: case NGHTTP2_HEADERS:
if(iframe->padlen == 0 &&
iframe->frame.hd.flags & NGHTTP2_FLAG_PAD_LOW) {
rv = inbound_frame_compute_pad(iframe);
if(rv < 0) {
busy = 1;
rv = nghttp2_session_terminate_session(session,
NGHTTP2_PROTOCOL_ERROR);
if(nghttp2_is_fatal(rv)) {
return rv;
}
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
break;
}
iframe->frame.headers.padlen = rv;
if(iframe->frame.hd.flags & NGHTTP2_FLAG_PRIORITY) {
if(iframe->payloadleft < 4) {
busy = 1;
iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
break;
}
iframe->state = NGHTTP2_IB_READ_NBYTE;
iframe->left = 4;
iframe->buflen = 0;
break;
}
}
rv = session_process_headers_frame(session); rv = session_process_headers_frame(session);
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
return rv; return rv;
@ -3580,7 +3664,8 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
} }
break; break;
case NGHTTP2_IB_READ_HEADER_BLOCK: case NGHTTP2_IB_READ_HEADER_BLOCK:
case NGHTTP2_IB_IGN_HEADER_BLOCK: case NGHTTP2_IB_IGN_HEADER_BLOCK: {
ssize_t data_readlen;
#ifdef DEBUGBUILD #ifdef DEBUGBUILD
if(iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK) { if(iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK) {
fprintf(stderr, "[IB_READ_HEADER_BLOCK]\n"); fprintf(stderr, "[IB_READ_HEADER_BLOCK]\n");
@ -3591,24 +3676,41 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
readlen = inbound_frame_payload_readlen(iframe, in, last); readlen = inbound_frame_payload_readlen(iframe, in, last);
DEBUGF(fprintf(stderr, "readlen=%zu, payloadleft=%zu\n", DEBUGF(fprintf(stderr, "readlen=%zu, payloadleft=%zu\n",
readlen, iframe->payloadleft - readlen)); readlen, iframe->payloadleft - readlen));
data_readlen = inbound_frame_effective_readlen
(iframe, iframe->payloadleft - readlen, readlen);
if(data_readlen >= 0) {
size_t trail_padlen;
size_t hd_proclen = 0;
trail_padlen = nghttp2_frame_trail_padlen(&iframe->frame,
iframe->padlen);
DEBUGF(fprintf(stderr, "block final=%d\n", DEBUGF(fprintf(stderr, "block final=%d\n",
(iframe->frame.hd.flags & (iframe->frame.hd.flags &
NGHTTP2_FLAG_END_HEADERS) && NGHTTP2_FLAG_END_HEADERS) &&
iframe->payloadleft == readlen)); iframe->payloadleft - data_readlen == trail_padlen));
rv = inflate_header_block(session, &iframe->frame, &readlen,
(uint8_t*)in, readlen, rv = inflate_header_block
(session, &iframe->frame, &hd_proclen,
(uint8_t*)in, data_readlen,
(iframe->frame.hd.flags & (iframe->frame.hd.flags &
NGHTTP2_FLAG_END_HEADERS) && NGHTTP2_FLAG_END_HEADERS) &&
iframe->payloadleft == readlen, iframe->payloadleft - data_readlen == trail_padlen,
iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK); iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK);
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
return rv; return rv;
} }
in += readlen;
iframe->payloadleft -= readlen;
if(rv == NGHTTP2_ERR_PAUSE) { if(rv == NGHTTP2_ERR_PAUSE) {
in += hd_proclen;
iframe->payloadleft -= hd_proclen;
return in - first; return in - first;
} }
in += readlen;
iframe->payloadleft -= readlen;
if(rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { if(rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
/* The application says no more headers. We decompress the /* The application says no more headers. We decompress the
rest of the header block but not invoke on_header_callback rest of the header block but not invoke on_header_callback
@ -3619,6 +3721,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
return rv; return rv;
} }
busy = 1;
iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK; iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
break; break;
} }
@ -3627,32 +3730,40 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
if(iframe->payloadleft == 0) { if(iframe->payloadleft == 0) {
nghttp2_inbound_frame_reset(session); nghttp2_inbound_frame_reset(session);
} else { } else {
busy = 1;
iframe->state = NGHTTP2_IB_IGN_PAYLOAD; iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
} }
break; break;
} }
} else {
in += readlen;
iframe->payloadleft -= readlen;
}
if(iframe->payloadleft) { if(iframe->payloadleft) {
break; break;
} }
if(iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK) {
rv = session_after_header_block_received(session);
if(nghttp2_is_fatal(rv)) {
return rv;
}
}
if((iframe->frame.hd.flags & NGHTTP2_FLAG_END_HEADERS) == 0) { if((iframe->frame.hd.flags & NGHTTP2_FLAG_END_HEADERS) == 0) {
iframe->left = NGHTTP2_FRAME_HEAD_LENGTH; iframe->left = NGHTTP2_FRAME_HEAD_LENGTH;
iframe->error_code = 0; iframe->error_code = 0;
iframe->buflen = 0; iframe->buflen = 0;
iframe->padlen = 0;
if(iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK) { if(iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK) {
iframe->state = NGHTTP2_IB_EXPECT_CONTINUATION; iframe->state = NGHTTP2_IB_EXPECT_CONTINUATION;
} else { } else {
iframe->state = NGHTTP2_IB_IGN_CONTINUATION; iframe->state = NGHTTP2_IB_IGN_CONTINUATION;
} }
} else { } else {
if(iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK) {
rv = session_after_header_block_received(session);
if(nghttp2_is_fatal(rv)) {
return rv;
}
}
nghttp2_inbound_frame_reset(session); nghttp2_inbound_frame_reset(session);
} }
break; break;
}
case NGHTTP2_IB_IGN_PAYLOAD: case NGHTTP2_IB_IGN_PAYLOAD:
DEBUGF(fprintf(stderr, "[IB_IGN_PAYLOAD]\n")); DEBUGF(fprintf(stderr, "[IB_IGN_PAYLOAD]\n"));
readlen = inbound_frame_payload_readlen(iframe, in, last); readlen = inbound_frame_payload_readlen(iframe, in, last);
@ -3761,9 +3872,30 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
iframe->state = NGHTTP2_IB_IGN_PAYLOAD; iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
break; break;
} }
if(cont_hd.flags & NGHTTP2_FLAG_END_HEADERS) { iframe->frame.hd.flags |= cont_hd.flags &
iframe->frame.hd.flags |= NGHTTP2_FLAG_END_HEADERS; (NGHTTP2_FLAG_END_HEADERS |
NGHTTP2_FLAG_PAD_HIGH | NGHTTP2_FLAG_PAD_LOW);
rv = inbound_frame_handle_pad(iframe, &cont_hd);
if(rv < 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(rv == 1) {
if(iframe->state == NGHTTP2_IB_EXPECT_CONTINUATION) {
iframe->state = NGHTTP2_IB_READ_PAD_CONTINUATION;
} else {
iframe->state = NGHTTP2_IB_IGN_PAD_CONTINUATION;
}
break;
}
busy = 1; busy = 1;
if(iframe->state == NGHTTP2_IB_EXPECT_CONTINUATION) { if(iframe->state == NGHTTP2_IB_EXPECT_CONTINUATION) {
iframe->state = NGHTTP2_IB_READ_HEADER_BLOCK; iframe->state = NGHTTP2_IB_READ_HEADER_BLOCK;
@ -3771,6 +3903,46 @@ 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_IGN_PAD_CONTINUATION:
#ifdef DEBUGBUILD
if(iframe->state == NGHTTP2_IB_READ_PAD_CONTINUATION) {
fprintf(stderr, "[IB_READ_PAD_CONTINUATION]\n");
} else {
fprintf(stderr, "[IB_IGN_PAD_CONTINUATION]\n");
}
#endif /* DEBUGBUILD */
readlen = inbound_frame_buf_read(iframe, in, last);
in += readlen;
iframe->payloadleft -= readlen;
DEBUGF(fprintf(stderr, "readlen=%zu, payloadleft=%zu, left=%zu\n",
readlen, iframe->payloadleft, iframe->left));
if(iframe->left) {
return in - first;
}
busy = 1;
rv = inbound_frame_compute_pad(iframe);
if(rv < 0) {
rv = nghttp2_session_terminate_session(session,
NGHTTP2_PROTOCOL_ERROR);
if(nghttp2_is_fatal(rv)) {
return rv;
}
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
break;
}
iframe->padlen = rv;
if(iframe->frame.hd.type == NGHTTP2_HEADERS) {
iframe->frame.headers.padlen += rv;
} else {
iframe->frame.push_promise.padlen += rv;
}
if(iframe->state == NGHTTP2_IB_READ_PAD_CONTINUATION) {
iframe->state = NGHTTP2_IB_READ_HEADER_BLOCK;
} else {
iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
}
break;
case NGHTTP2_IB_READ_DATA: case NGHTTP2_IB_READ_DATA:
DEBUGF(fprintf(stderr, "[IB_READ_DATA]\n")); DEBUGF(fprintf(stderr, "[IB_READ_DATA]\n"));
readlen = inbound_frame_payload_readlen(iframe, in, last); readlen = inbound_frame_payload_readlen(iframe, in, last);
@ -3779,7 +3951,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
DEBUGF(fprintf(stderr, "readlen=%zu, payloadleft=%zu\n", DEBUGF(fprintf(stderr, "readlen=%zu, payloadleft=%zu\n",
readlen, iframe->payloadleft)); readlen, iframe->payloadleft));
if(readlen > 0) { if(readlen > 0) {
size_t data_readlen = readlen; ssize_t data_readlen;
rv = nghttp2_session_update_recv_connection_window_size rv = nghttp2_session_update_recv_connection_window_size
(session, readlen); (session, readlen);
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
@ -3798,17 +3970,8 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
} }
} }
} }
if(nghttp2_frame_data_trail_padlen(&iframe->frame.data) > data_readlen = inbound_frame_effective_readlen
iframe->payloadleft) { (iframe, iframe->payloadleft, readlen);
size_t trail_padlen;
trail_padlen = nghttp2_frame_data_trail_padlen(&iframe->frame.data)
- iframe->payloadleft;
if(readlen < trail_padlen) {
data_readlen = 0;
} else {
data_readlen -= trail_padlen;
}
}
DEBUGF(fprintf(stderr, "data_readlen=%zu\n", data_readlen)); DEBUGF(fprintf(stderr, "data_readlen=%zu\n", data_readlen));
if(data_readlen > 0 && session->callbacks.on_data_chunk_recv_callback) { if(data_readlen > 0 && session->callbacks.on_data_chunk_recv_callback) {
rv = session->callbacks.on_data_chunk_recv_callback rv = session->callbacks.on_data_chunk_recv_callback
@ -4066,11 +4229,11 @@ 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->opt_flags & NGHTTP2_OPTMASK_NO_DATA_PADDING) == 0 && if(session->pad_alignment &&
payloadlen > 0 && (size_t)payloadlen < datamax) { payloadlen > 0 && (size_t)payloadlen < datamax) {
rv = nghttp2_frame_add_pad(buf_ptr, buflen_ptr, bufoff_ptr, rv = nghttp2_frame_add_pad(buf_ptr, buflen_ptr, bufoff_ptr,
&flags, payloadlen, datamax, &flags, payloadlen, datamax,
session->data_pad_alignment); session->pad_alignment);
if(rv < 0) { if(rv < 0) {
return rv; return rv;
} }

View File

@ -44,10 +44,7 @@
*/ */
typedef enum { typedef enum {
NGHTTP2_OPTMASK_NO_AUTO_STREAM_WINDOW_UPDATE = 1 << 0, NGHTTP2_OPTMASK_NO_AUTO_STREAM_WINDOW_UPDATE = 1 << 0,
NGHTTP2_OPTMASK_NO_AUTO_CONNECTION_WINDOW_UPDATE = 1 << 1, NGHTTP2_OPTMASK_NO_AUTO_CONNECTION_WINDOW_UPDATE = 1 << 1
/* Option to disable DATA frame padding, which is currently hidden
from outside, but provided for ease of testing */
NGHTTP2_OPTMASK_NO_DATA_PADDING = 1 << 2,
} nghttp2_optmask; } nghttp2_optmask;
typedef struct { typedef struct {
@ -89,6 +86,8 @@ typedef enum {
NGHTTP2_IB_READ_GOAWAY_DEBUG, NGHTTP2_IB_READ_GOAWAY_DEBUG,
NGHTTP2_IB_EXPECT_CONTINUATION, NGHTTP2_IB_EXPECT_CONTINUATION,
NGHTTP2_IB_IGN_CONTINUATION, NGHTTP2_IB_IGN_CONTINUATION,
NGHTTP2_IB_READ_PAD_CONTINUATION,
NGHTTP2_IB_IGN_PAD_CONTINUATION,
NGHTTP2_IB_READ_DATA, NGHTTP2_IB_READ_DATA,
NGHTTP2_IB_IGN_DATA NGHTTP2_IB_IGN_DATA
} nghttp2_inbound_state; } nghttp2_inbound_state;
@ -105,6 +104,8 @@ typedef struct {
size_t left; size_t left;
/* How many bytes we still need to receive for current frame */ /* How many bytes we still need to receive for current frame */
size_t payloadleft; size_t payloadleft;
/* padding length for the current frame */
size_t padlen;
nghttp2_inbound_state state; nghttp2_inbound_state state;
/* TODO, remove this. Error code */ /* TODO, remove this. Error code */
int error_code; int error_code;
@ -152,8 +153,8 @@ 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;
/* DATA padding alignemnt. See NGHTTP2_OPT_DATA_PAD_ALIGNMENT. */ /* padding alignemnt. See NGHTTP2_OPT_PAD_ALIGNMENT. */
size_t data_pad_alignment; size_t pad_alignment;
/* 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 */

View File

@ -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),
data_pad_alignment(NGHTTP2_DATA_PAD_ALIGNMENT), pad_alignment(NGHTTP2_PAD_ALIGNMENT),
header_table_size(-1), header_table_size(-1),
port(0), port(0),
verbose(false), verbose(false),
@ -365,11 +365,11 @@ int Http2Handler::on_connect()
nghttp2_opt_set opt_set; nghttp2_opt_set opt_set;
memset(&opt_set, 0, sizeof(opt_set)); memset(&opt_set, 0, sizeof(opt_set));
opt_set.data_pad_alignment = sessions_->get_config()->data_pad_alignment; opt_set.pad_alignment = sessions_->get_config()->pad_alignment;
fill_callback(callbacks, sessions_->get_config()); fill_callback(callbacks, sessions_->get_config());
r = nghttp2_session_server_new2(&session_, &callbacks, this, r = nghttp2_session_server_new2(&session_, &callbacks, this,
NGHTTP2_OPT_DATA_PAD_ALIGNMENT, &opt_set); NGHTTP2_OPT_PAD_ALIGNMENT, &opt_set);
if(r != 0) { if(r != 0) {
return r; return r;
} }

View File

@ -56,7 +56,7 @@ struct Config {
std::string cert_file; std::string cert_file;
void *data_ptr; void *data_ptr;
size_t output_upper_thres; size_t output_upper_thres;
size_t data_pad_alignment; size_t pad_alignment;
ssize_t header_table_size; ssize_t header_table_size;
uint16_t port; uint16_t port;
bool verbose; bool verbose;

View File

@ -244,6 +244,18 @@ void print_flags(const nghttp2_frame_hd& hd)
} }
s += "PRIORITY"; s += "PRIORITY";
} }
if(hd.flags & NGHTTP2_FLAG_PAD_LOW) {
if(!s.empty()) {
s += " | ";
}
s += "PAD_LOW";
}
if(hd.flags & NGHTTP2_FLAG_PAD_HIGH) {
if(!s.empty()) {
s += " | ";
}
s += "PAD_HIGH";
}
break; break;
case NGHTTP2_SETTINGS: case NGHTTP2_SETTINGS:
if(hd.flags & NGHTTP2_FLAG_ACK) { if(hd.flags & NGHTTP2_FLAG_ACK) {
@ -254,6 +266,18 @@ void print_flags(const nghttp2_frame_hd& hd)
if(hd.flags & NGHTTP2_FLAG_END_PUSH_PROMISE) { if(hd.flags & NGHTTP2_FLAG_END_PUSH_PROMISE) {
s += "END_PUSH_PROMISE"; s += "END_PUSH_PROMISE";
} }
if(hd.flags & NGHTTP2_FLAG_PAD_LOW) {
if(!s.empty()) {
s += " | ";
}
s += "PAD_LOW";
}
if(hd.flags & NGHTTP2_FLAG_PAD_HIGH) {
if(!s.empty()) {
s += " | ";
}
s += "PAD_HIGH";
}
break; break;
case NGHTTP2_PING: case NGHTTP2_PING:
if(hd.flags & NGHTTP2_FLAG_ACK) { if(hd.flags & NGHTTP2_FLAG_ACK) {
@ -297,10 +321,9 @@ void print_frame(print_type ptype, const nghttp2_frame *frame)
} }
break; break;
case NGHTTP2_HEADERS: case NGHTTP2_HEADERS:
if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
print_frame_attr_indent(); print_frame_attr_indent();
printf("(pri=%d)\n", frame->headers.pri); printf("(pri=%d, padlen=%zu)\n",
} frame->headers.pri, frame->headers.padlen);
switch(frame->headers.cat) { switch(frame->headers.cat) {
case NGHTTP2_HCAT_REQUEST: case NGHTTP2_HCAT_REQUEST:
print_frame_attr_indent(); print_frame_attr_indent();
@ -342,8 +365,9 @@ void print_frame(print_type ptype, const nghttp2_frame *frame)
break; break;
case NGHTTP2_PUSH_PROMISE: case NGHTTP2_PUSH_PROMISE:
print_frame_attr_indent(); print_frame_attr_indent();
printf("(promised_stream_id=%d)\n", printf("(promised_stream_id=%d, padlen=%zu)\n",
frame->push_promise.promised_stream_id); frame->push_promise.promised_stream_id,
frame->push_promise.padlen);
print_nv(frame->push_promise.nva, frame->push_promise.nvlen); print_nv(frame->push_promise.nva, frame->push_promise.nvlen);
break; break;
case NGHTTP2_PING: case NGHTTP2_PING:

View File

@ -82,7 +82,7 @@ struct Config {
std::string keyfile; std::string keyfile;
std::string datafile; std::string datafile;
size_t output_upper_thres; size_t output_upper_thres;
size_t data_pad_alignment; size_t pad_alignment;
ssize_t peer_max_concurrent_streams; ssize_t peer_max_concurrent_streams;
ssize_t header_table_size; ssize_t header_table_size;
int32_t pri; int32_t pri;
@ -100,7 +100,7 @@ struct Config {
bool continuation; bool continuation;
Config() Config()
: output_upper_thres(1024*1024), : output_upper_thres(1024*1024),
data_pad_alignment(NGHTTP2_DATA_PAD_ALIGNMENT), pad_alignment(NGHTTP2_PAD_ALIGNMENT),
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,10 @@ 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.data_pad_alignment = config.data_pad_alignment; opt_set.pad_alignment = config.pad_alignment;
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_DATA_PAD_ALIGNMENT, NGHTTP2_OPT_PAD_ALIGNMENT,
&opt_set); &opt_set);
if(rv != 0) { if(rv != 0) {
return -1; return -1;
@ -1710,8 +1710,8 @@ void print_help(std::ostream& out)
<< " is large enough as it is seen as unlimited.\n" << " is large enough as it is seen as unlimited.\n"
<< " -c, --header-table-size=<N>\n" << " -c, --header-table-size=<N>\n"
<< " Specify decoder header table size.\n" << " Specify decoder header table size.\n"
<< " -b, --data-pad=<ALIGNMENT>\n" << " -b, --pad=<ALIGNMENT>\n"
<< " Alignment of DATA frame padding.\n" << " Alignment of frame payload padding.\n"
<< " --color Force colored log output.\n" << " --color Force colored log output.\n"
<< " --continuation Send large header to test CONTINUATION.\n" << " --continuation Send large header to test CONTINUATION.\n"
<< std::endl; << std::endl;
@ -1766,7 +1766,7 @@ int main(int argc, char **argv)
print_help(std::cout); print_help(std::cout);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
case 'b': case 'b':
config.data_pad_alignment = strtol(optarg, nullptr, 10); config.pad_alignment = strtol(optarg, nullptr, 10);
break; break;
case 'n': case 'n':
config.null_out = true; config.null_out = true;

View File

@ -115,8 +115,8 @@ void print_help(std::ostream& out)
<< " -p/=/foo.png -p/doc=/bar.css\n" << " -p/=/foo.png -p/doc=/bar.css\n"
<< " PATH and PUSH_PATHs are relative to document\n" << " PATH and PUSH_PATHs are relative to document\n"
<< " root. See --htdocs option.\n" << " root. See --htdocs option.\n"
<< " -b, --data-pad=<ALIGNMENT>\n" << " -b, --pad=<ALIGNMENT>\n"
<< " Alignment of DATA frame padding.\n" << " Alignment of frame payload padding.\n"
<< " -h, --help Print this help.\n" << " -h, --help Print this help.\n"
<< std::endl; << std::endl;
} }
@ -155,7 +155,7 @@ int main(int argc, char **argv)
config.verify_client = true; config.verify_client = true;
break; break;
case 'b': case 'b':
config.data_pad_alignment = strtol(optarg, nullptr, 10); config.pad_alignment = strtol(optarg, nullptr, 10);
break; break;
case 'd': case 'd':
config.htdocs = optarg; config.htdocs = optarg;

View File

@ -74,6 +74,7 @@ void test_nghttp2_frame_pack_headers()
nghttp2_headers frame, oframe; nghttp2_headers frame, oframe;
uint8_t *buf = NULL; uint8_t *buf = NULL;
size_t buflen = 0; size_t buflen = 0;
size_t bufoff;
ssize_t framelen; ssize_t framelen;
nghttp2_nv *nva; nghttp2_nv *nva;
ssize_t nvlen; ssize_t nvlen;
@ -89,17 +90,21 @@ void test_nghttp2_frame_pack_headers()
NGHTTP2_FLAG_END_STREAM|NGHTTP2_FLAG_END_HEADERS, NGHTTP2_FLAG_END_STREAM|NGHTTP2_FLAG_END_HEADERS,
1000000007, 1000000007,
1 << 20, nva, nvlen); 1 << 20, nva, nvlen);
framelen = nghttp2_frame_pack_headers(&buf, &buflen, &frame, &deflater); framelen = nghttp2_frame_pack_headers(&buf, &buflen, &bufoff, &frame,
&deflater, 0);
CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf, framelen)); CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf + bufoff,
check_frame_header(framelen - NGHTTP2_FRAME_HEAD_LENGTH, NGHTTP2_HEADERS, framelen - bufoff));
check_frame_header(framelen - bufoff - NGHTTP2_FRAME_HEAD_LENGTH,
NGHTTP2_HEADERS,
NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS, NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS,
1000000007, &oframe.hd); 1000000007, &oframe.hd);
/* We didn't include PRIORITY flag so priority is not packed */ /* We didn't include PRIORITY flag so priority is not packed */
CU_ASSERT(1 << 30 == oframe.pri); CU_ASSERT(1 << 30 == oframe.pri);
CU_ASSERT(framelen - 8 == CU_ASSERT(framelen - (ssize_t)bufoff - 8 ==
inflate_hd(&inflater, &out, buf + 8, framelen - 8)); inflate_hd(&inflater, &out,
buf + bufoff + 8, framelen - bufoff - 8));
CU_ASSERT(7 == out.nvlen); CU_ASSERT(7 == out.nvlen);
CU_ASSERT(nvnameeq("method", &out.nva[0])); CU_ASSERT(nvnameeq("method", &out.nva[0]));
@ -111,10 +116,13 @@ void test_nghttp2_frame_pack_headers()
memset(&oframe, 0, sizeof(oframe)); memset(&oframe, 0, sizeof(oframe));
/* 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, &frame, &deflater); framelen = nghttp2_frame_pack_headers(&buf, &buflen, &bufoff, &frame,
&deflater, 0);
CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf, framelen)); CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf + bufoff,
check_frame_header(framelen - NGHTTP2_FRAME_HEAD_LENGTH, NGHTTP2_HEADERS, framelen - bufoff));
check_frame_header(framelen - bufoff - NGHTTP2_FRAME_HEAD_LENGTH,
NGHTTP2_HEADERS,
NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS |
NGHTTP2_FLAG_PRIORITY, NGHTTP2_FLAG_PRIORITY,
1000000007, &oframe.hd); 1000000007, &oframe.hd);
@ -140,6 +148,7 @@ void test_nghttp2_frame_pack_headers_frame_too_large(void)
nghttp2_headers frame; nghttp2_headers frame;
uint8_t *buf = NULL; uint8_t *buf = NULL;
size_t buflen = 0; size_t buflen = 0;
size_t bufoff;
ssize_t framelen; ssize_t framelen;
nghttp2_nv *nva; nghttp2_nv *nva;
ssize_t nvlen; ssize_t nvlen;
@ -163,7 +172,8 @@ void test_nghttp2_frame_pack_headers_frame_too_large(void)
NGHTTP2_FLAG_END_STREAM|NGHTTP2_FLAG_END_HEADERS, NGHTTP2_FLAG_END_STREAM|NGHTTP2_FLAG_END_HEADERS,
1000000007, 1000000007,
0, nva, nvlen); 0, nva, nvlen);
framelen = nghttp2_frame_pack_headers(&buf, &buflen, &frame, &deflater); framelen = nghttp2_frame_pack_headers(&buf, &buflen, &bufoff, &frame,
&deflater, 0);
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);

View File

@ -336,9 +336,10 @@ void test_nghttp2_session_recv(void)
}; };
uint8_t *framedata = NULL; uint8_t *framedata = NULL;
size_t framedatalen = 0; size_t framedatalen = 0;
size_t bufoff;
ssize_t framelen; ssize_t framelen;
nghttp2_frame frame; nghttp2_frame frame;
int i; size_t i;
nghttp2_outbound_item *item; nghttp2_outbound_item *item;
nghttp2_nv *nva; nghttp2_nv *nva;
ssize_t nvlen; ssize_t nvlen;
@ -355,13 +356,13 @@ void test_nghttp2_session_recv(void)
nvlen = nghttp2_nv_array_copy(&nva, nv, ARRLEN(nv)); nvlen = nghttp2_nv_array_copy(&nva, nv, ARRLEN(nv));
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS,
1, NGHTTP2_PRI_DEFAULT, nva, nvlen); 1, NGHTTP2_PRI_DEFAULT, nva, nvlen);
framelen = nghttp2_frame_pack_headers(&framedata, &framedatalen, framelen = nghttp2_frame_pack_headers(&framedata, &framedatalen, &bufoff,
&frame.headers, &frame.headers,
&deflater); &deflater, 0);
scripted_data_feed_init(&df, framedata, framelen); scripted_data_feed_init(&df, framedata + bufoff, framelen - bufoff);
/* Send 1 byte per each read */ /* Send 1 byte per each read */
for(i = 0; i < framelen; ++i) { for(i = 0; i < framelen - bufoff; ++i) {
df.feedseq[i] = 1; df.feedseq[i] = 1;
} }
nghttp2_frame_headers_free(&frame.headers); nghttp2_frame_headers_free(&frame.headers);
@ -375,13 +376,13 @@ void test_nghttp2_session_recv(void)
/* Received HEADERS without header block, which is valid */ /* Received HEADERS without header block, which is valid */
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS,
5, NGHTTP2_PRI_DEFAULT, NULL, 0); 5, NGHTTP2_PRI_DEFAULT, NULL, 0);
framelen = nghttp2_frame_pack_headers(&framedata, &framedatalen, framelen = nghttp2_frame_pack_headers(&framedata, &framedatalen, &bufoff,
&frame.headers, &frame.headers,
&deflater); &deflater, 0);
nghttp2_frame_headers_free(&frame.headers); nghttp2_frame_headers_free(&frame.headers);
scripted_data_feed_init(&df, framedata, framelen); scripted_data_feed_init(&df, framedata + bufoff, framelen - bufoff);
user_data.frame_recv_cb_called = 0; user_data.frame_recv_cb_called = 0;
CU_ASSERT(0 == nghttp2_session_recv(session)); CU_ASSERT(0 == nghttp2_session_recv(session));
CU_ASSERT(1 == user_data.frame_recv_cb_called); CU_ASSERT(1 == user_data.frame_recv_cb_called);
@ -421,6 +422,7 @@ void test_nghttp2_session_recv_invalid_stream_id(void)
my_user_data user_data; my_user_data user_data;
uint8_t *framedata = NULL; uint8_t *framedata = NULL;
size_t framedatalen = 0; size_t framedatalen = 0;
size_t bufoff;
ssize_t framelen; ssize_t framelen;
nghttp2_frame frame; nghttp2_frame frame;
nghttp2_hd_deflater deflater; nghttp2_hd_deflater deflater;
@ -436,11 +438,11 @@ void test_nghttp2_session_recv_invalid_stream_id(void)
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2, nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
NGHTTP2_PRI_DEFAULT, NULL, 0); NGHTTP2_PRI_DEFAULT, NULL, 0);
framelen = nghttp2_frame_pack_headers(&framedata, &framedatalen, framelen = nghttp2_frame_pack_headers(&framedata, &framedatalen, &bufoff,
&frame.headers, &frame.headers,
&deflater); &deflater, 0);
scripted_data_feed_init(&df, framedata, framelen); scripted_data_feed_init(&df, framedata + bufoff, framelen - bufoff);
nghttp2_frame_headers_free(&frame.headers); nghttp2_frame_headers_free(&frame.headers);
CU_ASSERT(0 == nghttp2_session_recv(session)); CU_ASSERT(0 == nghttp2_session_recv(session));
@ -462,6 +464,7 @@ void test_nghttp2_session_recv_invalid_frame(void)
}; };
uint8_t *framedata = NULL; uint8_t *framedata = NULL;
size_t framedatalen = 0; size_t framedatalen = 0;
size_t bufoff;
ssize_t framelen; ssize_t framelen;
nghttp2_frame frame; nghttp2_frame frame;
nghttp2_nv *nva; nghttp2_nv *nva;
@ -480,11 +483,11 @@ void test_nghttp2_session_recv_invalid_frame(void)
nvlen = nghttp2_nv_array_copy(&nva, nv, ARRLEN(nv)); nvlen = nghttp2_nv_array_copy(&nva, nv, ARRLEN(nv));
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1, nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
NGHTTP2_PRI_DEFAULT, nva, nvlen); NGHTTP2_PRI_DEFAULT, nva, nvlen);
framelen = nghttp2_frame_pack_headers(&framedata, &framedatalen, framelen = nghttp2_frame_pack_headers(&framedata, &framedatalen, &bufoff,
&frame.headers, &frame.headers,
&deflater); &deflater, 0);
scripted_data_feed_init(&df, framedata, framelen); scripted_data_feed_init(&df, framedata + bufoff, framelen - bufoff);
CU_ASSERT(0 == nghttp2_session_recv(session)); CU_ASSERT(0 == nghttp2_session_recv(session));
CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == nghttp2_session_send(session));
@ -492,7 +495,7 @@ void test_nghttp2_session_recv_invalid_frame(void)
/* Receive exactly same bytes of HEADERS is treated as subsequent /* Receive exactly same bytes of HEADERS is treated as subsequent
HEADERS (e.g., trailers */ HEADERS (e.g., trailers */
scripted_data_feed_init(&df, framedata, framelen); scripted_data_feed_init(&df, framedata + bufoff, framelen - bufoff);
CU_ASSERT(0 == nghttp2_session_recv(session)); CU_ASSERT(0 == nghttp2_session_recv(session));
CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == nghttp2_session_send(session));
@ -660,6 +663,7 @@ void test_nghttp2_session_recv_continuation(void)
uint8_t *framedata = NULL; uint8_t *framedata = NULL;
size_t framedatacap = 0; size_t framedatacap = 0;
size_t framedatalen; size_t framedatalen;
size_t bufoff;
size_t framedataoff; size_t framedataoff;
ssize_t rv; ssize_t rv;
my_user_data ud; my_user_data ud;
@ -681,13 +685,14 @@ void test_nghttp2_session_recv_continuation(void)
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE,
1, NGHTTP2_PRI_DEFAULT, nva, nvlen); 1, NGHTTP2_PRI_DEFAULT, nva, nvlen);
framedatalen = nghttp2_frame_pack_headers(&framedata, &framedatacap, framedatalen = nghttp2_frame_pack_headers(&framedata, &framedatacap,
&bufoff,
&frame.headers, &frame.headers,
&deflater); &deflater, 0);
nghttp2_frame_headers_free(&frame.headers); nghttp2_frame_headers_free(&frame.headers);
memcpy(data, framedata, 9); memcpy(data, framedata + bufoff, 9);
datalen = 9; datalen = 9;
framedataoff = NGHTTP2_FRAME_HEAD_LENGTH + 1; framedataoff = bufoff + NGHTTP2_FRAME_HEAD_LENGTH + 1;
nghttp2_put_uint16be(data, 1); nghttp2_put_uint16be(data, 1);
@ -735,12 +740,12 @@ void test_nghttp2_session_recv_continuation(void)
nvlen = nghttp2_nv_array_copy(&nva, nv1, ARRLEN(nv1)); nvlen = nghttp2_nv_array_copy(&nva, nv1, ARRLEN(nv1));
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE,
1, NGHTTP2_PRI_DEFAULT, nva, nvlen); 1, NGHTTP2_PRI_DEFAULT, nva, nvlen);
framedatalen = nghttp2_frame_pack_headers(&framedata, &framedatacap, framedatalen = nghttp2_frame_pack_headers(&framedata, &framedatacap, &bufoff,
&frame.headers, &frame.headers,
&deflater); &deflater, 0);
nghttp2_frame_headers_free(&frame.headers); nghttp2_frame_headers_free(&frame.headers);
memcpy(data, framedata, framedatalen); memcpy(data, framedata + bufoff, framedatalen - bufoff);
datalen = framedatalen; datalen = framedatalen - bufoff;
/* Followed by PRIORITY */ /* Followed by PRIORITY */
nghttp2_frame_priority_init(&frame.priority, 1, 0); nghttp2_frame_priority_init(&frame.priority, 1, 0);
@ -782,6 +787,7 @@ void test_nghttp2_session_continue(void)
uint8_t buffer[4096]; uint8_t buffer[4096];
uint8_t *bufp = buffer; uint8_t *bufp = buffer;
size_t buflen; size_t buflen;
size_t bufoff;
nghttp2_frame frame; nghttp2_frame frame;
nghttp2_nv *nva; nghttp2_nv *nva;
ssize_t nvlen; ssize_t nvlen;
@ -804,22 +810,24 @@ void test_nghttp2_session_continue(void)
nvlen = nghttp2_nv_array_copy(&nva, nv1, ARRLEN(nv1)); nvlen = nghttp2_nv_array_copy(&nva, nv1, ARRLEN(nv1));
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS,
1, NGHTTP2_PRI_DEFAULT, nva, nvlen); 1, NGHTTP2_PRI_DEFAULT, nva, nvlen);
framelen1 = nghttp2_frame_pack_headers(&framedata, &framedatalen, framelen1 = nghttp2_frame_pack_headers(&framedata, &framedatalen, &bufoff,
&frame.headers, &frame.headers,
&deflater); &deflater, 0);
nghttp2_frame_headers_free(&frame.headers); nghttp2_frame_headers_free(&frame.headers);
memcpy(buffer, framedata, framelen1); memcpy(buffer, framedata + bufoff, framelen1 - bufoff);
framelen1 -= bufoff;
nvlen = nghttp2_nv_array_copy(&nva, nv2, ARRLEN(nv2)); nvlen = nghttp2_nv_array_copy(&nva, nv2, ARRLEN(nv2));
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS,
3, NGHTTP2_PRI_DEFAULT, nva, nvlen); 3, NGHTTP2_PRI_DEFAULT, nva, nvlen);
framelen2 = nghttp2_frame_pack_headers(&framedata, &framedatalen, framelen2 = nghttp2_frame_pack_headers(&framedata, &framedatalen, &bufoff,
&frame.headers, &frame.headers,
&deflater); &deflater, 0);
nghttp2_frame_headers_free(&frame.headers); nghttp2_frame_headers_free(&frame.headers);
memcpy(buffer + framelen1, framedata, framelen2); memcpy(buffer + framelen1, framedata + bufoff, framelen2 - bufoff);
framelen2 -= bufoff;
buflen = framelen1 + framelen2; buflen = framelen1 + framelen2;
/* Receive 1st HEADERS and pause */ /* Receive 1st HEADERS and pause */
@ -955,6 +963,7 @@ 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));
@ -2173,6 +2182,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));
@ -2244,6 +2254,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,
@ -2415,6 +2426,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,
@ -3858,7 +3870,7 @@ void test_nghttp2_session_pack_data_with_padding(void)
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->data_pad_alignment = 512; session->pad_alignment = 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);
@ -3869,7 +3881,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(session->data_pad_alignment - datalen == frame->padlen); CU_ASSERT(session->pad_alignment - 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);
@ -3893,7 +3905,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(session->data_pad_alignment - datalen == frame->padlen); CU_ASSERT(session->pad_alignment - datalen == frame->padlen);
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));

View File

@ -159,3 +159,8 @@ 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;
}

View File

@ -29,6 +29,7 @@
# 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"
@ -57,4 +58,6 @@ 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 */