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  }