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