diff --git a/lib/includes/nghttp2/nghttp2.h b/lib/includes/nghttp2/nghttp2.h index 314538fa..50c40e11 100644 --- a/lib/includes/nghttp2/nghttp2.h +++ b/lib/includes/nghttp2/nghttp2.h @@ -879,8 +879,13 @@ typedef int (*nghttp2_on_frame_send_callback) * sent because of the error. The error is indicated by the * |lib_error_code|, which is one of the values defined in * :type:`nghttp2_error`. + * + * 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 void (*nghttp2_on_frame_not_send_callback) +typedef int (*nghttp2_on_frame_not_send_callback) (nghttp2_session *session, nghttp2_frame *frame, int lib_error_code, void *user_data); diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c index 4e2da2b6..5ade5e8a 100644 --- a/lib/nghttp2_session.c +++ b/lib/nghttp2_session.c @@ -1474,8 +1474,10 @@ int nghttp2_session_send(nghttp2_session *session) it. */ nghttp2_frame *frame = nghttp2_outbound_item_get_ctrl_frame(item); if(frame->hd.type != NGHTTP2_WINDOW_UPDATE) { - session->callbacks.on_frame_not_send_callback - (session, frame, framebuflen, session->user_data); + if(session->callbacks.on_frame_not_send_callback + (session, frame, framebuflen, session->user_data) != 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } } } nghttp2_outbound_item_free(item); diff --git a/src/shrpx_http2_upstream.cc b/src/shrpx_http2_upstream.cc index 4269416d..95a39a42 100644 --- a/src/shrpx_http2_upstream.cc +++ b/src/shrpx_http2_upstream.cc @@ -331,9 +331,9 @@ int on_data_chunk_recv_callback(nghttp2_session *session, } // namespace namespace { -void on_frame_not_send_callback(nghttp2_session *session, - nghttp2_frame *frame, - int lib_error_code, void *user_data) +int on_frame_not_send_callback(nghttp2_session *session, + nghttp2_frame *frame, + int lib_error_code, void *user_data) { auto upstream = reinterpret_cast(user_data); ULOG(WARNING, upstream) << "Failed to send control frame type=" @@ -348,6 +348,7 @@ void on_frame_not_send_callback(nghttp2_session *session, upstream->rst_stream(downstream, NGHTTP2_INTERNAL_ERROR); } } + return 0; } } // namespace diff --git a/src/shrpx_spdy_session.cc b/src/shrpx_spdy_session.cc index 12c87ab1..d2e3e92c 100644 --- a/src/shrpx_spdy_session.cc +++ b/src/shrpx_spdy_session.cc @@ -970,7 +970,7 @@ int before_frame_send_callback(nghttp2_session *session, } // namespace namespace { -void on_frame_not_send_callback(nghttp2_session *session, +int on_frame_not_send_callback(nghttp2_session *session, nghttp2_frame *frame, int lib_error_code, void *user_data) { @@ -986,19 +986,20 @@ void on_frame_not_send_callback(nghttp2_session *session, auto sd = reinterpret_cast (nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)); if(!sd) { - return; + return 0; } if(sd->dconn) { auto downstream = sd->dconn->get_downstream(); if(!downstream || downstream->get_downstream_stream_id() != frame->hd.stream_id) { - return; + return 0; } downstream->set_response_state(Downstream::MSG_RESET); call_downstream_readcb(spdy, downstream); } spdy->remove_stream_data(sd); } + return 0; } } // namespace diff --git a/tests/nghttp2_session_test.c b/tests/nghttp2_session_test.c index 32ef3166..aa4dc33c 100644 --- a/tests/nghttp2_session_test.c +++ b/tests/nghttp2_session_test.c @@ -155,15 +155,16 @@ static int on_frame_send_callback(nghttp2_session *session, return 0; } -static void on_frame_not_send_callback(nghttp2_session *session, - nghttp2_frame *frame, - int lib_error, - void *user_data) +static int on_frame_not_send_callback(nghttp2_session *session, + nghttp2_frame *frame, + int lib_error, + void *user_data) { my_user_data *ud = (my_user_data*)user_data; ++ud->frame_not_send_cb_called; ud->not_sent_frame_type = frame->hd.type; ud->not_sent_error = lib_error; + return 0; } static int on_data_chunk_recv_callback(nghttp2_session *session,