19
19
// Package grpchttp2 defines HTTP/2 types and a framer API and implementation.
20
20
package grpchttp2
21
21
22
- import (
23
- "golang.org/x/net/http2/hpack"
24
- "google.golang.org/grpc/mem"
25
- )
22
+ import "golang.org/x/net/http2/hpack"
26
23
27
24
// FrameType represents the type of an HTTP/2 Frame.
28
25
// See [Frame Type].
@@ -109,41 +106,60 @@ type FrameHeader struct {
109
106
// Each concrete Frame type defined below implements the Frame interface.
110
107
type Frame interface {
111
108
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 ()
112
115
}
113
116
114
117
// 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.
118
119
//
119
120
// [DATA frame]: https://httpwg.org/specs/rfc7540.html#DATA
120
121
type DataFrame struct {
121
122
hdr * FrameHeader
122
- Data * mem.Buffer
123
+ free func ()
124
+ Data []byte
123
125
}
124
126
125
127
// Header returns the 9 byte HTTP/2 header for this frame.
126
128
func (f * DataFrame ) Header () * FrameHeader {
127
129
return f .hdr
128
130
}
129
131
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
+
130
139
// HeadersFrame is the representation of a [HEADERS Frame]. The HEADERS frame
131
140
// 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.
134
141
//
135
142
// [HEADERS Frame]: https://httpwg.org/specs/rfc7540.html#HEADERS
136
143
type HeadersFrame struct {
137
144
hdr * FrameHeader
138
- HdrBlock * mem.Buffer
145
+ free func ()
146
+ HdrBlock []byte
139
147
}
140
148
141
149
// Header returns the 9 byte HTTP/2 header for this frame.
142
150
func (f * HeadersFrame ) Header () * FrameHeader {
143
151
return f .hdr
144
152
}
145
153
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
147
163
// frame allows for immediate termination of a stream
148
164
//
149
165
// [RST_STREAM Frame]: https://httpwg.org/specs/rfc7540.html#RST_STREAM
@@ -157,9 +173,14 @@ func (f *RSTStreamFrame) Header() *FrameHeader {
157
173
return f .hdr
158
174
}
159
175
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.
163
184
//
164
185
// [SETTINGS Frame]: https://httpwg.org/specs/rfc7540.html#SETTINGS
165
186
type SettingsFrame struct {
@@ -172,44 +193,57 @@ func (f *SettingsFrame) Header() *FrameHeader {
172
193
return f .hdr
173
194
}
174
195
196
+ // Free is a no-op for SettingsFrame.
197
+ func (f * SettingsFrame ) Free () {}
198
+
175
199
// PingFrame is the representation of a [PING Frame]. The PING frame is a
176
200
// mechanism for measuring a minimal round-trip time from the sender, as well
177
201
// as determining whether an idle connection is still functional.
178
202
//
179
- // It is the user's responsibility to call Data.Free() when it is no longer
180
- // needed.
181
- //
182
203
// [PING Frame]: https://httpwg.org/specs/rfc7540.html#PING
183
204
type PingFrame struct {
184
205
hdr * FrameHeader
185
- Data * mem.Buffer
206
+ free func ()
207
+ Data []byte
186
208
}
187
209
188
210
// Header returns the 9 byte HTTP/2 header for this frame.
189
211
func (f * PingFrame ) Header () * FrameHeader {
190
212
return f .hdr
191
213
}
192
214
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
+
193
222
// GoAwayFrame is the representation of a [GOAWAY Frame]. The GOAWAY frame is
194
223
// used to initiate shutdown of a connection or to signal serious error
195
224
// conditions.
196
225
//
197
- // It is the user's responsibility to call DebugData.Free() when it is no longer
198
- // needed.
199
- //
200
226
// [GOAWAY Frame]: https://httpwg.org/specs/rfc7540.html#GOAWAY
201
227
type GoAwayFrame struct {
202
228
hdr * FrameHeader
229
+ free func ()
203
230
LastStreamID uint32
204
231
Code ErrCode
205
- DebugData * mem. Buffer
232
+ DebugData [] byte
206
233
}
207
234
208
235
// Header returns the 9 byte HTTP/2 header for this frame.
209
236
func (f * GoAwayFrame ) Header () * FrameHeader {
210
237
return f .hdr
211
238
}
212
239
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
+
213
247
// WindowUpdateFrame is the representation of a [WINDOW_UPDATE Frame]. The
214
248
// WINDOW_UPDATE frame is used to implement flow control.
215
249
//
@@ -227,24 +261,31 @@ func (f *WindowUpdateFrame) Header() *FrameHeader {
227
261
// ContinuationFrame is the representation of a [CONTINUATION Frame]. The
228
262
// CONTINUATION frame is used to continue a sequence of header block fragments.
229
263
//
230
- // It is the user's responsibility to call HdrBlock.Free() when it is no longer
231
- // needed.
232
- //
233
264
// [CONTINUATION Frame]: https://httpwg.org/specs/rfc7540.html#CONTINUATION
234
265
type ContinuationFrame struct {
235
266
hdr * FrameHeader
236
- HdrBlock * mem.Buffer
267
+ free func ()
268
+ HdrBlock []byte
237
269
}
238
270
239
271
// Header returns the 9 byte HTTP/2 header for this frame.
240
272
func (f * ContinuationFrame ) Header () * FrameHeader {
241
273
return f .hdr
242
274
}
243
275
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
+
244
283
// MetaHeadersFrame is the representation of one HEADERS frame and zero or more
245
284
// contiguous CONTINUATION frames and the decoding of their HPACK-encoded
246
285
// contents. This frame type is not transmitted over the network and is only
247
286
// generated by the ReadFrame() function.
287
+ //
288
+ // Since there is no underlying buffer in this Frame, Free() is a no-op.
248
289
type MetaHeadersFrame struct {
249
290
hdr * FrameHeader
250
291
Fields []hpack.HeaderField
@@ -258,17 +299,24 @@ func (f *MetaHeadersFrame) Header() *FrameHeader {
258
299
return f .hdr
259
300
}
260
301
302
+ // Free is a no-op for MetaHeadersFrame.
303
+ func (f * MetaHeadersFrame ) Free () {}
304
+
261
305
// Framer encapsulates the functionality to read and write HTTP/2 frames.
262
306
type Framer interface {
263
307
// 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().
265
310
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.
272
320
WriteRSTStream (streamID uint32 , code ErrCode ) error
273
321
// WriteSettings writes an HTTP/2 SETTINGS frame to the connection.
274
322
WriteSettings (settings ... Setting ) error
@@ -277,9 +325,13 @@ type Framer interface {
277
325
// WritePing writes an HTTP/2 PING frame to the connection.
278
326
WritePing (ack bool , data [8 ]byte ) error
279
327
// 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.
280
330
WriteGoAway (maxStreamID uint32 , code ErrCode , debugData []byte ) error
281
331
// WriteWindowUpdate writes an HTTP/2 WINDOW_UPDATE frame to the stream.
282
332
WriteWindowUpdate (streamID , inc uint32 ) error
283
333
// 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.
284
336
WriteContinuation (streamID uint32 , endHeaders bool , headerBlock []byte ) error
285
337
}
0 commit comments