google.golang.org/grpc@v1.72.2/internal/transport/grpchttp2/framer.go (about) 1 /* 2 * 3 * Copyright 2024 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 // Package grpchttp2 defines HTTP/2 types and a framer API and implementation. 20 package grpchttp2 21 22 import "golang.org/x/net/http2/hpack" 23 24 const initHeaderTableSize = 4096 // Default HTTP/2 header table size. 25 26 // FrameType represents the type of an HTTP/2 Frame. 27 // See [Frame Type]. 28 // 29 // [Frame Type]: https://httpwg.org/specs/rfc7540.html#FrameType 30 type FrameType uint8 31 32 // Frame types defined in the HTTP/2 Spec. 33 const ( 34 FrameTypeData FrameType = 0x0 35 FrameTypeHeaders FrameType = 0x1 36 FrameTypeRSTStream FrameType = 0x3 37 FrameTypeSettings FrameType = 0x4 38 FrameTypePing FrameType = 0x6 39 FrameTypeGoAway FrameType = 0x7 40 FrameTypeWindowUpdate FrameType = 0x8 41 FrameTypeContinuation FrameType = 0x9 42 ) 43 44 // Flag represents one or more flags set on an HTTP/2 Frame. 45 type Flag uint8 46 47 // Flags defined in the HTTP/2 Spec. 48 const ( 49 FlagDataEndStream Flag = 0x1 50 FlagDataPadded Flag = 0x8 51 FlagHeadersEndStream Flag = 0x1 52 FlagHeadersEndHeaders Flag = 0x4 53 FlagHeadersPadded Flag = 0x8 54 FlagHeadersPriority Flag = 0x20 55 FlagSettingsAck Flag = 0x1 56 FlagPingAck Flag = 0x1 57 FlagContinuationEndHeaders Flag = 0x4 58 ) 59 60 // IsSet returns a boolean indicating whether the passed flag is set on this 61 // flag instance. 62 func (f Flag) IsSet(flag Flag) bool { 63 return f&flag != 0 64 } 65 66 // Setting represents the id and value pair of an HTTP/2 setting. 67 // See [Setting Format]. 68 // 69 // [Setting Format]: https://httpwg.org/specs/rfc7540.html#SettingFormat 70 type Setting struct { 71 ID SettingID 72 Value uint32 73 } 74 75 // SettingID represents the id of an HTTP/2 setting. 76 // See [Setting Values]. 77 // 78 // [Setting Values]: https://httpwg.org/specs/rfc7540.html#SettingValues 79 type SettingID uint16 80 81 // Setting IDs defined in the HTTP/2 Spec. 82 const ( 83 SettingsHeaderTableSize SettingID = 0x1 84 SettingsEnablePush SettingID = 0x2 85 SettingsMaxConcurrentStreams SettingID = 0x3 86 SettingsInitialWindowSize SettingID = 0x4 87 SettingsMaxFrameSize SettingID = 0x5 88 SettingsMaxHeaderListSize SettingID = 0x6 89 ) 90 91 // FrameHeader is the 9 byte header of any HTTP/2 Frame. 92 // See [Frame Header]. 93 // 94 // [Frame Header]: https://httpwg.org/specs/rfc7540.html#FrameHeader 95 type FrameHeader struct { 96 // Size is the size of the frame's payload without the 9 header bytes. 97 // As per the HTTP/2 spec, size can be up to 3 bytes, but only frames 98 // up to 16KB can be processed without agreement. 99 Size uint32 100 // Type is a byte that represents the Frame Type. 101 Type FrameType 102 // Flags is a byte representing the flags set on this Frame. 103 Flags Flag 104 // StreamID is the ID for the stream which this frame is for. If the 105 // frame is connection specific instead of stream specific, the 106 // streamID is 0. 107 StreamID uint32 108 } 109 110 // Frame represents an HTTP/2 Frame. This interface struct is only to be used 111 // on the read path of the Framer. The writing path expects the data to be 112 // passed individually, not using this type. 113 // 114 // Each concrete Frame type defined below implements the Frame interface. 115 type Frame interface { 116 // Header returns the HTTP/2 9 byte header from the current Frame. 117 Header() *FrameHeader 118 // Free frees the underlying buffer if present so it can be reused by the 119 // framer. 120 // 121 // TODO: Remove method from the interface once the mem package gets merged. 122 // Free will be called on each mem.Buffer individually. 123 Free() 124 } 125 126 // DataFrame is the representation of a [DATA frame]. DATA frames convey 127 // arbitrary, variable-length sequences of octets associated with a stream. 128 // 129 // [DATA frame]: https://httpwg.org/specs/rfc7540.html#DATA 130 type DataFrame struct { 131 hdr *FrameHeader 132 free func() 133 Data []byte 134 } 135 136 // Header returns the 9 byte HTTP/2 header for this frame. 137 func (f *DataFrame) Header() *FrameHeader { 138 return f.hdr 139 } 140 141 // Free frees the buffer containing the data in this frame. 142 func (f *DataFrame) Free() { 143 if f.free != nil { 144 f.free() 145 } 146 } 147 148 // HeadersFrame is the representation of a [HEADERS Frame]. The HEADERS frame 149 // is used to open a stream, and additionally carries a header block fragment. 150 // 151 // [HEADERS Frame]: https://httpwg.org/specs/rfc7540.html#HEADERS 152 type HeadersFrame struct { 153 hdr *FrameHeader 154 free func() 155 HdrBlock []byte 156 } 157 158 // Header returns the 9 byte HTTP/2 header for this frame. 159 func (f *HeadersFrame) Header() *FrameHeader { 160 return f.hdr 161 } 162 163 // Free frees the buffer containing the header block in this frame. 164 func (f *HeadersFrame) Free() { 165 if f.free != nil { 166 f.free() 167 } 168 } 169 170 // RSTStreamFrame is the representation of a [RST_STREAM Frame]. There is no 171 // underlying byte array in this frame, so Free() is a no-op. The RST_STREAM 172 // frame allows for immediate termination of a stream 173 // 174 // [RST_STREAM Frame]: https://httpwg.org/specs/rfc7540.html#RST_STREAM 175 type RSTStreamFrame struct { 176 hdr *FrameHeader 177 Code ErrCode 178 } 179 180 // Header returns the 9 byte HTTP/2 header for this frame. 181 func (f *RSTStreamFrame) Header() *FrameHeader { 182 return f.hdr 183 } 184 185 // Free is a no-op for RSTStreamFrame. 186 func (f *RSTStreamFrame) Free() {} 187 188 // SettingsFrame is the representation of a [SETTINGS Frame]. There is no 189 // underlying byte array in this frame, so Free() is a no-op. 190 // 191 // The SETTINGS frame conveys configuration parameters that affect how 192 // endpoints communicate, such as preferences and constraints on peer behavior. 193 // 194 // [SETTINGS Frame]: https://httpwg.org/specs/rfc7540.html#SETTINGS 195 type SettingsFrame struct { 196 hdr *FrameHeader 197 Settings []Setting 198 } 199 200 // Header returns the 9 byte HTTP/2 header for this frame. 201 func (f *SettingsFrame) Header() *FrameHeader { 202 return f.hdr 203 } 204 205 // Free is a no-op for SettingsFrame. 206 func (f *SettingsFrame) Free() {} 207 208 // PingFrame is the representation of a [PING Frame]. The PING frame is a 209 // mechanism for measuring a minimal round-trip time from the sender, as well 210 // as determining whether an idle connection is still functional. 211 // 212 // [PING Frame]: https://httpwg.org/specs/rfc7540.html#PING 213 type PingFrame struct { 214 hdr *FrameHeader 215 free func() 216 Data []byte 217 } 218 219 // Header returns the 9 byte HTTP/2 header for this frame. 220 func (f *PingFrame) Header() *FrameHeader { 221 return f.hdr 222 } 223 224 // Free frees the buffer containing the data in this frame. 225 func (f *PingFrame) Free() { 226 if f.free != nil { 227 f.free() 228 } 229 } 230 231 // GoAwayFrame is the representation of a [GOAWAY Frame]. The GOAWAY frame is 232 // used to initiate shutdown of a connection or to signal serious error 233 // conditions. 234 // 235 // [GOAWAY Frame]: https://httpwg.org/specs/rfc7540.html#GOAWAY 236 type GoAwayFrame struct { 237 hdr *FrameHeader 238 free func() 239 LastStreamID uint32 240 Code ErrCode 241 DebugData []byte 242 } 243 244 // Header returns the 9 byte HTTP/2 header for this frame. 245 func (f *GoAwayFrame) Header() *FrameHeader { 246 return f.hdr 247 } 248 249 // Free frees the buffer containing the debug data in this frame. 250 func (f *GoAwayFrame) Free() { 251 if f.free != nil { 252 f.free() 253 } 254 } 255 256 // WindowUpdateFrame is the representation of a [WINDOW_UPDATE Frame]. The 257 // WINDOW_UPDATE frame is used to implement flow control. 258 // 259 // [WINDOW_UPDATE Frame]: https://httpwg.org/specs/rfc7540.html#WINDOW_UPDATE 260 type WindowUpdateFrame struct { 261 hdr *FrameHeader 262 Inc uint32 263 } 264 265 // Header returns the 9 byte HTTP/2 header for this frame. 266 func (f *WindowUpdateFrame) Header() *FrameHeader { 267 return f.hdr 268 } 269 270 // Free is a no-op for WindowUpdateFrame. 271 func (f *WindowUpdateFrame) Free() {} 272 273 // ContinuationFrame is the representation of a [CONTINUATION Frame]. The 274 // CONTINUATION frame is used to continue a sequence of header block fragments. 275 // 276 // [CONTINUATION Frame]: https://httpwg.org/specs/rfc7540.html#CONTINUATION 277 type ContinuationFrame struct { 278 hdr *FrameHeader 279 free func() 280 HdrBlock []byte 281 } 282 283 // Header returns the 9 byte HTTP/2 header for this frame. 284 func (f *ContinuationFrame) Header() *FrameHeader { 285 return f.hdr 286 } 287 288 // Free frees the buffer containing the header block in this frame. 289 func (f *ContinuationFrame) Free() { 290 if f.free != nil { 291 f.free() 292 } 293 } 294 295 // MetaHeadersFrame is the representation of one HEADERS frame and zero or more 296 // contiguous CONTINUATION frames and the decoding of their HPACK-encoded 297 // contents. This frame type is not transmitted over the network and is only 298 // generated by the ReadFrame() function. 299 // 300 // Since there is no underlying buffer in this Frame, Free() is a no-op. 301 type MetaHeadersFrame struct { 302 hdr *FrameHeader 303 Fields []hpack.HeaderField 304 // Truncated indicates whether the MetaHeadersFrame has been truncated due 305 // to being longer than the MaxHeaderListSize. 306 Truncated bool 307 } 308 309 // Header returns the 9 byte HTTP/2 header for this frame. 310 func (f *MetaHeadersFrame) Header() *FrameHeader { 311 return f.hdr 312 } 313 314 // Free is a no-op for MetaHeadersFrame. 315 func (f *MetaHeadersFrame) Free() {} 316 317 // UnknownFrame is a struct that is returned when the framer encounters an 318 // unsupported frame. 319 type UnknownFrame struct { 320 hdr *FrameHeader 321 Payload []byte 322 free func() 323 } 324 325 // Header returns the 9 byte HTTP/2 header for this frame. 326 func (f *UnknownFrame) Header() *FrameHeader { 327 return f.hdr 328 } 329 330 // Free frees the underlying data in the frame. 331 func (f *UnknownFrame) Free() { 332 if f.free != nil { 333 f.free() 334 } 335 } 336 337 // Framer encapsulates the functionality to read and write HTTP/2 frames. 338 type Framer interface { 339 // ReadFrame returns grpchttp2.Frame. It is the caller's responsibility to 340 // call Frame.Free() once it is done using it. Note that once the mem 341 // package gets merged, this API will change in favor of Buffer.Free(). 342 ReadFrame() (Frame, error) 343 // WriteData writes an HTTP/2 DATA frame to the stream. 344 // TODO: Once the mem package gets merged, data will change type to 345 // mem.BufferSlice. 346 WriteData(streamID uint32, endStream bool, data ...[]byte) error 347 // WriteData writes an HTTP/2 HEADERS frame to the stream. 348 // TODO: Once the mem package gets merged, headerBlock will change type to 349 // mem.Buffer. 350 WriteHeaders(streamID uint32, endStream, endHeaders bool, headerBlocks []byte) error 351 // WriteData writes an HTTP/2 RST_STREAM frame to the stream. 352 WriteRSTStream(streamID uint32, code ErrCode) error 353 // WriteSettings writes an HTTP/2 SETTINGS frame to the connection. 354 WriteSettings(settings ...Setting) error 355 // WriteSettingsAck writes an HTTP/2 SETTINGS frame with the ACK flag set. 356 WriteSettingsAck() error 357 // WritePing writes an HTTP/2 PING frame to the connection. 358 WritePing(ack bool, data [8]byte) error 359 // WriteGoAway writes an HTTP/2 GOAWAY frame to the connection. 360 // TODO: Once the mem package gets merged, debugData will change type to 361 // mem.Buffer. 362 WriteGoAway(maxStreamID uint32, code ErrCode, debugData []byte) error 363 // WriteWindowUpdate writes an HTTP/2 WINDOW_UPDATE frame to the stream. 364 WriteWindowUpdate(streamID, inc uint32) error 365 // WriteContinuation writes an HTTP/2 CONTINUATION frame to the stream. 366 // TODO: Once the mem package gets merged, data will change type to 367 // mem.Buffer. 368 WriteContinuation(streamID uint32, endHeaders bool, headerBlock []byte) error 369 }