Send additional debug info when terminating session

This commit is contained in:
Tatsuhiro Tsujikawa 2014-07-12 22:57:17 +09:00
parent 25326b40db
commit 35ffeb5ff4
2 changed files with 172 additions and 94 deletions

View File

@ -132,25 +132,49 @@ static int session_detect_idle_stream(nghttp2_session *session,
return 0;
}
static int session_terminate_session
(nghttp2_session *session, int32_t last_stream_id,
nghttp2_error_code error_code, const char *reason)
{
const uint8_t *debug_data;
size_t debug_datalen;
if(session->goaway_flags & NGHTTP2_GOAWAY_FAIL_ON_SEND) {
return 0;
}
session->goaway_flags |= NGHTTP2_GOAWAY_FAIL_ON_SEND;
if(reason == NULL) {
debug_data = NULL;
debug_datalen = 0;
} else {
debug_data = (const uint8_t*)reason;
debug_datalen = strlen(reason);
}
return nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, last_stream_id,
error_code, debug_data, debug_datalen);
}
int nghttp2_session_terminate_session(nghttp2_session *session,
nghttp2_error_code error_code)
{
return nghttp2_session_terminate_session2(session,
session->last_proc_stream_id,
error_code);
return session_terminate_session(session, session->last_proc_stream_id,
error_code, NULL);
}
int nghttp2_session_terminate_session2(nghttp2_session *session,
int32_t last_stream_id,
nghttp2_error_code error_code)
{
if(session->goaway_flags & NGHTTP2_GOAWAY_FAIL_ON_SEND) {
return 0;
}
session->goaway_flags |= NGHTTP2_GOAWAY_FAIL_ON_SEND;
return session_terminate_session(session, last_stream_id, error_code, NULL);
}
return nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, last_stream_id,
error_code, NULL, 0);
int nghttp2_session_terminate_session_with_reason
(nghttp2_session *session, nghttp2_error_code error_code, const char *reason)
{
return session_terminate_session(session, session->last_proc_stream_id,
error_code, reason);
}
int nghttp2_session_is_my_stream_id(nghttp2_session *session,
@ -511,8 +535,8 @@ int nghttp2_session_reprioritize_stream
nghttp2_stream *root_stream;
if(pri_spec->stream_id == stream->stream_id) {
return nghttp2_session_terminate_session(session,
NGHTTP2_PROTOCOL_ERROR);
return nghttp2_session_terminate_session_with_reason
(session, NGHTTP2_PROTOCOL_ERROR, "depend on itself");
}
if(pri_spec->stream_id == 0) {
@ -2296,8 +2320,8 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session,
if(rv == NGHTTP2_ERR_HEADER_COMP) {
/* If header compression error occurred, should terminiate
connection. */
rv = nghttp2_session_terminate_session(session,
NGHTTP2_INTERNAL_ERROR);
rv = nghttp2_session_terminate_session
(session, NGHTTP2_INTERNAL_ERROR);
}
if(nghttp2_is_fatal(rv)) {
return rv;
@ -2522,7 +2546,8 @@ static int session_inflate_handle_invalid_stream
static int session_handle_invalid_connection
(nghttp2_session *session,
nghttp2_frame *frame,
nghttp2_error_code error_code)
nghttp2_error_code error_code,
const char *reason)
{
if(session->callbacks.on_invalid_frame_recv_callback) {
if(session->callbacks.on_invalid_frame_recv_callback
@ -2530,16 +2555,18 @@ static int session_handle_invalid_connection
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
}
return nghttp2_session_terminate_session(session, error_code);
return nghttp2_session_terminate_session_with_reason
(session, error_code, reason);
}
static int session_inflate_handle_invalid_connection
(nghttp2_session *session,
nghttp2_frame *frame,
nghttp2_error_code error_code)
nghttp2_error_code error_code,
const char *reason)
{
int rv;
rv = session_handle_invalid_connection(session, frame, error_code);
rv = session_handle_invalid_connection(session, frame, error_code, reason);
if(nghttp2_is_fatal(rv)) {
return rv;
}
@ -2770,7 +2797,8 @@ int nghttp2_session_on_request_headers_received(nghttp2_session *session,
nghttp2_stream *stream;
if(frame->hd.stream_id == 0) {
return session_inflate_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR);
(session, frame, NGHTTP2_PROTOCOL_ERROR,
"request HEADERS: stream_id == 0");
}
if(session->goaway_flags) {
/* We don't accept new stream after GOAWAY is sent or received. */
@ -2781,18 +2809,21 @@ int nghttp2_session_on_request_headers_received(nghttp2_session *session,
stream ID, it MUST issue connection error with error code
PROTOCOL_ERROR */
return session_inflate_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR);
(session, frame, NGHTTP2_PROTOCOL_ERROR,
"request HEADERS: invalid stream_id");
}
session->last_recv_stream_id = frame->hd.stream_id;
if(session_is_incoming_concurrent_streams_max(session)) {
return session_inflate_handle_invalid_connection
(session, frame, NGHTTP2_ENHANCE_YOUR_CALM);
(session, frame, NGHTTP2_ENHANCE_YOUR_CALM,
"request HEADERS: max concurrent streams exceeded");
}
if(frame->headers.pri_spec.stream_id == frame->hd.stream_id) {
return session_inflate_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR);
(session, frame, NGHTTP2_PROTOCOL_ERROR,
"request HEADERS: depend on itself");
}
if(session_is_incoming_concurrent_streams_pending_max(session)) {
@ -2828,7 +2859,8 @@ int nghttp2_session_on_response_headers_received(nghttp2_session *session,
nghttp2_session_is_my_stream_id(session, frame->hd.stream_id));
if(frame->hd.stream_id == 0) {
return session_inflate_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR);
(session, frame, NGHTTP2_PROTOCOL_ERROR,
"response HEADERS: stream_id == 0");
}
if(stream->shut_flags & NGHTTP2_SHUT_RD) {
/* half closed (remote): from the spec:
@ -2856,7 +2888,8 @@ int nghttp2_session_on_push_response_headers_received(nghttp2_session *session,
assert(stream->state == NGHTTP2_STREAM_RESERVED);
if(frame->hd.stream_id == 0) {
return session_inflate_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR);
(session, frame, NGHTTP2_PROTOCOL_ERROR,
"push response HEADERS: stream_id == 0");
}
if(session->goaway_flags) {
/* We don't accept new stream after GOAWAY is sent or received. */
@ -2865,7 +2898,8 @@ int nghttp2_session_on_push_response_headers_received(nghttp2_session *session,
if(session_is_incoming_concurrent_streams_max(session)) {
return session_inflate_handle_invalid_connection
(session, frame, NGHTTP2_ENHANCE_YOUR_CALM);
(session, frame, NGHTTP2_ENHANCE_YOUR_CALM,
"push response HEADERS: max concurrent streams exceeded");
}
if(session_is_incoming_concurrent_streams_pending_max(session)) {
return session_inflate_handle_invalid_stream
@ -2888,7 +2922,7 @@ int nghttp2_session_on_headers_received(nghttp2_session *session,
int rv = 0;
if(frame->hd.stream_id == 0) {
return session_inflate_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR);
(session, frame, NGHTTP2_PROTOCOL_ERROR, "HEADERS: stream_id == 0");
}
if(stream->state == NGHTTP2_STREAM_RESERVED) {
/* reserved. The valid push response HEADERS is processed by
@ -2896,7 +2930,7 @@ int nghttp2_session_on_headers_received(nghttp2_session *session,
generic HEADERS is called invalid cases for HEADERS against
reserved state. */
return session_inflate_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR);
(session, frame, NGHTTP2_PROTOCOL_ERROR, "HEADERS: stream in reserved");
}
if((stream->shut_flags & NGHTTP2_SHUT_RD)) {
/* half closed (remote): from the spec:
@ -2951,7 +2985,8 @@ static int session_process_headers_frame(nghttp2_session *session)
nghttp2_buf_len(&iframe->sbuf));
if(rv != 0) {
return nghttp2_session_terminate_session(session, NGHTTP2_PROTOCOL_ERROR);
return nghttp2_session_terminate_session_with_reason
(session, NGHTTP2_PROTOCOL_ERROR, "HEADERS: could not unpack");
}
stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
if(!stream) {
@ -2984,20 +3019,20 @@ int nghttp2_session_on_priority_received(nghttp2_session *session,
nghttp2_stream *stream;
if(frame->hd.stream_id == 0) {
return session_handle_invalid_connection(session, frame,
NGHTTP2_PROTOCOL_ERROR);
return session_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR, "PRIORITY: stream_id == 0");
}
stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id);
if(!stream) {
if(session_detect_idle_stream(session, frame->hd.stream_id)) {
return session_handle_invalid_connection(session, frame,
NGHTTP2_PROTOCOL_ERROR);
return session_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR, "PRIORITY: stream in idle");
}
return 0;
}
if(state_reserved_remote(session, stream)) {
return session_handle_invalid_connection(session, frame,
NGHTTP2_PROTOCOL_ERROR);
return session_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR, "PRIORITY: stream in reserved");
}
/* Only update priority of the stream, only if it is not pushed
stream and is initiated by remote peer, or it is pushed stream
@ -3035,14 +3070,14 @@ int nghttp2_session_on_rst_stream_received(nghttp2_session *session,
int rv;
nghttp2_stream *stream;
if(frame->hd.stream_id == 0) {
return session_handle_invalid_connection(session, frame,
NGHTTP2_PROTOCOL_ERROR);
return session_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR, "RST_STREAM: stream_id == 0");
}
stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
if(!stream) {
if(session_detect_idle_stream(session, frame->hd.stream_id)) {
return session_handle_invalid_connection(session, frame,
NGHTTP2_PROTOCOL_ERROR);
return session_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR, "RST_STREAM: stream in idle");
}
}
@ -3271,17 +3306,18 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
int initial_window_size_seen = 0;
if(frame->hd.stream_id != 0) {
return session_handle_invalid_connection(session, frame,
NGHTTP2_PROTOCOL_ERROR);
return session_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR, "SETTINGS: stream_id != 0");
}
if(frame->hd.flags & NGHTTP2_FLAG_ACK) {
if(frame->settings.niv != 0) {
return session_handle_invalid_connection
(session, frame, NGHTTP2_FRAME_SIZE_ERROR);
(session, frame, NGHTTP2_FRAME_SIZE_ERROR,
"SETTINGS: ACK and payload != 0");
}
if(session->inflight_niv == -1) {
return session_handle_invalid_connection(session, frame,
NGHTTP2_PROTOCOL_ERROR);
return session_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR, "SETTINGS: unexpected ACK");
}
rv = nghttp2_session_update_local_settings(session, session->inflight_iv,
session->inflight_niv);
@ -3296,7 +3332,8 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
if(rv == NGHTTP2_ERR_HEADER_COMP) {
error_code = NGHTTP2_COMPRESSION_ERROR;
}
return session_handle_invalid_connection(session, frame, error_code);
return session_handle_invalid_connection
(session, frame, error_code, NULL);
}
return session_call_on_frame_received(session, frame);
}
@ -3318,7 +3355,8 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
if(entry->value > NGHTTP2_MAX_HEADER_TABLE_SIZE) {
return session_handle_invalid_connection
(session, frame, NGHTTP2_COMPRESSION_ERROR);
(session, frame, NGHTTP2_COMPRESSION_ERROR,
"SETTINGS: too large SETTINGS_HEADER_TABLE_SIZE");
}
rv = nghttp2_hd_deflate_change_table_size(&session->hd_deflater,
@ -3328,7 +3366,7 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
return rv;
} else {
return session_handle_invalid_connection
(session, frame, NGHTTP2_COMPRESSION_ERROR);
(session, frame, NGHTTP2_COMPRESSION_ERROR, NULL);
}
}
@ -3344,12 +3382,14 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
if(entry->value != 0 && entry->value != 1) {
return session_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR);
(session, frame, NGHTTP2_PROTOCOL_ERROR,
"SETTINGS: invalid SETTINGS_ENBLE_PUSH");
}
if(!session->server && entry->value != 0) {
return session_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR);
(session, frame, NGHTTP2_PROTOCOL_ERROR,
"SETTINGS: server attempted to enable push");
}
session->remote_settings.enable_push = entry->value;
@ -3376,7 +3416,8 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
/* Check that initial_window_size < (1u << 31) */
if(entry->value > NGHTTP2_MAX_WINDOW_SIZE) {
return session_handle_invalid_connection
(session, frame, NGHTTP2_FLOW_CONTROL_ERROR);
(session, frame, NGHTTP2_FLOW_CONTROL_ERROR,
"SETTINGS: too large SETTINGS_INITIAL_WINDOW_SIZE");
}
rv = session_update_remote_initial_window_size(session, entry->value);
@ -3387,7 +3428,7 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
if(rv != 0) {
return session_handle_invalid_connection
(session, frame, NGHTTP2_FLOW_CONTROL_ERROR);
(session, frame, NGHTTP2_FLOW_CONTROL_ERROR, NULL);
}
session->remote_settings.initial_window_size = entry->value;
@ -3405,7 +3446,7 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
}
return session_handle_invalid_connection
(session, frame, NGHTTP2_INTERNAL_ERROR);
(session, frame, NGHTTP2_INTERNAL_ERROR, NULL);
}
}
@ -3437,36 +3478,41 @@ int nghttp2_session_on_push_promise_received(nghttp2_session *session,
if(frame->hd.stream_id == 0) {
return session_inflate_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR);
(session, frame, NGHTTP2_PROTOCOL_ERROR, "PUSH_PROMISE: stream_id == 0");
}
if(session->server || session->local_settings.enable_push == 0) {
return session_inflate_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR);
(session, frame, NGHTTP2_PROTOCOL_ERROR, "PUSH_PROMISE: push disabled");
}
if(session->goaway_flags) {
/* We just dicard PUSH_PROMISE after GOAWAY is sent or
received. */
return NGHTTP2_ERR_IGN_HEADER_BLOCK;
}
if(!nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) {
return session_inflate_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR,
"PUSH_PROMISE: invalid stream_id");
}
if(!session_is_new_peer_stream_id
(session, frame->push_promise.promised_stream_id)) {
/* The spec says if an endpoint receives a PUSH_PROMISE with
illegal stream ID is subject to a connection error of type
PROTOCOL_ERROR. */
return session_inflate_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR);
(session, frame, NGHTTP2_PROTOCOL_ERROR,
"PUSH_PROMISE: invalid promised_stream_id");
}
session->last_recv_stream_id = frame->push_promise.promised_stream_id;
if(!nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) {
return session_inflate_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR);
}
stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
if(!stream || stream->state == NGHTTP2_STREAM_CLOSING) {
if(!stream) {
if(session_detect_idle_stream(session, frame->hd.stream_id)) {
return session_inflate_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR);
(session, frame, NGHTTP2_PROTOCOL_ERROR,
"PUSH_PROMISE: stream in idle");
}
}
rv = nghttp2_session_add_rst_stream
@ -3529,7 +3575,8 @@ static int session_process_push_promise_frame(nghttp2_session *session)
iframe->sbuf.pos, nghttp2_buf_len(&iframe->sbuf));
if(rv != 0) {
return nghttp2_session_terminate_session(session, NGHTTP2_PROTOCOL_ERROR);
return nghttp2_session_terminate_session_with_reason
(session, NGHTTP2_PROTOCOL_ERROR, "PUSH_PROMISE: could not unpack");
}
return nghttp2_session_on_push_promise_received(session, frame);
@ -3540,8 +3587,8 @@ int nghttp2_session_on_ping_received(nghttp2_session *session,
{
int rv = 0;
if(frame->hd.stream_id != 0) {
return session_handle_invalid_connection(session, frame,
NGHTTP2_PROTOCOL_ERROR);
return session_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR, "PING: stream_id != 0");
}
if((frame->hd.flags & NGHTTP2_FLAG_ACK) == 0) {
/* Peer sent ping, so ping it back */
@ -3570,14 +3617,15 @@ int nghttp2_session_on_goaway_received(nghttp2_session *session,
nghttp2_frame *frame)
{
if(frame->hd.stream_id != 0) {
return session_handle_invalid_connection(session, frame,
NGHTTP2_PROTOCOL_ERROR);
return session_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR, "GOAWAY: stream_id != 0");
}
/* Draft says Endpoints MUST NOT increase the value they send in the
last stream identifier. */
if(session->remote_last_stream_id < frame->goaway.last_stream_id) {
return session_handle_invalid_connection(session, frame,
NGHTTP2_PROTOCOL_ERROR);
return session_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR,
"GOAWAY: invalid last_stream_id");
}
session->remote_last_stream_id = frame->goaway.last_stream_id;
@ -3608,8 +3656,8 @@ int nghttp2_session_on_altsvc_received(nghttp2_session *session,
already rejected ALTSVC if it is received by server. */
if(frame->hd.stream_id != 0 &&
!nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) {
return session_handle_invalid_connection(session, frame,
NGHTTP2_PROTOCOL_ERROR);
return session_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR, "ALTSVC: invalid stream_id");
}
return session_call_on_frame_received(session, frame);
@ -3630,8 +3678,8 @@ static int session_process_altsvc_frame(nghttp2_session *session)
nghttp2_buf_len(&iframe->lbuf));
if(rv != 0) {
return session_handle_invalid_connection(session, frame,
NGHTTP2_FRAME_SIZE_ERROR);
return session_handle_invalid_connection
(session, frame, NGHTTP2_FRAME_SIZE_ERROR, "ALTSVC: could not unpack");
}
nghttp2_buf_wrap_init(&iframe->lbuf, NULL, 0);
@ -3681,7 +3729,7 @@ static int session_on_connection_window_update_received
if(NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment <
session->remote_window_size) {
return session_handle_invalid_connection
(session, frame, NGHTTP2_FLOW_CONTROL_ERROR);
(session, frame, NGHTTP2_FLOW_CONTROL_ERROR, NULL);
}
session->remote_window_size += frame->window_update.window_size_increment;
/* To queue the DATA deferred by connection-level flow-control, we
@ -3706,14 +3754,16 @@ static int session_on_stream_window_update_received
stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
if(!stream) {
if(session_detect_idle_stream(session, frame->hd.stream_id)) {
return session_handle_invalid_connection(session, frame,
NGHTTP2_PROTOCOL_ERROR);
return session_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR,
"WINDOW_UPDATE to idle stream");
}
return 0;
}
if(stream->state == NGHTTP2_STREAM_RESERVED) {
return session_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR);
(session, frame, NGHTTP2_PROTOCOL_ERROR,
"WINDOW_UPADATE to reserved stream");
}
if(NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment <
stream->remote_window_size) {
@ -3952,6 +4002,7 @@ static int session_on_data_received_fail_fast(nghttp2_session *session)
nghttp2_stream *stream;
nghttp2_inbound_frame *iframe;
int32_t stream_id;
const char *failure_reason;
iframe = &session->iframe;
stream_id = iframe->frame.hd.stream_id;
@ -3960,16 +4011,19 @@ static int session_on_data_received_fail_fast(nghttp2_session *session)
/* The spec says that if a DATA frame is received whose stream ID
is 0, the recipient MUST respond with a connection error of
type PROTOCOL_ERROR. */
failure_reason = "DATA: stream_id == 0";
goto fail;
}
stream = nghttp2_session_get_stream(session, stream_id);
if(!stream) {
if(session_detect_idle_stream(session, stream_id)) {
failure_reason = "DATA: stream in idle";
goto fail;
}
return NGHTTP2_ERR_IGN_PAYLOAD;
}
if(stream->shut_flags & NGHTTP2_SHUT_RD) {
failure_reason = "DATA: stream in half-closed(remote)";
goto fail;
}
@ -3978,11 +4032,13 @@ static int session_on_data_received_fail_fast(nghttp2_session *session)
return NGHTTP2_ERR_IGN_PAYLOAD;
}
if(stream->state != NGHTTP2_STREAM_OPENED) {
failure_reason = "DATA: stream not opened";
goto fail;
}
return 0;
}
if(stream->state == NGHTTP2_STREAM_RESERVED) {
failure_reason = "DATA: stream in reserved";
goto fail;
}
if(stream->state == NGHTTP2_STREAM_CLOSING) {
@ -3990,7 +4046,8 @@ static int session_on_data_received_fail_fast(nghttp2_session *session)
}
return 0;
fail:
rv = nghttp2_session_terminate_session(session, NGHTTP2_PROTOCOL_ERROR);
rv = nghttp2_session_terminate_session_with_reason
(session, NGHTTP2_PROTOCOL_ERROR, failure_reason);
if(nghttp2_is_fatal(rv)) {
return rv;
}
@ -4193,8 +4250,9 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd);
if(rv < 0) {
iframe->state = NGHTTP2_IB_IGN_DATA;
rv = nghttp2_session_terminate_session(session,
NGHTTP2_PROTOCOL_ERROR);
rv = nghttp2_session_terminate_session_with_reason
(session, NGHTTP2_PROTOCOL_ERROR,
"DATA: insufficient padding space");
if(nghttp2_is_fatal(rv)) {
return rv;
@ -4228,8 +4286,9 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
rv = nghttp2_session_terminate_session(session,
NGHTTP2_PROTOCOL_ERROR);
rv = nghttp2_session_terminate_session_with_reason
(session, NGHTTP2_PROTOCOL_ERROR,
"HEADERS: insufficient padding space");
if(nghttp2_is_fatal(rv)) {
return rv;
}
@ -4353,8 +4412,9 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
if(rv < 0) {
busy = 1;
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
rv = nghttp2_session_terminate_session(session,
NGHTTP2_PROTOCOL_ERROR);
rv = nghttp2_session_terminate_session_with_reason
(session, NGHTTP2_PROTOCOL_ERROR,
"PUSH_PROMISE: insufficient padding space");
if(nghttp2_is_fatal(rv)) {
return rv;
}
@ -4412,8 +4472,8 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
/* Receiving CONTINUATION in this state are subject to
connection error of type PROTOCOL_ERROR */
rv = nghttp2_session_terminate_session(session,
NGHTTP2_PROTOCOL_ERROR);
rv = nghttp2_session_terminate_session_with_reason
(session, NGHTTP2_PROTOCOL_ERROR, "CONTINUATION: unexpected");
if(nghttp2_is_fatal(rv)) {
return rv;
}
@ -4429,8 +4489,9 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
iframe->frame.hd.flags = NGHTTP2_FLAG_NONE;
if(session->server) {
rv = nghttp2_session_terminate_session(session,
NGHTTP2_PROTOCOL_ERROR);
rv = nghttp2_session_terminate_session_with_reason
(session, NGHTTP2_PROTOCOL_ERROR,
"ALTSVC: reserved for server only");
if(nghttp2_is_fatal(rv)) {
return rv;
}
@ -4488,8 +4549,8 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
padlen = inbound_frame_compute_pad(iframe);
if(padlen < 0) {
busy = 1;
rv = nghttp2_session_terminate_session(session,
NGHTTP2_PROTOCOL_ERROR);
rv = nghttp2_session_terminate_session_with_reason
(session, NGHTTP2_PROTOCOL_ERROR, "HEADERS: invalid padding");
if(nghttp2_is_fatal(rv)) {
return rv;
}
@ -4554,8 +4615,9 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
padlen = inbound_frame_compute_pad(iframe);
if(padlen < 0) {
busy = 1;
rv = nghttp2_session_terminate_session(session,
NGHTTP2_PROTOCOL_ERROR);
rv = nghttp2_session_terminate_session_with_reason
(session, NGHTTP2_PROTOCOL_ERROR,
"PUSH_PROMISE: invalid padding");
if(nghttp2_is_fatal(rv)) {
return rv;
}
@ -4910,8 +4972,9 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
"got stream_id=%d, type=%d\n",
iframe->frame.hd.stream_id, NGHTTP2_CONTINUATION,
cont_hd.stream_id, cont_hd.type));
rv = nghttp2_session_terminate_session(session,
NGHTTP2_PROTOCOL_ERROR);
rv = nghttp2_session_terminate_session_with_reason
(session, NGHTTP2_PROTOCOL_ERROR,
"unexpected non-CONTINUATION frame or stream_id is invalid");
if(nghttp2_is_fatal(rv)) {
return rv;
}
@ -4931,8 +4994,8 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
"recv: headers too large %zu\n",
iframe->headers_payload_length));
rv = nghttp2_session_terminate_session(session,
NGHTTP2_INTERNAL_ERROR);
rv = nghttp2_session_terminate_session_with_reason
(session, NGHTTP2_INTERNAL_ERROR, "header is too large");
if(nghttp2_is_fatal(rv)) {
return rv;
}
@ -4993,8 +5056,8 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
padlen = inbound_frame_compute_pad(iframe);
if(padlen < 0) {
rv = nghttp2_session_terminate_session(session,
NGHTTP2_PROTOCOL_ERROR);
rv = nghttp2_session_terminate_session_with_reason
(session, NGHTTP2_PROTOCOL_ERROR, "DATA: invalid padding");
if(nghttp2_is_fatal(rv)) {
return rv;
}

View File

@ -726,4 +726,19 @@ int nghttp2_session_reprioritize_stream
(nghttp2_session *session, nghttp2_stream *stream,
const nghttp2_priority_spec *pri_spec);
/*
* Terminates current |session| with the |error_code|. The |reason|
* is NULL-terminated debug string.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
* NGHTTP2_ERR_INVALID_ARGUMENT
* The |reason| is too long.
*/
int nghttp2_session_terminate_session_with_reason
(nghttp2_session *session, nghttp2_error_code error_code, const char *reason);
#endif /* NGHTTP2_SESSION_H */