Add promised_stream_user_data parameter to nghttp2_submit_push_promise
This is very useful to associate application specific data to promised stream. nghttp2_nv_array_copy now does not complain the header field is large.
This commit is contained in:
parent
86aa905c10
commit
d1c1deaf03
|
@ -2140,6 +2140,13 @@ int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags,
|
||||||
* This function creates copies of all name/value pairs in |nva|. It
|
* This function creates copies of all name/value pairs in |nva|. It
|
||||||
* also lower-cases all names in |nva|.
|
* also lower-cases all names in |nva|.
|
||||||
*
|
*
|
||||||
|
* The |promised_stream_user_data| is a pointer to an arbitrary data
|
||||||
|
* which is associated to the promised stream this frame will open and
|
||||||
|
* make it in reserved state. It is available using
|
||||||
|
* `nghttp2_session_get_stream_user_data()`. The application can
|
||||||
|
* access it in :type:`nghttp2_before_frame_send_callback` and
|
||||||
|
* :type:`nghttp2_on_frame_send_callback` of this frame.
|
||||||
|
*
|
||||||
* Since the library reorders the frames and tries to send the highest
|
* Since the library reorders the frames and tries to send the highest
|
||||||
* prioritized one first and the HTTP/2.0 specification requires the
|
* prioritized one first and the HTTP/2.0 specification requires the
|
||||||
* stream ID must be strictly increasing, the promised stream ID
|
* stream ID must be strictly increasing, the promised stream ID
|
||||||
|
@ -2160,7 +2167,8 @@ int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags,
|
||||||
*/
|
*/
|
||||||
int nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,
|
int nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,
|
||||||
int32_t stream_id,
|
int32_t stream_id,
|
||||||
const nghttp2_nv *nva, size_t nvlen);
|
const nghttp2_nv *nva, size_t nvlen,
|
||||||
|
void *promised_stream_user_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
|
|
|
@ -598,10 +598,6 @@ ssize_t nghttp2_nv_array_copy(nghttp2_nv **nva_ptr,
|
||||||
size_t buflen = 0;
|
size_t buflen = 0;
|
||||||
nghttp2_nv *p;
|
nghttp2_nv *p;
|
||||||
for(i = 0; i < nvlen; ++i) {
|
for(i = 0; i < nvlen; ++i) {
|
||||||
if(nva[i].namelen > NGHTTP2_HD_MAX_NAME ||
|
|
||||||
nva[i].valuelen > NGHTTP2_HD_MAX_VALUE) {
|
|
||||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
buflen += nva[i].namelen + nva[i].valuelen;
|
buflen += nva[i].namelen + nva[i].valuelen;
|
||||||
}
|
}
|
||||||
/* If all name/value pair is 0-length, remove them */
|
/* If all name/value pair is 0-length, remove them */
|
||||||
|
|
|
@ -481,9 +481,6 @@ void nghttp2_nv_array_sort(nghttp2_nv *nva, size_t nvlen);
|
||||||
*
|
*
|
||||||
* NGHTTP2_ERR_NOMEM
|
* NGHTTP2_ERR_NOMEM
|
||||||
* Out of memory.
|
* Out of memory.
|
||||||
* NGHTTP2_ERR_INVALID_ARGUMENT
|
|
||||||
* The length of name or value in |nva| is strictly larger than
|
|
||||||
* NGHTTP2_MAX_HD_VALUE_LENGTH.
|
|
||||||
*/
|
*/
|
||||||
ssize_t nghttp2_nv_array_copy(nghttp2_nv **nva_ptr,
|
ssize_t nghttp2_nv_array_copy(nghttp2_nv **nva_ptr,
|
||||||
const nghttp2_nv *nva, size_t nvlen);
|
const nghttp2_nv *nva, size_t nvlen);
|
||||||
|
|
|
@ -1303,6 +1303,9 @@ static ssize_t nghttp2_session_prep_frame(nghttp2_session *session,
|
||||||
}
|
}
|
||||||
case NGHTTP2_PUSH_PROMISE: {
|
case NGHTTP2_PUSH_PROMISE: {
|
||||||
nghttp2_stream *stream;
|
nghttp2_stream *stream;
|
||||||
|
nghttp2_headers_aux_data *aux_data;
|
||||||
|
aux_data = (nghttp2_headers_aux_data*)item->aux_data;
|
||||||
|
|
||||||
rv = nghttp2_session_predicate_push_promise_send(session,
|
rv = nghttp2_session_predicate_push_promise_send(session,
|
||||||
frame->hd.stream_id);
|
frame->hd.stream_id);
|
||||||
if(rv != 0) {
|
if(rv != 0) {
|
||||||
|
@ -1325,12 +1328,13 @@ static ssize_t nghttp2_session_prep_frame(nghttp2_session *session,
|
||||||
|
|
||||||
stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
|
stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
|
||||||
assert(stream);
|
assert(stream);
|
||||||
if(nghttp2_session_open_stream
|
if(!nghttp2_session_open_stream
|
||||||
(session, frame->push_promise.promised_stream_id,
|
(session, frame->push_promise.promised_stream_id,
|
||||||
NGHTTP2_STREAM_FLAG_PUSH,
|
NGHTTP2_STREAM_FLAG_PUSH,
|
||||||
nghttp2_pushed_stream_pri(stream),
|
nghttp2_pushed_stream_pri(stream),
|
||||||
NGHTTP2_STREAM_RESERVED,
|
NGHTTP2_STREAM_RESERVED,
|
||||||
NULL) == NULL) {
|
aux_data ?
|
||||||
|
aux_data->stream_user_data : NULL)) {
|
||||||
return NGHTTP2_ERR_NOMEM;
|
return NGHTTP2_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -181,28 +181,41 @@ int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags,
|
||||||
|
|
||||||
int nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,
|
int nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,
|
||||||
int32_t stream_id,
|
int32_t stream_id,
|
||||||
const nghttp2_nv *nva, size_t nvlen)
|
const nghttp2_nv *nva, size_t nvlen,
|
||||||
|
void *promised_stream_user_data)
|
||||||
{
|
{
|
||||||
nghttp2_frame *frame;
|
nghttp2_frame *frame;
|
||||||
nghttp2_nv *nva_copy;
|
nghttp2_nv *nva_copy;
|
||||||
uint8_t flags_copy;
|
uint8_t flags_copy;
|
||||||
|
nghttp2_headers_aux_data *aux_data = NULL;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
frame = malloc(sizeof(nghttp2_frame));
|
frame = malloc(sizeof(nghttp2_frame));
|
||||||
if(frame == NULL) {
|
if(frame == NULL) {
|
||||||
return NGHTTP2_ERR_NOMEM;
|
return NGHTTP2_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
|
if(promised_stream_user_data) {
|
||||||
|
aux_data = malloc(sizeof(nghttp2_headers_aux_data));
|
||||||
|
if(aux_data == NULL) {
|
||||||
|
free(frame);
|
||||||
|
return NGHTTP2_ERR_NOMEM;
|
||||||
|
}
|
||||||
|
aux_data->data_prd = NULL;
|
||||||
|
aux_data->stream_user_data = promised_stream_user_data;
|
||||||
|
}
|
||||||
rv = nghttp2_nv_array_copy(&nva_copy, nva, nvlen);
|
rv = nghttp2_nv_array_copy(&nva_copy, nva, nvlen);
|
||||||
if(rv < 0) {
|
if(rv < 0) {
|
||||||
|
free(aux_data);
|
||||||
free(frame);
|
free(frame);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
flags_copy = NGHTTP2_FLAG_END_HEADERS;
|
flags_copy = NGHTTP2_FLAG_END_HEADERS;
|
||||||
nghttp2_frame_push_promise_init(&frame->push_promise, flags_copy,
|
nghttp2_frame_push_promise_init(&frame->push_promise, flags_copy,
|
||||||
stream_id, -1, nva_copy, nvlen);
|
stream_id, -1, nva_copy, nvlen);
|
||||||
rv = nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL);
|
rv = nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, aux_data);
|
||||||
if(rv != 0) {
|
if(rv != 0) {
|
||||||
nghttp2_frame_push_promise_free(&frame->push_promise);
|
nghttp2_frame_push_promise_free(&frame->push_promise);
|
||||||
|
free(aux_data);
|
||||||
free(frame);
|
free(frame);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -515,7 +515,8 @@ int Http2Handler::submit_push_promise(Request *req,
|
||||||
http2::make_nv_ls(":authority", (*itr).second)
|
http2::make_nv_ls(":authority", (*itr).second)
|
||||||
};
|
};
|
||||||
return nghttp2_submit_push_promise(session_, NGHTTP2_FLAG_END_HEADERS,
|
return nghttp2_submit_push_promise(session_, NGHTTP2_FLAG_END_HEADERS,
|
||||||
req->stream_id, nva.data(), nva.size());
|
req->stream_id, nva.data(), nva.size(),
|
||||||
|
nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Http2Handler::add_stream(int32_t stream_id, std::unique_ptr<Request> req)
|
void Http2Handler::add_stream(int32_t stream_id, std::unique_ptr<Request> req)
|
||||||
|
|
|
@ -406,8 +406,9 @@ void test_nghttp2_nv_array_copy(void)
|
||||||
|
|
||||||
nghttp2_nv_array_del(nva);
|
nghttp2_nv_array_del(nva);
|
||||||
|
|
||||||
|
/* Large header field is acceptable */
|
||||||
rv = nghttp2_nv_array_copy(&nva, &bignv, 1);
|
rv = nghttp2_nv_array_copy(&nva, &bignv, 1);
|
||||||
CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
|
CU_ASSERT(1 == rv);
|
||||||
|
|
||||||
free(bignv.value);
|
free(bignv.value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2201,7 +2201,7 @@ void test_nghttp2_session_reprioritize_stream(void)
|
||||||
|
|
||||||
CU_ASSERT(0 == nghttp2_submit_push_promise(session,
|
CU_ASSERT(0 == nghttp2_submit_push_promise(session,
|
||||||
NGHTTP2_FLAG_END_HEADERS,
|
NGHTTP2_FLAG_END_HEADERS,
|
||||||
3, NULL, 0));
|
3, NULL, 0, NULL));
|
||||||
ud.block_count = 0;
|
ud.block_count = 0;
|
||||||
CU_ASSERT(0 == nghttp2_session_send(session));
|
CU_ASSERT(0 == nghttp2_session_send(session));
|
||||||
/* Now PUSH_PROMISE is in aob */
|
/* Now PUSH_PROMISE is in aob */
|
||||||
|
@ -2846,7 +2846,7 @@ void test_nghttp2_submit_push_promise(void)
|
||||||
NGHTTP2_PRI_DEFAULT,
|
NGHTTP2_PRI_DEFAULT,
|
||||||
NGHTTP2_STREAM_OPENING, NULL);
|
NGHTTP2_STREAM_OPENING, NULL);
|
||||||
CU_ASSERT(0 == nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1,
|
CU_ASSERT(0 == nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1,
|
||||||
nv, ARRLEN(nv)));
|
nv, ARRLEN(nv), &ud));
|
||||||
|
|
||||||
ud.frame_send_cb_called = 0;
|
ud.frame_send_cb_called = 0;
|
||||||
ud.sent_frame_type = 0;
|
ud.sent_frame_type = 0;
|
||||||
|
@ -2855,6 +2855,7 @@ void test_nghttp2_submit_push_promise(void)
|
||||||
CU_ASSERT(NGHTTP2_PUSH_PROMISE == ud.sent_frame_type);
|
CU_ASSERT(NGHTTP2_PUSH_PROMISE == ud.sent_frame_type);
|
||||||
stream = nghttp2_session_get_stream(session, 2);
|
stream = nghttp2_session_get_stream(session, 2);
|
||||||
CU_ASSERT(NGHTTP2_STREAM_RESERVED == stream->state);
|
CU_ASSERT(NGHTTP2_STREAM_RESERVED == stream->state);
|
||||||
|
CU_ASSERT(&ud == nghttp2_session_get_stream_user_data(session, 2));
|
||||||
|
|
||||||
nghttp2_session_del(session);
|
nghttp2_session_del(session);
|
||||||
}
|
}
|
||||||
|
@ -3039,7 +3040,8 @@ void test_nghttp2_submit_invalid_nv(void)
|
||||||
/* nghttp2_submit_push_promise */
|
/* nghttp2_submit_push_promise */
|
||||||
CU_ASSERT(0 ==
|
CU_ASSERT(0 ==
|
||||||
nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 2,
|
nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 2,
|
||||||
empty_name_nv, ARRLEN(empty_name_nv)));
|
empty_name_nv, ARRLEN(empty_name_nv),
|
||||||
|
NULL));
|
||||||
|
|
||||||
nghttp2_session_del(session);
|
nghttp2_session_del(session);
|
||||||
}
|
}
|
||||||
|
@ -4128,7 +4130,7 @@ void test_nghttp2_session_pack_headers_with_padding(void)
|
||||||
/* Check PUSH_PROMISE */
|
/* Check PUSH_PROMISE */
|
||||||
CU_ASSERT(0 ==
|
CU_ASSERT(0 ==
|
||||||
nghttp2_submit_push_promise(sv_session, NGHTTP2_FLAG_NONE, 1,
|
nghttp2_submit_push_promise(sv_session, NGHTTP2_FLAG_NONE, 1,
|
||||||
nva, ARRLEN(nva)));
|
nva, ARRLEN(nva), NULL));
|
||||||
acc.length = 0;
|
acc.length = 0;
|
||||||
CU_ASSERT(0 == nghttp2_session_send(sv_session));
|
CU_ASSERT(0 == nghttp2_session_send(sv_session));
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue