Add int return value to nghttp2_on_frame_recv_callback

This commit is contained in:
Tatsuhiro Tsujikawa 2013-08-29 21:03:39 +09:00
parent 39d50f9b88
commit a59cd3be82
9 changed files with 86 additions and 44 deletions

View File

@ -779,8 +779,13 @@ typedef ssize_t (*nghttp2_recv_callback)
* *
* Callback function invoked by `nghttp2_session_recv()` when a * Callback function invoked by `nghttp2_session_recv()` when a
* non-DATA frame is received. * non-DATA frame is received.
*
* 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
* return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
*/ */
typedef void (*nghttp2_on_frame_recv_callback) typedef int (*nghttp2_on_frame_recv_callback)
(nghttp2_session *session, nghttp2_frame *frame, void *user_data); (nghttp2_session *session, nghttp2_frame *frame, void *user_data);
/** /**

View File

@ -1567,13 +1567,18 @@ static void nghttp2_session_call_on_request_recv
} }
} }
static void nghttp2_session_call_on_frame_received static int nghttp2_session_call_on_frame_received
(nghttp2_session *session, nghttp2_frame *frame) (nghttp2_session *session, nghttp2_frame *frame)
{ {
int rv;
if(session->callbacks.on_frame_recv_callback) { if(session->callbacks.on_frame_recv_callback) {
session->callbacks.on_frame_recv_callback(session, frame, rv = session->callbacks.on_frame_recv_callback(session, frame,
session->user_data); session->user_data);
if(rv != 0) {
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
} }
return 0;
} }
/* /*
@ -1709,7 +1714,10 @@ int nghttp2_session_on_request_headers_received(nghttp2_session *session,
if(flags & NGHTTP2_FLAG_END_STREAM) { if(flags & NGHTTP2_FLAG_END_STREAM) {
nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
} }
nghttp2_session_call_on_frame_received(session, frame); r = nghttp2_session_call_on_frame_received(session, frame);
if(r != 0) {
return r;
}
if(flags & NGHTTP2_FLAG_END_STREAM) { if(flags & NGHTTP2_FLAG_END_STREAM) {
nghttp2_session_call_on_request_recv(session, frame->hd.stream_id); nghttp2_session_call_on_request_recv(session, frame->hd.stream_id);
} }
@ -1723,6 +1731,7 @@ int nghttp2_session_on_response_headers_received(nghttp2_session *session,
nghttp2_frame *frame, nghttp2_frame *frame,
nghttp2_stream *stream) nghttp2_stream *stream)
{ {
int rv;
/* This function is only called if stream->state == /* This function is only called if stream->state ==
NGHTTP2_STREAM_OPENING and stream_id is local side initiated. */ NGHTTP2_STREAM_OPENING and stream_id is local side initiated. */
assert(stream->state == NGHTTP2_STREAM_OPENING && assert(stream->state == NGHTTP2_STREAM_OPENING &&
@ -1738,7 +1747,10 @@ int nghttp2_session_on_response_headers_received(nghttp2_session *session,
} }
if((stream->shut_flags & NGHTTP2_SHUT_RD) == 0) { if((stream->shut_flags & NGHTTP2_SHUT_RD) == 0) {
stream->state = NGHTTP2_STREAM_OPENED; stream->state = NGHTTP2_STREAM_OPENED;
nghttp2_session_call_on_frame_received(session, frame); rv = nghttp2_session_call_on_frame_received(session, frame);
if(rv != 0) {
return rv;
}
if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
/* This is the last frame of this stream, so disallow /* This is the last frame of this stream, so disallow
further receptions. */ further receptions. */
@ -1783,8 +1795,7 @@ int nghttp2_session_on_push_response_headers_received(nghttp2_session *session,
} }
nghttp2_stream_promise_fulfilled(stream); nghttp2_stream_promise_fulfilled(stream);
++session->num_incoming_streams; ++session->num_incoming_streams;
nghttp2_session_call_on_frame_received(session, frame); return nghttp2_session_call_on_frame_received(session, frame);
return 0;
} }
int nghttp2_session_on_headers_received(nghttp2_session *session, int nghttp2_session_on_headers_received(nghttp2_session *session,
@ -1807,7 +1818,10 @@ int nghttp2_session_on_headers_received(nghttp2_session *session,
if(nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) { if(nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) {
if(stream->state == NGHTTP2_STREAM_OPENED) { if(stream->state == NGHTTP2_STREAM_OPENED) {
valid = 1; valid = 1;
nghttp2_session_call_on_frame_received(session, frame); r = nghttp2_session_call_on_frame_received(session, frame);
if(r != 0) {
return r;
}
if(frame->hd.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);
nghttp2_session_close_stream_if_shut_rdwr(session, stream); nghttp2_session_close_stream_if_shut_rdwr(session, stream);
@ -1825,7 +1839,10 @@ int nghttp2_session_on_headers_received(nghttp2_session *session,
condition. */ condition. */
valid = 1; valid = 1;
if(stream->state != NGHTTP2_STREAM_CLOSING) { if(stream->state != NGHTTP2_STREAM_CLOSING) {
nghttp2_session_call_on_frame_received(session, frame); r = nghttp2_session_call_on_frame_received(session, frame);
if(r != 0) {
return r;
}
if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
nghttp2_session_call_on_request_recv(session, frame->hd.stream_id); nghttp2_session_call_on_request_recv(session, frame->hd.stream_id);
nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
@ -1858,6 +1875,7 @@ int nghttp2_session_on_headers_received(nghttp2_session *session,
int nghttp2_session_on_priority_received(nghttp2_session *session, int nghttp2_session_on_priority_received(nghttp2_session *session,
nghttp2_frame *frame) nghttp2_frame *frame)
{ {
int rv;
nghttp2_stream *stream; nghttp2_stream *stream;
if(frame->hd.stream_id == 0) { if(frame->hd.stream_id == 0) {
return nghttp2_session_handle_invalid_connection(session, frame, return nghttp2_session_handle_invalid_connection(session, frame,
@ -1870,7 +1888,10 @@ int nghttp2_session_on_priority_received(nghttp2_session *session,
nghttp2_session_reprioritize_stream(session, stream, nghttp2_session_reprioritize_stream(session, stream,
frame->priority.pri); frame->priority.pri);
} }
nghttp2_session_call_on_frame_received(session, frame); rv = nghttp2_session_call_on_frame_received(session, frame);
if(rv != 0) {
return rv;
}
} }
return 0; return 0;
} }
@ -1878,11 +1899,15 @@ int nghttp2_session_on_priority_received(nghttp2_session *session,
int nghttp2_session_on_rst_stream_received(nghttp2_session *session, int nghttp2_session_on_rst_stream_received(nghttp2_session *session,
nghttp2_frame *frame) nghttp2_frame *frame)
{ {
int rv;
if(frame->hd.stream_id == 0) { if(frame->hd.stream_id == 0) {
return nghttp2_session_handle_invalid_connection(session, frame, return nghttp2_session_handle_invalid_connection(session, frame,
NGHTTP2_PROTOCOL_ERROR); NGHTTP2_PROTOCOL_ERROR);
} }
nghttp2_session_call_on_frame_received(session, frame); rv = nghttp2_session_call_on_frame_received(session, frame);
if(rv != 0) {
return rv;
}
nghttp2_session_close_stream(session, frame->hd.stream_id, nghttp2_session_close_stream(session, frame->hd.stream_id,
frame->rst_stream.error_code); frame->rst_stream.error_code);
return 0; return 0;
@ -2167,13 +2192,13 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
} }
session->remote_settings[entry->settings_id] = entry->value; session->remote_settings[entry->settings_id] = entry->value;
} }
nghttp2_session_call_on_frame_received(session, frame); return nghttp2_session_call_on_frame_received(session, frame);
return 0;
} }
int nghttp2_session_on_push_promise_received(nghttp2_session *session, int nghttp2_session_on_push_promise_received(nghttp2_session *session,
nghttp2_frame *frame) nghttp2_frame *frame)
{ {
int rv;
nghttp2_stream *stream; nghttp2_stream *stream;
if(session->server || frame->hd.stream_id == 0) { if(session->server || frame->hd.stream_id == 0) {
return nghttp2_session_handle_invalid_connection(session, frame, return nghttp2_session_handle_invalid_connection(session, frame,
@ -2222,7 +2247,10 @@ int nghttp2_session_on_push_promise_received(nghttp2_session *session,
if(!promised_stream) { if(!promised_stream) {
return NGHTTP2_ERR_NOMEM; return NGHTTP2_ERR_NOMEM;
} }
nghttp2_session_call_on_frame_received(session, frame); rv = nghttp2_session_call_on_frame_received(session, frame);
if(rv != 0) {
return rv;
}
} }
} else { } else {
if(session->callbacks.on_invalid_frame_recv_callback) { if(session->callbacks.on_invalid_frame_recv_callback) {
@ -2255,9 +2283,11 @@ int nghttp2_session_on_ping_received(nghttp2_session *session,
/* Peer sent ping, so ping it back */ /* Peer sent ping, so ping it back */
r = nghttp2_session_add_ping(session, NGHTTP2_FLAG_PONG, r = nghttp2_session_add_ping(session, NGHTTP2_FLAG_PONG,
frame->ping.opaque_data); frame->ping.opaque_data);
if(r != 0) {
return r;
}
} }
nghttp2_session_call_on_frame_received(session, frame); return nghttp2_session_call_on_frame_received(session, frame);
return r;
} }
int nghttp2_session_on_goaway_received(nghttp2_session *session, int nghttp2_session_on_goaway_received(nghttp2_session *session,
@ -2265,8 +2295,7 @@ int nghttp2_session_on_goaway_received(nghttp2_session *session,
{ {
session->last_stream_id = frame->goaway.last_stream_id; session->last_stream_id = frame->goaway.last_stream_id;
session->goaway_flags |= NGHTTP2_GOAWAY_RECV; session->goaway_flags |= NGHTTP2_GOAWAY_RECV;
nghttp2_session_call_on_frame_received(session, frame); return nghttp2_session_call_on_frame_received(session, frame);
return 0;
} }
static int nghttp2_push_back_deferred_data_func(nghttp2_map_entry *entry, static int nghttp2_push_back_deferred_data_func(nghttp2_map_entry *entry,
@ -2307,6 +2336,7 @@ static int nghttp2_session_push_back_deferred_data(nghttp2_session *session)
int nghttp2_session_on_window_update_received(nghttp2_session *session, int nghttp2_session_on_window_update_received(nghttp2_session *session,
nghttp2_frame *frame) nghttp2_frame *frame)
{ {
int rv;
if(frame->hd.stream_id == 0) { if(frame->hd.stream_id == 0) {
/* Handle connection-level flow control */ /* Handle connection-level flow control */
if(session->remote_flow_control == 0) { if(session->remote_flow_control == 0) {
@ -2314,8 +2344,7 @@ int nghttp2_session_on_window_update_received(nghttp2_session *session,
WINDOW_UPDATE are asynchronous, so it is hard to determine WINDOW_UPDATE are asynchronous, so it is hard to determine
that the peer is misbehaving or not without measuring that the peer is misbehaving or not without measuring
RTT. For now, we just ignore such frames. */ RTT. For now, we just ignore such frames. */
nghttp2_session_call_on_frame_received(session, frame); return nghttp2_session_call_on_frame_received(session, frame);
return 0;
} }
if(NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment < if(NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment <
session->remote_window_size) { session->remote_window_size) {
@ -2323,7 +2352,10 @@ int nghttp2_session_on_window_update_received(nghttp2_session *session,
(session, frame, NGHTTP2_FLOW_CONTROL_ERROR); (session, frame, NGHTTP2_FLOW_CONTROL_ERROR);
} }
session->remote_window_size += frame->window_update.window_size_increment; session->remote_window_size += frame->window_update.window_size_increment;
nghttp2_session_call_on_frame_received(session, frame); rv = nghttp2_session_call_on_frame_received(session, frame);
if(rv != 0) {
return rv;
}
/* To queue the DATA deferred by connection-level flow-control, we /* To queue the DATA deferred by connection-level flow-control, we
have to check all streams. Bad. */ have to check all streams. Bad. */
if(session->remote_window_size > 0) { if(session->remote_window_size > 0) {
@ -2341,8 +2373,7 @@ int nghttp2_session_on_window_update_received(nghttp2_session *session,
} }
if(stream->remote_flow_control == 0) { if(stream->remote_flow_control == 0) {
/* Same reason with connection-level flow control */ /* Same reason with connection-level flow control */
nghttp2_session_call_on_frame_received(session, frame); return nghttp2_session_call_on_frame_received(session, frame);
return 0;
} }
if(NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment < if(NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment <
stream->remote_window_size) { stream->remote_window_size) {
@ -2368,7 +2399,7 @@ int nghttp2_session_on_window_update_received(nghttp2_session *session,
return r; return r;
} }
} }
nghttp2_session_call_on_frame_received(session, frame); return nghttp2_session_call_on_frame_received(session, frame);
} }
} }
} }

View File

@ -685,7 +685,7 @@ const char *REQUIRED_HEADERS[] = {
} // namespace } // namespace
namespace { namespace {
void hd_on_frame_recv_callback int hd_on_frame_recv_callback
(nghttp2_session *session, nghttp2_frame *frame, void *user_data) (nghttp2_session *session, nghttp2_frame *frame, void *user_data)
{ {
auto hd = reinterpret_cast<Http2Handler*>(user_data); auto hd = reinterpret_cast<Http2Handler*>(user_data);
@ -701,7 +701,7 @@ void hd_on_frame_recv_callback
if(!http2::check_http2_headers(frame->headers.nva, if(!http2::check_http2_headers(frame->headers.nva,
frame->headers.nvlen)) { frame->headers.nvlen)) {
nghttp2_submit_rst_stream(session, stream_id, NGHTTP2_PROTOCOL_ERROR); nghttp2_submit_rst_stream(session, stream_id, NGHTTP2_PROTOCOL_ERROR);
return; return 0;
} }
for(size_t i = 0; REQUIRED_HEADERS[i]; ++i) { for(size_t i = 0; REQUIRED_HEADERS[i]; ++i) {
if(!http2::get_unique_header(frame->headers.nva, if(!http2::get_unique_header(frame->headers.nva,
@ -709,7 +709,7 @@ void hd_on_frame_recv_callback
REQUIRED_HEADERS[i])) { REQUIRED_HEADERS[i])) {
nghttp2_submit_rst_stream(session, stream_id, nghttp2_submit_rst_stream(session, stream_id,
NGHTTP2_PROTOCOL_ERROR); NGHTTP2_PROTOCOL_ERROR);
return; return 0;
} }
} }
auto req = util::make_unique<Request>(stream_id); auto req = util::make_unique<Request>(stream_id);
@ -724,6 +724,7 @@ void hd_on_frame_recv_callback
default: default:
break; break;
} }
return 0;
} }
} // namespace } // namespace

View File

@ -323,13 +323,14 @@ void print_frame(print_type ptype, nghttp2_frame *frame)
} }
} // namespace } // namespace
void on_frame_recv_callback int on_frame_recv_callback
(nghttp2_session *session, nghttp2_frame *frame, void *user_data) (nghttp2_session *session, nghttp2_frame *frame, void *user_data)
{ {
print_timer(); print_timer();
printf(" recv "); printf(" recv ");
print_frame(PRINT_RECV, frame); print_frame(PRINT_RECV, frame);
fflush(stdout); fflush(stdout);
return 0;
} }
void on_invalid_frame_recv_callback void on_invalid_frame_recv_callback

View File

@ -39,7 +39,7 @@ namespace nghttp2 {
void print_nv(char **nv); void print_nv(char **nv);
void on_frame_recv_callback int on_frame_recv_callback
(nghttp2_session *session, nghttp2_frame *frame, void *user_data); (nghttp2_session *session, nghttp2_frame *frame, void *user_data);
void on_invalid_frame_recv_callback void on_invalid_frame_recv_callback

View File

@ -1024,7 +1024,7 @@ void check_response_header
} }
} }
void on_frame_recv_callback2 int on_frame_recv_callback2
(nghttp2_session *session, nghttp2_frame *frame, void *user_data) (nghttp2_session *session, nghttp2_frame *frame, void *user_data)
{ {
if(frame->hd.type == NGHTTP2_HEADERS && if(frame->hd.type == NGHTTP2_HEADERS &&
@ -1041,6 +1041,7 @@ void on_frame_recv_callback2
if(config.verbose) { if(config.verbose) {
on_frame_recv_callback(session, frame, user_data); on_frame_recv_callback(session, frame, user_data);
} }
return 0;
} }
void on_stream_close_callback void on_stream_close_callback

View File

@ -173,7 +173,7 @@ int Http2Upstream::upgrade_upstream(HttpsUpstream *http)
} }
namespace { namespace {
void on_frame_recv_callback int on_frame_recv_callback
(nghttp2_session *session, nghttp2_frame *frame, void *user_data) (nghttp2_session *session, nghttp2_frame *frame, void *user_data)
{ {
auto upstream = reinterpret_cast<Http2Upstream*>(user_data); auto upstream = reinterpret_cast<Http2Upstream*>(user_data);
@ -212,7 +212,7 @@ void on_frame_recv_callback
// Assuming that nva is sorted by name. // Assuming that nva is sorted by name.
if(!http2::check_http2_headers(nva, nvlen)) { if(!http2::check_http2_headers(nva, nvlen)) {
upstream->rst_stream(downstream, NGHTTP2_PROTOCOL_ERROR); upstream->rst_stream(downstream, NGHTTP2_PROTOCOL_ERROR);
return; return 0;
} }
for(size_t i = 0; i < nvlen; ++i) { for(size_t i = 0; i < nvlen; ++i) {
@ -233,7 +233,7 @@ void on_frame_recv_callback
http2::value_lws(method) || http2::value_lws(method) ||
(!is_connect && (!scheme || http2::value_lws(scheme)))) { (!is_connect && (!scheme || http2::value_lws(scheme)))) {
upstream->rst_stream(downstream, NGHTTP2_PROTOCOL_ERROR); upstream->rst_stream(downstream, NGHTTP2_PROTOCOL_ERROR);
return; return 0;
} }
if(!is_connect && if(!is_connect &&
(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) { (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) {
@ -242,7 +242,7 @@ void on_frame_recv_callback
// If content-length is missing, // If content-length is missing,
// Downstream::push_upload_data_chunk will fail and // Downstream::push_upload_data_chunk will fail and
upstream->rst_stream(downstream, NGHTTP2_PROTOCOL_ERROR); upstream->rst_stream(downstream, NGHTTP2_PROTOCOL_ERROR);
return; return 0;
} }
} }
@ -270,12 +270,12 @@ void on_frame_recv_callback
// If downstream connection fails, issue RST_STREAM. // If downstream connection fails, issue RST_STREAM.
upstream->rst_stream(downstream, NGHTTP2_INTERNAL_ERROR); upstream->rst_stream(downstream, NGHTTP2_INTERNAL_ERROR);
downstream->set_request_state(Downstream::CONNECT_FAIL); downstream->set_request_state(Downstream::CONNECT_FAIL);
return; return 0;
} }
rv = downstream->push_request_headers(); rv = downstream->push_request_headers();
if(rv != 0) { if(rv != 0) {
upstream->rst_stream(downstream, NGHTTP2_INTERNAL_ERROR); upstream->rst_stream(downstream, NGHTTP2_INTERNAL_ERROR);
return; return 0;
} }
downstream->set_request_state(Downstream::HEADER_COMPLETE); downstream->set_request_state(Downstream::HEADER_COMPLETE);
if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
@ -286,6 +286,7 @@ void on_frame_recv_callback
default: default:
break; break;
} }
return 0;
} }
} // namespace } // namespace

View File

@ -722,7 +722,7 @@ void on_stream_close_callback
} // namespace } // namespace
namespace { namespace {
void on_frame_recv_callback int on_frame_recv_callback
(nghttp2_session *session, nghttp2_frame *frame, void *user_data) (nghttp2_session *session, nghttp2_frame *frame, void *user_data)
{ {
int rv; int rv;
@ -755,7 +755,7 @@ void on_frame_recv_callback
NGHTTP2_PROTOCOL_ERROR); NGHTTP2_PROTOCOL_ERROR);
downstream->set_response_state(Downstream::MSG_RESET); downstream->set_response_state(Downstream::MSG_RESET);
call_downstream_readcb(spdy, downstream); call_downstream_readcb(spdy, downstream);
return; return 0;
} }
for(size_t i = 0; i < nvlen; ++i) { for(size_t i = 0; i < nvlen; ++i) {
@ -771,7 +771,7 @@ void on_frame_recv_callback
NGHTTP2_PROTOCOL_ERROR); NGHTTP2_PROTOCOL_ERROR);
downstream->set_response_state(Downstream::MSG_RESET); downstream->set_response_state(Downstream::MSG_RESET);
call_downstream_readcb(spdy, downstream); call_downstream_readcb(spdy, downstream);
return; return 0;
} }
downstream->set_response_http_status downstream->set_response_http_status
(strtoul(http2::value_to_str(status).c_str(), nullptr, 10)); (strtoul(http2::value_to_str(status).c_str(), nullptr, 10));
@ -826,7 +826,7 @@ void on_frame_recv_callback
if(upstream->resume_read(SHRPX_MSG_BLOCK, downstream) != 0) { if(upstream->resume_read(SHRPX_MSG_BLOCK, downstream) != 0) {
// If resume_read fails, just drop connection. Not ideal. // If resume_read fails, just drop connection. Not ideal.
delete upstream->get_client_handler(); delete upstream->get_client_handler();
return; return 0;
} }
downstream->set_request_state(Downstream::HEADER_COMPLETE); downstream->set_request_state(Downstream::HEADER_COMPLETE);
if(LOG_ENABLED(INFO)) { if(LOG_ENABLED(INFO)) {
@ -890,6 +890,7 @@ void on_frame_recv_callback
default: default:
break; break;
} }
return 0;
} }
} // namespace } // namespace

View File

@ -126,12 +126,13 @@ static ssize_t accumulator_send_callback(nghttp2_session *session,
return len; return len;
} }
static void on_frame_recv_callback(nghttp2_session *session, static int on_frame_recv_callback(nghttp2_session *session,
nghttp2_frame *frame, nghttp2_frame *frame,
void *user_data) void *user_data)
{ {
my_user_data *ud = (my_user_data*)user_data; my_user_data *ud = (my_user_data*)user_data;
++ud->frame_recv_cb_called; ++ud->frame_recv_cb_called;
return 0;
} }
static void on_invalid_frame_recv_callback(nghttp2_session *session, static void on_invalid_frame_recv_callback(nghttp2_session *session,