diff options
Diffstat (limited to 'src/core/ext/transport/chttp2/transport/frame_settings.cc')
-rw-r--r-- | src/core/ext/transport/chttp2/transport/frame_settings.cc | 112 |
1 files changed, 33 insertions, 79 deletions
diff --git a/src/core/ext/transport/chttp2/transport/frame_settings.cc b/src/core/ext/transport/chttp2/transport/frame_settings.cc index e4bf9d4fdb..c0e24c336e 100644 --- a/src/core/ext/transport/chttp2/transport/frame_settings.cc +++ b/src/core/ext/transport/chttp2/transport/frame_settings.cc @@ -33,6 +33,7 @@ #include "src/core/ext/transport/chttp2/transport/flow_control.h" #include "src/core/ext/transport/chttp2/transport/frame_goaway.h" +#include "src/core/ext/transport/chttp2/transport/http2_settings.h" #include "src/core/ext/transport/chttp2/transport/http_trace.h" #include "src/core/ext/transport/chttp2/transport/internal.h" #include "src/core/ext/transport/chttp2/transport/legacy_frame.h" @@ -55,38 +56,6 @@ static uint8_t* fill_header(uint8_t* out, uint32_t length, uint8_t flags) { return out; } -grpc_slice grpc_chttp2_settings_create(uint32_t* old_settings, - const uint32_t* new_settings, - uint32_t force_mask, size_t count) { - size_t i; - uint32_t n = 0; - grpc_slice output; - uint8_t* p; - - for (i = 0; i < count; i++) { - n += (new_settings[i] != old_settings[i] || (force_mask & (1u << i)) != 0); - } - - output = GRPC_SLICE_MALLOC(9 + 6 * n); - p = fill_header(GRPC_SLICE_START_PTR(output), 6 * n, 0); - - for (i = 0; i < count; i++) { - if (new_settings[i] != old_settings[i] || (force_mask & (1u << i)) != 0) { - *p++ = static_cast<uint8_t>(grpc_setting_id_to_wire_id[i] >> 8); - *p++ = static_cast<uint8_t>(grpc_setting_id_to_wire_id[i]); - *p++ = static_cast<uint8_t>(new_settings[i] >> 24); - *p++ = static_cast<uint8_t>(new_settings[i] >> 16); - *p++ = static_cast<uint8_t>(new_settings[i] >> 8); - *p++ = static_cast<uint8_t>(new_settings[i]); - old_settings[i] = new_settings[i]; - } - } - - GPR_ASSERT(p == GRPC_SLICE_END_PTR(output)); - - return output; -} - grpc_slice grpc_chttp2_settings_ack_create(void) { grpc_slice output = GRPC_SLICE_MALLOC(9); fill_header(GRPC_SLICE_START_PTR(output), 0, GRPC_CHTTP2_FLAG_ACK); @@ -95,10 +64,9 @@ grpc_slice grpc_chttp2_settings_ack_create(void) { grpc_error_handle grpc_chttp2_settings_parser_begin_frame( grpc_chttp2_settings_parser* parser, uint32_t length, uint8_t flags, - uint32_t* settings) { - parser->target_settings = settings; - memcpy(parser->incoming_settings, settings, - GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t)); + grpc_core::Http2Settings& settings) { + parser->target_settings = &settings; + parser->incoming_settings.Init(settings); parser->is_ack = 0; parser->state = GRPC_CHTTP2_SPS_ID0; if (flags == GRPC_CHTTP2_FLAG_ACK) { @@ -125,7 +93,6 @@ grpc_error_handle grpc_chttp2_settings_parser_parse(void* p, static_cast<grpc_chttp2_settings_parser*>(p); const uint8_t* cur = GRPC_SLICE_START_PTR(slice); const uint8_t* end = GRPC_SLICE_END_PTR(slice); - grpc_chttp2_setting_id id; if (parser->is_ack) { return absl::OkStatus(); @@ -137,8 +104,7 @@ grpc_error_handle grpc_chttp2_settings_parser_parse(void* p, if (cur == end) { parser->state = GRPC_CHTTP2_SPS_ID0; if (is_last) { - memcpy(parser->target_settings, parser->incoming_settings, - GRPC_CHTTP2_NUM_SETTINGS * sizeof(uint32_t)); + *parser->target_settings = *parser->incoming_settings; t->num_pending_induced_frames++; grpc_slice_buffer_add(&t->qbuf, grpc_chttp2_settings_ack_create()); grpc_chttp2_initiate_write(t, @@ -187,7 +153,7 @@ grpc_error_handle grpc_chttp2_settings_parser_parse(void* p, parser->value |= (static_cast<uint32_t>(*cur)) << 8; cur++; ABSL_FALLTHROUGH_INTENDED; - case GRPC_CHTTP2_SPS_VAL3: + case GRPC_CHTTP2_SPS_VAL3: { if (cur == end) { parser->state = GRPC_CHTTP2_SPS_VAL3; return absl::OkStatus(); @@ -197,47 +163,35 @@ grpc_error_handle grpc_chttp2_settings_parser_parse(void* p, parser->value |= *cur; cur++; - if (grpc_wire_id_to_setting_id(parser->id, &id)) { - const grpc_chttp2_setting_parameters* sp = - &grpc_chttp2_settings_parameters[id]; - if (parser->value < sp->min_value || parser->value > sp->max_value) { - switch (sp->invalid_value_behavior) { - case GRPC_CHTTP2_CLAMP_INVALID_VALUE: - parser->value = grpc_core::Clamp(parser->value, sp->min_value, - sp->max_value); - break; - case GRPC_CHTTP2_DISCONNECT_ON_INVALID_VALUE: - grpc_chttp2_goaway_append( - t->last_new_stream_id, sp->error_value, - grpc_slice_from_static_string("HTTP2 settings error"), - &t->qbuf); - return GRPC_ERROR_CREATE(absl::StrFormat( - "invalid value %u passed for %s", parser->value, sp->name)); - } - } - if (id == GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE && - parser->incoming_settings[id] != parser->value) { - t->initial_window_update += static_cast<int64_t>(parser->value) - - parser->incoming_settings[id]; - if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace) || - GRPC_TRACE_FLAG_ENABLED(grpc_flowctl_trace)) { - gpr_log(GPR_INFO, "%p[%s] adding %d for initial_window change", t, - t->is_client ? "cli" : "svr", - static_cast<int>(t->initial_window_update)); - } - } - parser->incoming_settings[id] = parser->value; - if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) { - gpr_log(GPR_INFO, "CHTTP2:%s:%s: got setting %s = %d", - t->is_client ? "CLI" : "SVR", - std::string(t->peer_string.as_string_view()).c_str(), - sp->name, parser->value); + if (parser->id == grpc_core::Http2Settings::kInitialWindowSizeWireId) { + t->initial_window_update += + static_cast<int64_t>(parser->value) - + parser->incoming_settings->initial_window_size(); + if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace) || + GRPC_TRACE_FLAG_ENABLED(grpc_flowctl_trace)) { + gpr_log(GPR_INFO, "%p[%s] adding %d for initial_window change", t, + t->is_client ? "cli" : "svr", + static_cast<int>(t->initial_window_update)); } - } else if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) { - gpr_log(GPR_DEBUG, "CHTTP2: Ignoring unknown setting %d (value %d)", - parser->id, parser->value); } - break; + auto error = + parser->incoming_settings->Apply(parser->id, parser->value); + if (error != GRPC_HTTP2_NO_ERROR) { + grpc_chttp2_goaway_append( + t->last_new_stream_id, error, + grpc_slice_from_static_string("HTTP2 settings error"), &t->qbuf); + return GRPC_ERROR_CREATE(absl::StrFormat( + "invalid value %u passed for %s", parser->value, + grpc_core::Http2Settings::WireIdToName(parser->id).c_str())); + } + if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) { + gpr_log(GPR_INFO, "CHTTP2:%s:%s: got setting %s = %d", + t->is_client ? "CLI" : "SVR", + std::string(t->peer_string.as_string_view()).c_str(), + grpc_core::Http2Settings::WireIdToName(parser->id).c_str(), + parser->value); + } + } break; } } } |