mirror of https://github.com/grpc/grpc.git
[chaotic-good] Revamp wire format (#37765)
Update the chaotic-good wire format with some learnings from the past year, and set up things for the next round of changes we'd like to make:
* Instead of a composite FRAGMENT frame, split out CLIENT_INITIAL_METADATA, CLIENT_END_OF_STREAM, MESSAGE, SERVER_INITIAL_METADATA, SERVER_TRAILING_METADATA as separate frame types - this eliminates a ton of complexity in the transport, and corresponds to how we used the wire format in practice anyway.
* Switch the frame payload for metadata, settings to be protobuf instead of HPACK - this eliminates the ordering requirements on interpreting these frames between streams, which I expect to open up some flexibility with head of line avoidance in the future. It's a heck of a lot easier to read and reason about the code. It's also easier to predict the size of the frame at encode time, which lets us treat metadata and payloads more uniformly in the protocol.
* Add a connection id field to our header, in preparation for allowing multiple data connections
* Allow payloads to be shipped on the control channel ('connection id 0') and use this for sending small messages
Closes #37765
COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/37765 from ctiller:tiefling 7b57f72367
PiperOrigin-RevId: 695766541
pull/37866/head
parent
8342a109ae
commit
630d790fe1
44 changed files with 2010 additions and 1744 deletions
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,51 @@ |
||||
// Copyright 2024 The gRPC authors. |
||||
// |
||||
// Licensed under the Apache License, Version 2.0 (the "License"); |
||||
// you may not use this file except in compliance with the License. |
||||
// You may obtain a copy of the License at |
||||
// |
||||
// http://www.apache.org/licenses/LICENSE-2.0 |
||||
// |
||||
// Unless required by applicable law or agreed to in writing, software |
||||
// distributed under the License is distributed on an "AS IS" BASIS, |
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
// See the License for the specific language governing permissions and |
||||
// limitations under the License. |
||||
|
||||
syntax = "proto3"; |
||||
|
||||
package chaotic_good_frame; |
||||
|
||||
message Settings { |
||||
// Connection id |
||||
// - sent server->client on the control channel to specify the |
||||
// data channel connection id |
||||
// - sent client->server on the data channel to complete the |
||||
// connection |
||||
bytes connection_id = 1; |
||||
// Flag true if this is a data channel (and not a control channel) |
||||
bool data_channel = 2; |
||||
// Requested alignment for the data channel |
||||
// Client and server each send this with their preferences |
||||
uint32 alignment = 3; |
||||
} |
||||
|
||||
message UnknownMetadata { |
||||
string key = 1; |
||||
bytes value = 2; |
||||
} |
||||
|
||||
message ClientMetadata { |
||||
optional string path = 1; |
||||
optional string authority = 2; |
||||
optional uint64 timeout_ms = 3; |
||||
|
||||
repeated UnknownMetadata unknown_metadata = 100; |
||||
} |
||||
|
||||
message ServerMetadata { |
||||
optional uint32 status = 1; |
||||
optional bytes message = 2; |
||||
|
||||
repeated UnknownMetadata unknown_metadata = 100; |
||||
} |
@ -1,79 +0,0 @@ |
||||
// Copyright 2024 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/core/ext/transport/chaotic_good/settings_metadata.h" |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "absl/status/status.h" |
||||
#include "src/core/util/crash.h" |
||||
|
||||
namespace grpc_core { |
||||
namespace chaotic_good { |
||||
|
||||
Arena::PoolPtr<grpc_metadata_batch> SettingsMetadata::ToMetadataBatch() { |
||||
auto md = Arena::MakePooledForOverwrite<grpc_metadata_batch>(); |
||||
auto add = [&md](absl::string_view key, std::string value) { |
||||
md->Append(key, Slice::FromCopiedString(value), |
||||
[key, value](absl::string_view error, const Slice&) { |
||||
Crash(absl::StrCat("Failed to add metadata '", key, "' = '", |
||||
value, "': ", error)); |
||||
}); |
||||
}; |
||||
if (connection_type.has_value()) { |
||||
add("chaotic-good-connection-type", |
||||
connection_type.value() == ConnectionType::kControl ? "control" |
||||
: "data"); |
||||
} |
||||
if (connection_id.has_value()) { |
||||
add("chaotic-good-connection-id", connection_id.value()); |
||||
} |
||||
if (alignment.has_value()) { |
||||
add("chaotic-good-alignment", absl::StrCat(alignment.value())); |
||||
} |
||||
return md; |
||||
} |
||||
|
||||
absl::StatusOr<SettingsMetadata> SettingsMetadata::FromMetadataBatch( |
||||
const grpc_metadata_batch& batch) { |
||||
SettingsMetadata md; |
||||
std::string buffer; |
||||
auto v = batch.GetStringValue("chaotic-good-connection-type", &buffer); |
||||
if (v.has_value()) { |
||||
if (*v == "control") { |
||||
md.connection_type = ConnectionType::kControl; |
||||
} else if (*v == "data") { |
||||
md.connection_type = ConnectionType::kData; |
||||
} else { |
||||
return absl::UnavailableError( |
||||
absl::StrCat("Invalid connection type: ", *v)); |
||||
} |
||||
} |
||||
v = batch.GetStringValue("chaotic-good-connection-id", &buffer); |
||||
if (v.has_value()) { |
||||
md.connection_id = std::string(*v); |
||||
} |
||||
v = batch.GetStringValue("chaotic-good-alignment", &buffer); |
||||
if (v.has_value()) { |
||||
uint32_t alignment; |
||||
if (!absl::SimpleAtoi(*v, &alignment)) { |
||||
return absl::UnavailableError(absl::StrCat("Invalid alignment: ", *v)); |
||||
} |
||||
md.alignment = alignment; |
||||
} |
||||
return md; |
||||
} |
||||
|
||||
} // namespace chaotic_good
|
||||
} // namespace grpc_core
|
@ -1,45 +0,0 @@ |
||||
// Copyright 2024 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef GRPC_SRC_CORE_EXT_TRANSPORT_CHAOTIC_GOOD_SETTINGS_METADATA_H |
||||
#define GRPC_SRC_CORE_EXT_TRANSPORT_CHAOTIC_GOOD_SETTINGS_METADATA_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "absl/types/optional.h" |
||||
#include "src/core/lib/resource_quota/arena.h" |
||||
#include "src/core/lib/transport/metadata_batch.h" |
||||
|
||||
namespace grpc_core { |
||||
namespace chaotic_good { |
||||
|
||||
// Captures metadata sent in a chaotic good settings frame.
|
||||
struct SettingsMetadata { |
||||
enum class ConnectionType { |
||||
kControl, |
||||
kData, |
||||
}; |
||||
absl::optional<ConnectionType> connection_type; |
||||
absl::optional<std::string> connection_id; |
||||
absl::optional<uint32_t> alignment; |
||||
|
||||
Arena::PoolPtr<grpc_metadata_batch> ToMetadataBatch(); |
||||
static absl::StatusOr<SettingsMetadata> FromMetadataBatch( |
||||
const grpc_metadata_batch& batch); |
||||
}; |
||||
|
||||
} // namespace chaotic_good
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif // GRPC_SRC_CORE_EXT_TRANSPORT_CHAOTIC_GOOD_SETTINGS_METADATA_H
|
@ -0,0 +1,50 @@ |
||||
// Copyright 2024 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef GRPC_SRC_CORE_LIB_PROMISE_DETAIL_PROMISE_VARIANT_H |
||||
#define GRPC_SRC_CORE_LIB_PROMISE_DETAIL_PROMISE_VARIANT_H |
||||
|
||||
#include "absl/types/variant.h" |
||||
|
||||
namespace grpc_core { |
||||
|
||||
namespace promise_detail { |
||||
|
||||
// Visitor function for PromiseVariant - calls the poll operator on the inner
|
||||
// type
|
||||
class PollVisitor { |
||||
public: |
||||
template <typename T> |
||||
auto operator()(T& x) { |
||||
return x(); |
||||
} |
||||
}; |
||||
|
||||
// Helper type - given a variant V, provides the poll operator (which simply
|
||||
// visits the inner type on the variant with PollVisitor)
|
||||
template <typename V> |
||||
class PromiseVariant { |
||||
public: |
||||
explicit PromiseVariant(V variant) : variant_(std::move(variant)) {} |
||||
auto operator()() { return absl::visit(PollVisitor(), variant_); } |
||||
|
||||
private: |
||||
V variant_; |
||||
}; |
||||
|
||||
} // namespace promise_detail
|
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif // GRPC_SRC_CORE_LIB_PROMISE_DETAIL_PROMISE_VARIANT_H
|
Loading…
Reference in new issue