1 // Copyright 2022 gRPC authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef GRPC_SRC_CORE_EXT_TRANSPORT_CHAOTIC_GOOD_FRAME_H 16 #define GRPC_SRC_CORE_EXT_TRANSPORT_CHAOTIC_GOOD_FRAME_H 17 18 #include <grpc/support/port_platform.h> 19 20 #include <cstdint> 21 #include <memory> 22 #include <string> 23 24 #include "absl/status/status.h" 25 #include "absl/types/variant.h" 26 27 #include "src/core/ext/transport/chaotic_good/frame_header.h" 28 #include "src/core/ext/transport/chttp2/transport/hpack_encoder.h" 29 #include "src/core/ext/transport/chttp2/transport/hpack_parser.h" 30 #include "src/core/lib/resource_quota/arena.h" 31 #include "src/core/lib/slice/slice_buffer.h" 32 #include "src/core/lib/transport/metadata_batch.h" 33 #include "src/core/lib/transport/transport.h" 34 35 namespace grpc_core { 36 namespace chaotic_good { 37 38 class FrameInterface { 39 public: 40 virtual absl::Status Deserialize(HPackParser* parser, 41 const FrameHeader& header, 42 SliceBuffer& slice_buffer) = 0; 43 virtual SliceBuffer Serialize(HPackCompressor* encoder) const = 0; 44 45 protected: EqVal(const Message & a,const Message & b)46 static bool EqVal(const Message& a, const Message& b) { 47 return a.payload()->JoinIntoString() == b.payload()->JoinIntoString() && 48 a.flags() == b.flags(); 49 } EqVal(const grpc_metadata_batch & a,const grpc_metadata_batch & b)50 static bool EqVal(const grpc_metadata_batch& a, 51 const grpc_metadata_batch& b) { 52 return a.DebugString() == b.DebugString(); 53 } 54 template <typename T> EqHdl(const Arena::PoolPtr<T> & a,const Arena::PoolPtr<T> & b)55 static bool EqHdl(const Arena::PoolPtr<T>& a, const Arena::PoolPtr<T>& b) { 56 if (a == nullptr && b == nullptr) return true; 57 if (a == nullptr || b == nullptr) return false; 58 return EqVal(*a, *b); 59 } 60 ~FrameInterface() = default; 61 }; 62 63 struct SettingsFrame final : public FrameInterface { 64 absl::Status Deserialize(HPackParser* parser, const FrameHeader& header, 65 SliceBuffer& slice_buffer) override; 66 SliceBuffer Serialize(HPackCompressor* encoder) const override; 67 68 bool operator==(const SettingsFrame&) const { return true; } 69 }; 70 71 struct ClientFragmentFrame final : public FrameInterface { 72 absl::Status Deserialize(HPackParser* parser, const FrameHeader& header, 73 SliceBuffer& slice_buffer) override; 74 SliceBuffer Serialize(HPackCompressor* encoder) const override; 75 76 uint32_t stream_id; 77 ClientMetadataHandle headers; 78 bool end_of_stream = false; 79 80 bool operator==(const ClientFragmentFrame& other) const { 81 return stream_id == other.stream_id && EqHdl(headers, other.headers) && 82 end_of_stream == other.end_of_stream; 83 } 84 }; 85 86 struct ServerFragmentFrame final : public FrameInterface { 87 absl::Status Deserialize(HPackParser* parser, const FrameHeader& header, 88 SliceBuffer& slice_buffer) override; 89 SliceBuffer Serialize(HPackCompressor* encoder) const override; 90 91 uint32_t stream_id; 92 ServerMetadataHandle headers; 93 ServerMetadataHandle trailers; 94 95 bool operator==(const ServerFragmentFrame& other) const { 96 return stream_id == other.stream_id && EqHdl(headers, other.headers) && 97 EqHdl(trailers, other.trailers); 98 } 99 }; 100 101 struct CancelFrame final : public FrameInterface { 102 absl::Status Deserialize(HPackParser* parser, const FrameHeader& header, 103 SliceBuffer& slice_buffer) override; 104 SliceBuffer Serialize(HPackCompressor* encoder) const override; 105 106 uint32_t stream_id; 107 108 bool operator==(const CancelFrame& other) const { 109 return stream_id == other.stream_id; 110 } 111 }; 112 113 using ClientFrame = absl::variant<ClientFragmentFrame, CancelFrame>; 114 using ServerFrame = absl::variant<ServerFragmentFrame>; 115 116 } // namespace chaotic_good 117 } // namespace grpc_core 118 119 #endif // GRPC_SRC_CORE_EXT_TRANSPORT_CHAOTIC_GOOD_FRAME_H 120