Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

transport/grpchttp2: revert #7477 usage of mem package #7485

Merged
merged 1 commit into from
Aug 7, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 86 additions & 34 deletions internal/transport/grpchttp2/framer.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@
// Package grpchttp2 defines HTTP/2 types and a framer API and implementation.
package grpchttp2

import (
"golang.org/x/net/http2/hpack"
"google.golang.org/grpc/mem"
)
import "golang.org/x/net/http2/hpack"

// FrameType represents the type of an HTTP/2 Frame.
// See [Frame Type].
Expand Down Expand Up @@ -109,41 +106,60 @@
// Each concrete Frame type defined below implements the Frame interface.
type Frame interface {
Header() *FrameHeader
// Free frees the underlying buffer if present so it can be reused by the
// framer.
//
// TODO: Remove method from the interface once the mem package gets merged.
// Free will be called on each mem.Buffer individually.
Free()
}

// DataFrame is the representation of a [DATA frame]. DATA frames convey
// arbitrary, variable-length sequences of octets associated with a stream. It
// is the user's responsibility to call Data.Free() when it is no longer
// needed.
// arbitrary, variable-length sequences of octets associated with a stream.
//
// [DATA frame]: https://httpwg.org/specs/rfc7540.html#DATA
type DataFrame struct {
hdr *FrameHeader
Data *mem.Buffer
free func()
Data []byte
}

// Header returns the 9 byte HTTP/2 header for this frame.
func (f *DataFrame) Header() *FrameHeader {
return f.hdr
}

// Free frees the buffer containing the data in this frame.
func (f *DataFrame) Free() {
if f.free != nil {
f.free()

Check warning on line 135 in internal/transport/grpchttp2/framer.go

View check run for this annotation

Codecov / codecov/patch

internal/transport/grpchttp2/framer.go#L133-L135

Added lines #L133 - L135 were not covered by tests
}
}

// HeadersFrame is the representation of a [HEADERS Frame]. The HEADERS frame
// is used to open a stream, and additionally carries a header block fragment.
// It is the user's responsibility to call HdrBlock.Free() when it is no longer
// needed.
//
// [HEADERS Frame]: https://httpwg.org/specs/rfc7540.html#HEADERS
type HeadersFrame struct {
hdr *FrameHeader
HdrBlock *mem.Buffer
free func()
HdrBlock []byte
}

// Header returns the 9 byte HTTP/2 header for this frame.
func (f *HeadersFrame) Header() *FrameHeader {
return f.hdr
}

// RSTStreamFrame is the representation of a [RST_STREAM Frame]. The RST_STREAM
// Free frees the buffer containing the header block in this frame.
func (f *HeadersFrame) Free() {
if f.free != nil {
f.free()

Check warning on line 157 in internal/transport/grpchttp2/framer.go

View check run for this annotation

Codecov / codecov/patch

internal/transport/grpchttp2/framer.go#L155-L157

Added lines #L155 - L157 were not covered by tests
}
}

// RSTStreamFrame is the representation of a [RST_STREAM Frame]. There is no
// underlying byte array in this frame, so Free() is a no-op. The RST_STREAM
// frame allows for immediate termination of a stream
//
// [RST_STREAM Frame]: https://httpwg.org/specs/rfc7540.html#RST_STREAM
Expand All @@ -157,9 +173,14 @@
return f.hdr
}

// SettingsFrame is the representation of a [SETTINGS Frame]. The SETTINGS frame
// conveys configuration parameters that affect how endpoints communicate, such
// as preferences and constraints on peer behavior.
// Free is a no-op for RSTStreamFrame.
func (f *RSTStreamFrame) Free() {}

Check warning on line 177 in internal/transport/grpchttp2/framer.go

View check run for this annotation

Codecov / codecov/patch

internal/transport/grpchttp2/framer.go#L177

Added line #L177 was not covered by tests

// SettingsFrame is the representation of a [SETTINGS Frame]. There is no
// underlying byte array in this frame, so Free() is a no-op.
//
// The SETTINGS frame conveys configuration parameters that affect how
// endpoints communicate, such as preferences and constraints on peer behavior.
//
// [SETTINGS Frame]: https://httpwg.org/specs/rfc7540.html#SETTINGS
type SettingsFrame struct {
Expand All @@ -172,44 +193,57 @@
return f.hdr
}

// Free is a no-op for SettingsFrame.
func (f *SettingsFrame) Free() {}

Check warning on line 197 in internal/transport/grpchttp2/framer.go

View check run for this annotation

Codecov / codecov/patch

internal/transport/grpchttp2/framer.go#L197

Added line #L197 was not covered by tests

// PingFrame is the representation of a [PING Frame]. The PING frame is a
// mechanism for measuring a minimal round-trip time from the sender, as well
// as determining whether an idle connection is still functional.
//
// It is the user's responsibility to call Data.Free() when it is no longer
// needed.
//
// [PING Frame]: https://httpwg.org/specs/rfc7540.html#PING
type PingFrame struct {
hdr *FrameHeader
Data *mem.Buffer
free func()
Data []byte
}

// Header returns the 9 byte HTTP/2 header for this frame.
func (f *PingFrame) Header() *FrameHeader {
return f.hdr
}

// Free frees the buffer containing the data in this frame.
func (f *PingFrame) Free() {
if f.free != nil {
f.free()

Check warning on line 218 in internal/transport/grpchttp2/framer.go

View check run for this annotation

Codecov / codecov/patch

internal/transport/grpchttp2/framer.go#L216-L218

Added lines #L216 - L218 were not covered by tests
}
}

