• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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_CHTTP2_TRANSPORT_FRAME_H
16 #define GRPC_SRC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_H
17 
18 #include <grpc/support/port_platform.h>
19 
20 #include <cstdint>
21 #include <string>
22 #include <vector>
23 
24 #include "absl/status/statusor.h"
25 #include "absl/strings/string_view.h"
26 #include "absl/types/span.h"
27 #include "absl/types/variant.h"
28 #include "src/core/lib/slice/slice.h"
29 #include "src/core/lib/slice/slice_buffer.h"
30 
31 namespace grpc_core {
32 
33 ///////////////////////////////////////////////////////////////////////////////
34 // Frame types
35 //
36 // Define structs for each kind of frame that chttp2 reasons about.
37 //
38 // Each struct gets the members defined by the HTTP/2 spec for that frame type
39 // *that the semantic layers of chttp2 neead to reason about*.
40 //
41 // That means, for instance, that we drop padding and prioritization data from
42 // these structs, as they are handled by the HTTP/2 framing layer and are
43 // meaningless to the semantic layers above.
44 //
45 // If a frame type is associated with a stream, it has a stream_id member.
46 // If that frame type is only used at the channel layer it does not.
47 //
48 // Instead of carrying bitfields of flags like the wire format, we instead
49 // declare a bool per flag to make producing/consuming code easier to write.
50 //
51 // Equality operators are defined for use in unit tests.
52 
53 // DATA frame
54 struct Http2DataFrame {
55   uint32_t stream_id = 0;
56   bool end_stream = false;
57   SliceBuffer payload;
58 
59   bool operator==(const Http2DataFrame& other) const {
60     return stream_id == other.stream_id && end_stream == other.end_stream &&
61            payload.JoinIntoString() == other.payload.JoinIntoString();
62   }
63 };
64 
65 // HEADER frame
66 struct Http2HeaderFrame {
67   uint32_t stream_id = 0;
68   bool end_headers = false;
69   bool end_stream = false;
70   SliceBuffer payload;
71 
72   bool operator==(const Http2HeaderFrame& other) const {
73     return stream_id == other.stream_id && end_headers == other.end_headers &&
74            end_stream == other.end_stream &&
75            payload.JoinIntoString() == other.payload.JoinIntoString();
76   }
77 };
78 
79 // CONTINUATION frame
80 struct Http2ContinuationFrame {
81   uint32_t stream_id = 0;
82   bool end_headers = false;
83   SliceBuffer payload;
84 
85   bool operator==(const Http2ContinuationFrame& other) const {
86     return stream_id == other.stream_id && end_headers == other.end_headers &&
87            payload.JoinIntoString() == other.payload.JoinIntoString();
88   }
89 };
90 
91 // RST_STREAM frame
92 struct Http2RstStreamFrame {
93   uint32_t stream_id = 0;
94   uint32_t error_code = 0;
95 
96   bool operator==(const Http2RstStreamFrame& other) const {
97     return stream_id == other.stream_id && error_code == other.error_code;
98   }
99 };
100 
101 // SETTINGS frame
102 struct Http2SettingsFrame {
103   struct Setting {
SettingHttp2SettingsFrame::Setting104     Setting(uint16_t id, uint32_t value) : id(id), value(value) {}
105 
106     uint16_t id;
107     uint32_t value;
108 
109     bool operator==(const Setting& other) const {
110       return id == other.id && value == other.value;
111     }
112   };
113   bool ack = false;
114   std::vector<Setting> settings;
115 
116   bool operator==(const Http2SettingsFrame& other) const {
117     return ack == other.ack && settings == other.settings;
118   }
119 };
120 
121 // PING frame
122 struct Http2PingFrame {
123   bool ack = false;
124   uint64_t opaque = 0;
125 
126   bool operator==(const Http2PingFrame& other) const {
127     return ack == other.ack && opaque == other.opaque;
128   }
129 };
130 
131 // GOAWAY frame
132 struct Http2GoawayFrame {
133   uint32_t last_stream_id = 0;
134   uint32_t error_code = 0;
135   Slice debug_data;
136 
137   bool operator==(const Http2GoawayFrame& other) const {
138     return last_stream_id == other.last_stream_id &&
139            error_code == other.error_code &&
140            debug_data.as_string_view() == other.debug_data.as_string_view();
141   }
142 };
143 
144 // WINDOW_UPDATE frame
145 struct Http2WindowUpdateFrame {
146   uint32_t stream_id;
147   uint32_t increment;
148 
149   bool operator==(const Http2WindowUpdateFrame& other) const {
150     return stream_id == other.stream_id && increment == other.increment;
151   }
152 };
153 
154 // Security-related frame
155 struct Http2SecurityFrame {
156   SliceBuffer payload;
157 
158   bool operator==(const Http2SecurityFrame& other) const {
159     return payload.JoinIntoString() == other.payload.JoinIntoString();
160   }
161 };
162 
163 // Type of frame was unknown (and should be ignored)
164 struct Http2UnknownFrame {
165   bool operator==(const Http2UnknownFrame&) const { return true; }
166 };
167 
168 ///////////////////////////////////////////////////////////////////////////////
169 // Frame variant
170 //
171 // A union of all the frame types above, so that we may pass around an
172 // arbitrary frame between layers as appropriate.
173 using Http2Frame =
174     absl::variant<Http2DataFrame, Http2HeaderFrame, Http2ContinuationFrame,
175                   Http2RstStreamFrame, Http2SettingsFrame, Http2PingFrame,
176                   Http2GoawayFrame, Http2WindowUpdateFrame, Http2SecurityFrame,
177                   Http2UnknownFrame>;
178 
179 ///////////////////////////////////////////////////////////////////////////////
180 // Frame header
181 //
182 // Define a struct for the frame header.
183 // Parsing this type is the first step in parsing a frame.
184 // No validation on the header is done during parsing - the fields should be
185 // instead interpreted by the frame type parser.
186 struct Http2FrameHeader {
187   uint32_t length;
188   uint8_t type;
189   uint8_t flags;
190   uint32_t stream_id;
191   // Serialize header to 9 byte long buffer output
192   // Crashes if length > 16777215 (as this is unencodable)
193   void Serialize(uint8_t* output) const;
194   // Parse header from 9 byte long buffer input
195   static Http2FrameHeader Parse(const uint8_t* input);
196   std::string ToString() const;
197 
198   bool operator==(const Http2FrameHeader& other) const {
199     return length == other.length && type == other.type &&
200            flags == other.flags && stream_id == other.stream_id;
201   }
202 };
203 
204 ///////////////////////////////////////////////////////////////////////////////
205 // Parsing & serialization
206 
207 // Given a frame header and a payload, parse the payload into a frame and
208 // return it.
209 // If this function returns an error, that should be considered a connection
210 // error.
211 // If a frame should simply be ignored, this function returns a
212 // Http2UnknownFrame.
213 // It is expected that hdr.length == payload.Length().
214 absl::StatusOr<Http2Frame> ParseFramePayload(const Http2FrameHeader& hdr,
215                                              SliceBuffer payload);
216 
217 // Serialize frame and append to out, leaves frames in an unknown state (may
218 // move things out of frames)
219 void Serialize(absl::Span<Http2Frame> frames, SliceBuffer& out);
220 
221 }  // namespace grpc_core
222 
223 #endif  // GRPC_SRC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_H
224