This commit is contained in:
Sergei Gunchenko 2022-11-01 05:21:21 +09:00 committed by GitHub
commit bba8ddb613
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 57 additions and 10 deletions

View File

@ -2756,6 +2756,19 @@ NGHTTP2_EXTERN void
nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(
nghttp2_option *option, int val);
/**
* @function
*
* This option prevents the library from sending empty SETTINGS frame with ACK
* flag set automatically when SETTINGS frame is received.
* If this option is set to nonzero, the library won't send empty
* SETTINGS frame with ACK flag set in the response for incoming SETTINGS
* frame. The application can send SETTINGS frame with ACK flag set using
* `nghttp2_submit_settings()` with :enum:`nghttp2_flag.NGHTTP2_FLAG_ACK`
* as flags parameter.
*/
NGHTTP2_EXTERN void nghttp2_option_set_no_auto_settings_ack(nghttp2_option *option, int val);
/**
* @function
*
@ -4345,8 +4358,21 @@ NGHTTP2_EXTERN int nghttp2_submit_rst_stream(nghttp2_session *session,
* pointer to the array of :type:`nghttp2_settings_entry`. The |niv|
* indicates the number of :type:`nghttp2_settings_entry`.
*
* The |flags| is currently ignored and should be
* :enum:`nghttp2_flag.NGHTTP2_FLAG_NONE`.
* The |flags| must be one of the following values:
*
* * :enum:`nghttp2_flag.NGHTTP2_FLAG_NONE`
* * :enum:`nghttp2_flag.NGHTTP2_FLAG_ACK`
*
* Unless `nghttp2_option_set_no_auto_settings_ack()` is used, the |flags|
* should be :enum:`nghttp2_flag.NGHTTP2_FLAG_NONE` and
* SETTINGS with :enum:`nghttp2_flag.NGHTTP2_FLAG_ACK` is
* automatically submitted by the library and application could not
* send it at its will.
*
* Otherwise the application must confirm the received settings by
* calling `nghttp2_submit_settings` with the flags set to
* :enum:`nghttp2_flag.NGHTTP2_FLAG_ACK` and empty settings
* (e.g. the |niv| must be 0).
*
* This function does not take ownership of the |iv|. This function
* copies all the elements in the |iv|.
@ -4355,16 +4381,19 @@ NGHTTP2_EXTERN int nghttp2_submit_rst_stream(nghttp2_session *session,
* size becomes strictly larger than NGHTTP2_MAX_WINDOW_SIZE,
* RST_STREAM is issued against such a stream.
*
* SETTINGS with :enum:`nghttp2_flag.NGHTTP2_FLAG_ACK` is
* automatically submitted by the library and application could not
* send it at its will.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_ARGUMENT`
* The |iv| contains invalid value (e.g., initial window size
* strictly greater than (1 << 31) - 1.
* strictly greater than (1 << 31) - 1;
* or the |flags| is set to :enum:`nghttp2_flag.NGHTTP2_FLAG_ACK`
* but the manual SETTINGS confirmation was not configured with
* `nghttp2_option_set_no_auto_settings_ack()`;
* or the |flags| is set to :enum:`nghttp2_flag.NGHTTP2_FLAG_ACK`
* and the |niv| is non-zero;
* or the |flags| is neither :enum:`nghttp2_flag.NGHTTP2_FLAG_NONE`
* nor :enum:`nghttp2_flag.NGHTTP2_FLAG_ACK`.
* :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM`
* Out of memory.
*/

View File

@ -143,3 +143,8 @@ void nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(
NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION;
option->no_rfc9113_leading_and_trailing_ws_validation = val;
}
void nghttp2_option_set_no_auto_settings_ack(nghttp2_option *option, int val) {
option->opt_set_mask |= NGHTTP2_OPT_NO_AUTO_SETTINGS_ACK;
option->no_auto_settings_ack = val;
}

View File

@ -70,6 +70,7 @@ typedef enum {
NGHTTP2_OPT_MAX_SETTINGS = 1 << 12,
NGHTTP2_OPT_SERVER_FALLBACK_RFC7540_PRIORITIES = 1 << 13,
NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 1 << 14,
NGHTTP2_OPT_NO_AUTO_SETTINGS_ACK = 1 << 15,
} nghttp2_option_flag;
/**
@ -141,6 +142,10 @@ struct nghttp2_option {
* NGHTTP2_OPT_USER_RECV_EXT_TYPES
*/
uint8_t user_recv_ext_types[32];
/**
* NGHTTP2_OPT_NO_AUTO_SETTINGS_ACK
*/
int no_auto_settings_ack;
};
#endif /* NGHTTP2_OPTION_H */

View File

@ -573,6 +573,11 @@ static int session_new(nghttp2_session **session_ptr,
(*session_ptr)->opt_flags |=
NGHTTP2_OPTMASK_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION;
}
if ((option->opt_set_mask & NGHTTP2_OPT_NO_AUTO_SETTINGS_ACK) &&
option->no_auto_settings_ack) {
(*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_AUTO_SETTINGS_ACK;
}
}
rv = nghttp2_hd_deflate_init2(&(*session_ptr)->hd_deflater,
@ -4961,7 +4966,7 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
}
}
if (!noack && !session_is_closing(session)) {
if (!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_SETTINGS_ACK) && !noack && !session_is_closing(session)) {
rv = nghttp2_session_add_settings(session, NGHTTP2_FLAG_ACK, NULL, 0);
if (rv != 0) {

View File

@ -55,6 +55,7 @@ typedef enum {
NGHTTP2_OPTMASK_NO_CLOSED_STREAMS = 1 << 4,
NGHTTP2_OPTMASK_SERVER_FALLBACK_RFC7540_PRIORITIES = 1 << 5,
NGHTTP2_OPTMASK_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 1 << 6,
NGHTTP2_OPTMASK_NO_AUTO_SETTINGS_ACK = 1 << 7,
} nghttp2_optmask;
/*

View File

@ -308,8 +308,10 @@ int nghttp2_submit_shutdown_notice(nghttp2_session *session) {
int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags,
const nghttp2_settings_entry *iv, size_t niv) {
(void)flags;
return nghttp2_session_add_settings(session, NGHTTP2_FLAG_NONE, iv, niv);
if (flags == NGHTTP2_FLAG_ACK && !(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_SETTINGS_ACK)) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
return nghttp2_session_add_settings(session, flags, iv, niv);
}
int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,