// GoAwayFrame is the representation of a [GOAWAY Frame]. The GOAWAY frame is
// used to initiate shutdown of a connection or to signal serious error
// conditions.
//
// It is the user's responsibility to call DebugData.Free() when it is no longer
// needed.
//
// [GOAWAY Frame]: https://httpwg.org/specs/rfc7540.html#GOAWAY
type GoAwayFrame struct {
hdr *FrameHeader
free func()
LastStreamID uint32
Code ErrCode
DebugData *mem.Buffer
DebugData []byte
}

// Header returns the 9 byte HTTP/2 header for this frame.
func (f *GoAwayFrame) Header() *FrameHeader {
return f.hdr
}

// Free frees the buffer containing the debug data in this frame.
func (f *GoAwayFrame) Free() {
if f.free != nil {
f.free()

Check warning on line 243 in internal/transport/grpchttp2/framer.go

View check run for this annotation

Codecov / codecov/patch

internal/transport/grpchttp2/framer.go#L241-L243

Added lines #L241 - L243 were not covered by tests
}
}

// WindowUpdateFrame is the representation of a [WINDOW_UPDATE Frame]. The
// WINDOW_UPDATE frame is used to implement flow control.
//
Expand All @@ -227,24 +261,31 @@
// ContinuationFrame is the representation of a [CONTINUATION Frame]. The
// CONTINUATION frame is used to continue a sequence of header block fragments.
//
// It is the user's responsibility to call HdrBlock.Free() when it is no longer
// needed.
//
// [CONTINUATION Frame]: https://httpwg.org/specs/rfc7540.html#CONTINUATION
type ContinuationFrame struct {
hdr *FrameHeader
HdrBlock *mem.Buffer
free func()
HdrBlock []byte
}

// Header returns the 9 byte HTTP/2 header for this frame.
func (f *ContinuationFrame) Header() *FrameHeader {
return f.hdr
}

// Free frees the buffer containing the header block in this frame.
func (f *ContinuationFrame) Free() {
if f.free != nil {
f.free()

Check warning on line 279 in internal/transport/grpchttp2/framer.go

View check run for this annotation

Codecov / codecov/patch

internal/transport/grpchttp2/framer.go#L277-L279

Added lines #L277 - L279 were not covered by tests
}
}

// MetaHeadersFrame is the representation of one HEADERS frame and zero or more
// contiguous CONTINUATION frames and the decoding of their HPACK-encoded
// contents. This frame type is not transmitted over the network and is only
// generated by the ReadFrame() function.
//
// Since there is no underlying buffer in this Frame, Free() is a no-op.
type MetaHeadersFrame struct {
hdr *FrameHeader
Fields []hpack.HeaderField
Expand All @@ -258,17 +299,24 @@
return f.hdr
}

// Free is a no-op for MetaHeadersFrame.
func (f *MetaHeadersFrame) Free() {}

Check warning on line 303 in internal/transport/grpchttp2/framer.go

View check run for this annotation

Codecov / codecov/patch

internal/transport/grpchttp2/framer.go#L303

Added line #L303 was not covered by tests

// Framer encapsulates the functionality to read and write HTTP/2 frames.
type Framer interface {
// ReadFrame returns grpchttp2.Frame. It is the caller's responsibility to
// free the underlying buffer when done using the Frame.
// call Frame.Free() once it is done using it. Note that once the mem
// package gets merged, this API will change in favor of Buffer.Free().
ReadFrame() (Frame, error)
// WriteData writes an HTTP/2 DATA frame to the stream. The data is expected
// to be freed by the caller.
WriteData(streamID uint32, endStream bool, data mem.BufferSlice) error
// WriteHeaders writes an HTTP/2 HEADERS frame to the stream.
WriteHeaders(streamID uint32, endStream, endHeaders bool, headerBlock []byte) error
// WriteRSTStream writes an HTTP/2 RST_STREAM frame to the stream.
// WriteData writes an HTTP/2 DATA frame to the stream.
// TODO: Once the mem package gets merged, data will change type to
// mem.BufferSlice.
WriteData(streamID uint32, endStream bool, data ...[]byte) error
// WriteData writes an HTTP/2 HEADERS frame to the stream.
// TODO: Once the mem package gets merged, headerBlock will change type to
// mem.Buffer.
WriteHeaders(streamID uint32, endStream, endHeaders bool, headerBlocks []byte) error
// WriteData writes an HTTP/2 RST_STREAM frame to the stream.
WriteRSTStream(streamID uint32, code ErrCode) error
// WriteSettings writes an HTTP/2 SETTINGS frame to the connection.
WriteSettings(settings ...Setting) error
Expand All @@ -277,9 +325,13 @@
// WritePing writes an HTTP/2 PING frame to the connection.
WritePing(ack bool, data [8]byte) error
// WriteGoAway writes an HTTP/2 GOAWAY frame to the connection.
// TODO: Once the mem package gets merged, debugData will change type to
// mem.Buffer.
WriteGoAway(maxStreamID uint32, code ErrCode, debugData []byte) error
// WriteWindowUpdate writes an HTTP/2 WINDOW_UPDATE frame to the stream.
WriteWindowUpdate(streamID, inc uint32) error
// WriteContinuation writes an HTTP/2 CONTINUATION frame to the stream.
// TODO: Once the mem package gets merged, data will change type to
// mem.Buffer.
WriteContinuation(streamID uint32, endHeaders bool, headerBlock []byte) error
}
Loading