Commit 3f3f258c authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

Add padding to PUSH_PROMISE

parent 1e95c8b3
......@@ -266,7 +266,7 @@ ssize_t nghttp2_frame_pack_headers(uint8_t **buf_ptr,
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;
return *bufoff_ptr + NGHTTP2_FRAME_HEAD_LENGTH + frame->hd.length;
}
int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
......@@ -396,35 +396,45 @@ int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr,
ssize_t nghttp2_frame_pack_push_promise(uint8_t **buf_ptr,
size_t *buflen_ptr,
size_t *bufoff_ptr,
nghttp2_push_promise *frame,
nghttp2_hd_deflater *deflater)
{
ssize_t framelen;
size_t nv_offset = NGHTTP2_FRAME_HEAD_LENGTH + 4;
size_t payloadoff = NGHTTP2_FRAME_HEAD_LENGTH + 2;
size_t nv_offset = payloadoff + 4;
ssize_t rv;
size_t payloadlen;
rv = nghttp2_hd_deflate_hd(deflater, buf_ptr, buflen_ptr, nv_offset,
frame->nva, frame->nvlen);
if(rv < 0) {
return rv;
}
framelen = rv + nv_offset;
if(NGHTTP2_FRAME_HEAD_LENGTH + NGHTTP2_MAX_FRAME_LENGTH < rv + nv_offset) {
frame->hd.length = NGHTTP2_MAX_FRAME_LENGTH;
frame->hd.flags &= ~NGHTTP2_FLAG_END_HEADERS;
} else {
frame->hd.length = framelen - NGHTTP2_FRAME_HEAD_LENGTH;
}
payloadlen = 4 + rv;
*bufoff_ptr = 2;
frame->padlen = 0;
frame->hd.length = payloadlen;
/* If frame->nvlen == 0, *buflen_ptr may be smaller than
nv_offset */
rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, nv_offset);
if(rv < 0) {
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 */
nghttp2_frame_pack_frame_hd(*buf_ptr, &frame->hd);
nghttp2_put_uint32be(&(*buf_ptr)[8], frame->promised_stream_id);
return framelen;
if(NGHTTP2_MAX_FRAME_LENGTH < payloadlen) {
/* Needs CONTINUATION */
nghttp2_frame_hd hd = frame->hd;
hd.flags &= ~NGHTTP2_FLAG_END_HEADERS;
hd.length = NGHTTP2_MAX_FRAME_LENGTH;
nghttp2_frame_pack_frame_hd(*buf_ptr + *bufoff_ptr, &hd);
} else {
nghttp2_frame_pack_frame_hd(*buf_ptr + *bufoff_ptr, &frame->hd);
}
nghttp2_put_uint32be(&(*buf_ptr)[payloadoff], frame->promised_stream_id);
return *bufoff_ptr + NGHTTP2_FRAME_HEAD_LENGTH + frame->hd.length;
}
int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
......
......@@ -256,12 +256,20 @@ int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr,
* expansion occurred, memory previously pointed by |*buf_ptr| may
* change. |*buf_ptr| and |*buflen_ptr| are updated accordingly.
*
* The first byte the frame is serialized is returned in the
* |*bufoff_ptr|. Currently, it is always 2 to account for possible
* PAD_HIGH and PAD_LOW.
*
* frame->hd.length is assigned after length is determined during
* packing process. If payload length is strictly larger than
* NGHTTP2_MAX_FRAME_LENGTH, payload data is still serialized as is,
* but frame->hd.length is set to NGHTTP2_MAX_FRAME_LENGTH and
* NGHTTP2_FLAG_END_HEADERS flag is cleared from frame->hd.flags.
*
* This function returns the size of packed frame (which includes
* |*bufoff_ptr| bytes) if it succeeds, or returns one of the
* following negative error codes:
*
* This function returns the size of packed frame if it succeeds, or
* returns one of the following negative error codes:
*
......@@ -274,6 +282,7 @@ int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr,
*/
ssize_t nghttp2_frame_pack_push_promise(uint8_t **buf_ptr,
size_t *buflen_ptr,
size_t *bufoff_ptr,
nghttp2_push_promise *frame,
nghttp2_hd_deflater *deflater);
......
This diff is collapsed.
......@@ -263,10 +263,12 @@ void test_nghttp2_frame_pack_push_promise()
nghttp2_push_promise 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;
ssize_t nv_offset;
nva_out_init(&out);
nghttp2_hd_deflate_init(&deflater);
......@@ -276,16 +278,19 @@ void test_nghttp2_frame_pack_push_promise()
nvlen = HEADERS_LENGTH;
nghttp2_frame_push_promise_init(&frame, NGHTTP2_FLAG_END_PUSH_PROMISE,
1000000007, (1U << 31) - 1, nva, nvlen);
framelen = nghttp2_frame_pack_push_promise(&buf, &buflen, &frame, &deflater);
framelen = nghttp2_frame_pack_push_promise(&buf, &buflen, &bufoff, &frame,
&deflater);
CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf, framelen));
check_frame_header(framelen - NGHTTP2_FRAME_HEAD_LENGTH,
CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe,
buf + bufoff, framelen - bufoff));
check_frame_header(framelen - bufoff - NGHTTP2_FRAME_HEAD_LENGTH,
NGHTTP2_PUSH_PROMISE,
NGHTTP2_FLAG_END_PUSH_PROMISE, 1000000007, &oframe.hd);
CU_ASSERT((1U << 31) - 1 == oframe.promised_stream_id);
CU_ASSERT(framelen - 12 ==
inflate_hd(&inflater, &out, buf + 12, framelen - 12));
nv_offset = bufoff + NGHTTP2_FRAME_HEAD_LENGTH + 4;
CU_ASSERT(framelen - nv_offset ==
inflate_hd(&inflater, &out, buf + nv_offset, framelen - nv_offset));
CU_ASSERT(7 == out.nvlen);
CU_ASSERT(nvnameeq("method", &out.nva[0]));
......
......@@ -4044,7 +4044,7 @@ void test_nghttp2_session_pack_headers_with_padding(void)
nghttp2_session *session, *sv_session;
accumulator acc;
my_user_data ud;
nghttp2_session_callbacks callbacks, sv_callbacks;
nghttp2_session_callbacks callbacks;
nghttp2_nv nva[8190];
size_t i;
......@@ -4059,15 +4059,13 @@ void test_nghttp2_session_pack_headers_with_padding(void)
callbacks.send_callback = accumulator_send_callback;
callbacks.on_frame_send_callback = on_frame_send_callback;
callbacks.select_padding_callback = select_padding_callback;
callbacks.on_frame_recv_callback = on_frame_recv_callback;
acc.length = 0;
ud.acc = &acc;
memset(&sv_callbacks, 0, sizeof(sv_callbacks));
sv_callbacks.on_frame_recv_callback = on_frame_recv_callback;
nghttp2_session_client_new(&session, &callbacks, &ud);
nghttp2_session_server_new(&sv_session, &sv_callbacks, &ud);
nghttp2_session_server_new(&sv_session, &callbacks, &ud);
ud.padding_boundary = 16385;
......@@ -4083,6 +4081,20 @@ void test_nghttp2_session_pack_headers_with_padding(void)
CU_ASSERT(1 == ud.frame_recv_cb_called);
CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(sv_session));
/* Check PUSH_PROMISE */
CU_ASSERT(0 ==
nghttp2_submit_push_promise(sv_session, NGHTTP2_FLAG_NONE, 1,
nva, ARRLEN(nva)));
acc.length = 0;
CU_ASSERT(0 == nghttp2_session_send(sv_session));
CU_ASSERT(acc.length > NGHTTP2_MAX_FRAME_LENGTH);
ud.frame_recv_cb_called = 0;
CU_ASSERT((ssize_t)acc.length ==
nghttp2_session_mem_recv(session, acc.buf, acc.length));
CU_ASSERT(1 == ud.frame_recv_cb_called);
CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
nghttp2_session_del(sv_session);
nghttp2_session_del(session);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment