Skip to content

Commit f150e01

Browse files
tanvi-jagtapcopybara-github
authored andcommitted
[PH2][Settings] Adding helper function
PiperOrigin-RevId: 793920539
1 parent 303b395 commit f150e01

File tree

2 files changed

+128
-0
lines changed

2 files changed

+128
-0
lines changed

src/core/ext/transport/chttp2/transport/http2_settings_manager.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,61 @@ class Http2SettingsManager {
5959
// This function is not idempotent.
6060
std::optional<Http2SettingsFrame> MaybeSendUpdate();
6161

62+
// To be called from a promise based HTTP2 transport only
63+
http2::Http2ErrorCode ApplyIncomingSettings(
64+
std::vector<Http2SettingsFrame::Setting>& settings) {
65+
for (const auto& setting : settings) {
66+
http2::Http2ErrorCode error1 =
67+
count_updates_.IsUpdatePermitted(setting.id, setting.value, peer_);
68+
if (GPR_UNLIKELY(error1 != http2::Http2ErrorCode::kNoError)) {
69+
return error1;
70+
}
71+
http2::Http2ErrorCode error = peer_.Apply(setting.id, setting.value);
72+
if (GPR_UNLIKELY(error != http2::Http2ErrorCode::kNoError)) {
73+
return error;
74+
}
75+
}
76+
return http2::Http2ErrorCode::kNoError;
77+
}
78+
6279
// Call when we receive an ACK from our peer.
6380
// This function is not idempotent.
6481
GRPC_MUST_USE_RESULT bool AckLastSend();
6582

6683
private:
84+
struct CountUpdates {
85+
http2::Http2ErrorCode IsUpdatePermitted(const uint16_t setting_id,
86+
const uint32_t value,
87+
const Http2Settings& peer) {
88+
switch (setting_id) {
89+
case Http2Settings::kGrpcAllowTrueBinaryMetadataWireId:
90+
// These settings must not change more than once. This is a gRPC
91+
// defined settings.
92+
if (allow_true_binary_metadata_update &&
93+
peer.allow_true_binary_metadata() != static_cast<bool>(value)) {
94+
return http2::Http2ErrorCode::kConnectError;
95+
}
96+
allow_true_binary_metadata_update = true;
97+
break;
98+
case Http2Settings::kGrpcAllowSecurityFrameWireId:
99+
// These settings must not change more than once. This is a gRPC
100+
// defined settings.
101+
if (allow_security_frame_update &&
102+
peer.allow_security_frame() != static_cast<bool>(value)) {
103+
return http2::Http2ErrorCode::kConnectError;
104+
}
105+
allow_security_frame_update = true;
106+
break;
107+
default:
108+
break;
109+
}
110+
return http2::Http2ErrorCode::kNoError;
111+
}
112+
bool allow_true_binary_metadata_update = false;
113+
bool allow_security_frame_update = false;
114+
};
115+
CountUpdates count_updates_;
116+
67117
enum class UpdateState : uint8_t {
68118
kFirst,
69119
kSending,

test/core/transport/chttp2/http2_settings_test.cc

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,84 @@ TEST(Http2SettingsManagerTest, AckAfterAckFails) {
560560
EXPECT_FALSE(settings_manager.AckLastSend());
561561
}
562562

563+
TEST(Http2SettingsManagerTest, ApplyIncomingSettingsEmpty) {
564+
Http2SettingsManager settings_manager;
565+
std::vector<Http2SettingsFrame::Setting> settings;
566+
EXPECT_EQ(settings_manager.ApplyIncomingSettings(settings),
567+
Http2ErrorCode::kNoError);
568+
}
569+
570+
TEST(Http2SettingsManagerTest, ApplyIncomingSettingsValid) {
571+
Http2SettingsManager settings_manager;
572+
std::vector<Http2SettingsFrame::Setting> settings = {
573+
{Http2Settings::kHeaderTableSizeWireId, 1000},
574+
{Http2Settings::kMaxConcurrentStreamsWireId, 200}};
575+
EXPECT_EQ(settings_manager.ApplyIncomingSettings(settings),
576+
Http2ErrorCode::kNoError);
577+
EXPECT_EQ(settings_manager.peer().header_table_size(), 1000u);
578+
EXPECT_EQ(settings_manager.peer().max_concurrent_streams(), 200u);
579+
}
580+
581+
TEST(Http2SettingsManagerTest, ApplyIncomingSettingsInvalidValue) {
582+
Http2SettingsManager settings_manager;
583+
// MaxFrameSize must be between 16384 and 16777215
584+
std::vector<Http2SettingsFrame::Setting> settings = {
585+
{Http2Settings::kMaxFrameSizeWireId, 16383}};
586+
EXPECT_EQ(settings_manager.ApplyIncomingSettings(settings),
587+
Http2ErrorCode::kProtocolError);
588+
std::vector<Http2SettingsFrame::Setting> settings1 = {
589+
{Http2Settings::kMaxFrameSizeWireId, 16777216}};
590+
EXPECT_EQ(settings_manager.ApplyIncomingSettings(settings1),
591+
Http2ErrorCode::kProtocolError);
592+
}
593+
594+
TEST(Http2SettingsManagerTest,
595+
ApplyIncomingSettingsAllowTrueBinaryMetadataTwice) {
596+
Http2SettingsManager settings_manager;
597+
std::vector<Http2SettingsFrame::Setting> settings = {
598+
{Http2Settings::kGrpcAllowTrueBinaryMetadataWireId, 1}};
599+
EXPECT_EQ(settings_manager.ApplyIncomingSettings(settings),
600+
Http2ErrorCode::kNoError);
601+
EXPECT_EQ(settings_manager.ApplyIncomingSettings(settings),
602+
Http2ErrorCode::kNoError);
603+
}
604+
605+
TEST(Http2SettingsManagerTest,
606+
ApplyIncomingSettingsAllowTrueBinaryMetadataTwiceDifferentValue) {
607+
Http2SettingsManager settings_manager;
608+
std::vector<Http2SettingsFrame::Setting> settings1 = {
609+
{Http2Settings::kGrpcAllowTrueBinaryMetadataWireId, 1}};
610+
EXPECT_EQ(settings_manager.ApplyIncomingSettings(settings1),
611+
Http2ErrorCode::kNoError);
612+
std::vector<Http2SettingsFrame::Setting> settings2 = {
613+
{Http2Settings::kGrpcAllowTrueBinaryMetadataWireId, 0}};
614+
EXPECT_EQ(settings_manager.ApplyIncomingSettings(settings2),
615+
Http2ErrorCode::kConnectError);
616+
}
617+
618+
TEST(Http2SettingsManagerTest, ApplyIncomingSettingsAllowSecurityFrameTwice) {
619+
Http2SettingsManager settings_manager;
620+
std::vector<Http2SettingsFrame::Setting> settings = {
621+
{Http2Settings::kGrpcAllowSecurityFrameWireId, 1}};
622+
EXPECT_EQ(settings_manager.ApplyIncomingSettings(settings),
623+
Http2ErrorCode::kNoError);
624+
EXPECT_EQ(settings_manager.ApplyIncomingSettings(settings),
625+
Http2ErrorCode::kNoError);
626+
}
627+
628+
TEST(Http2SettingsManagerTest,
629+
ApplyIncomingSettingsAllowSecurityFrameTwiceDifferentValue) {
630+
Http2SettingsManager settings_manager;
631+
std::vector<Http2SettingsFrame::Setting> settings1 = {
632+
{Http2Settings::kGrpcAllowSecurityFrameWireId, 1}};
633+
EXPECT_EQ(settings_manager.ApplyIncomingSettings(settings1),
634+
Http2ErrorCode::kNoError);
635+
std::vector<Http2SettingsFrame::Setting> settings2 = {
636+
{Http2Settings::kGrpcAllowSecurityFrameWireId, 0}};
637+
EXPECT_EQ(settings_manager.ApplyIncomingSettings(settings2),
638+
Http2ErrorCode::kConnectError);
639+
}
640+
563641
} // namespace grpc_core
564642

565643
int main(int argc, char** argv) {

0 commit comments

Comments
 (0)