1919// Package grpchttp2 defines HTTP/2 types and a framer API and implementation.
2020package grpchttp2
2121
22- import (
23- "golang.org/x/net/http2/hpack"
24- "google.golang.org/grpc/mem"
25- )
22+ import "golang.org/x/net/http2/hpack"
2623
2724// FrameType represents the type of an HTTP/2 Frame.
2825// See [Frame Type].
@@ -109,41 +106,60 @@ type FrameHeader struct {
109106// Each concrete Frame type defined below implements the Frame interface.
110107type Frame interface {
111108 Header () * FrameHeader
109+ // Free frees the underlying buffer if present so it can be reused by the
110+ // framer.
111+ //
112+ // TODO: Remove method from the interface once the mem package gets merged.
113+ // Free will be called on each mem.Buffer individually.
114+ Free ()
112115}
113116
114117// DataFrame is the representation of a [DATA frame]. DATA frames convey
115- // arbitrary, variable-length sequences of octets associated with a stream. It
116- // is the user's responsibility to call Data.Free() when it is no longer
117- // needed.
118+ // arbitrary, variable-length sequences of octets associated with a stream.
118119//
119120// [DATA frame]: https://httpwg.org/specs/rfc7540.html#DATA
120121type DataFrame struct {
121122 hdr * FrameHeader
122- Data * mem.Buffer
123+ free func ()
124+ Data []byte
123125}
124126
125127// Header returns the 9 byte HTTP/2 header for this frame.
126128func (f * DataFrame ) Header () * FrameHeader {
127129 return f .hdr
128130}
129131
132+ // Free frees the buffer containing the data in this frame.
133+ func (f * DataFrame ) Free () {
134+ if f .free != nil {
135+ f .free ()
136+ }
137+ }
138+
130139// HeadersFrame is the representation of a [HEADERS Frame]. The HEADERS frame
131140// is used to open a stream, and additionally carries a header block fragment.
132- // It is the user's responsibility to call HdrBlock.Free() when it is no longer
133- // needed.
134141//
135142// [HEADERS Frame]: https://httpwg.org/specs/rfc7540.html#HEADERS
136143type HeadersFrame struct {
137144 hdr * FrameHeader
138- HdrBlock * mem.Buffer
145+ free func ()
146+ HdrBlock []byte
139147}
140148
141149// Header returns the 9 byte HTTP/2 header for this frame.
142150func (f * HeadersFrame ) Header () * FrameHeader {
143151 return f .hdr
144152}
145153
146- // RSTStreamFrame is the representation of a [RST_STREAM Frame]. The RST_STREAM
154+ // Free frees the buffer containing the header block in this frame.
155+ func (f * HeadersFrame ) Free () {
156+ if f .free != nil {
157+ f .free ()
158+ }
159+ }
160+
161+ // RSTStreamFrame is the representation of a [RST_STREAM Frame]. There is no
162+ // underlying byte array in this frame, so Free() is a no-op. The RST_STREAM
147163// frame allows for immediate termination of a stream
148164//
149165// [RST_STREAM Frame]: https://httpwg.org/specs/rfc7540.html#RST_STREAM
@@ -157,9 +173,14 @@ func (f *RSTStreamFrame) Header() *FrameHeader {
157173 return f .hdr
158174}
159175
160- // SettingsFrame is the representation of a [SETTINGS Frame]. The SETTINGS frame
161- // conveys configuration parameters that affect how endpoints communicate, such
162- // as preferences and constraints on peer behavior.
176+ // Free is a no-op for RSTStreamFrame.
177+ func (f * RSTStreamFrame ) Free () {}
178+
179+ // SettingsFrame is the representation of a [SETTINGS Frame]. There is no
180+ // underlying byte array in this frame, so Free() is a no-op.
181+ //
182+ // The SETTINGS frame conveys configuration parameters that affect how
183+ // endpoints communicate, such as preferences and constraints on peer behavior.
163184//
164185// [SETTINGS Frame]: https://httpwg.org/specs/rfc7540.html#SETTINGS
165186type SettingsFrame struct {
@@ -172,44 +193,57 @@ func (f *SettingsFrame) Header() *FrameHeader {
172193 return f .hdr
173194}
174195
196+ // Free is a no-op for SettingsFrame.
197+ func (f * SettingsFrame ) Free () {}
198+
175199// PingFrame is the representation of a [PING Frame]. The PING frame is a
176200// mechanism for measuring a minimal round-trip time from the sender, as well
177201// as determining whether an idle connection is still functional.
178202//
179- // It is the user's responsibility to call Data.Free() when it is no longer
180- // needed.
181- //
182203// [PING Frame]: https://httpwg.org/specs/rfc7540.html#PING
183204type PingFrame struct {
184205 hdr * FrameHeader
185- Data * mem.Buffer
206+ free func ()
207+ Data []byte
186208}
187209
188210// Header returns the 9 byte HTTP/2 header for this frame.
189211func (f * PingFrame ) Header () * FrameHeader {
190212 return f .hdr
191213}
192214
215+ // Free frees the buffer containing the data in this frame.
216+ func (f * PingFrame ) Free () {
217+ if f .free != nil {
218+ f .free ()
219+ }
220+ }
221+
193222// GoAwayFrame is the representation of a [GOAWAY Frame]. The GOAWAY frame is
194223// used to initiate shutdown of a connection or to signal serious error
195224// conditions.
196225//
197- // It is the user's responsibility to call DebugData.Free() when it is no longer
198- // needed.
199- //
200226// [GOAWAY Frame]: https://httpwg.org/specs/rfc7540.html#GOAWAY
201227type GoAwayFrame struct {
202228 hdr * FrameHeader
229+ free func ()
203230 LastStreamID uint32
204231 Code ErrCode
205- DebugData * mem. Buffer
232+ DebugData [] byte
206233}
207234
208235// Header returns the 9 byte HTTP/2 header for this frame.
209236func (f * GoAwayFrame ) Header () * FrameHeader {
210237 return f .hdr
211238}
212239
240+ // Free frees the buffer containing the debug data in this frame.
241+ func (f * GoAwayFrame ) Free () {
242+ if f .free != nil {
243+ f .free ()
244+ }
245+ }
246+
213247// WindowUpdateFrame is the representation of a [WINDOW_UPDATE Frame]. The
214248// WINDOW_UPDATE frame is used to implement flow control.
215249//
@@ -227,24 +261,31 @@ func (f *WindowUpdateFrame) Header() *FrameHeader {
227261// ContinuationFrame is the representation of a [CONTINUATION Frame]. The
228262// CONTINUATION frame is used to continue a sequence of header block fragments.
229263//
230- // It is the user's responsibility to call HdrBlock.Free() when it is no longer
231- // needed.
232- //
233264// [CONTINUATION Frame]: https://httpwg.org/specs/rfc7540.html#CONTINUATION
234265type ContinuationFrame struct {
235266 hdr * FrameHeader
236- HdrBlock * mem.Buffer
267+ free func ()
268+ HdrBlock []byte
237269}
238270
239271// Header returns the 9 byte HTTP/2 header for this frame.
240272func (f * ContinuationFrame ) Header () * FrameHeader {
241273 return f .hdr
242274}
243275
276+ // Free frees the buffer containing the header block in this frame.
277+ func (f * ContinuationFrame ) Free () {
278+ if f .free != nil {
279+ f .free ()
280+ }
281+ }
282+
244283// MetaHeadersFrame is the representation of one HEADERS frame and zero or more
245284// contiguous CONTINUATION frames and the decoding of their HPACK-encoded
246285// contents. This frame type is not transmitted over the network and is only
247286// generated by the ReadFrame() function.
287+ //
288+ // Since there is no underlying buffer in this Frame, Free() is a no-op.
248289type MetaHeadersFrame struct {
249290 hdr * FrameHeader
250291 Fields []hpack.HeaderField
@@ -258,17 +299,24 @@ func (f *MetaHeadersFrame) Header() *FrameHeader {
258299 return f .hdr
259300}
260301
302+ // Free is a no-op for MetaHeadersFrame.
303+ func (f * MetaHeadersFrame ) Free () {}
304+
261305// Framer encapsulates the functionality to read and write HTTP/2 frames.
262306type Framer interface {
263307 // ReadFrame returns grpchttp2.Frame. It is the caller's responsibility to
264- // free the underlying buffer when done using the Frame.
308+ // call Frame.Free() once it is done using it. Note that once the mem
309+ // package gets merged, this API will change in favor of Buffer.Free().
265310 ReadFrame () (Frame , error )
266- // WriteData writes an HTTP/2 DATA frame to the stream. The data is expected
267- // to be freed by the caller.
268- WriteData (streamID uint32 , endStream bool , data mem.BufferSlice ) error
269- // WriteHeaders writes an HTTP/2 HEADERS frame to the stream.
270- WriteHeaders (streamID uint32 , endStream , endHeaders bool , headerBlock []byte ) error
271- // WriteRSTStream writes an HTTP/2 RST_STREAM frame to the stream.
311+ // WriteData writes an HTTP/2 DATA frame to the stream.
312+ // TODO: Once the mem package gets merged, data will change type to
313+ // mem.BufferSlice.
314+ WriteData (streamID uint32 , endStream bool , data ... []byte ) error
315+ // WriteData writes an HTTP/2 HEADERS frame to the stream.
316+ // TODO: Once the mem package gets merged, headerBlock will change type to
317+ // mem.Buffer.
318+ WriteHeaders (streamID uint32 , endStream , endHeaders bool , headerBlocks []byte ) error
319+ // WriteData writes an HTTP/2 RST_STREAM frame to the stream.
272320 WriteRSTStream (streamID uint32 , code ErrCode ) error
273321 // WriteSettings writes an HTTP/2 SETTINGS frame to the connection.
274322 WriteSettings (settings ... Setting ) error
@@ -277,9 +325,13 @@ type Framer interface {
277325 // WritePing writes an HTTP/2 PING frame to the connection.
278326 WritePing (ack bool , data [8 ]byte ) error
279327 // WriteGoAway writes an HTTP/2 GOAWAY frame to the connection.
328+ // TODO: Once the mem package gets merged, debugData will change type to
329+ // mem.Buffer.
280330 WriteGoAway (maxStreamID uint32 , code ErrCode , debugData []byte ) error
281331 // WriteWindowUpdate writes an HTTP/2 WINDOW_UPDATE frame to the stream.
282332 WriteWindowUpdate (streamID , inc uint32 ) error
283333 // WriteContinuation writes an HTTP/2 CONTINUATION frame to the stream.
334+ // TODO: Once the mem package gets merged, data will change type to
335+ // mem.Buffer.
284336 WriteContinuation (streamID uint32 , endHeaders bool , headerBlock []byte ) error
285337}
0 commit comments