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