Embed aux_data to nghttp2_outbound_item so that we can save some malloc() calls

This commit is contained in:
Tatsuhiro Tsujikawa 2014-09-30 21:45:15 +09:00
parent df56b69060
commit e20b417b84
6 changed files with 52 additions and 68 deletions

View File

@ -37,9 +37,6 @@ void nghttp2_outbound_item_free(nghttp2_outbound_item *item)
switch(frame->hd.type) { switch(frame->hd.type) {
case NGHTTP2_HEADERS: case NGHTTP2_HEADERS:
nghttp2_frame_headers_free(&frame->headers); nghttp2_frame_headers_free(&frame->headers);
if(item->aux_data) {
free(((nghttp2_headers_aux_data*)item->aux_data)->data_prd);
}
break; break;
case NGHTTP2_PRIORITY: case NGHTTP2_PRIORITY:
nghttp2_frame_priority_free(&frame->priority); nghttp2_frame_priority_free(&frame->priority);
@ -76,5 +73,4 @@ void nghttp2_outbound_item_free(nghttp2_outbound_item *item)
assert(0); assert(0);
} }
free(item->frame); free(item->frame);
free(item->aux_data);
} }

View File

@ -39,18 +39,24 @@
/* Highest weight for PING */ /* Highest weight for PING */
#define NGHTTP2_OB_PING_WEIGHT 302 #define NGHTTP2_OB_PING_WEIGHT 302
/* struct used for HEADERS and PUSH_PROMISE frame */
typedef struct { typedef struct {
nghttp2_data_provider *data_prd; nghttp2_data_provider data_prd;
void *stream_user_data; void *stream_user_data;
} nghttp2_headers_aux_data; } nghttp2_headers_aux_data;
/* Additional data which cannot be stored in nghttp2_frame struct */
typedef union {
nghttp2_headers_aux_data headers;
} nghttp2_aux_data;
typedef struct { typedef struct {
nghttp2_aux_data aux_data;
int64_t seq; int64_t seq;
/* Reset count of weight. See comment for last_cycle in /* Reset count of weight. See comment for last_cycle in
nghttp2_session.h */ nghttp2_session.h */
uint64_t cycle; uint64_t cycle;
void *frame; void *frame;
void *aux_data;
/* Type of |frame|. NGHTTP2_CTRL: nghttp2_frame*, NGHTTP2_DATA: /* Type of |frame|. NGHTTP2_CTRL: nghttp2_frame*, NGHTTP2_DATA:
nghttp2_private_data* */ nghttp2_private_data* */
nghttp2_frame_category frame_cat; nghttp2_frame_category frame_cat;

View File

@ -640,7 +640,7 @@ int nghttp2_session_reprioritize_stream
int nghttp2_session_add_frame(nghttp2_session *session, int nghttp2_session_add_frame(nghttp2_session *session,
nghttp2_frame_category frame_cat, nghttp2_frame_category frame_cat,
void *abs_frame, void *abs_frame,
void *aux_data) nghttp2_aux_data *aux_data)
{ {
/* TODO Return error if stream is not found for the frame requiring /* TODO Return error if stream is not found for the frame requiring
stream presence. */ stream presence. */
@ -654,7 +654,13 @@ int nghttp2_session_add_frame(nghttp2_session *session,
item->frame_cat = frame_cat; item->frame_cat = frame_cat;
item->frame = abs_frame; item->frame = abs_frame;
item->aux_data = aux_data;
if(aux_data) {
item->aux_data = *aux_data;
} else {
memset(&item->aux_data, 0, sizeof(item->aux_data));
}
item->seq = session->next_seq++; item->seq = session->next_seq++;
/* We use cycle for DATA only */ /* We use cycle for DATA only */
item->cycle = 0; item->cycle = 0;
@ -1546,7 +1552,7 @@ static int session_prep_frame(nghttp2_session *session,
nghttp2_headers_aux_data *aux_data; nghttp2_headers_aux_data *aux_data;
size_t estimated_payloadlen; size_t estimated_payloadlen;
aux_data = (nghttp2_headers_aux_data*)item->aux_data; aux_data = &item->aux_data.headers;
estimated_payloadlen = session_estimate_headers_payload estimated_payloadlen = session_estimate_headers_payload
(session, frame->headers.nva, frame->headers.nvlen, (session, frame->headers.nva, frame->headers.nvlen,
@ -1570,7 +1576,7 @@ static int session_prep_frame(nghttp2_session *session,
NGHTTP2_STREAM_FLAG_NONE, NGHTTP2_STREAM_FLAG_NONE,
&frame->headers.pri_spec, &frame->headers.pri_spec,
NGHTTP2_STREAM_INITIAL, NGHTTP2_STREAM_INITIAL,
aux_data ? aux_data->stream_user_data : NULL); aux_data->stream_user_data);
if(stream == NULL) { if(stream == NULL) {
return NGHTTP2_ERR_NOMEM; return NGHTTP2_ERR_NOMEM;
@ -1580,7 +1586,7 @@ static int session_prep_frame(nghttp2_session *session,
(session, frame->hd.stream_id) == 0) { (session, frame->hd.stream_id) == 0) {
frame->headers.cat = NGHTTP2_HCAT_PUSH_RESPONSE; frame->headers.cat = NGHTTP2_HCAT_PUSH_RESPONSE;
if(aux_data && aux_data->stream_user_data) { if(aux_data->stream_user_data) {
nghttp2_stream *stream; nghttp2_stream *stream;
stream = nghttp2_session_get_stream(session, frame->hd.stream_id); stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
@ -1671,7 +1677,7 @@ static int session_prep_frame(nghttp2_session *session,
nghttp2_priority_spec pri_spec; nghttp2_priority_spec pri_spec;
size_t estimated_payloadlen; size_t estimated_payloadlen;
aux_data = (nghttp2_headers_aux_data*)item->aux_data; aux_data = &item->aux_data.headers;
estimated_payloadlen = session_estimate_headers_payload estimated_payloadlen = session_estimate_headers_payload
(session, frame->push_promise.nva, frame->push_promise.nvlen, 0); (session, frame->push_promise.nva, frame->push_promise.nvlen, 0);
@ -1709,8 +1715,7 @@ static int session_prep_frame(nghttp2_session *session,
NGHTTP2_STREAM_FLAG_PUSH, NGHTTP2_STREAM_FLAG_PUSH,
&pri_spec, &pri_spec,
NGHTTP2_STREAM_RESERVED, NGHTTP2_STREAM_RESERVED,
aux_data ? aux_data->stream_user_data)) {
aux_data->stream_user_data : NULL)) {
return NGHTTP2_ERR_NOMEM; return NGHTTP2_ERR_NOMEM;
} }
break; break;
@ -2094,11 +2099,11 @@ static int session_after_frame_sent(nghttp2_session *session)
return rv; return rv;
} }
/* We assume aux_data is a pointer to nghttp2_headers_aux_data */ /* We assume aux_data is a pointer to nghttp2_headers_aux_data */
aux_data = (nghttp2_headers_aux_data*)item->aux_data; aux_data = &item->aux_data.headers;
if(aux_data && aux_data->data_prd) { if(aux_data->data_prd.read_callback) {
/* nghttp2_submit_data() makes a copy of aux_data->data_prd */ /* nghttp2_submit_data() makes a copy of aux_data->data_prd */
rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM,
frame->hd.stream_id, aux_data->data_prd); frame->hd.stream_id, &aux_data->data_prd);
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
return rv; return rv;
} }
@ -2122,10 +2127,10 @@ static int session_after_frame_sent(nghttp2_session *session)
return rv; return rv;
} }
/* We assume aux_data is a pointer to nghttp2_headers_aux_data */ /* We assume aux_data is a pointer to nghttp2_headers_aux_data */
aux_data = (nghttp2_headers_aux_data*)item->aux_data; aux_data = &item->aux_data.headers;
if(aux_data && aux_data->data_prd) { if(aux_data->data_prd.read_callback) {
rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM,
frame->hd.stream_id, aux_data->data_prd); frame->hd.stream_id, &aux_data->data_prd);
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
return rv; return rv;
} }

View File

@ -263,10 +263,12 @@ int nghttp2_session_is_my_stream_id(nghttp2_session *session,
* |frame_cat| must be either NGHTTP2_CTRL or NGHTTP2_DATA. If the * |frame_cat| must be either NGHTTP2_CTRL or NGHTTP2_DATA. If the
* |frame_cat| is NGHTTP2_CTRL, the |frame| must be a pointer to * |frame_cat| is NGHTTP2_CTRL, the |frame| must be a pointer to
* nghttp2_frame. If the |frame_cat| is NGHTTP2_DATA, it must be a * nghttp2_frame. If the |frame_cat| is NGHTTP2_DATA, it must be a
* pointer to nghttp2_private_data. |aux_data| is a pointer to the arbitrary * pointer to nghttp2_private_data. |aux_data| specifies additional
* data. Its interpretation is defined per the type of the frame. When * data. Which union member is filled depends on the type of the
* this function succeeds, it takes ownership of |frame| and * frame. Currently, HEADERS and PUSH_PROMISE frames use headers
* |aux_data|, so caller must not free them on success. * member. When this function succeeds, it takes ownership of
* |frame|. So caller must not free it on success. The content of
* |aux_data| is just copied.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
@ -276,7 +278,7 @@ int nghttp2_session_is_my_stream_id(nghttp2_session *session,
*/ */
int nghttp2_session_add_frame(nghttp2_session *session, int nghttp2_session_add_frame(nghttp2_session *session,
nghttp2_frame_category frame_cat, nghttp2_frame_category frame_cat,
void *abs_frame, void *aux_data); void *abs_frame, nghttp2_aux_data *aux_data);
/* /*
* Adds RST_STREAM frame for the stream |stream_id| with the error * Adds RST_STREAM frame for the stream |stream_id| with the error

View File

@ -48,8 +48,7 @@ static int32_t submit_headers_shared
int rv; int rv;
uint8_t flags_copy; uint8_t flags_copy;
nghttp2_frame *frame = NULL; nghttp2_frame *frame = NULL;
nghttp2_data_provider *data_prd_copy = NULL; nghttp2_aux_data aux_data = {{{{0}, 0}, 0}};
nghttp2_headers_aux_data *aux_data = NULL;
nghttp2_headers_category hcat; nghttp2_headers_category hcat;
if(stream_id == 0) { if(stream_id == 0) {
@ -58,22 +57,11 @@ static int32_t submit_headers_shared
} }
if(data_prd != NULL && data_prd->read_callback != NULL) { if(data_prd != NULL && data_prd->read_callback != NULL) {
data_prd_copy = malloc(sizeof(nghttp2_data_provider)); aux_data.headers.data_prd = *data_prd;
if(data_prd_copy == NULL) {
rv = NGHTTP2_ERR_NOMEM;
goto fail;
}
*data_prd_copy = *data_prd;
}
if(data_prd || stream_user_data) {
aux_data = malloc(sizeof(nghttp2_headers_aux_data));
if(aux_data == NULL) {
rv = NGHTTP2_ERR_NOMEM;
goto fail;
}
aux_data->data_prd = data_prd_copy;
aux_data->stream_user_data = stream_user_data;
} }
aux_data.headers.stream_user_data = stream_user_data;
frame = malloc(sizeof(nghttp2_frame)); frame = malloc(sizeof(nghttp2_frame));
if(frame == NULL) { if(frame == NULL) {
rv = NGHTTP2_ERR_NOMEM; rv = NGHTTP2_ERR_NOMEM;
@ -103,8 +91,7 @@ static int32_t submit_headers_shared
hcat, pri_spec, nva_copy, nvlen); hcat, pri_spec, nva_copy, nvlen);
rv = nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, rv = nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, &aux_data);
aux_data);
if(rv != 0) { if(rv != 0) {
nghttp2_frame_headers_free(&frame->headers); nghttp2_frame_headers_free(&frame->headers);
@ -122,8 +109,7 @@ static int32_t submit_headers_shared
nghttp2_nv_array_del(nva_copy); nghttp2_nv_array_del(nva_copy);
fail2: fail2:
free(frame); free(frame);
free(aux_data);
free(data_prd_copy);
return rv; return rv;
} }
@ -266,7 +252,7 @@ int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,
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; nghttp2_aux_data aux_data = {{{{0}, 0}, 0}};
int32_t promised_stream_id; int32_t promised_stream_id;
int rv; int rv;
@ -282,18 +268,11 @@ int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,
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)); aux_data.headers.stream_user_data = promised_stream_user_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;
} }
@ -302,7 +281,6 @@ int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,
/* All 32bit signed stream IDs are spent. */ /* All 32bit signed stream IDs are spent. */
if(session->next_stream_id > INT32_MAX) { if(session->next_stream_id > INT32_MAX) {
free(aux_data);
free(frame); free(frame);
return NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE; return NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE;
@ -315,11 +293,10 @@ int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,
stream_id, promised_stream_id, stream_id, promised_stream_id,
nva_copy, nvlen); nva_copy, nvlen);
rv = nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, aux_data); 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 rv; return rv;

View File

@ -1705,15 +1705,14 @@ void test_nghttp2_session_add_frame(void)
MAKE_NV("version", "HTTP/1.1") MAKE_NV("version", "HTTP/1.1")
}; };
nghttp2_frame *frame; nghttp2_frame *frame;
nghttp2_headers_aux_data *aux_data = nghttp2_aux_data aux_data;
malloc(sizeof(nghttp2_headers_aux_data));
nghttp2_nv *nva; nghttp2_nv *nva;
ssize_t nvlen; ssize_t nvlen;
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;
memset(aux_data, 0, sizeof(nghttp2_headers_aux_data)); memset(&aux_data, 0, sizeof(aux_data));
acc.length = 0; acc.length = 0;
user_data.acc = &acc; user_data.acc = &acc;
@ -1731,7 +1730,7 @@ void test_nghttp2_session_add_frame(void)
session->next_stream_id += 2; session->next_stream_id += 2;
CU_ASSERT(0 == nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, CU_ASSERT(0 == nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame,
aux_data)); &aux_data));
CU_ASSERT(0 == nghttp2_pq_empty(&session->ob_ss_pq)); CU_ASSERT(0 == nghttp2_pq_empty(&session->ob_ss_pq));
CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(NGHTTP2_HEADERS == acc.buf[3]); CU_ASSERT(NGHTTP2_HEADERS == acc.buf[3]);
@ -2660,10 +2659,9 @@ void test_nghttp2_session_send_headers_start_stream(void)
nghttp2_session_callbacks callbacks; nghttp2_session_callbacks callbacks;
nghttp2_frame *frame = malloc(sizeof(nghttp2_frame)); nghttp2_frame *frame = malloc(sizeof(nghttp2_frame));
nghttp2_stream *stream; nghttp2_stream *stream;
nghttp2_headers_aux_data *aux_data = nghttp2_aux_data aux_data;
malloc(sizeof(nghttp2_headers_aux_data));
memset(aux_data, 0, sizeof(nghttp2_headers_aux_data)); memset(&aux_data, 0, sizeof(aux_data));
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
callbacks.send_callback = null_send_callback; callbacks.send_callback = null_send_callback;
@ -2674,7 +2672,7 @@ void test_nghttp2_session_send_headers_start_stream(void)
NGHTTP2_HCAT_REQUEST, NULL, NULL, 0); NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
session->next_stream_id += 2; session->next_stream_id += 2;
nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, aux_data); nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, &aux_data);
CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == nghttp2_session_send(session));
stream = nghttp2_session_get_stream(session, 1); stream = nghttp2_session_get_stream(session, 1);
CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state); CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);