Support graceful shutdown using multiple GOAWAY
Add last_stream_id parameter to nghttp2_submit_goaway(). To terminate connection immediately with application chosen last stream ID, nghttp2_session_terminate_session2() was added.
This commit is contained in:
parent
975524a125
commit
b78a51da0e
|
@ -270,10 +270,10 @@ static int on_stream_close_callback(nghttp2_session *session,
|
||||||
req = nghttp2_session_get_stream_user_data(session, stream_id);
|
req = nghttp2_session_get_stream_user_data(session, stream_id);
|
||||||
if(req) {
|
if(req) {
|
||||||
int rv;
|
int rv;
|
||||||
rv = nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, NGHTTP2_NO_ERROR,
|
rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR);
|
||||||
NULL, 0);
|
|
||||||
if(rv != 0) {
|
if(rv != 0) {
|
||||||
diec("nghttp2_submit_goaway", rv);
|
diec("nghttp2_session_terminate_session", rv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -2003,13 +2003,13 @@ int32_t nghttp2_session_get_stream_remote_window_size(nghttp2_session* session,
|
||||||
*
|
*
|
||||||
* Signals the session so that the connection should be terminated.
|
* Signals the session so that the connection should be terminated.
|
||||||
*
|
*
|
||||||
* GOAWAY frame with the given |error_code| will be submitted if it
|
* The last stream ID is the ID of a stream for which
|
||||||
* has not been transmitted. After the transmission, both
|
* :type:`nghttp2_on_frame_recv_callback` was called most recently.
|
||||||
* `nghttp2_session_want_read()` and `nghttp2_session_want_write()`
|
*
|
||||||
* return 0. If GOAWAY frame has already transmitted at the time when
|
* The |error_code| is the error code of this GOAWAY frame.
|
||||||
* this function is invoked, `nghttp2_session_want_read()` and
|
*
|
||||||
* `nghttp2_session_want_write()` returns 0 immediately after this
|
* After the transmission, both `nghttp2_session_want_read()` and
|
||||||
* function succeeds.
|
* `nghttp2_session_want_write()` return 0.
|
||||||
*
|
*
|
||||||
* This function should be called when the connection should be
|
* This function should be called when the connection should be
|
||||||
* terminated after sending GOAWAY. If the remaining streams should
|
* terminated after sending GOAWAY. If the remaining streams should
|
||||||
|
@ -2024,6 +2024,25 @@ int32_t nghttp2_session_get_stream_remote_window_size(nghttp2_session* session,
|
||||||
int nghttp2_session_terminate_session(nghttp2_session *session,
|
int nghttp2_session_terminate_session(nghttp2_session *session,
|
||||||
nghttp2_error_code error_code);
|
nghttp2_error_code error_code);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* Signals the session so that the connection should be terminated.
|
||||||
|
*
|
||||||
|
* This function behaves like `nghttp2_session_terminate_session()`,
|
||||||
|
* but the last stream ID can be specified by the application for fine
|
||||||
|
* grained control of stream.
|
||||||
|
*
|
||||||
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
|
* negative error codes:
|
||||||
|
*
|
||||||
|
* :enum:`NGHTTP2_ERR_NOMEM`
|
||||||
|
* Out of memory.
|
||||||
|
*/
|
||||||
|
int nghttp2_session_terminate_session2(nghttp2_session *session,
|
||||||
|
int32_t last_stream_id,
|
||||||
|
nghttp2_error_code error_code);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
|
@ -2529,7 +2548,8 @@ int nghttp2_submit_ping(nghttp2_session *session, uint8_t flags,
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* Submits GOAWAY frame with the error code |error_code|.
|
* Submits GOAWAY frame with the last stream ID |last_stream_id| and
|
||||||
|
* the error code |error_code|.
|
||||||
*
|
*
|
||||||
* The |flags| is currently ignored and should be
|
* The |flags| is currently ignored and should be
|
||||||
* :enum:`NGHTTP2_FLAG_NONE`.
|
* :enum:`NGHTTP2_FLAG_NONE`.
|
||||||
|
@ -2541,15 +2561,22 @@ int nghttp2_submit_ping(nghttp2_session *session, uint8_t flags,
|
||||||
* keep this memory after the return of this function. If the
|
* keep this memory after the return of this function. If the
|
||||||
* |opaque_data_len| is 0, the |opaque_data| could be ``NULL``.
|
* |opaque_data_len| is 0, the |opaque_data| could be ``NULL``.
|
||||||
*
|
*
|
||||||
|
* To shutdown gracefully, first send GOAWAY with ``last_stream_id =
|
||||||
|
* (1u << 31) - 1``. After 1 RTT, call either
|
||||||
|
* `nghttp2_submit_goaway()`, `nghttp2_session_terminate_session()` or
|
||||||
|
* `nghttp2_session_terminate_session2()`. The latter 2 will close
|
||||||
|
* HTTP/2 session immediately after transmission of the frame.
|
||||||
|
*
|
||||||
* 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:
|
||||||
*
|
*
|
||||||
* :enum:`NGHTTP2_ERR_NOMEM`
|
* :enum:`NGHTTP2_ERR_NOMEM`
|
||||||
* Out of memory.
|
* Out of memory.
|
||||||
* NGHTTP2_ERR_INVALID_ARGUMENT
|
* :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
|
||||||
* The |opaque_data_len| is too large.
|
* The |opaque_data_len| is too large.
|
||||||
*/
|
*/
|
||||||
int nghttp2_submit_goaway(nghttp2_session *session, uint8_t flags,
|
int nghttp2_submit_goaway(nghttp2_session *session, uint8_t flags,
|
||||||
|
int32_t last_stream_id,
|
||||||
nghttp2_error_code error_code,
|
nghttp2_error_code error_code,
|
||||||
const uint8_t *opaque_data, size_t opaque_data_len);
|
const uint8_t *opaque_data, size_t opaque_data_len);
|
||||||
|
|
||||||
|
|
|
@ -134,14 +134,23 @@ static int session_detect_idle_stream(nghttp2_session *session,
|
||||||
|
|
||||||
int nghttp2_session_terminate_session(nghttp2_session *session,
|
int nghttp2_session_terminate_session(nghttp2_session *session,
|
||||||
nghttp2_error_code error_code)
|
nghttp2_error_code error_code)
|
||||||
|
{
|
||||||
|
return nghttp2_session_terminate_session2(session,
|
||||||
|
session->last_proc_stream_id,
|
||||||
|
error_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
if(session->goaway_flags & NGHTTP2_GOAWAY_FAIL_ON_SEND) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
session->goaway_flags |= NGHTTP2_GOAWAY_FAIL_ON_SEND;
|
session->goaway_flags |= NGHTTP2_GOAWAY_FAIL_ON_SEND;
|
||||||
|
|
||||||
return nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, error_code,
|
return nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, last_stream_id,
|
||||||
NULL, 0);
|
error_code, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp2_session_is_my_stream_id(nghttp2_session *session,
|
int nghttp2_session_is_my_stream_id(nghttp2_session *session,
|
||||||
|
|
|
@ -246,10 +246,11 @@ int nghttp2_submit_rst_stream(nghttp2_session *session, uint8_t flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp2_submit_goaway(nghttp2_session *session, uint8_t flags,
|
int nghttp2_submit_goaway(nghttp2_session *session, uint8_t flags,
|
||||||
|
int32_t last_stream_id,
|
||||||
nghttp2_error_code error_code,
|
nghttp2_error_code error_code,
|
||||||
const uint8_t *opaque_data, size_t opaque_data_len)
|
const uint8_t *opaque_data, size_t opaque_data_len)
|
||||||
{
|
{
|
||||||
return nghttp2_session_add_goaway(session, session->last_proc_stream_id,
|
return nghttp2_session_add_goaway(session, last_stream_id,
|
||||||
error_code, opaque_data, opaque_data_len);
|
error_code, opaque_data, opaque_data_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4429,7 +4429,8 @@ void test_nghttp2_session_on_ctrl_not_send(void)
|
||||||
user_data.frame_not_send_cb_called = 0;
|
user_data.frame_not_send_cb_called = 0;
|
||||||
/* Send GOAWAY */
|
/* Send GOAWAY */
|
||||||
CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE,
|
CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE,
|
||||||
NGHTTP2_NO_ERROR, NULL, 0));
|
(1u << 31) - 1, NGHTTP2_NO_ERROR,
|
||||||
|
NULL, 0));
|
||||||
|
|
||||||
session->next_stream_id = 9;
|
session->next_stream_id = 9;
|
||||||
|
|
||||||
|
@ -4456,7 +4457,7 @@ void test_nghttp2_session_get_outbound_queue_size(void)
|
||||||
CU_ASSERT(1 == nghttp2_session_get_outbound_queue_size(session));
|
CU_ASSERT(1 == nghttp2_session_get_outbound_queue_size(session));
|
||||||
|
|
||||||
CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE,
|
CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE,
|
||||||
NGHTTP2_NO_ERROR, NULL, 0));
|
3, NGHTTP2_NO_ERROR, NULL, 0));
|
||||||
CU_ASSERT(2 == nghttp2_session_get_outbound_queue_size(session));
|
CU_ASSERT(2 == nghttp2_session_get_outbound_queue_size(session));
|
||||||
|
|
||||||
nghttp2_session_del(session);
|
nghttp2_session_del(session);
|
||||||
|
|
Loading…
Reference in New Issue