Remove nghttp2_on_data_recv_callback and nghttp2_on_data_send_callback

nghttp2_data is added to nghttp2_frame union. When DATA is
received, nghttp2_on_frame_recv_callback is called. When DATA is
sent, nghttp2_on_frame_send_callback is called.
This commit is contained in:
Tatsuhiro Tsujikawa 2014-01-27 22:13:41 +09:00
parent fc07a62337
commit a3082b7c1e
13 changed files with 138 additions and 237 deletions

View File

@ -579,6 +579,16 @@ typedef struct {
nghttp2_data_source_read_callback read_callback; nghttp2_data_source_read_callback read_callback;
} nghttp2_data_provider; } nghttp2_data_provider;
/**
* @struct
*
* The DATA frame. The received data is delivered via
* :type:`nghttp2_on_data_chunk_recv_callback`.
*/
typedef struct {
nghttp2_frame_hd hd;
} nghttp2_data;
/** /**
* @enum * @enum
* *
@ -795,6 +805,10 @@ typedef union {
* The frame header, which is convenient to inspect frame header. * The frame header, which is convenient to inspect frame header.
*/ */
nghttp2_frame_hd hd; nghttp2_frame_hd hd;
/**
* The DATA frame.
*/
nghttp2_data data;
/** /**
* The HEADERS frame. * The HEADERS frame.
*/ */
@ -869,9 +883,9 @@ typedef ssize_t (*nghttp2_recv_callback)
/** /**
* @functypedef * @functypedef
* *
* Callback function invoked by `nghttp2_session_recv()` when a * Callback function invoked by `nghttp2_session_recv()` when a aframe
* non-DATA frame is received. The |user_data| pointer is the third * is received. The |user_data| pointer is the third argument passed
* argument passed in to the call to `nghttp2_session_client_new()` or * in to the call to `nghttp2_session_client_new()` or
* `nghttp2_session_server_new()`. * `nghttp2_session_server_new()`.
* *
* If frame is HEADERS or PUSH_PROMISE, the ``nva`` and ``nvlen`` * If frame is HEADERS or PUSH_PROMISE, the ``nva`` and ``nvlen``
@ -923,7 +937,7 @@ typedef int (*nghttp2_on_invalid_frame_recv_callback)
* to. The |flags| is the flags of DATA frame which this data chunk is * to. The |flags| is the flags of DATA frame which this data chunk is
* contained. ``(flags & NGHTTP2_FLAG_END_STREAM) != 0`` does not * contained. ``(flags & NGHTTP2_FLAG_END_STREAM) != 0`` does not
* necessarily mean this chunk of data is the last one in the * necessarily mean this chunk of data is the last one in the
* stream. You should use :type:`nghttp2_on_data_recv_callback` to * stream. You should use :type:`nghttp2_on_frame_recv_callback` to
* know all data frames are received. The |user_data| pointer is the * know all data frames are received. The |user_data| pointer is the
* third argument passed in to the call to * third argument passed in to the call to
* `nghttp2_session_client_new()` or `nghttp2_session_server_new()`. * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`.
@ -946,24 +960,6 @@ typedef int (*nghttp2_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,
const uint8_t *data, size_t len, void *user_data); const uint8_t *data, size_t len, void *user_data);
/**
* @functypedef
*
* Callback function invoked when DATA frame is received. The actual
* data it contains are received by
* :type:`nghttp2_on_data_chunk_recv_callback`. The |user_data|
* pointer is the third argument passed in to the call to
* `nghttp2_session_client_new()` or `nghttp2_session_server_new()`.
*
* The implementation of this function must return 0 if it
* succeeds. If nonzero is returned, it is treated as fatal error and
* `nghttp2_session_recv()` and `nghttp2_session_send()` functions
* immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
*/
typedef int (*nghttp2_on_data_recv_callback)
(nghttp2_session *session, uint16_t length, uint8_t flags, int32_t stream_id,
void *user_data);
/** /**
* @functypedef * @functypedef
* *
@ -986,10 +982,9 @@ typedef int (*nghttp2_before_frame_send_callback)
/** /**
* @functypedef * @functypedef
* *
* Callback function invoked after the non-DATA frame |frame| is sent. * Callback function invoked after the frame |frame| is sent. The
* The |user_data| pointer is the third argument passed in to the call * |user_data| pointer is the third argument passed in to the call to
* to `nghttp2_session_client_new()` or * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`.
* `nghttp2_session_server_new()`.
* *
* The implementation of this function must return 0 if it * The implementation of this function must return 0 if it
* succeeds. If nonzero is returned, it is treated as fatal error and * succeeds. If nonzero is returned, it is treated as fatal error and
@ -1018,22 +1013,6 @@ typedef int (*nghttp2_on_frame_not_send_callback)
(nghttp2_session *session, const nghttp2_frame *frame, int lib_error_code, (nghttp2_session *session, const nghttp2_frame *frame, int lib_error_code,
void *user_data); void *user_data);
/**
* @functypedef
*
* Callback function invoked after DATA frame is sent. The |user_data|
* pointer is the third argument passed in to the call to
* `nghttp2_session_client_new()` or `nghttp2_session_server_new()`.
*
* The implementation of this function must return 0 if it
* succeeds. If nonzero is returned, it is treated as fatal error and
* `nghttp2_session_recv()` and `nghttp2_session_send()` functions
* immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
*/
typedef int (*nghttp2_on_data_send_callback)
(nghttp2_session *session, uint16_t length, uint8_t flags, int32_t stream_id,
void *user_data);
/** /**
* @functypedef * @functypedef
* *
@ -1190,10 +1169,6 @@ typedef struct {
* received. * received.
*/ */
nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback; nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback;
/**
* Callback function invoked when DATA frame is received.
*/
nghttp2_on_data_recv_callback on_data_recv_callback;
/** /**
* Callback function invoked before the non-DATA frame is sent. * Callback function invoked before the non-DATA frame is sent.
*/ */
@ -1207,10 +1182,6 @@ typedef struct {
* because of an error. * because of an error.
*/ */
nghttp2_on_frame_not_send_callback on_frame_not_send_callback; nghttp2_on_frame_not_send_callback on_frame_not_send_callback;
/**
* Callback function invoked after DATA frame is sent.
*/
nghttp2_on_data_send_callback on_data_send_callback;
/** /**
* Callback function invoked when the stream is closed. * Callback function invoked when the stream is closed.
*/ */
@ -1432,13 +1403,9 @@ void nghttp2_session_del(nghttp2_session *session);
* invoked. * invoked.
* 6. :member:`nghttp2_session_callbacks.send_callback` is invoked one * 6. :member:`nghttp2_session_callbacks.send_callback` is invoked one
* or more times to send the frame. * or more times to send the frame.
* 7. If the frame is a control frame, * 7. :member:`nghttp2_session_callbacks.on_frame_send_callback` is
* :member:`nghttp2_session_callbacks.on_frame_send_callback` is
* invoked. * invoked.
* 8. If the frame is a DATA frame, * 8. If the transmission of the frame triggers closure of the stream,
* :member:`nghttp2_session_callbacks.on_data_send_callback` is
* invoked.
* 9. If the transmission of the frame triggers closure of the stream,
* the stream is closed and * the stream is closed and
* :member:`nghttp2_session_callbacks.on_stream_close_callback` is * :member:`nghttp2_session_callbacks.on_stream_close_callback` is
* invoked. * invoked.
@ -1474,7 +1441,7 @@ int nghttp2_session_send(nghttp2_session *session);
* :member:`nghttp2_session_callbacks.on_data_chunk_recv_callback` * :member:`nghttp2_session_callbacks.on_data_chunk_recv_callback`
* is invoked. * is invoked.
* 2. If one DATA frame is completely received, * 2. If one DATA frame is completely received,
* :member:`nghttp2_session_callbacks.on_data_recv_callback` is * :member:`nghttp2_session_callbacks.on_frame_recv_callback` is
* invoked. If the frame is the final frame of the request, * invoked. If the frame is the final frame of the request,
* :member:`nghttp2_session_callbacks.on_request_recv_callback` * :member:`nghttp2_session_callbacks.on_request_recv_callback`
* is invoked. If the reception of the frame triggers the * is invoked. If the reception of the frame triggers the

View File

@ -181,7 +181,8 @@ void nghttp2_frame_window_update_init(nghttp2_window_update *frame,
void nghttp2_frame_window_update_free(nghttp2_window_update *frame) void nghttp2_frame_window_update_free(nghttp2_window_update *frame)
{} {}
void nghttp2_frame_data_init(nghttp2_private_data *frame, uint8_t flags, void nghttp2_frame_private_data_init(nghttp2_private_data *frame,
uint8_t flags,
int32_t stream_id, int32_t stream_id,
const nghttp2_data_provider *data_prd) const nghttp2_data_provider *data_prd)
{ {
@ -191,7 +192,7 @@ void nghttp2_frame_data_init(nghttp2_private_data *frame, uint8_t flags,
frame->data_prd = *data_prd; frame->data_prd = *data_prd;
} }
void nghttp2_frame_data_free(nghttp2_private_data *frame) void nghttp2_frame_private_data_free(nghttp2_private_data *frame)
{} {}
/* /*

View File

@ -416,11 +416,12 @@ void nghttp2_frame_window_update_init(nghttp2_window_update *frame,
void nghttp2_frame_window_update_free(nghttp2_window_update *frame); void nghttp2_frame_window_update_free(nghttp2_window_update *frame);
void nghttp2_frame_data_init(nghttp2_private_data *frame, uint8_t flags, void nghttp2_frame_private_data_init(nghttp2_private_data *frame,
uint8_t flags,
int32_t stream_id, int32_t stream_id,
const nghttp2_data_provider *data_prd); const nghttp2_data_provider *data_prd);
void nghttp2_frame_data_free(nghttp2_private_data *frame); void nghttp2_frame_private_data_free(nghttp2_private_data *frame);
/* /*
* Makes copy of |iv| and return the copy. The |niv| is the number of * Makes copy of |iv| and return the copy. The |niv| is the number of

View File

@ -66,7 +66,7 @@ void nghttp2_outbound_item_free(nghttp2_outbound_item *item)
} else if(item->frame_cat == NGHTTP2_CAT_DATA) { } else if(item->frame_cat == NGHTTP2_CAT_DATA) {
nghttp2_private_data *data_frame; nghttp2_private_data *data_frame;
data_frame = nghttp2_outbound_item_get_data_frame(item); data_frame = nghttp2_outbound_item_get_data_frame(item);
nghttp2_frame_data_free(data_frame); nghttp2_frame_private_data_free(data_frame);
} else { } else {
/* Unreachable */ /* Unreachable */
assert(0); assert(0);

View File

@ -1387,6 +1387,20 @@ nghttp2_outbound_item* nghttp2_session_pop_next_ob_item
} }
} }
static int session_call_on_frame_send(nghttp2_session *session,
nghttp2_frame *frame)
{
int rv;
if(session->callbacks.on_frame_send_callback) {
rv = session->callbacks.on_frame_send_callback(session, frame,
session->user_data);
if(rv != 0) {
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
}
return 0;
}
/* /*
* Called after a frame is sent. * Called after a frame is sent.
* *
@ -1431,11 +1445,9 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session)
CONTINUATION frame. */ CONTINUATION frame. */
frame->hd.length = session->aob.framebuflen - NGHTTP2_FRAME_HEAD_LENGTH; frame->hd.length = session->aob.framebuflen - NGHTTP2_FRAME_HEAD_LENGTH;
} }
if(session->callbacks.on_frame_send_callback) { r = session_call_on_frame_send(session, frame);
if(session->callbacks.on_frame_send_callback(session, frame, if(nghttp2_is_fatal(r)) {
session->user_data) != 0) { return r;
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
} }
switch(frame->hd.type) { switch(frame->hd.type) {
case NGHTTP2_HEADERS: { case NGHTTP2_HEADERS: {
@ -1573,16 +1585,18 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session)
} else if(item->frame_cat == NGHTTP2_CAT_DATA) { } else if(item->frame_cat == NGHTTP2_CAT_DATA) {
int r; int r;
nghttp2_private_data *data_frame; nghttp2_private_data *data_frame;
data_frame = nghttp2_outbound_item_get_data_frame(session->aob.item); data_frame = nghttp2_outbound_item_get_data_frame(session->aob.item);
if(session->callbacks.on_data_send_callback) { if(session->callbacks.on_frame_send_callback) {
if(session->callbacks.on_data_send_callback nghttp2_frame public_data_frame = { data_frame->hd };
(session, /* flags may have NGHTTP2_FLAG_END_STREAM even if the sent chunk
session->aob.framebuflen - NGHTTP2_FRAME_HEAD_LENGTH, is not the end of the stream */
data_frame->eof ? data_frame->hd.flags : if(!data_frame->eof) {
(data_frame->hd.flags & (~NGHTTP2_FLAG_END_STREAM)), public_data_frame.hd.flags &= ~NGHTTP2_FLAG_END_STREAM;
data_frame->hd.stream_id, }
session->user_data) != 0) { r = session_call_on_frame_send(session, &public_data_frame);
return NGHTTP2_ERR_CALLBACK_FAILURE; if(nghttp2_is_fatal(r)) {
return r;
} }
} }
if(data_frame->eof && (data_frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) { if(data_frame->eof && (data_frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) {
@ -3137,34 +3151,31 @@ static int session_process_window_update_frame(nghttp2_session *session)
/* } */ /* } */
int nghttp2_session_on_data_received(nghttp2_session *session, int nghttp2_session_on_data_received(nghttp2_session *session,
uint16_t length, uint8_t flags, nghttp2_frame *frame)
int32_t stream_id)
{ {
int rv = 0; int rv = 0;
nghttp2_stream *stream; nghttp2_stream *stream;
stream = nghttp2_session_get_stream(session, stream_id); stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
if(!stream) { if(!stream) {
/* This should be treated as stream error, but it results in lots /* This should be treated as stream error, but it results in lots
of RST_STREAM. So just ignore frame against nonexistent stream of RST_STREAM. So just ignore frame against nonexistent stream
for now. */ for now. */
return 0; return 0;
} }
if(session->callbacks.on_data_recv_callback) { rv = nghttp2_session_call_on_frame_received(session, frame);
if(session->callbacks.on_data_recv_callback if(nghttp2_is_fatal(rv)) {
(session, length, flags, stream_id, session->user_data) != 0) { return rv;
return NGHTTP2_ERR_CALLBACK_FAILURE;
} }
} if(!nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) {
if(!nghttp2_session_is_my_stream_id(session, stream_id)) { if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
if(flags & NGHTTP2_FLAG_END_STREAM) { rv = nghttp2_session_call_on_request_recv(session, frame->hd.stream_id);
rv = nghttp2_session_call_on_request_recv(session, stream_id);
if(rv != 0) { if(rv != 0) {
return rv; return rv;
} }
} }
} }
if(flags & NGHTTP2_FLAG_END_STREAM) { if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
rv = nghttp2_session_close_stream_if_shut_rdwr(session, stream); rv = nghttp2_session_close_stream_if_shut_rdwr(session, stream);
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
@ -3178,10 +3189,8 @@ int nghttp2_session_on_data_received(nghttp2_session *session,
static int nghttp2_session_process_data_frame(nghttp2_session *session) static int nghttp2_session_process_data_frame(nghttp2_session *session)
{ {
int r; int r;
nghttp2_frame *frame = &session->iframe.frame; nghttp2_frame *public_data_frame = &session->iframe.frame;
r = nghttp2_session_on_data_received(session, r = nghttp2_session_on_data_received(session, public_data_frame);
frame->hd.length, frame->hd.flags,
frame->hd.stream_id);
if(nghttp2_is_fatal(r)) { if(nghttp2_is_fatal(r)) {
return r; return r;
} else { } else {

View File

@ -488,17 +488,19 @@ int nghttp2_session_on_window_update_received(nghttp2_session *session,
nghttp2_frame *frame); nghttp2_frame *frame);
/* /*
* Called when DATA is received. * Called when DATA is received, assuming |frame| is properly
* initialized.
* *
* 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:
* *
* NGHTTP2_ERR_NOMEM * NGHTTP2_ERR_NOMEM
* Out of memory. * Out of memory.
* NGHTTP2_ERR_CALLBACK_FAILURE
* The callback function failed.
*/ */
int nghttp2_session_on_data_received(nghttp2_session *session, int nghttp2_session_on_data_received(nghttp2_session *session,
uint16_t length, uint8_t flags, nghttp2_frame *frame);
int32_t stream_id);
/* /*
* Returns nghttp2_stream* object whose stream ID is |stream_id|. It * Returns nghttp2_stream* object whose stream ID is |stream_id|. It

View File

@ -311,10 +311,10 @@ int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
if(flags & NGHTTP2_FLAG_END_STREAM) { if(flags & NGHTTP2_FLAG_END_STREAM) {
nflags |= NGHTTP2_FLAG_END_STREAM; nflags |= NGHTTP2_FLAG_END_STREAM;
} }
nghttp2_frame_data_init(data_frame, nflags, stream_id, data_prd); nghttp2_frame_private_data_init(data_frame, nflags, stream_id, data_prd);
r = nghttp2_session_add_frame(session, NGHTTP2_CAT_DATA, data_frame, NULL); r = nghttp2_session_add_frame(session, NGHTTP2_CAT_DATA, data_frame, NULL);
if(r != 0) { if(r != 0) {
nghttp2_frame_data_free(data_frame); nghttp2_frame_private_data_free(data_frame);
free(data_frame); free(data_frame);
} }
return r; return r;

View File

@ -853,6 +853,9 @@ int hd_on_frame_recv_callback
verbose_on_frame_recv_callback(session, frame, user_data); verbose_on_frame_recv_callback(session, frame, user_data);
} }
switch(frame->hd.type) { switch(frame->hd.type) {
case NGHTTP2_DATA:
// TODO Handle POST
break;
case NGHTTP2_HEADERS: case NGHTTP2_HEADERS:
switch(frame->headers.cat) { switch(frame->headers.cat) {
case NGHTTP2_HCAT_REQUEST: { case NGHTTP2_HCAT_REQUEST: {
@ -939,37 +942,6 @@ int on_data_chunk_recv_callback
} }
} // namespace } // namespace
namespace {
int hd_on_data_recv_callback
(nghttp2_session *session, uint16_t length, uint8_t flags, int32_t stream_id,
void *user_data)
{
// TODO Handle POST
auto hd = static_cast<Http2Handler*>(user_data);
if(hd->get_config()->verbose) {
print_session_id(hd->session_id());
verbose_on_data_recv_callback(session, length, flags, stream_id,
user_data);
}
return 0;
}
} // namespace
namespace {
int hd_on_data_send_callback
(nghttp2_session *session, uint16_t length, uint8_t flags, int32_t stream_id,
void *user_data)
{
auto hd = static_cast<Http2Handler*>(user_data);
if(hd->get_config()->verbose) {
print_session_id(hd->session_id());
verbose_on_data_send_callback(session, length, flags, stream_id,
user_data);
}
return 0;
}
} // namespace
namespace { namespace {
int on_stream_close_callback int on_stream_close_callback
(nghttp2_session *session, int32_t stream_id, nghttp2_error_code error_code, (nghttp2_session *session, int32_t stream_id, nghttp2_error_code error_code,
@ -997,8 +969,6 @@ void fill_callback(nghttp2_session_callbacks& callbacks, const Config *config)
callbacks.on_frame_recv_callback = hd_on_frame_recv_callback; callbacks.on_frame_recv_callback = hd_on_frame_recv_callback;
callbacks.before_frame_send_callback = hd_before_frame_send_callback; callbacks.before_frame_send_callback = hd_before_frame_send_callback;
callbacks.on_frame_send_callback = hd_on_frame_send_callback; callbacks.on_frame_send_callback = hd_on_frame_send_callback;
callbacks.on_data_recv_callback = hd_on_data_recv_callback;
callbacks.on_data_send_callback = hd_on_data_send_callback;
if(config->verbose) { if(config->verbose) {
callbacks.on_invalid_frame_recv_callback = callbacks.on_invalid_frame_recv_callback =
verbose_on_invalid_frame_recv_callback; verbose_on_invalid_frame_recv_callback;

View File

@ -262,6 +262,8 @@ void print_frame(print_type ptype, const nghttp2_frame *frame)
print_flags(frame->hd); print_flags(frame->hd);
} }
switch(frame->hd.type) { switch(frame->hd.type) {
case NGHTTP2_DATA:
break;
case NGHTTP2_HEADERS: case NGHTTP2_HEADERS:
if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) { if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
print_frame_attr_indent(); print_frame_attr_indent();
@ -411,43 +413,6 @@ int verbose_on_frame_send_callback
return 0; return 0;
} }
namespace {
void print_data_frame(print_type ptype, uint16_t length, uint8_t flags,
int32_t stream_id)
{
printf("%sDATA%s frame ",
frame_name_ansi_esc(ptype), ansi_escend());
nghttp2_frame_hd hd = {length, stream_id, NGHTTP2_DATA, flags};
print_frame_hd(hd);
if(flags) {
print_frame_attr_indent();
print_flags(hd);
}
}
} // namespace
int verbose_on_data_recv_callback
(nghttp2_session *session, uint16_t length, uint8_t flags, int32_t stream_id,
void *user_data)
{
print_timer();
printf(" recv ");
print_data_frame(PRINT_RECV, length, flags, stream_id);
fflush(stdout);
return 0;
}
int verbose_on_data_send_callback
(nghttp2_session *session, uint16_t length, uint8_t flags, int32_t stream_id,
void *user_data)
{
print_timer();
printf(" send ");
print_data_frame(PRINT_SEND, length, flags, stream_id);
fflush(stdout);
return 0;
}
namespace { namespace {
std::chrono::steady_clock::time_point base_tv; std::chrono::steady_clock::time_point base_tv;
} // namespace } // namespace

View File

@ -62,14 +62,6 @@ int verbose_on_unknown_frame_recv_callback(nghttp2_session *session,
int verbose_on_frame_send_callback int verbose_on_frame_send_callback
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data); (nghttp2_session *session, const nghttp2_frame *frame, void *user_data);
int verbose_on_data_recv_callback
(nghttp2_session *session, uint16_t length, uint8_t flags, int32_t stream_id,
void *user_data);
int verbose_on_data_send_callback
(nghttp2_session *session, uint16_t length, uint8_t flags, int32_t stream_id,
void *user_data);
// Returns difference between |a| and |b| in milliseconds, assuming // Returns difference between |a| and |b| in milliseconds, assuming
// |a| is more recent than |b|. // |a| is more recent than |b|.
template<typename TimePoint> template<typename TimePoint>

View File

@ -1585,8 +1585,6 @@ int run(char **uris, int n)
callbacks.before_frame_send_callback = before_frame_send_callback; callbacks.before_frame_send_callback = before_frame_send_callback;
if(config.verbose) { if(config.verbose) {
callbacks.on_frame_send_callback = verbose_on_frame_send_callback; callbacks.on_frame_send_callback = verbose_on_frame_send_callback;
callbacks.on_data_recv_callback = verbose_on_data_recv_callback;
callbacks.on_data_send_callback = verbose_on_data_send_callback;
callbacks.on_invalid_frame_recv_callback = callbacks.on_invalid_frame_recv_callback =
verbose_on_invalid_frame_recv_callback; verbose_on_invalid_frame_recv_callback;
callbacks.on_unknown_frame_recv_callback = callbacks.on_unknown_frame_recv_callback =

View File

@ -347,6 +347,17 @@ int on_frame_recv_callback
int rv; int rv;
auto upstream = static_cast<Http2Upstream*>(user_data); auto upstream = static_cast<Http2Upstream*>(user_data);
switch(frame->hd.type) { switch(frame->hd.type) {
case NGHTTP2_DATA: {
auto downstream = upstream->find_downstream(frame->hd.stream_id);
if(!downstream) {
break;
}
if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
downstream->end_upload_data();
downstream->set_request_state(Downstream::MSG_COMPLETE);
}
break;
}
case NGHTTP2_HEADERS: { case NGHTTP2_HEADERS: {
if(frame->headers.cat != NGHTTP2_HCAT_REQUEST) { if(frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
break; break;
@ -412,21 +423,6 @@ int on_data_chunk_recv_callback(nghttp2_session *session,
} }
} // namespace } // namespace
namespace {
int on_data_recv_callback(nghttp2_session *session,
uint16_t length, uint8_t flags, int32_t stream_id,
void *user_data)
{
auto upstream = static_cast<Http2Upstream*>(user_data);
auto downstream = upstream->find_downstream(stream_id);
if(downstream && (flags & NGHTTP2_FLAG_END_STREAM)) {
downstream->end_upload_data();
downstream->set_request_state(Downstream::MSG_COMPLETE);
}
return 0;
}
} // namespace
namespace { namespace {
int on_frame_send_callback(nghttp2_session* session, int on_frame_send_callback(nghttp2_session* session,
const nghttp2_frame *frame, void *user_data) const nghttp2_frame *frame, void *user_data)
@ -506,7 +502,6 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
callbacks.on_stream_close_callback = on_stream_close_callback; callbacks.on_stream_close_callback = on_stream_close_callback;
callbacks.on_frame_recv_callback = on_frame_recv_callback; callbacks.on_frame_recv_callback = on_frame_recv_callback;
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback; callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
callbacks.on_data_recv_callback = on_data_recv_callback;
callbacks.on_frame_send_callback = on_frame_send_callback; callbacks.on_frame_send_callback = on_frame_send_callback;
callbacks.on_frame_not_send_callback = on_frame_not_send_callback; callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
callbacks.on_unknown_frame_recv_callback = on_unknown_frame_recv_callback; callbacks.on_unknown_frame_recv_callback = on_unknown_frame_recv_callback;

View File

@ -66,7 +66,6 @@ typedef struct {
int32_t stream_id; int32_t stream_id;
size_t block_count; size_t block_count;
int data_chunk_recv_cb_called; int data_chunk_recv_cb_called;
int data_recv_cb_called;
const nghttp2_frame *frame; const nghttp2_frame *frame;
size_t fixed_sendlen; size_t fixed_sendlen;
int header_cb_called; int header_cb_called;
@ -201,15 +200,6 @@ static int pause_on_data_chunk_recv_callback(nghttp2_session *session,
return NGHTTP2_ERR_PAUSE; return NGHTTP2_ERR_PAUSE;
} }
static int on_data_recv_callback(nghttp2_session *session,
uint16_t length, uint8_t flags,
int32_t stream_id, void *user_data)
{
my_user_data *ud = (my_user_data*)user_data;
++ud->data_recv_cb_called;
return 0;
}
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,
@ -553,7 +543,7 @@ void test_nghttp2_session_recv_data(void)
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;
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback; callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
callbacks.on_data_recv_callback = on_data_recv_callback; callbacks.on_frame_recv_callback = on_frame_recv_callback;
nghttp2_session_client_new(&session, &callbacks, &ud); nghttp2_session_client_new(&session, &callbacks, &ud);
@ -568,12 +558,12 @@ void test_nghttp2_session_recv_data(void)
/* stream 1 is not opened, so it must be responded with connection /* stream 1 is not opened, so it must be responded with connection
error. This is not mandated by the spec */ error. This is not mandated by the spec */
ud.data_chunk_recv_cb_called = 0; ud.data_chunk_recv_cb_called = 0;
ud.data_recv_cb_called = 0; ud.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, data, 8+4096); rv = nghttp2_session_mem_recv(session, data, 8+4096);
CU_ASSERT(8+4096 == rv); CU_ASSERT(8+4096 == rv);
CU_ASSERT(0 == ud.data_chunk_recv_cb_called); CU_ASSERT(0 == ud.data_chunk_recv_cb_called);
CU_ASSERT(0 == ud.data_recv_cb_called); CU_ASSERT(0 == ud.frame_recv_cb_called);
item = nghttp2_session_get_next_ob_item(session); item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NULL == item); CU_ASSERT(NULL == item);
@ -587,12 +577,12 @@ void test_nghttp2_session_recv_data(void)
stream->local_window_size = 16383; stream->local_window_size = 16383;
ud.data_chunk_recv_cb_called = 0; ud.data_chunk_recv_cb_called = 0;
ud.data_recv_cb_called = 0; ud.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, data, 8+4096); rv = nghttp2_session_mem_recv(session, data, 8+4096);
CU_ASSERT(8+4096 == rv); CU_ASSERT(8+4096 == rv);
CU_ASSERT(0 == ud.data_chunk_recv_cb_called); CU_ASSERT(0 == ud.data_chunk_recv_cb_called);
CU_ASSERT(0 == ud.data_recv_cb_called); CU_ASSERT(0 == ud.frame_recv_cb_called);
item = nghttp2_session_get_next_ob_item(session); item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NULL == item); CU_ASSERT(NULL == item);
@ -600,24 +590,24 @@ void test_nghttp2_session_recv_data(void)
stream->state = NGHTTP2_STREAM_OPENED; stream->state = NGHTTP2_STREAM_OPENED;
ud.data_chunk_recv_cb_called = 0; ud.data_chunk_recv_cb_called = 0;
ud.data_recv_cb_called = 0; ud.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, data, 8+4096); rv = nghttp2_session_mem_recv(session, data, 8+4096);
CU_ASSERT(8+4096 == rv); CU_ASSERT(8+4096 == rv);
CU_ASSERT(1 == ud.data_chunk_recv_cb_called); CU_ASSERT(1 == ud.data_chunk_recv_cb_called);
CU_ASSERT(1 == ud.data_recv_cb_called); CU_ASSERT(1 == ud.frame_recv_cb_called);
CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session)); CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
ud.data_chunk_recv_cb_called = 0; ud.data_chunk_recv_cb_called = 0;
ud.data_recv_cb_called = 0; ud.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, data, 8+4096); rv = nghttp2_session_mem_recv(session, data, 8+4096);
CU_ASSERT(8+4096 == rv); CU_ASSERT(8+4096 == rv);
/* Now we got data more than initial-window-size / 2, WINDOW_UPDATE /* Now we got data more than initial-window-size / 2, WINDOW_UPDATE
must be queued */ must be queued */
CU_ASSERT(1 == ud.data_chunk_recv_cb_called); CU_ASSERT(1 == ud.data_chunk_recv_cb_called);
CU_ASSERT(1 == ud.data_recv_cb_called); CU_ASSERT(1 == ud.frame_recv_cb_called);
item = nghttp2_session_get_next_ob_item(session); item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_WINDOW_UPDATE == OB_CTRL_TYPE(item)); CU_ASSERT(NGHTTP2_WINDOW_UPDATE == OB_CTRL_TYPE(item));
CU_ASSERT(1 == OB_CTRL(item)->window_update.hd.stream_id); CU_ASSERT(1 == OB_CTRL(item)->window_update.hd.stream_id);
@ -647,12 +637,12 @@ void test_nghttp2_session_recv_data(void)
nghttp2_frame_pack_frame_hd(data, &hd); nghttp2_frame_pack_frame_hd(data, &hd);
ud.data_chunk_recv_cb_called = 0; ud.data_chunk_recv_cb_called = 0;
ud.data_recv_cb_called = 0; ud.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, data, 8+4096); rv = nghttp2_session_mem_recv(session, data, 8+4096);
CU_ASSERT(8+4096 == rv); CU_ASSERT(8+4096 == rv);
CU_ASSERT(0 == ud.data_chunk_recv_cb_called); CU_ASSERT(0 == ud.data_chunk_recv_cb_called);
CU_ASSERT(0 == ud.data_recv_cb_called); CU_ASSERT(0 == ud.frame_recv_cb_called);
item = nghttp2_session_get_next_ob_item(session); item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item)); CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == OB_CTRL(item)->goaway.error_code); CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == OB_CTRL(item)->goaway.error_code);
@ -807,7 +797,6 @@ void test_nghttp2_session_continue(void)
callbacks.send_callback = null_send_callback; callbacks.send_callback = null_send_callback;
callbacks.on_frame_recv_callback = on_frame_recv_callback; callbacks.on_frame_recv_callback = on_frame_recv_callback;
callbacks.on_data_chunk_recv_callback = pause_on_data_chunk_recv_callback; callbacks.on_data_chunk_recv_callback = pause_on_data_chunk_recv_callback;
callbacks.on_data_recv_callback = on_data_recv_callback;
callbacks.on_header_callback = pause_on_header_callback; callbacks.on_header_callback = pause_on_header_callback;
callbacks.on_end_headers_callback = on_end_headers_callback; callbacks.on_end_headers_callback = on_end_headers_callback;
@ -920,24 +909,24 @@ void test_nghttp2_session_continue(void)
buflen = sizeof(buffer); buflen = sizeof(buffer);
/* Intentionally specify larger buffer size to see pause is kicked /* Intentionally specify larger buffer size to see pause is kicked
in. */ in. */
user_data.data_recv_cb_called = 0; user_data.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, buffer, sizeof(buffer)); rv = nghttp2_session_mem_recv(session, buffer, sizeof(buffer));
CU_ASSERT(16 + NGHTTP2_FRAME_HEAD_LENGTH == rv); CU_ASSERT(16 + NGHTTP2_FRAME_HEAD_LENGTH == rv);
CU_ASSERT(0 == user_data.data_recv_cb_called); CU_ASSERT(0 == user_data.frame_recv_cb_called);
/* Next nghttp2_session_mem_recv invokes on_data_recv_callback and /* Next nghttp2_session_mem_recv invokes on_frame_recv_callback and
pause again in on_data_chunk_recv_callback since we pass same pause again in on_data_chunk_recv_callback since we pass same
DATA frame. */ DATA frame. */
user_data.data_recv_cb_called = 0; user_data.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, buffer, sizeof(buffer)); rv = nghttp2_session_mem_recv(session, buffer, sizeof(buffer));
CU_ASSERT(16 + NGHTTP2_FRAME_HEAD_LENGTH == rv); CU_ASSERT(16 + NGHTTP2_FRAME_HEAD_LENGTH == rv);
CU_ASSERT(1 == user_data.data_recv_cb_called); CU_ASSERT(1 == user_data.frame_recv_cb_called);
/* And finally call on_data_recv_callback with 0 size input */ /* And finally call on_frame_recv_callback with 0 size input */
user_data.data_recv_cb_called = 0; user_data.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, NULL, 0); rv = nghttp2_session_mem_recv(session, NULL, 0);
CU_ASSERT(0 == rv); CU_ASSERT(0 == rv);
CU_ASSERT(1 == user_data.data_recv_cb_called); CU_ASSERT(1 == user_data.frame_recv_cb_called);
free(framedata); free(framedata);
nghttp2_hd_deflate_free(&deflater); nghttp2_hd_deflate_free(&deflater);
@ -1720,6 +1709,7 @@ void test_nghttp2_session_on_data_received(void)
my_user_data user_data; my_user_data user_data;
nghttp2_outbound_item *top; nghttp2_outbound_item *top;
nghttp2_stream *stream; nghttp2_stream *stream;
nghttp2_frame frame;
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
@ -1727,25 +1717,36 @@ void test_nghttp2_session_on_data_received(void)
stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
NGHTTP2_PRI_DEFAULT, NGHTTP2_PRI_DEFAULT,
NGHTTP2_STREAM_OPENING, NULL); NGHTTP2_STREAM_OPENING, NULL);
CU_ASSERT(0 == nghttp2_session_on_data_received(session, 4096,
NGHTTP2_FLAG_NONE, 2)); frame.hd.length = 4096;
frame.hd.flags = NGHTTP2_FLAG_NONE;
frame.hd.stream_id = 2;
CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
CU_ASSERT(0 == stream->shut_flags); CU_ASSERT(0 == stream->shut_flags);
CU_ASSERT(0 == nghttp2_session_on_data_received(session, 4096,
NGHTTP2_FLAG_END_STREAM, 2)); frame.hd.flags = NGHTTP2_FLAG_END_STREAM;
CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags); CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags);
/* If NGHTTP2_STREAM_CLOSING state, DATA frame is discarded. */ /* If NGHTTP2_STREAM_CLOSING state, DATA frame is discarded. */
stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE, stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
NGHTTP2_PRI_DEFAULT, NGHTTP2_PRI_DEFAULT,
NGHTTP2_STREAM_CLOSING, NULL); NGHTTP2_STREAM_CLOSING, NULL);
CU_ASSERT(0 == nghttp2_session_on_data_received(session, 4096,
NGHTTP2_FLAG_NONE, 4)); frame.hd.flags = NGHTTP2_FLAG_NONE;
frame.hd.stream_id = 4;
CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
CU_ASSERT(NULL == nghttp2_session_get_ob_pq_top(session)); CU_ASSERT(NULL == nghttp2_session_get_ob_pq_top(session));
/* Check INVALID_STREAM case: DATA frame with stream ID which does /* Check INVALID_STREAM case: DATA frame with stream ID which does
not exist. */ not exist. */
CU_ASSERT(0 == nghttp2_session_on_data_received(session, 4096,
NGHTTP2_FLAG_NONE, 6)); frame.hd.stream_id = 6;
CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
top = nghttp2_session_get_ob_pq_top(session); top = nghttp2_session_get_ob_pq_top(session);
/* DATA against nonexistent stream is just ignored for now */ /* DATA against nonexistent stream is just ignored for now */
CU_ASSERT(top == NULL); CU_ASSERT(top == NULL);
@ -3224,7 +3225,7 @@ void test_nghttp2_session_stop_data_with_rst_stream(void)
ud.block_count = 2; ud.block_count = 2;
/* Sends SYN_REPLY + DATA[0] */ /* Sends SYN_REPLY + DATA[0] */
CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type); CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
/* data for DATA[1] is read from data_prd but it is not sent */ /* data for DATA[1] is read from data_prd but it is not sent */
CU_ASSERT(ud.data_source_length == 8*1024); CU_ASSERT(ud.data_source_length == 8*1024);
@ -3950,7 +3951,7 @@ void test_nghttp2_session_data_backoff_by_high_pri_frame(void)
ud.block_count = 2; ud.block_count = 2;
/* Sends SYN_STREAM + DATA[0] */ /* Sends SYN_STREAM + DATA[0] */
CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type); CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
/* data for DATA[1] is read from data_prd but it is not sent */ /* data for DATA[1] is read from data_prd but it is not sent */
CU_ASSERT(ud.data_source_length == 8*1024); CU_ASSERT(ud.data_source_length == 8*1024);